|
|
1.1 root 1:
2: /*
3: * rmdir -- remove directories
4: */
5: #include <sys/stat.h>
6: #include <sys/dir.h>
7: #include <signal.h>
8: #include <stdio.h>
9: #include <errno.h>
10:
11:
12: #define equal( s1, s2) (strcmp( s1, s2) == 0)
13:
14: int fflag, /* force flag */
15: interrupted;
16: struct stat dot;
17:
18: char *getparent(),
19: *getchild(),
20: *strncpy(),
21: *strcat(),
22: *strcpy(),
23: *concat();
24:
25: /*
26: * main
27: * Interrupts are handled to prevent the formation of mangled directories.
28: */
29: main( argc, argv)
30: register char **argv;
31: {
32: register int status = 0;
33:
34: if (*++argv!= NULL && equal( *argv, "-f")) {
35: if (getuid())
36: fatal("only superuser can force");
37: ++fflag;
38: ++argv;
39: }
40: if (stat( ".", &dot))
41: fatal("can't find .");
42: catch(SIGINT);
43: catch(SIGHUP);
44: signal(SIGQUIT, SIG_IGN);
45:
46: if (*argv == NULL) {
47: fprintf(stderr, "Usage: rmdir [ -f ] dir ...\n");
48: exit(1);
49: }
50: else
51: while (*argv) {
52: if (rmdir(*argv++) < 0)
53: status = 1; /* error */
54: if (interrupted)
55: exit(1);
56: }
57: exit(status);
58: }
59:
60:
61: /*
62: * remove a directory
63: * The directory and its "." and ".." entries are unlinked if everything
64: * looks kosher. The force option causes most checking to be suppressed
65: * and unlinks only what is specifically named. `rmdir' takes a dim view
66: * to non-hierarchical directories.
67: */
68: rmdir(dir)
69: register char *dir;
70: {
71: register char *child;
72: register FILE *f;
73: struct stat s;
74: struct direct d;
75:
76:
77: if ((int) (child = getchild( dir)) < 0) {
78: error("can't get child dir name %s", dir);
79: return(-1);
80: }
81: if (access( dir, 0) || stat( dir, &s)) {
82: error("can't find %s", dir);
83: return(-1);
84: }
85: if ((s.st_mode&S_IFMT) != S_IFDIR) {
86: error("%s not a directory", dir);
87: return(-1);
88: }
89: if (access( getparent( dir), 3)) {
90: error("no permission to remove %s", dir);
91: return(-1);
92: }
93: if (fflag == 0) {
94: if (equal( child, ".") || equal( child, "..")) {
95: error("%s not allowed", dir);
96: return(-1);
97: }
98: if (s.st_ino==dot.st_ino && s.st_dev==dot.st_dev) {
99: error("but %s is your working directory", dir);
100: return(-1);
101: }
102: f = fopen( dir, "r");
103: if (f==NULL || access( dir, 4)) {
104: error("can't read %s", dir);
105: return(-1);
106: }
107: while (fread( &d, sizeof d, 1, f) == 1) {
108: if (d.d_ino == 0)
109: continue;
110: if (equal( d.d_name, ".") || equal( d.d_name, ".."))
111: continue;
112: error("%s not empty", dir);
113: return(-1);
114: }
115: fclose(f);
116:
117: if (s.st_nlink <= 2) {
118: unlink( concat( dir, "/."));
119: unlink( concat( dir, "/.."));
120: }
121: }
122:
123: if (unlink( dir)) {
124: error("unlink %s failed", dir);
125: return(-1);
126: }
127: return(0);
128: }
129:
130:
131: /*
132: * return name of parent
133: */
134: char *
135: getparent( dir)
136: char *dir;
137: {
138: register i;
139: register char *p;
140: static char *par;
141: int tmp;
142:
143: if (par)
144: free( par);
145: i = strlen( dir);
146: par = malloc( i+1);
147: if (par == NULL)
148: nomemory( );
149: strcpy( par, dir);
150:
151: for (p=par+i; p>par; )
152: if (*--p != '/')
153: break;
154: for (++p; *--p!='/'; )
155: if (p == par) {
156: *p = '.';
157: break;
158: }
159: *++p = '\0';
160: if (par[tmp = strlen(par)-1] == '/')
161: par[tmp] = 0; /* kill any ending slash */
162: return (par);
163: }
164:
165:
166: /*
167: * return rightmost component of pathname
168: */
169: char *
170: getchild( dir)
171: register char *dir;
172: {
173: register char *p,
174: *q;
175: int i;
176: static char ch[DIRSIZ+1];
177:
178: p = &dir[strlen( dir)];
179: do {
180: if (p == dir) {
181: error("not permitted");
182: return(-1);
183: }
184: } while (*--p == '/');
185: q = p;
186: while (q > dir)
187: if (*--q == '/') {
188: ++q;
189: break;
190: }
191: i = p+1 - q;
192: if (i > DIRSIZ)
193: i = DIRSIZ;
194: return (strncpy( ch, q, i));
195: }
196:
197:
198: /*
199: * return concatenation of `s1' and `s2'
200: */
201: char *
202: concat( s1, s2)
203: char *s1,
204: *s2;
205: {
206: static char *str;
207:
208: if (str)
209: free( str);
210: str = malloc( strlen( s1)+strlen( s2)+1);
211: if (str == NULL)
212: nomemory( );
213: strcpy( str, s1);
214: return (strcat( str, s2));
215: }
216:
217:
218: nomemory( )
219: {
220: fatal("out of memory");
221: }
222:
223:
224: onintr( )
225: {
226:
227: signal( SIGINT, SIG_IGN);
228: signal( SIGHUP, SIG_IGN);
229: ++interrupted;
230: }
231:
232:
233: catch( sig)
234: {
235:
236: if( signal( sig, SIG_IGN) == SIG_DFL)
237: signal( sig, onintr);
238: }
239:
240:
241: error(arg1)
242: char *arg1;
243: {
244: fprintf( stderr, "rmdir: %r\n", &arg1);
245: }
246:
247: fatal(arg1)
248: char *arg1;
249: {
250: error(arg1);
251: exit(1);
252: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.