/* rmdir -- remove a directory */ /* written by Eric R. Smith and placed in the public domain */ #include #include #include #include #include #include #include "symdir.h" #include "lib.h" /* * BUG(?): rmdir(foo) will unlink foo even if it is a symbolic link to a * non-directory file (unless it's an automatic link, in which case the * rmdir works iff the actual directory is removed). */ int rmdir(_path) const char *_path; { SYMDIR *dir = 0; SYMENTRY *ent = 0; char path[FILENAME_MAX], *s; int r, nm_change; nm_change = _unx2dos(_path, path); /* * _unx2dos returns _NM_LINK and sets __link_path for symbolic links */ if (nm_change == _NM_LINK) { /* _path was to a symbolic link */ dir = _read_symdir(__link_path); if (!dir || !(ent = _symdir_lookup(dir, __link_name))) return -1; } /* if symbolic links are active, insist that names match */ else if (_lOK && nm_change == _NM_CHANGE) { errno = ENOENT; return -1; } /* * delete path if _path was not a symlink, or if it was an automatic * symlink. */ r = (!ent || (ent->flags & SD_AUTO)); if (dir) _free_symdir(dir); if (r) { /* * remember to delete the ".dir" file in the directory as well; the user * shouldn't have to do this. _read_symdir(path) also removes "path" * from the symbolic directory cache. */ dir = _read_symdir(path); if (dir) { for (s = path; *s; s++) ; *s = '\\'; strcpy(s+1, _lDIR); /* append ".dir" */ (void)Fdelete(path); *s = 0; /* restore name */ } r = Ddelete(path); if (r < 0 && dir) /* rewrite symbolic directory if dir was nonempty */ (void)_write_symdir (path, dir); } if (r < 0) { errno = -r; r = -1; } else if (ent) { /* unlink symbolic link */ r = unlink(_path); } return r; }