]> git.sesse.net Git - betaftpd/commitdiff
Implemented directory listing recursion (not very much testing yet). Both mmap()...
authorsgunderson <sgunderson>
Sun, 20 Aug 2000 17:26:49 +0000 (17:26 +0000)
committersgunderson <sgunderson>
Sun, 20 Aug 2000 17:26:49 +0000 (17:26 +0000)
cmds.c
cmds.h

diff --git a/cmds.c b/cmds.c
index ef471eea0ba9dafd8bf7ab101d6d46a0f437f640..422f52fc35119c5ead0b0becb22cac53f4cbe086 100644 (file)
--- a/cmds.c
+++ b/cmds.c
@@ -985,9 +985,14 @@ int _mwrite(const char * const buf, const struct ftran * const f,
 
 /*
  * mwrite:     This is a short_hand define, making calls to _mwrite() very
- *             similiar to calls to write().
+ *             similiar to calls to write(). It works both with and without
+ *             mmap().
  */
+#if HAVE_MMAP
 #define mwrite(buf, count) pos = _mwrite((buf), (f), (pos), (count), (size));
+#else
+#define mwrite(buf, count) write(f->local_file, buf, count);
+#endif
 
 /*
  * long_listing():
@@ -1058,9 +1063,9 @@ int long_listing(char * const retbuf, const char * const pathname, const int do_
                        return 0;
                }
 
-               i = snprintf(temp, 1024, "%c%s %3u %-8s %-8s %8lu %12s %s\r\n",
+               snprintf(temp, 1024, "%c%s %3u %-8s %-8s %8lu %12s %s\r\n",
 #else
-               i = snprintf(temp, 1024, "%c%c%c%c%c%c%c%c%c%c %3u %-8s %-8s %8lu %12s %s",
+               snprintf(temp, 1024, "%c%c%c%c%c%c%c%c%c%c %3u %-8s %-8s %8lu %12s %s",
 #endif
                        decode_mode(buf.st_mode),
 #if WANT_NONROOT
@@ -1078,7 +1083,8 @@ int long_listing(char * const retbuf, const char * const pathname, const int do_
 #endif
                        buf.st_nlink, username, groupname,
                        (unsigned long)(buf.st_size), newd, pathname);
-
+               i = strlen(temp);
+       
 #if 0
                /*
                 * vim needs this extra character for some reason... It's too 
@@ -1109,7 +1115,7 @@ int cmd_list(struct conn * const c)
 {
        struct list_options lo;
 
-/*     lo.recursive = 0; */
+       lo.recursive = 0;
        lo.long_listing = 1;
        lo.classify = 0;
 
@@ -1128,7 +1134,7 @@ int cmd_nlst(struct conn * const c)
 {
        struct list_options lo;
 
-/*     lo.recursive = 0; */
+       lo.recursive = 0;
        lo.long_listing = 0;
        lo.classify = 0;
 
@@ -1213,10 +1219,10 @@ void do_listing(struct conn * const c, struct list_options * const lo)
                size = num_files * 160;
                f->file_data = malloc(size + 1);
                TRAP_ERROR(f->file_data == NULL, 550, return);
-               list_core(c, ptr, lo, size);
+               list_core(c, ptr, "", lo, size, 0);
        }
 #else
-       list_core(c, ptr, lo);
+       list_core(c, ptr, "", lo);
 #endif
 
 #if WANT_DCACHE
@@ -1273,8 +1279,8 @@ int get_num_files(struct conn * const c, const char * const pathname,
                return -1;
        }
 
-#if 0  /* the rest of the code doesn't support recursion yet */
        if (lo->recursive) {
+               int i;
                        for (i = 0; i < pglob.gl_pathc; i++) {
                        char *temp = pglob.gl_pathv[i];
                        struct stat buf;
@@ -1287,7 +1293,6 @@ int get_num_files(struct conn * const c, const char * const pathname,
                        }
                }
        }
-#endif
 
        return num_files;
 }
@@ -1302,20 +1307,20 @@ int get_num_files(struct conn * const c, const char * const pathname,
  *             under 80 for long listings, and a little under 160 for
  *             short listings), the list will be truncated. Fix...
  *
+ *             The return value only makes sense if mmap()'ing, since it
+ *             returns the number of bytes written into the buffer.
+ *
  *             This function is rather long.
  */
