/* * rmdir dirname [dirname...] */ int uid; int gid; struct { int dev; int inode; int modes; char nlinks; char uid; char gid; char size0; int size; int addr[8]; int actime[2]; int modtime[2]; } statbuff; main(argc, argv) char **argv; { if (argc<2) { printf("Usage: rmdir dirname [dirname...]\n"); exit(1); } gid = getgid() & 0377; uid = getuid() & 0377; while (--argc) rmdir(*++argv); } rmdir(pathname) char *pathname; { char buff[100]; char dirbuff[16]; register char *p, *q, *pdir; register fd, m; /* * Copy filename to buffer -- leave p pointing at last char */ q = pathname; for (p=buff; *p = *q++; p++) if (p >= &buff[sizeof buff - 4]) { printf("%.64s... : name too long\n", pathname); return; } /* * Check for write permission in parent directory */ pdir = parent(pathname); if (stat(pdir, &statbuff) < 0) { printf("Can't find %s\n", pdir); return; } if (uid) { m = statbuff.modes; if (uid == statbuff.uid) m =>> 6; else if (gid == statbuff.gid) m =>> 3; if ((m & 02) == 0) { printf("No write permission in %s\n", pdir); return; } } /* * make sure it's empty first */ if ((fd = open(pathname, 0)) < 0) { printf("%s: can't open\n", pathname); return; } while ( (m = read(fd, dirbuff, sizeof dirbuff)) == sizeof dirbuff ) if ( (dirbuff[0] | dirbuff[1]) && !dotname(&dirbuff[2]) ) { printf("%s: not empty\n", pathname); close(fd); return; } close(fd); if (m != 0) { perror(pathname); return; } /* * remove standard entries . and .. */ p[0] = '/'; p[1] = '.'; p[2] = '\0'; if (unlink(buff) < 0) { perror(buff); return; } p[2] = '.'; p[3] = '\0'; if (unlink(buff) < 0) { perror(buff); return; } /* * now remove the directory itself */ if (unlink(pathname) < 0) perror(pathname); } /* * Check for standard names '.' or '..' */ dotname(name) char *name; { register char *p; p = name; return (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0'))); } /* * Given a filename, construct the name of its parent directory */ parent(fname) char *fname; { static char pbuff[100]; register char *f, *p, *slash; register c; /* * Copy filename to buffer, remembering position of last '/' */ slash = 0; f = fname; for (p = pbuff; c = *f++; p++) { if (c == '/') slash = p; *p = c; } /* * no slash found - parent is "." * otherwise - parent is "xxx/." */ if (slash == 0) return("."); slash[1] = '.'; slash[2] = '\0'; return(pbuff); }