Add AT_REMOVEFILE flag to unlinkat(2).

This allows unlinkat(2) to delete files and directories in the same call,
which is useful for the implementation of remove(3).
This commit is contained in:
Jonas 'Sortie' Termansen 2013-01-06 19:14:30 +01:00
parent 1fa2df3e6a
commit 3b35dad9f7
3 changed files with 7 additions and 8 deletions

View File

@ -38,11 +38,7 @@ __BEGIN_DECLS
/* TODO: F_RDLCK, F_UNLCK, F_WRLCK missing here */
/* TODO: AT_FDCWD missing here */
/* TODO: AT_EACCESS missing here */
/* TODO: AT_SYMLINK_NOFOLLOW missing here */
/* TODO: AT_SYMLINK_FOLLOW missing here */
/* TODO: AT_REMOVEDIR missing here */
/* TODO: POSIX_FADV_* missing here */

View File

@ -58,6 +58,7 @@ __BEGIN_DECLS
#define AT_REMOVEDIR (1<<0)
#define AT_EACCESS (1<<1)
#define AT_SYMLINK_NOFOLLOW (1<<2)
#define AT_REMOVEFILE (1<<3)
__END_DECLS

View File

@ -183,6 +183,8 @@ static int sys_access(const char* path, int mode)
static int sys_unlinkat(int dirfd, const char* path, int flags)
{
if ( !(flags & (AT_REMOVEFILE | AT_REMOVEDIR)) )
flags |= AT_REMOVEFILE;
char* pathcopy = GetStringFromUser(path);
if ( !pathcopy )
return -1;
@ -190,11 +192,11 @@ static int sys_unlinkat(int dirfd, const char* path, int flags)
const char* relpath = pathcopy;
Ref<Descriptor> from = PrepareLookup(&relpath, dirfd);
if ( !from ) { delete[] pathcopy; return -1; }
int ret;
if ( flags & AT_REMOVEDIR )
ret = from->rmdir(&ctx, relpath);
else
int ret = -1;
if ( ret < 0 && (flags & AT_REMOVEFILE) )
ret = from->unlink(&ctx, relpath);
if ( ret < 0 && (flags & AT_REMOVEDIR) )
ret = from->rmdir(&ctx, relpath);
delete[] pathcopy;
return ret;
}