-void list_core(struct conn * const c, const char * const pathname,
-              struct list_options * const lo
+int list_core(struct conn * const c, const char * const pathname,
+             char * const disp_pathname, struct list_options * const lo
 #if HAVE_MMAP
-               , const int size
+               , const int size, int pos
 #endif
                )
 {
        int i;
        glob_t pglob;
-#if HAVE_MMAP
-       int pos = 0;
-#endif
        struct ftran * const f = c->transfer;
 
         /*
@@ -1327,12 +1332,28 @@ void list_core(struct conn * const c, const char * const pathname,
 #ifdef GLOB_NOMATCH
        case GLOB_NOMATCH:
 #endif
-                break;
+                break;         /* note: break, not return */
         default:
                 numeric(c, 550, strerror(EACCES));
-                return;
+#if HAVE_MMAP
+               return pos;
+#else
+                return 0;
+#endif
         }
 
+       if (lo->recursive) {
+               if (disp_pathname[0] == '\0') {
+                       mwrite(".:\r\n", 4);
+               } else {
+                       char temp[1024];
+                       int i;
+
+                       snprintf(temp, 1024, "%s:\r\n", disp_pathname);
+                       i = strlen(temp);
+                       mwrite(temp, i);
+               }
+       }
        if (lo->long_listing) {
                /* FIX: we may get too high total number if we are running nonroot! */
                struct stat buf;
@@ -1344,12 +1365,9 @@ void list_core(struct conn * const c, const char * const pathname,
                                total += buf.st_blocks;
                        }
                }
-               i = snprintf(temp, 1024, "total %lu\r\n", total >> 1); 
-#if HAVE_MMAP
+               snprintf(temp, 1024, "total %lu\r\n", total >> 1);
+               i = strlen(temp);
                mwrite(temp, i);
-#else
-               write(f->local_file, temp, i);
-#endif
        }
 
        for (i = 0; i < pglob.gl_pathc; i++) {
@@ -1380,15 +1398,43 @@ void list_core(struct conn * const c, const char * const pathname,
                        }
                }
 
-               /* support recursion here some day... */
-
-#if HAVE_MMAP
                mwrite(buf, strlen(buf));
                mwrite("\r\n", 2);
-#else
-               write(f->local_file, buf, strlen(buf));
-               write(f->local_file, "\r\n", 2);
+       }
+
+       /*
+        * If recursion is on, dive into any subdirectories now -- note
+        * that each entry is stat()'ed twice, hopefully the OS will manage,
+        * and we've got our own dcache anyways -- this could be fixed at
+        * the expense of some memory, consider for later inclusion.
+        */
+       if (lo->recursive) {
+               for (i = 0; i < pglob.gl_pathc; i++) {
+                       struct stat buf;
+                       const char * const temp = pglob.gl_pathv[i];
+
+                       /* don't dive into `.' or `..' */
+                        if (lstat(temp, &buf) != -1 && S_ISDIR(buf.st_mode) &&
+                               (temp[0] != '.' || (temp[1] != '.' && temp[1] != '\0'))) {
+                               char tmp2[1024];
+
+                               mwrite("\r\n", 2);
+
+                               /* attach the pathname to the end of the displayed path */
+                               if (disp_pathname[0] == '\0') {
+                                       snprintf(tmp2, 1024, "%s", temp);
+                               } else {
+                                       snprintf(tmp2, 1024, "%s/%s", disp_pathname, temp);
+                               }
+
+                               chdir(temp);
+                               pos = list_core(c, "*", tmp2, lo, 
+#if HAVE_MMAP
+                                       size, pos);
 #endif
+                               chdir("..");
+                       }
+               }
        }
 
 #if HAVE_MMAP
@@ -1398,6 +1444,11 @@ void list_core(struct conn * const c, const char * const pathname,
 #endif
 
        globfree(&pglob);
+#if HAVE_MMAP
+       return pos;
+#else
+       return 0;
+#endif
 }
 
 /*
@@ -1811,11 +1862,9 @@ int prepare_for_listing(struct conn * const c, char ** const ptr,
        if (optr != NULL) {
                while (*++optr) {
                        switch (*optr & (255-32)) {     /* uppercase */
-#if 0
                        case 'R':       /* actually case sensitive... */
                                lo->recursive = 1;
                                break;
-#endif
                        case 'L':
                                lo->long_listing = 1;
                                break;
diff --git a/cmds.h b/cmds.h
index b7735ff23f51f4a58a07bbc87bff7b62de1db5f7..88b04d19fc6e6b5fd63a69d87ec16d97eb898f47 100644 (file)
--- a/cmds.h
+++ b/cmds.h
@@ -108,13 +108,22 @@ int prepare_for_listing(struct conn * const c, char ** const ptr,
 void do_listing(struct conn * const c, struct list_options * const lo);
 int get_num_files(struct conn * const c, const char * const pathname,
                    struct list_options * const lo);
-void list_core(struct conn * const c, const char * const pathname,
-              struct list_options * const lo
+int list_core(struct conn * const c, const char * const pathname,
+                  char * const disp_pathname, struct list_options * const lo
 #if HAVE_MMAP
-               , const int size
+               , const int size, int pos
 #endif
 );
 char classify(const mode_t mode);
 void do_store(struct conn * const c, int append);
 char *do_pwd(struct conn * const c, char * const retbuf, const char * const dir);
 
+#ifndef HAVE_POLL
+/*
+ * Even on select()-only systems, we use some poll() constants, so
+ * we'll have to make them up if we don't already have them. These
+ * are taken from my glibc 2.1 system.
+ */
+#define POLLIN         0x001
+#define POLLOUT                0x004
+#endif