xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/unlink.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
1 #include "lib.h"
2 #include <unistd.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include "sys9.h"
8 #include "dir.h"
9 
10 
11 /*
12  * BUG: errno mapping
13  */
14 
15 int
unlink(const char * path)16 unlink(const char *path)
17 {
18 	int n, i, fd;
19 	long long nn;
20 	Dir *db1, *db2, nd;
21 	Fdinfo *f;
22  	char *p, newname[PATH_MAX], newelem[32];
23 
24 	/* if the file is already open, make it close-on-exec (and rename to qid) */
25 	if((db1 = _dirstat(path)) == nil) {
26 		_syserrno();
27 		return -1;
28 	}
29 	fd = -1;
30 	for(i=0, f = _fdinfo;i < OPEN_MAX; i++, f++) {
31 		if((f->flags&FD_ISOPEN) && (db2=_dirfstat(i)) != nil) {
32 			if(db1->qid.path == db2->qid.path &&
33 			   db1->qid.vers == db2->qid.vers &&
34 			   db1->type == db2->type &&
35 			   db1->dev == db2->dev) {
36 				sprintf(newelem, "%8.8lx%8.8lx", (ulong)(db2->qid.path>>32), (ulong)db2->qid.path);
37 				_nulldir(&nd);
38 				nd.name = newelem;
39 				if(_dirfwstat(i, &nd) < 0)
40 					p = (char*)path;
41 				else {
42 					p = strrchr(path, '/');
43 					if(p == 0)
44 						p = newelem;
45 					else {
46 						memmove(newname, path, p-path);
47 						newname[p-path] = '/';
48 						strcpy(newname+(p-path)+1, newelem);
49 						p = newname;
50 					}
51 				}
52 				/* reopen remove on close */
53 				fd = _OPEN(p, 64|(f->oflags));
54 				if(fd < 0){
55 					free(db2);
56 					continue;
57 				}
58 				nn = _SEEK(i, 0, 1);
59 				if(nn < 0)
60 					nn = 0;
61 				_SEEK(fd, nn, 0);
62 				_DUP(fd, i);
63 				_CLOSE(fd);
64 				free(db1);
65 				return 0;
66 			}
67 			free(db2);
68 		}
69 	}
70 	n = 0;
71 	if(fd == -1)
72 		if((n=_REMOVE(path)) < 0)
73 			_syserrno();
74 	free(db1);
75 	return n;
76 }
77