X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=fd.c;h=800106e132b2bc21085f65803d70b6bad492f854;hb=HEAD;hp=d858ae623ba6203719e70930625df97867166e67;hpb=d1b7b2dbccd20ef72c54b7e06117ef1f92500c04;p=paraslash.git diff --git a/fd.c b/fd.c index d858ae62..1af902f9 100644 --- a/fd.c +++ b/fd.c @@ -387,71 +387,32 @@ int para_open(const char *path, int flags, mode_t mode) } /** - * Save the cwd and open a given directory. + * Create a directory, don't fail if it already exists. * - * \param dirname Path to the directory to open. - * \param dir Result pointer. - * \param cwd File descriptor of the current working directory. - * - * \return Standard. - * - * Opening the current directory (".") and calling fchdir() to return is - * usually faster and more reliable than saving cwd in some buffer and calling - * chdir() afterwards. - * - * If \a cwd is not \p NULL "." is opened and the resulting file descriptor is - * stored in \a cwd. If the function returns success, and \a cwd is not \p - * NULL, the caller must close this file descriptor (probably after calling - * fchdir(*cwd)). - * - * On errors, the function undos everything, so the caller needs neither close - * any files, nor change back to the original working directory. + * \param path Name of the directory to create. * - * \sa getcwd(3). + * This function passes the fixed mode value 0777 to mkdir(3) (which consults + * the file creation mask and restricts this value). * + * \return Zero if the path already existed as a directory or as a symbolic + * link which leads to a directory, one if the path did not exist and the + * directory has been created successfully, negative error code else. */ -static int para_opendir(const char *dirname, DIR **dir, int *cwd) +int para_mkdir(const char *path) { - int ret; + /* + * We call opendir(3) rather than relying on stat(2) because this way + * we don't need extra code to get the symlink case right. + */ + DIR *dir = opendir(path); - *dir = NULL; - if (cwd) { - ret = para_open(".", O_RDONLY, 0); - if (ret < 0) - return ret; - *cwd = ret; - } - if (chdir(dirname) != 0) { - ret = -ERRNO_TO_PARA_ERROR(errno); - goto close_cwd; - } - *dir = opendir("."); - if (*dir) - return 1; - ret = -ERRNO_TO_PARA_ERROR(errno); - /* Ignore return value of fchdir() and close(). We're busted anyway. */ - if (cwd) { - int __a_unused ret2 = fchdir(*cwd); /* STFU, gcc */ + if (dir) { + closedir(dir); + return 0; } -close_cwd: - if (cwd) - close(*cwd); - return ret; -} - -/** - * A wrapper for mkdir(2). - * - * \param path Name of the directory to create. - * \param mode The permissions to use. - * - * \return Standard. - */ -int para_mkdir(const char *path, mode_t mode) -{ - if (!mkdir(path, mode)) - return 1; - return -ERRNO_TO_PARA_ERROR(errno); + if (errno != ENOENT) + return -ERRNO_TO_PARA_ERROR(errno); + return mkdir(path, 0777) == 0? 1 : -ERRNO_TO_PARA_ERROR(errno); } /** @@ -617,64 +578,3 @@ void valid_fd_012(void) } } } - -/** - * Traverse the given directory recursively. - * - * \param dirname The directory to traverse. - * \param func The function to call for each entry. - * \param private_data Pointer to an arbitrary data structure. - * - * For each regular file under \a dirname, the supplied function \a func is - * called. The full path of the regular file and the \a private_data pointer - * are passed to \a func. Directories for which the calling process has no - * permissions to change to are silently ignored. - * - * \return Standard. - */ -int for_each_file_in_dir(const char *dirname, - int (*func)(const char *, void *), void *private_data) -{ - DIR *dir; - struct dirent *entry; - int cwd_fd, ret = para_opendir(dirname, &dir, &cwd_fd); - - if (ret < 0) - return ret == -ERRNO_TO_PARA_ERROR(EACCES)? 1 : ret; - /* scan cwd recursively */ - while ((entry = readdir(dir))) { - mode_t m; - char *tmp; - struct stat s; - - if (!strcmp(entry->d_name, ".")) - continue; - if (!strcmp(entry->d_name, "..")) - continue; - if (lstat(entry->d_name, &s) == -1) - continue; - m = s.st_mode; - if (!S_ISREG(m) && !S_ISDIR(m)) - continue; - tmp = make_message("%s/%s", dirname, entry->d_name); - if (!S_ISDIR(m)) { - ret = func(tmp, private_data); - free(tmp); - if (ret < 0) - goto out; - continue; - } - /* directory */ - ret = for_each_file_in_dir(tmp, func, private_data); - free(tmp); - if (ret < 0) - goto out; - } - ret = 1; -out: - closedir(dir); - if (fchdir(cwd_fd) < 0 && ret >= 0) - ret = -ERRNO_TO_PARA_ERROR(errno); - close(cwd_fd); - return ret; -}