#include #include #include #include #include #include #include /* Directory information. */ #include "global.h" typedef struct symlink_node { char mail_dir[MAX_PATH + 1]; char link_fname[MAX_PATH + 1]; int resolved; struct symlink_node *next; } SYMLINK_NODE; SYMLINK_NODE *head = 0; int symlinks_found = 0; int symlinks_processed = 0; static void add_to_unresolved_list(const char *mail_dir, const char *link_fname) { SYMLINK_NODE *ptr; if(!head) { head = (SYMLINK_NODE *) malloc(sizeof(SYMLINK_NODE)); ptr = head; } else { for(ptr=head; ptr->next; ptr=ptr->next); ptr->next = (SYMLINK_NODE *) malloc(sizeof(SYMLINK_NODE)); ptr = ptr->next; } strncpy(ptr->mail_dir, mail_dir, MAX_PATH + 1); strncpy(ptr->link_fname, link_fname, MAX_PATH + 1); ptr->resolved = 0; ptr->next = (SYMLINK_NODE *) 0; } int path_is_symlink(const char *path) { struct stat buf; if(lstat (path, &buf)) return 0; return S_ISLNK (buf.st_mode); } int is_symlink (const char *dirname, const char *fname) { char path[MAX_PATH + 1]; snprintf (path, MAX_PATH + 1, "%s/%s", dirname, fname); return path_is_symlink(path); } int is_directory (const char *dirname, const char *fname) { struct stat buf; char path[MAX_PATH + 1]; snprintf (path, MAX_PATH + 1, "%s/%s", dirname, fname); stat (path, &buf); return S_ISDIR (buf.st_mode); } static void make_hard_link(const char *fname, const char *link_end) { unlink(fname); if(link(link_end, fname)) perror(link_end); else symlinks_processed++; } static void process_symlink(const char *mail_path, const char *fname) { char link_path[MAX_PATH + 1]; char link_end[MAX_PATH + 1]; char current_dir[MAX_PATH + 1]; int len; snprintf(link_path, MAX_PATH + 1, "%s/%s", mail_path, fname); len = readlink(link_path, link_end, MAX_PATH); if(len == -1) { perror(link_path); } else { *(link_end + len) = '\0'; /* get current directory so we can return */ if(!getcwd(current_dir, MAX_PATH + 1)) perror("Can't get current working directory."); symlinks_found++; if(chdir(mail_path)) perror(mail_path); if(path_is_symlink(link_end)) { add_to_unresolved_list(mail_path,fname); } else { make_hard_link(fname, link_end); } if(chdir(current_dir)) perror(current_dir); } } static void do_person(const char *people_path, const char *person) { DIR *dir_p; struct dirent *dir_entry_p; char mail_path[MAX_PATH + 1]; if(is_directory(people_path, person)) { // printf("Checking user: %s...\n", person); printf("."); fflush(stdout); snprintf(mail_path, MAX_PATH + 1, "%s/%s/mail", people_path, person); dir_p = opendir (mail_path); if (!dir_p) { perror("Unable to open 'mail' directory, so skipping"); return; } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) { if(strstr(dir_entry_p->d_name, ".fil") && is_symlink(mail_path, dir_entry_p->d_name)) process_symlink(mail_path, dir_entry_p->d_name); } } closedir (dir_p); } } static void do_course(const char *group_path, const char *course) { DIR *dir_p; struct dirent *dir_entry_p; char people_path[MAX_PATH + 1]; if(is_directory(group_path, course)) { // printf("Entering course: %s...\n", course); snprintf(people_path, MAX_PATH + 1, "%s/%s/people", group_path, course); dir_p = opendir (people_path); if (!dir_p) { perror("Unable to open 'people' directory, so skipping"); return; } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) do_person(people_path, dir_entry_p->d_name); } closedir (dir_p); } } void do_course_group (const char *group) { DIR *dir_p; struct dirent *dir_entry_p; char group_path[MAX_PATH + 1]; if(is_directory(COURSE_PATH, group)) { snprintf(group_path, MAX_PATH + 1, "%s%s", COURSE_PATH, group); // printf("Entering course group: %s...\n", group_path); dir_p = opendir (group_path); if (!dir_p) { perror("Unable to open directory"); return; } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) do_course(group_path, dir_entry_p->d_name); } closedir (dir_p); } } static int symlink_resolved (SYMLINK_NODE *data) { int len; char link_path[MAX_PATH + 1]; char link_end[MAX_PATH + 1]; char current_dir[MAX_PATH + 1]; puts("in symlink_resolved()"); snprintf(link_path, MAX_PATH + 1, "%s/%s", data->mail_dir, data->link_fname); len = readlink(link_path, link_end, MAX_PATH); if(len == -1) { perror(link_path); return 0; } else { *(link_end + len) = '\0'; /* get current directory so we can return */ if(!getcwd(current_dir, MAX_PATH + 1)) perror("Can't get current working directory."); if(chdir(data->mail_dir)) perror(data->mail_dir); if(path_is_symlink(link_end)) { if(chdir(current_dir)) perror(current_dir); return 0; } else { make_hard_link(data->link_fname, link_end); if(chdir(current_dir)) perror(current_dir); return 1; } } } static void process_unresolved_list() { SYMLINK_NODE *ptr; int success = 0; do { success = 0; for(ptr=head; ptr; ptr=ptr->next) if(!ptr->resolved) { if(symlink_resolved(ptr)) success = 1; } } while (success); } void do_upgrade () { DIR *dir_p; struct dirent *dir_entry_p; dir_p = opendir (COURSE_PATH); if (!dir_p) { printf("\n\nUnable to open directory: %s\n", COURSE_PATH); printf("Be sure to run this from your installation's 'src' directory!\n\n"); exit(1); } while (NULL != (dir_entry_p = readdir (dir_p))) { if (strcmp (dir_entry_p->d_name, ".") && strcmp (dir_entry_p->d_name, "..")) do_course_group(dir_entry_p->d_name); } closedir (dir_p); process_unresolved_list(); } int main() { do_upgrade(); printf("\n\nFound %d symbolic links. Converted %d of them to hard links.\n\nDone!\n", symlinks_found, symlinks_processed); return 0; }