]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
fd: Simplify and move for_each_file_in_dir().
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 25 Sep 2022 19:17:38 +0000 (21:17 +0200)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 7 May 2023 18:45:22 +0000 (20:45 +0200)
With only one user it can be static in aft.c. Modify the function
so that it no longer changes the current working directory, remove
para_opendir() because it is unused now, dedox the documentation and
streamline it a bit.

aft.c
fd.c
fd.h

diff --git a/aft.c b/aft.c
index b4d8c2dd359bbfbe143c8be75a89b016b0bfe505..0aa9c6ba7ac4588f1889bf4dda8ec52d3b9cf4d7 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -6,6 +6,7 @@
 #include <sys/mman.h>
 #include <fnmatch.h>
 #include <sys/shm.h>
+#include <dirent.h>
 #include <osl.h>
 #include <lopsub.h>
 
@@ -1906,6 +1907,53 @@ out_free:
        return send_ret;
 }
 
+/*
+ * Call back once for each regular file below a directory.
+ *
+ * Traverse the given directory recursively and call the supplied callback for
+ * each regular file encountered. The first argument to the callback will be
+ * the path to the regular file and the second argument will be the data
+ * pointer. All file types except regular files and directories are ignored. In
+ * particular, symlinks are not followed. Subdirectories are ignored silently
+ * if the calling process has insufficient access permissions.
+ */
+static int for_each_file_in_dir(const char *dirname,
+               int (*func)(const char *, void *), void *data)
+{
+       int ret;
+       DIR *dir;
+       struct dirent *entry;
+
+       dir = opendir(dirname);
+       if (!dir)
+               return errno == EACCES? 1 : -ERRNO_TO_PARA_ERROR(errno);
+       /* scan cwd recursively */
+       while ((entry = readdir(dir))) {
+               char *tmp;
+               struct stat s;
+
+               if (!strcmp(entry->d_name, "."))
+                       continue;
+               if (!strcmp(entry->d_name, ".."))
+                       continue;
+               tmp = make_message("%s/%s", dirname, entry->d_name);
+               ret = 0;
+               if (lstat(tmp, &s) != -1) {
+                       if (S_ISREG(s.st_mode))
+                               ret = func(tmp, data);
+                       else if (S_ISDIR(s.st_mode))
+                               ret = for_each_file_in_dir(tmp, func, data);
+               }
+               free(tmp);
+               if (ret < 0)
+                       goto out;
+       }
+       ret = 1;
+out:
+       closedir(dir);
+       return ret;
+}
+
 static int com_add(struct command_context *cc, struct lls_parse_result *lpr)
 {
        int i, ret;
diff --git a/fd.c b/fd.c
index f30bd8d69d0e17a54673fb367b0f82ff1d62b09f..1af902f9af440cbf570377ed219eea08e76417a2 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -386,59 +386,6 @@ int para_open(const char *path, int flags, mode_t mode)
        return -ERRNO_TO_PARA_ERROR(errno);
 }
 
-/**
- * Save the cwd and open a given directory.
- *
- * \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.
- *
- * \sa getcwd(3).
- *
- */
-static int para_opendir(const char *dirname, DIR **dir, int *cwd)
-{
-       int ret;
-
-       *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 */
-       }
-close_cwd:
-       if (cwd)
-               close(*cwd);
-       return ret;
-}
-
 /**
  * Create a directory, don't fail if it already exists.
  *
@@ -631,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;
-}
diff --git a/fd.h b/fd.h
index 8fb1fb651363bd816edfb680439b51496aed7a43..e4f3090301b94c90c96452a94fb4b5fa11b7d801 100644 (file)
--- a/fd.h
+++ b/fd.h
@@ -22,8 +22,7 @@ int read_nonblock(int fd, void *buf, size_t sz, size_t *num_bytes);
 int read_and_compare(int fd, const char *expectation);
 int xwrite(int fd, const char *buf, size_t len);
 int xwritev(int fd, struct iovec *iov, int iovcnt);
-int for_each_file_in_dir(const char *dirname,
-               int (*func)(const char *, void *), void *private_data);
+
 /**
  * Write a \p NULL-terminated buffer.
  *