mirror of https://github.com/FreeRDP/FreeRDP
fixes for drive cut, mode, read/write
This commit is contained in:
parent
997d40639c
commit
865b816b80
|
@ -299,15 +299,19 @@ DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
|
|||
|
||||
if (!drive_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
|
||||
{
|
||||
drive_file_free(file);
|
||||
(void) drive_file_free(file, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void drive_file_free(DRIVE_FILE* file)
|
||||
int drive_file_free(DRIVE_FILE* file, BOOL recursive)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
|
||||
if (file->fd != -1)
|
||||
close(file->fd);
|
||||
|
||||
|
@ -317,14 +321,36 @@ void drive_file_free(DRIVE_FILE* file)
|
|||
if (file->delete_pending)
|
||||
{
|
||||
if (file->is_dir)
|
||||
drive_file_remove_dir(file->fullpath);
|
||||
{
|
||||
if (recursive)
|
||||
{
|
||||
if (!drive_file_remove_dir(file->fullpath))
|
||||
{
|
||||
retval = EPERM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rmdir(file->fullpath) != 0)
|
||||
{
|
||||
retval = errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
unlink(file->fullpath);
|
||||
{
|
||||
if (unlink(file->fullpath) != 0)
|
||||
{
|
||||
retval = errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(file->pattern);
|
||||
free(file->fullpath);
|
||||
free(file);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
|
||||
|
@ -340,37 +366,55 @@ BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
|
|||
|
||||
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
|
||||
{
|
||||
ssize_t r;
|
||||
size_t left;
|
||||
BYTE *bufptr;
|
||||
|
||||
if (file->is_dir || file->fd == -1)
|
||||
return FALSE;
|
||||
|
||||
r = read(file->fd, buffer, *Length);
|
||||
bufptr = buffer;
|
||||
left = *Length;
|
||||
while (left > 0)
|
||||
{
|
||||
ssize_t bytesRead;
|
||||
bytesRead = read(file->fd, bufptr, left);
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
if ((errno == EAGAIN) || (errno == EINTR))
|
||||
continue;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else if (bytesRead == 0) break; /* EOF */
|
||||
bufptr += bytesRead;
|
||||
left -= bytesRead;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return FALSE;
|
||||
|
||||
*Length = (UINT32) r;
|
||||
*Length -= left;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length)
|
||||
BOOL drive_file_write(DRIVE_FILE* file, const BYTE* buffer, UINT32 Length)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
if (file->is_dir || file->fd == -1)
|
||||
return FALSE;
|
||||
|
||||
while (Length > 0)
|
||||
{
|
||||
r = write(file->fd, buffer, Length);
|
||||
ssize_t bytesWritten;
|
||||
bytesWritten = write(file->fd, buffer, Length);
|
||||
|
||||
if (r == -1)
|
||||
return FALSE;
|
||||
if (bytesWritten < 0)
|
||||
{
|
||||
if ((errno == EAGAIN) || (errno == EINTR))
|
||||
continue;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Length -= r;
|
||||
buffer += r;
|
||||
Length -= bytesWritten;
|
||||
buffer += bytesWritten;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -476,7 +520,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
|||
else
|
||||
m &= ~S_IWUSR;
|
||||
if (m != st.st_mode)
|
||||
fchmod(file->fd, st.st_mode);
|
||||
fchmod(file->fd, m);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
@ -497,6 +541,25 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
|||
Stream_Read_UINT8(input, file->delete_pending);
|
||||
else
|
||||
file->delete_pending = 1;
|
||||
if (file->delete_pending && file->is_dir)
|
||||
{
|
||||
/* mstsc causes this to FAIL if the directory is not empty,
|
||||
* and that's what the server is expecting. If we wait for
|
||||
* the close to flag a failure, cut and paste of a folder
|
||||
* will lose the folder's contents.
|
||||
*/
|
||||
int status;
|
||||
status = rmdir(file->fullpath);
|
||||
if (status == 0)
|
||||
{
|
||||
/* Put it back so the normal pending delete will work. */
|
||||
mkdir(file->fullpath, 0755);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FileRenameInformation:
|
||||
|
|
|
@ -108,11 +108,11 @@ struct _DRIVE_FILE
|
|||
|
||||
DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
|
||||
UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions);
|
||||
void drive_file_free(DRIVE_FILE* file);
|
||||
int drive_file_free(DRIVE_FILE* file, BOOL recursive);
|
||||
|
||||
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset);
|
||||
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length);
|
||||
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length);
|
||||
BOOL drive_file_write(DRIVE_FILE* file, const BYTE* buffer, UINT32 Length);
|
||||
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output);
|
||||
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input);
|
||||
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
||||
|
|
|
@ -159,7 +159,8 @@ static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
|
|||
|
||||
/* map errno to windows result */
|
||||
irp->IoStatus = drive_map_posix_err(file->err);
|
||||
drive_file_free(file);
|
||||
/* Already in the error path, no need to check return value here. */
|
||||
(void) drive_file_free(file, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -208,10 +209,12 @@ static void drive_process_irp_close(DRIVE_DEVICE* disk, IRP* irp)
|
|||
}
|
||||
else
|
||||
{
|
||||
int err;
|
||||
DEBUG_SVC("%s(%d) closed.", file->fullpath, file->id);
|
||||
|
||||
list_remove(disk->files, file);
|
||||
drive_file_free(file);
|
||||
if ((err = drive_file_free(file, FALSE)) != 0)
|
||||
irp->IoStatus = drive_map_posix_err(err);
|
||||
}
|
||||
|
||||
Stream_Zero(irp->output, 5); /* Padding(5) */
|
||||
|
@ -672,8 +675,9 @@ static void drive_free(DEVICE* device)
|
|||
|
||||
_aligned_free(disk->pIrpList);
|
||||
|
||||
/* Cleaning up; no need to check for drive_file_free error. */
|
||||
while ((file = (DRIVE_FILE*) list_dequeue(disk->files)) != NULL)
|
||||
drive_file_free(file);
|
||||
(void) drive_file_free(file, TRUE);
|
||||
|
||||
list_free(disk->files);
|
||||
|
||||
|
|
Loading…
Reference in New Issue