forked from Mirrors/wine-wine
server: Fail if non-empty directory marked for deletion.
Signed-off-by: Daniel Lehman <dlehman25@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
306c40e673
commit
a302ab44ac
|
@ -3185,17 +3185,14 @@ todo_wine
|
||||||
CloseHandle( handle2 );
|
CloseHandle( handle2 );
|
||||||
fdi.DoDeleteFile = TRUE;
|
fdi.DoDeleteFile = TRUE;
|
||||||
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation );
|
||||||
todo_wine
|
|
||||||
ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
|
ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res );
|
||||||
fileDeleted = DeleteFileA( buffer );
|
fileDeleted = DeleteFileA( buffer );
|
||||||
ok( fileDeleted, "File should have been deleted\n" );
|
ok( fileDeleted, "File should have been deleted\n" );
|
||||||
buffer[dirpos] = '\0';
|
buffer[dirpos] = '\0';
|
||||||
CloseHandle( handle );
|
CloseHandle( handle );
|
||||||
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND;
|
||||||
todo_wine
|
|
||||||
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
|
ok( !fileDeleted, "Directory shouldn't have been deleted\n" );
|
||||||
fileDeleted = RemoveDirectoryA( buffer );
|
fileDeleted = RemoveDirectoryA( buffer );
|
||||||
todo_wine
|
|
||||||
ok( fileDeleted, "Directory should have been deleted\n" );
|
ok( fileDeleted, "Directory should have been deleted\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
74
server/fd.c
74
server/fd.c
|
@ -23,6 +23,7 @@
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
@ -2364,6 +2365,31 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_dir_empty( int fd )
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
int empty;
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
if ((fd = dup( fd )) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!(dir = fdopendir( fd )))
|
||||||
|
{
|
||||||
|
close( fd );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
empty = 1;
|
||||||
|
while (empty && (de = readdir( dir )))
|
||||||
|
{
|
||||||
|
if (!strcmp( de->d_name, "." ) || !strcmp( de->d_name, ".." )) continue;
|
||||||
|
empty = 0;
|
||||||
|
}
|
||||||
|
closedir( dir );
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
|
||||||
/* set disposition for the fd */
|
/* set disposition for the fd */
|
||||||
static void set_fd_disposition( struct fd *fd, int unlink )
|
static void set_fd_disposition( struct fd *fd, int unlink )
|
||||||
{
|
{
|
||||||
|
@ -2381,24 +2407,38 @@ static void set_fd_disposition( struct fd *fd, int unlink )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fstat( fd->unix_fd, &st ) == -1)
|
if (unlink)
|
||||||
{
|
{
|
||||||
file_set_error();
|
if (fstat( fd->unix_fd, &st ) == -1)
|
||||||
return;
|
{
|
||||||
}
|
file_set_error();
|
||||||
|
return;
|
||||||
/* can't unlink special files */
|
}
|
||||||
if (unlink && !S_ISDIR(st.st_mode) && !S_ISREG(st.st_mode))
|
if (S_ISREG( st.st_mode )) /* can't unlink files we don't have permission to write */
|
||||||
{
|
{
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
||||||
return;
|
{
|
||||||
}
|
set_error( STATUS_CANNOT_DELETE );
|
||||||
|
return;
|
||||||
/* can't unlink files we don't have permission to write */
|
}
|
||||||
if (unlink && !(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) && !S_ISDIR(st.st_mode))
|
}
|
||||||
{
|
else if (S_ISDIR( st.st_mode )) /* can't remove non-empty directories */
|
||||||
set_error( STATUS_CANNOT_DELETE );
|
{
|
||||||
return;
|
switch (is_dir_empty( fd->unix_fd ))
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
file_set_error();
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
set_error( STATUS_DIRECTORY_NOT_EMPTY );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* can't unlink special files */
|
||||||
|
{
|
||||||
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fd->closed->unlink = unlink ? 1 : 0;
|
fd->closed->unlink = unlink ? 1 : 0;
|
||||||
|
|
Loading…
Reference in New Issue