BSD 1 development
authorKurt A. Shoens <kurt@ucbvax.Berkeley.EDU>
Sun, 27 Nov 1977 02:14:02 +0000 (18:14 -0800)
committerKurt A. Shoens <kurt@ucbvax.Berkeley.EDU>
Sun, 27 Nov 1977 02:14:02 +0000 (18:14 -0800)
Work on file s6/rmtree.c

Synthesized-from: 1bsd

s6/rmtree.c [new file with mode: 0644]

diff --git a/s6/rmtree.c b/s6/rmtree.c
new file mode 100644 (file)
index 0000000..82f1880
--- /dev/null
@@ -0,0 +1,341 @@
+#
+/* UCB rmtree
+ * rmtree dir . . .
+ * author: Kurt Shoens
+ * recursively removes files and directories
+ * in a subtree.  The -v flag prevents it from
+ * removing the final directory, ie the one
+ * you specify.  The incredible danger of
+ * this program must by now be apparent to you.  It
+ * asks you if you are sure on each argument.
+ */
+
+
+#define ENOTDIR 20
+#define ENOENT 2
+
+#define STACKSIZE 1024
+
+int vflag;
+int errs;
+int fflag;
+int cflag;
+int active;
+
+/* set warnflag true to get "last chance before . . . " */
+
+int warnflag 1;
+
+char pathname[STACKSIZE];
+
+char *pathptr;
+char *myname;
+
+extern errno;
+
+main(ct,av)
+       char **av;
+{
+       int level,i,thiser;
+       char crap[36];
+       setuid(getuid());
+       myname = av[0];
+/*
+ *     if (getuid())
+ *     {
+ *             printf("sorry, not super user\n");
+ *             exit(1);
+ *     }
+ */
+       if (ct<2)
+       {
+               usage(myname);
+               exit(9);
+       }
+       for (i=1;i<ct;++i)
+       {
+               if (*av[i] == '-')
+               {
+                       process(av[i]);
+                       continue;
+               }
+               ++active;
+               if (stat(av[i],crap))
+               {
+                       perror(av[i]);
+                       errs++;
+                       continue;
+               }
+               if (!dir(av[i]))
+               {
+                       errno = ENOTDIR;
+                       perror(av[i]);
+                       errs++;
+               }
+               else
+               {
+                       if (warning(av[i],warnflag && !fflag))
+                       {
+                               if (cflag && !vflag) chmod(av[i], 0700);
+                               pathptr = pathname;
+                               pushstr(av[i]);
+                               thiser = descend();
+                               errs =+ thiser;
+                               if (!vflag && !thiser) errs =+ rmdir(av[i]);
+                       }
+               }
+       }
+       if (!active)
+       {
+               usage(myname);
+               exit(9);
+       }
+       exit(errs);
+}
+
+descend()
+{
+       int offset,j,err,markerr,xcnt;
+       static f,inum,*ip;
+       register char *cp;
+       char name[16];
+       markerr=0;
+       offset=16;
+       f=open(pathname,0);
+       if (f==-1)
+       {
+               prs(pathname);
+               prs(": no read permission\n");
+               return(1);
+       }
+       j=read(f,name,16);
+       xcnt=0;
+       while (j)
+       {
+               ip=name;
+               inum= *ip;
+               if (!scomp(&name[2],".") && !scomp(&name[2],"..") && inum)
+               {
+                       if (!xcnt++) if (access(pathname,3))
+                       {
+                               prs(pathname);
+                               prs(": need both X and W permission\n");
+                               close(f);
+                               return(1);
+                       }
+                       pushstr(&name[2]);
+                       if (dir(pathname))
+                       {
+                               close(f);
+                               if (cflag) chmod(pathname, 0700);
+                               err=descend();
+                               if (!err) rmdir(pathname);
+                               else markerr=1;
+                               popstr();
+                               f = open(pathname,0);
+                               seek(f,offset,0);
+                       }
+                       else
+                       {
+
+                               /* if unlink fails, keeps going ?? */
+
+                               if (rm(pathname)) markerr=1;
+                               popstr();
+                       }
+               }
+               j=read(f,name,16);
+               offset=offset+16;
+       }
+       close(f);
+       return(markerr);
+}
+
+rmdir(str)
+       char *str;
+{
+       int p;
+       p = fork();
+       if (!p)
+       {
+               execl("/bin/rmdir","rmdir",str,0);
+               perror("/bin/rmdir");
+               exit(1);
+       }
+       else wait(&p);
+       return(p);
+}
+
+rm(f)
+       char *f;
+{
+       if (quota(f) && vflag) return(1);
+       if (unlink(f))
+       {
+               perror(f);
+               return(1);
+       }
+       return(0);
+}
+
+popstr()
+{
+       --pathptr;
+       while (*pathptr != '/') --pathptr;
+       while (*pathptr == '/') --pathptr;
+       *++pathptr = 0;
+}
+
+dir(n)
+       char *n;
+{
+     struct inode {
+       char  minor;        /* +0: minor device of i-node */
+       char  major;        /* +1: major device */
+       int   inumber;      /* +2 */
+       int   flags;        /* +4: see below */
+       char  nlinks;       /* +6: number of links to file */
+       char  uid;          /* +7: user ID of owner */
+       char  gid;          /* +8: group ID of owner */
+       char  size0;        /* +9: high byte of 24-bit size */
+       int   size1;        /* +10: low word of 24-bit size */
+       int   addr[8];      /* +12: block numbers or device number */
+       int   actime[2];     /* +28: time of last access */
+       int   modtime[2];    /* +32: time of last modification */
+     } buf;
+       if (stat(n,&buf)) return(0);
+       return((buf.flags & 060000) == 040000);
+}
+
+quota(n)
+       char *n;
+{
+     struct inode {
+       char  minor;        /* +0: minor device of i-node */
+       char  major;        /* +1: major device */
+       int   inumber;      /* +2 */
+       int   flags;        /* +4: see below */
+       char  nlinks;       /* +6: number of links to file */
+       char  uid;          /* +7: user ID of owner */
+       char  gid;          /* +8: group ID of owner */
+       char  size0;        /* +9: high byte of 24-bit size */
+       int   size1;        /* +10: low word of 24-bit size */
+       int   addr[8];      /* +12: block numbers or device number */
+       int   actime[2];     /* +28: time of last access */
+       int   modtime[2];    /* +32: time of last modification */
+     } buf;
+       if (stat(n,&buf)) return(0);
+       return((buf.flags & 060000) == 020000 && buf.addr[0] == -1);
+}
+
+scomp(n1,n2)
+       char *n1,*n2;
+{
+       char left,right;
+       left= *n1;
+       right= *n2;
+       while (left && right)
+       {
+               if (left!=right) return(0);
+               ++n1;
+               ++n2;
+               left= *n1;
+               right= *n2;
+       }
+       return(left==right);
+}
+
+actual(str)
+       char *str;
+{
+       register char *f;
+       register slash;
+       f = str;
+       if (*f == '/') return(f);
+       slash = 0;
+       while (*f) if (*f++ == '/') slash++;
+       if (!slash) return(str);
+       while (*f != '/') --f;
+       ++f;
+       return(f);
+}
+
+warning(file,f)
+       char *file;
+{
+       char line[20];
+       if (!f) return;
+       if (gtty(0,line)) return;
+       printf("last chance before OBLITERATING %s\n",file);
+       printf("ok? ");
+       line[read(0,line,20)] = 0;
+       return(*line == 'y' || *line == 'Y');
+}
+
+process(str)
+       char *str;
+{
+       while (*str) switch(*str++)
+       {
+       case 'c':
+               cflag++;
+               break;
+
+       case 'v':
+               vflag = 1;
+               break;
+
+       case 'f':
+               fflag = 1;
+               break;
+
+       case 's':
+               fflag = 0;
+               break;
+
+       case 'a':
+               vflag = 0;
+               break;
+
+       case '-':
+               break;
+
+       default:
+               printf("unknown switch: %c\n", *--str);
+               exit(1);
+       }
+}
+
+usage(str)
+       char *str;
+{
+       printf("Usage: %s [ -acfsv ] dir ...\n",str);
+       errs++;
+}
+
+prs(str)
+       char *str;
+{
+       register char *f;
+       f = str;
+       while (*f) ++f;
+       write(2, str, f-str);
+}
+
+pushstr(str)
+       char *str;
+{
+       if (pathptr != pathname) *pathptr++ = '/';
+       while (*pathptr++ = *str++) if (pathptr >= pathname + STACKSIZE)
+               panic("path name too long");
+       pathptr--;
+}
+
+panic(str)
+       char *str;
+{
+       prs("PANIC: ");
+       prs(str);
+       prs("\n");
+       exit(1);
+}