/* Delete a directory recursively. */ void rmdir_recursive (gchar *path) { GDir *cur_dir; const gchar *dir_file; cur_dir = g_dir_open (path, 0, NULL); if (cur_dir) { while ( (dir_file = g_dir_read_name (cur_dir))) { gchar *fpath = g_build_filename (path, dir_file, NULL); if (fpath) { if (g_file_test (fpath, G_FILE_TEST_IS_DIR)) { rmdir_recursive (fpath); } else { g_unlink (fpath); } g_free (fpath); } } g_dir_close (cur_dir); } g_rmdir (path); }
static int asepsis_handle_delete(const char* path1) { int res = 0; if (isPrefixPath(path1)) { return 0; } char prefixPath1[SAFE_PREFIX_PATH_BUFFER_SIZE]; if (!makePrefixPath(path1, prefixPath1)) { return 0; // the prefixed path would be too long } SUSPEND_LOCK_CHECK(); if (!isDirectory(prefixPath1)) { // nothing to do, source dir is not present in our cache SUSPEND_LOCK_RELEASE(); return 0; } // do mirror remove DLOG("handle delete %s", prefixPath1); SERIALIZATION_LOCK_CHECK(); res = rmdir_recursive(prefixPath1); // this is dangerous, but we know that our path has prefix at least if (res) { ERROR("unable to remove directory %s (%s)", prefixPath1, strerror(errno)); } SERIALIZATION_LOCK_RELEASE(); SUSPEND_LOCK_RELEASE(); return res; }
int tests_end(int result) { setup("tests_end"); /* Restore previous cwd and remove scratch dir. */ return (ok_unix(fchdir(current_dir), "fchdir") && ok_unix(close(current_dir), "close") && ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive")); }
/* FIXME: This function ought to be iterative! */ int rmdir_recursive(const char *basedir) { DIR *d = opendir(basedir); struct dirent *dp; if (!d) { perror(basedir); return -1; } while (dp = readdir(d)) { size_t len = strlen(basedir) + strlen(dp->d_name) + 3; struct stat sb; char *path; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; path = malloc(len); if (!path) { perror("malloc"); free(path); continue; } memset(path, 0, len); snprintf(path, len - 1, "%s/%s", basedir, dp->d_name); if (lstat(path, &sb)) { perror(path); free(path); continue; } if (sb.st_mode & S_IFDIR) rmdir_recursive(path); else unlink(path); free(path); } closedir(d); return rmdir(basedir); }
static int asepsis_handle_rename(const char* path1, const char* path2) { int res = 0; if (isPrefixPath(path1) || isPrefixPath(path2)) { return 0; } char prefixPath1[SAFE_PREFIX_PATH_BUFFER_SIZE]; if (!makePrefixPath(path1, prefixPath1)) { return 0; // the prefixed path would be too long } char prefixPath2[SAFE_PREFIX_PATH_BUFFER_SIZE]; if (!makePrefixPath(path2, prefixPath2)) { return 0; // the prefixed path would be too long } SUSPEND_LOCK_CHECK(); if (!isDirectory(prefixPath1)) { // nothing to do, source dir is not present in our cache SUSPEND_LOCK_RELEASE(); return 0; } // do mirror rename DLOG("handle rename %s -> %s", prefixPath1, prefixPath2); SERIALIZATION_LOCK_CHECK(); // here we need to be especially careful // rename(2) may fail under some special circumstances // 1. something gets into the way of renaming // 2. parent folder is missing for new name rmdir_recursive(prefixPath2); // there may be some old content (pathological case) ensureDirectoryForPath(prefixPath2); // like mkdir -p $prefixPath2 (but excluding last directory) // ok, now it should be safe to call rename res = rename(prefixPath1, prefixPath2); // this is dangerous, but we know that our path has prefix at least if (res) { ERROR("unable to rename directories %s -> %s (%s)", prefixPath1, prefixPath2, strerror(errno)); } SERIALIZATION_LOCK_RELEASE(); SUSPEND_LOCK_RELEASE(); return res; }
/* Remove directory if it is empty */ void remove_dir_if_empty (gchar* dir_path) { GDir *dir = (GDir *) NULL; gint file_occurrence = 0; /* if the project dir is empty delete it */ dir = g_dir_open (dir_path, 0, NULL); while (g_dir_read_name (dir)) { file_occurrence++; } if (file_occurrence == 0) { rmdir_recursive(dir_path); } }
static int tests_end(void) { #ifdef NO_SERVER setup("tests_end"); /* Restore previous cwd and remove scratch dir. */ int ok = ok_unix(fchdir(current_dir), "fchdir"); if (ok) ok = ok_unix(close(current_dir), "close"); if (ok) { if (!keep_scratch_dir) { ok = ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive"); } } return ok; #else return 0; #endif }
static int rmdir_recursive(const char *dir_path) { osd_directory *dir; const osd_directory_entry *ent; osd_directory_entry *ent2; char *newpath; dir = osd_opendir(dir_path); if (dir) { while((ent = osd_readdir(dir)) != NULL) { if (strcmp(ent->name, ".") && strcmp(ent->name, "..")) { newpath = (char*)malloc(strlen(dir_path) + 1 + strlen(ent->name) + 1); if (!newpath) return -1; strcpy(newpath, dir_path); strcat(newpath, PATH_SEPARATOR); strcat(newpath, ent->name); ent2 = osd_stat(newpath); if (ent2) { if (ent2->type == ENTTYPE_DIR) rmdir_recursive(newpath); else osd_rmfile(newpath); free(ent2); } free(newpath); } } osd_closedir(dir); } osd_rmdir(dir_path); return 0; }
foreach(const std::string& dir, dirs) { rmdir_recursive(dir); }
void do_backup(struct interval *interval, struct backup *backup) { time_t now_tt = time(NULL); struct tm *now = localtime(&now_tt); size_t proglen = strlen(backup->dest) + 21; size_t locklen = strlen(backup->dest) + 7; size_t nbackups = interval->count + 1; size_t len = strlen(backup->dest) + strlen(interval->name) + strlen(backup->name) + 21; pid_t pid; char *lockpath = malloc(locklen); char *progpath = malloc(proglen); char *latestpath = NULL; char *path = malloc(len + 1); int lockfd, progfd; if (!path || !lockpath) { perror("malloc"); goto out_free; } memset(lockpath, 0, locklen); memset(path, 0, len); snprintf(lockpath, locklen, "%s/.lock", backup->dest); snprintf(progpath, proglen, "%s/.backup_in_progress", backup->dest); snprintf(path, len - 17, "%s/%s-%s-", backup->dest, backup->name, interval->name); strftime(path + len - 18, 17, "%Y-%m-%d_%Hh%M", now); lockfd = open(lockpath, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if (lockfd == -1) { fprintf(stderr, "Locking backup directory for %s: %s\n", backup->name, strerror(errno)); goto out_free; } if (flock(lockfd, LOCK_EX | LOCK_NB)) { if (errno == EAGAIN) fprintf(stderr, "%s: Backup already in progress\n", backup->name); else fprintf(stderr, "Locking backup directory for %s: %s\n", backup->name, strerror(errno)); goto out_close_lock; } progfd = open(progpath, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if (progfd == -1) { /** * Backup in progress marker still around, we should * delete one backup. */ struct dirent *de; struct stat sb; char *latest = NULL; time_t latestmtime = 0; DIR *d; if (errno != EEXIST) { fprintf(stderr, "Locking backup directory for %s: %s\n", backup->name, strerror(errno)); goto out_unlock; } if (!(d = opendir(backup->dest))) { perror("opendir"); close(progfd); goto out_unlock; } while (de = readdir(d)) { size_t entry_len = strlen(backup->dest) + strlen(de->d_name) + 3; size_t minlen = MIN(strlen(de->d_name), strlen(backup->name)); char *entry = NULL; /* Check if the directory entry is a backup */ if (minlen < strlen(backup->name) || strncmp(de->d_name, backup->name, minlen)) { if (!backup->ccollect || strlen(de->d_name) < strlen(interval->name) || strncmp(de->d_name, interval->name, strlen(interval->name))) continue; } entry = malloc(entry_len); if (!entry) { perror("malloc"); continue; } memset(entry, 0, entry_len); snprintf(entry, entry_len - 1, "%s/%s", backup->dest, de->d_name); if (stat(entry, &sb)) perror(entry); else if (sb.st_mtime > latestmtime) { if (latest) free(latest); latest = entry; latestmtime = sb.st_mtime; } else free(entry); } closedir(d); if (latest) { fprintf(stderr, "Removing stale backup directory %s\n", latest); rmdir_recursive(latest); if (!stat(latest, &sb) || errno != ENOENT) { fprintf(stderr, "Unable to completely remove" " directory\n\n\t%s\n\nPlease clean " "up manually and retry.\n" "WARNING: Retrying immediately will " "delete a different directory!\n", latest); goto out_unlock; } free(latest); } } close(progfd); while (nbackups > interval->count) { DIR *dirp; char *oldest = NULL; struct dirent *de; struct stat sb; time_t oldest_time = 0, latest_time = 0; nbackups = 0; memset(&sb, 0, sizeof(struct stat)); if (!(dirp = opendir(backup->dest))) { perror("opendir"); goto out_unlock; } while (de = readdir(dirp)) { size_t entry_len = strlen(backup->dest) + strlen(de->d_name) + 3; size_t minlen = MIN(strlen(de->d_name), strlen(backup->name)); char *entry = NULL; /* Check if the directory entry is a backup */ if (minlen < strlen(backup->name) || strncmp(de->d_name, backup->name, minlen)) { if (!backup->ccollect || strlen(de->d_name) < strlen(interval->name) || strncmp(de->d_name, interval->name, strlen(interval->name))) continue; } nbackups++; entry = malloc(entry_len); if (!entry) { perror("malloc"); continue; } if (entry == oldest) fputs("WARNING: malloc did something weird!\n", stderr); memset(entry, 0, entry_len); snprintf(entry, entry_len - 1, "%s/%s", backup->dest, de->d_name); if (stat(entry, &sb)) perror(entry); else if (sb.st_mtime > latest_time) { if (latestpath) free(latestpath); latestpath = strdup(entry); latest_time = sb.st_mtime; if (!oldest_time || sb.st_mtime < oldest_time) { if (oldest) free(oldest); oldest = strdup(entry); oldest_time = sb.st_mtime; } } else if (!oldest_time || sb.st_mtime < oldest_time) { if (oldest) free(oldest); oldest = strdup(entry); oldest_time = sb.st_mtime; } free(entry); } closedir(dirp); if (oldest && nbackups > interval->count) { rmdir_recursive(oldest); if (!stat(oldest, &sb) || errno != ENOENT) { fprintf(stderr, "Unable to completely remove" " directory\n\n\t%s\n\nPlease clean " "up manually and retry.\n" "WARNING: Retrying immediately will " "delete a different directory!\n", oldest); goto out_unlock; } } if (oldest) free(oldest); } /* * We can mkdir only now because we weren't protected by the lock * before. */ if (mkdir(path, 0755)) { perror(path); goto out_unlock; } /** * Set a couple of variables for the preexec and postexec scripts. */ if (setenv("INTERVAL", interval->name, 1) || setenv("name", backup->name, 1) || setenv("source_full", backup->source, 1) || setenv("destination_full", path, 1) || setenv("destination_dir", path, 1) || setenv("destination_name", path + strlen(backup->dest) + 1, 1)) { perror("setenv"); goto out_unlock; } if (latestpath && setenv("previous_path", latestpath, 1)) { perror("setenv"); goto out_unsetenv; } /* * Call the pre-execution script * * XXX: Hmm, we really have to do something about code duplication here. */ if (backup->preexec) { /** * This code injection possibility would only be a security * problem if it wasn't precisely what we wanted. Please * stop bugging. */ int exitcode = system(backup->preexec); if (exitcode < 0) { perror("system"); rmdir_recursive(path); goto out_unsetenv; } if (WEXITSTATUS(exitcode)) { fprintf(stderr, "pre_exec process exited with code %d!\n", WEXITSTATUS(exitcode)); rmdir_recursive(path); goto out_unsetenv; } } /* * Call rsync and let it fill realpath with data from source. */ pid = fork(); if (pid < 0) { perror("fork"); goto out_unsetenv; } else if (!pid) { struct exclude *pos; char **argv; int argc = 9; int argi; for (pos = backup->excludelist.next; pos && pos != &backup->excludelist; pos = pos->next) ++argc; if (latestpath) ++argc; argv = malloc(argc * sizeof(char *)); argv[0] = RSYNC_PATH; argv[1] = "-a"; argv[2] = "--delete"; argv[3] = "--numeric-ids"; argv[4] = "--relative"; argv[5] = "--delete-excluded"; argi = 6; if (latestpath) { size_t alen = sizeof("--link-dest=") + strlen(latestpath) + 1; argv[argi] = malloc(alen); if (!argv[argi]) { perror("malloc"); exit(EXIT_FAILURE); } snprintf(argv[argi++], alen - 1, "--link-dest=%s", latestpath); } for (pos = backup->excludelist.next; pos && pos != &backup->excludelist; pos = pos->next) { size_t alen = sizeof("--exclude=") + strlen(pos->pattern) + 1; argv[argi] = malloc(alen); if (!argv[argi]) { perror("malloc"); exit(EXIT_FAILURE); } snprintf(argv[argi++], alen - 1, "--exclude=%s", pos->pattern); } argv[argi++] = backup->source; argv[argi++] = path; argv[argi++] = NULL; execv(RSYNC_PATH, argv); perror(RSYNC_PATH); } else { int exitcode = 0; if (waitpid(pid, &exitcode, 0) < 0) { perror("wait"); rmdir_recursive(path); goto out_unsetenv; } if (WEXITSTATUS(exitcode) && WEXITSTATUS(exitcode) != 24) { fprintf(stderr, "rsync process exited with code %d!\n", WEXITSTATUS(exitcode)); rmdir_recursive(path); goto out_unsetenv; } } /* * Call the pre-execution script * * XXX: Hmm, we really have to do something about code duplication here. */ if (backup->postexec) { /** * This code injection possibility would only be a security * problem if it wasn't precisely what we wanted. Please * stop bugging. */ int exitcode = system(backup->postexec); if (exitcode < 0) { perror("system"); goto out_unsetenv; } if (WEXITSTATUS(exitcode)) { fprintf(stderr, "post_exec process exited with code %d!\n", WEXITSTATUS(exitcode)); goto out_unsetenv; } } out_unsetenv: if (latestpath) unsetenv("previous_path"); unsetenv("destination_name"); unsetenv("destination_dir"); unsetenv("destination_full"); unsetenv("source_full"); unsetenv("INTERVAL"); unsetenv("name"); out_unlock: flock(lockfd, LOCK_UN); out_close_lock: close(lockfd); unlink(progpath); unlink(lockpath); out_free: if (latestpath) free(latestpath); if (progpath) free(progpath); if (lockpath) free(lockpath); if (path) free(path); }
int messdocs(const char *toc_filename, const char *dest_dir, const char *help_project_filename, const char *help_contents_filename, const char *help_filename) { char buf[4096]; struct messdocs_state state; int len; int done; FILE *in; FILE *chm_hhp; int i; char *s; XML_Memory_Handling_Suite memcallbacks; memset(&state, 0, sizeof(state)); state.m_pool = pool_alloc_lib(NULL); /* open the DOC */ in = fopen(toc_filename, "r"); if (!in) { fprintf(stderr, "Cannot open TOC file '%s'\n", toc_filename); goto error; } /* figure out the TOC directory */ state.m_toc_dir = pool_strdup_lib(state.m_pool, toc_filename); if (!state.m_toc_dir) goto outofmemory; for (i = strlen(state.m_toc_dir) - 1; (i > 0) && !osd_is_path_separator(state.m_toc_dir[i]); i--) state.m_toc_dir[i] = '\0'; /* clean the target directory */ rmdir_recursive(dest_dir); osd_mkdir(dest_dir); /* create the help contents file */ s = (char*)pool_malloc_lib(state.m_pool, strlen(dest_dir) + 1 + strlen(help_project_filename) + 1); if (!s) goto outofmemory; strcpy(s, dest_dir); strcat(s, PATH_SEPARATOR); strcat(s, help_contents_filename); state.m_chm_toc = fopen(s, "w"); state.m_dest_dir = dest_dir; if (!state.m_chm_toc) { fprintf(stderr, "Cannot open file %s\n", s); goto error; } fprintf(state.m_chm_toc, "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML//EN\"\n"); fprintf(state.m_chm_toc, "<HTML>\n"); fprintf(state.m_chm_toc, "<HEAD>\n"); fprintf(state.m_chm_toc, "</HEAD>\n"); fprintf(state.m_chm_toc, "<BODY>\n"); fprintf(state.m_chm_toc, "<OBJECT type=\"text/site properties\">\n"); fprintf(state.m_chm_toc, "\t<param name=\"Window Styles\" value=\"0x800625\">\n"); fprintf(state.m_chm_toc, "\t<param name=\"ImageType\" value=\"Folder\">\n"); fprintf(state.m_chm_toc, "\t<param name=\"Font\" value=\"Arial,8,0\">\n"); fprintf(state.m_chm_toc, "</OBJECT>\n"); fprintf(state.m_chm_toc, "<UL>\n"); /* create the XML parser */ memcallbacks.malloc_fcn = expat_malloc; memcallbacks.realloc_fcn = expat_realloc; memcallbacks.free_fcn = expat_free; state.m_parser = XML_ParserCreate_MM(NULL, &memcallbacks, NULL); if (!state.m_parser) goto outofmemory; XML_SetUserData(state.m_parser, &state); XML_SetElementHandler(state.m_parser, start_handler, end_handler); XML_SetCharacterDataHandler(state.m_parser, data_handler); do { len = (int) fread(buf, 1, sizeof(buf), in); done = feof(in); if (XML_Parse(state.m_parser, buf, len, done) == XML_STATUS_ERROR) { process_error(&state, NULL, NULL); break; } } while(!done); fprintf(state.m_chm_toc, "</UL>\n"); fprintf(state.m_chm_toc, "</BODY></HTML>"); fclose(state.m_chm_toc); /* create the help project file */ s = (char*)pool_malloc_lib(state.m_pool, strlen(dest_dir) + 1 + strlen(help_project_filename) + 1); if (!s) goto outofmemory; strcpy(s, dest_dir); strcat(s, PATH_SEPARATOR); strcat(s, help_project_filename); chm_hhp = fopen(s, "w"); if (!chm_hhp) { fprintf(stderr, "Cannot open file %s\n", s); goto error; } fprintf(chm_hhp, "[OPTIONS]\n"); fprintf(chm_hhp, "Compiled file=%s\n", help_filename); fprintf(chm_hhp, "Contents file=%s\n", help_contents_filename); fprintf(chm_hhp, "Default topic=%s\n", state.m_default_topic); fprintf(chm_hhp, "Language=0x409 English (United States)\n"); fprintf(chm_hhp, "Title=%s\n", state.m_title); fprintf(chm_hhp, "\n"); fclose(chm_hhp); /* finish up */ XML_ParserFree(state.m_parser); fclose(in); pool_free_lib(state.m_pool); return state.m_error ? -1 : 0; outofmemory: fprintf(stderr, "Out of memory"); error: if (state.m_chm_toc) fclose(state.m_chm_toc); if (in) fclose(in); return -1; }