ref: f2cfee358f329519e913a20142d96b1e0029633c
dir: /sys/src/ape/lib/ap/plan9/unlink.c/
#include "lib.h" #include <unistd.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include "sys9.h" #include "dir.h" /* * BUG: errno mapping */ int unlink(const char *path) { int n, i, fd; long long nn; Dir *db1, *db2, nd; Fdinfo *f; char *p, *newname, newelem[32]; /* if the file is already open, make it close-on-exec (and rename to qid) */ if((db1 = _dirstat(path)) == nil) { _syserrno(); return -1; } n = -1; fd = -1; for(i=0, f = _fdinfo;i < OPEN_MAX; i++, f++) { if((f->flags&FD_ISOPEN) && (db2=_dirfstat(i)) != nil) { if(db1->qid.path == db2->qid.path && db1->qid.vers == db2->qid.vers && db1->type == db2->type && db1->dev == db2->dev) { newname = 0; sprintf(newelem, "%8.8lx%8.8lx", (ulong)(db2->qid.path>>32), (ulong)db2->qid.path); _nulldir(&nd); nd.name = newelem; if(_dirfwstat(i, &nd) < 0) p = (char*)path; else { p = strrchr(path, '/'); if(p == 0) p = newelem; else { n = p-path; newname = malloc(n+1+sizeof(newelem)); if(newname == 0){ free(db2); free(db1); return -1; } memmove(newname, path, n); newname[n] = '/'; strcpy(newname+n+1, newelem); p = newname; } } /* reopen remove on close */ fd = _OPEN(p, ORCLOSE|(f->oflags)); if(fd < 0){ free(newname); free(db2); continue; } nn = _SEEK(i, 0, 1); if(nn < 0) nn = 0; _SEEK(fd, nn, 0); _DUP(fd, i); _CLOSE(fd); free(newname); free(db2); free(db1); return 0; } free(db2); } } if(fd == -1) if((n=_REMOVE(path)) < 0) _syserrno(); free(db1); return n; }