9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

rm.c (1733B)


      1 #include <u.h>
      2 #include <sys/stat.h>
      3 #include <libc.h>
      4 
      5 #define rmdir p9rmdir
      6 
      7 char	errbuf[ERRMAX];
      8 int	ignerr = 0;
      9 
     10 static void
     11 err(char *f)
     12 {
     13 	if(!ignerr){
     14 		errbuf[0] = '\0';
     15 		errstr(errbuf, sizeof errbuf);
     16 		fprint(2, "rm: %s: %s\n", f, errbuf);
     17 	}
     18 }
     19 
     20 int
     21 issymlink(char *name)
     22 {
     23 	struct stat s;
     24 	return lstat(name, &s) >= 0 && S_ISLNK(s.st_mode);
     25 }
     26 
     27 /*
     28  * f is a non-empty directory. Remove its contents and then it.
     29  */
     30 void
     31 rmdir(char *f)
     32 {
     33 	char *name;
     34 	int fd, i, j, n, ndir, nname;
     35 	Dir *dirbuf;
     36 
     37 	fd = open(f, OREAD);
     38 	if(fd < 0){
     39 		err(f);
     40 		return;
     41 	}
     42 	n = dirreadall(fd, &dirbuf);
     43 	close(fd);
     44 	if(n < 0){
     45 		err("dirreadall");
     46 		return;
     47 	}
     48 
     49 	nname = strlen(f)+1+STATMAX+1;	/* plenty! */
     50 	name = malloc(nname);
     51 	if(name == 0){
     52 		err("memory allocation");
     53 		return;
     54 	}
     55 
     56 	ndir = 0;
     57 	for(i=0; i<n; i++){
     58 		snprint(name, nname, "%s/%s", f, dirbuf[i].name);
     59 		if(remove(name) != -1 || issymlink(name))
     60 			dirbuf[i].qid.type = QTFILE;	/* so we won't recurse */
     61 		else{
     62 			if(dirbuf[i].qid.type & QTDIR)
     63 				ndir++;
     64 			else
     65 				err(name);
     66 		}
     67 	}
     68 	if(ndir)
     69 		for(j=0; j<n; j++)
     70 			if(dirbuf[j].qid.type & QTDIR){
     71 				snprint(name, nname, "%s/%s", f, dirbuf[j].name);
     72 				rmdir(name);
     73 			}
     74 	if(remove(f) == -1)
     75 		err(f);
     76 	free(name);
     77 	free(dirbuf);
     78 }
     79 void
     80 main(int argc, char *argv[])
     81 {
     82 	int i;
     83 	int recurse;
     84 	char *f;
     85 	Dir *db;
     86 
     87 	ignerr = 0;
     88 	recurse = 0;
     89 	ARGBEGIN{
     90 	case 'r':
     91 		recurse = 1;
     92 		break;
     93 	case 'f':
     94 		ignerr = 1;
     95 		break;
     96 	default:
     97 		fprint(2, "usage: rm [-fr] file ...\n");
     98 		exits("usage");
     99 	}ARGEND
    100 	for(i=0; i<argc; i++){
    101 		f = argv[i];
    102 		if(remove(f) != -1)
    103 			continue;
    104 		db = nil;
    105 		if(recurse && (db=dirstat(f))!=nil && (db->qid.type&QTDIR))
    106 			rmdir(f);
    107 		else
    108 			err(f);
    109 		free(db);
    110 	}
    111 	exits(errbuf);
    112 }