Example #1
0
/* 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);
}
Example #2
0
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"));
}
Example #4
0
/* 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);
}
Example #5
0
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;
}
Example #6
0
/* 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
}
Example #8
0
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;
}
Example #9
0
	foreach(const std::string& dir, dirs) {
		rmdir_recursive(dir);
	}
Example #10
0
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);
}
Example #11
0
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;
}