Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/lib/libsa Support limited filename globbing



details:   https://anonhg.NetBSD.org/src/rev/f1b7c11ba62e
branches:  trunk
changeset: 542556:f1b7c11ba62e
user:      dsl <dsl%NetBSD.org@localhost>
date:      Sat Feb 01 14:52:13 2003 +0000

description:
Support limited filename globbing
- agreed by christos

diffstat:

 sys/lib/libsa/ufs_ls.c |  165 +++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 126 insertions(+), 39 deletions(-)

diffs (210 lines):

diff -r d00c4b14ed04 -r f1b7c11ba62e sys/lib/libsa/ufs_ls.c
--- a/sys/lib/libsa/ufs_ls.c    Sat Feb 01 14:48:16 2003 +0000
+++ b/sys/lib/libsa/ufs_ls.c    Sat Feb 01 14:52:13 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ufs_ls.c,v 1.2 2002/05/09 02:44:39 simonb Exp $         */
+/*     $NetBSD: ufs_ls.c,v 1.3 2003/02/01 14:52:13 dsl Exp $    */
 
 /*
  * Copyright (c) 1993
@@ -37,13 +37,24 @@
 
 
 #include <sys/param.h>
+#include <string.h>
 #include <ufs/ufs/dinode.h>
 #include <ufs/ufs/dir.h>
 
 #include "stand.h"
 #include "ufs.h"
 
-static char    *typestr[] = {
+#define NELEM(x) (sizeof (x) / sizeof(*x))
+
+typedef struct entry_t entry_t;
+struct entry_t {
+       entry_t *e_next;
+       ino_t   e_ino;
+       uint8_t e_type;
+       char    e_name[1];
+};
+
+static const char    *typestr[] = {
        "unknown",
        "FIFO",
        "CHR",
@@ -61,61 +72,137 @@
        "WHT"
 };
 
+static int
+fn_match(const char *fname, const char *pattern)
+{
+       char fc, pc;
+
+       do {
+               fc = *fname++;
+               pc = *pattern++;
+               if (!fc && !pc)
+                       return 1;
+               if (pc == '?' && fc)
+                       pc = fc;
+       } while (fc == pc);
+
+       if (pc != '*')
+               return 0;
+       /* Too hard (and unnecessary really) too check for "*?name" etc....
+          "**" will look for a '*' and "*?" a '?' */
+       pc = *pattern++;
+       if (!pc)
+               return 1;
+       while ((fname = strchr(fname, pc)))
+               if (fn_match(++fname, pattern))
+                       return 1;
+       return 0;
+}
+
 void 
-ufs_ls(path)
-       const char *path;
+ufs_ls(const char *path)
 {
        int             fd;
        struct stat     sb;
        size_t          size;
        char            dirbuf[DIRBLKSIZ];
+       const char      *fname = 0;
+       char            *p;
+       entry_t         *names = 0, *n, **np;
 
-       fd = open(path, 0);
-       if (fd < 0) {
-               printf("ls: %s\n", strerror(errno));
-               return;
+       if ((fd = open(path, 0)) < 0
+           || fstat(fd, &sb) < 0
+           || (sb.st_mode & IFMT) != IFDIR) {
+               /* Path supplied isn't a directory, open parent
+                  directory and list matching files. */
+               if (fd >= 0)
+                       close(fd);
+               fname = strrchr(path, '/');
+               if (fname) {
+                       size = fname - path;
+                       p = alloc(size + 1);
+                       if (!p)
+                               goto out;
+                       memcpy(p, path, size);
+                       p[size] = 0;
+                       fd = open(p, 0);
+                       free(p, size + 1);
+               } else {
+                       fd = open("", 0);
+                       fname = path;
+               }
+
+               if (fd < 0) {
+                       printf("ls: %s\n", strerror(errno));
+                       return;
+               }
+               if (fstat(fd, &sb) < 0) {
+                       printf("stat: %s\n", strerror(errno));
+                       goto out;
+               }
+               if ((sb.st_mode & IFMT) != IFDIR) {
+                       printf("%s: %s\n", path, strerror(ENOTDIR));
+                       goto out;
+               }
        }
-       if (fstat(fd, &sb) < 0) {
-               printf("stat: %s\n", strerror(errno));
-               goto out;
-       }
-       if ((sb.st_mode & IFMT) != IFDIR) {
-               printf("%s: %s\n", path, strerror(ENOTDIR));
-               goto out;
-       }
+
        while ((size = read(fd, dirbuf, DIRBLKSIZ)) == DIRBLKSIZ) {
                struct direct  *dp, *edp;
 
                dp = (struct direct *) dirbuf;
                edp = (struct direct *) (dirbuf + size);
 
-               while (dp < edp) {
-                       if (dp->d_ino != (ino_t) 0) {
-                               char           *t;
+               for (; dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
+                       const char *t;
+                       if (dp->d_ino ==  0)
+                               continue;
 
-                               if (/* (dp->d_namlen > MAXNAMLEN + 1) || */
-                                   (dp->d_type >
-                                     sizeof(typestr) / sizeof(char *) - 1) ||
-                                   !(t = typestr[dp->d_type])) {
-                                       /*
-                                        * This does not handle "old"
-                                        * filesystems properly. On little
-                                        * endian machines, we get a bogus
-                                        * type name if the namlen matches a
-                                        * valid type identifier. We could
-                                        * check if we read namlen "0" and
-                                        * handle this case specially, if
-                                        * there were a pressing need...
-                                        */
-                                       printf("bad dir entry\n");
-                                       goto out;
-                               }
-                               printf("%d: %s (%s)\n", dp->d_ino,
-                                      dp->d_name, t);
+                       if (dp->d_type >= NELEM(typestr) ||
+                           !(t = typestr[dp->d_type])) {
+                               /*
+                                * This does not handle "old"
+                                * filesystems properly. On little
+                                * endian machines, we get a bogus
+                                * type name if the namlen matches a
+                                * valid type identifier. We could
+                                * check if we read namlen "0" and
+                                * handle this case specially, if
+                                * there were a pressing need...
+                                */
+                               printf("bad dir entry\n");
+                               goto out;
+                       }
+                       if (fname && !fn_match(dp->d_name, fname))
+                               continue;
+                       n = alloc(sizeof *n + strlen(dp->d_name));
+                       if (!n) {
+                               printf("%d: %s (%s)\n",
+                                       dp->d_ino, dp->d_name, t);
+                               continue;
                        }
-                       dp = (struct direct *) ((char *) dp + dp->d_reclen);
+                       n->e_ino = dp->d_ino;
+                       n->e_type = dp->d_type;
+                       strcpy(n->e_name, dp->d_name);
+                       for (np = &names; *np; np = &(*np)->e_next) {
+                               if (strcmp(n->e_name, (*np)->e_name) < 0)
+                                       break;
+                       }
+                       n->e_next = *np;
+                       *np = n;
                }
        }
+
+       if (names) {
+               do {
+                       n = names;
+                       printf("%d: %s (%s)\n",
+                               n->e_ino, n->e_name, typestr[n->e_type]);
+                       names = n->e_next;
+                       free(n, 0);
+               } while (names);
+       } else {
+               printf( "%s not found\n", path );
+       }
 out:
        close(fd);
 }



Home | Main Index | Thread Index | Old Index