diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 0119b6f1023..0d9e7df4b84 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -286,7 +286,6 @@ typedef struct async_fileio void* apc_user; char* buffer; unsigned int count; - off_t offset; int queue_apc_on_error; BOOL avail_mode; HANDLE event; @@ -371,6 +370,7 @@ NTSTATUS FILE_GetNtStatus(void) case ENOTTY: case EOPNOTSUPP:return STATUS_NOT_SUPPORTED; case ECONNRESET:return STATUS_PIPE_DISCONNECTED; + case EFAULT: return STATUS_ACCESS_VIOLATION; case ENOEXEC: /* ?? */ case ESPIPE: /* ?? */ case EEXIST: /* ?? */ @@ -402,16 +402,7 @@ static void WINAPI FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, ULON fileio_terminate(fileio, iosb); break; } - if ( fileio->avail_mode ) - result = read(fd, &fileio->buffer[already], fileio->count - already); - else - { - result = pread(fd, &fileio->buffer[already], - fileio->count - already, - fileio->offset + already); - if ((result < 0) && (errno == ESPIPE)) - result = read(fd, &fileio->buffer[already], fileio->count - already); - } + result = read(fd, &fileio->buffer[already], fileio->count - already); if (needs_close) close( fd ); if (result < 0) @@ -487,7 +478,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, PIO_STATUS_BLOCK io_status, void* buffer, ULONG length, PLARGE_INTEGER offset, PULONG key) { - int unix_handle, needs_close, flags; + int result, unix_handle, needs_close, flags; + enum server_fd_type type; TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n", hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key); @@ -496,9 +488,45 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, io_status->Information = 0; io_status->u.Status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle, - &needs_close, NULL, &flags ); + &needs_close, &type, &flags ); if (io_status->u.Status) return io_status->u.Status; + if (type == FD_TYPE_FILE && offset) + { + /* async I/O doesn't make sense on regular files */ + if (flags & FD_FLAG_OVERLAPPED) + { + while ((result = pread( unix_handle, buffer, length, offset->QuadPart )) == -1) + { + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == ESPIPE) + { + io_status->u.Status = STATUS_PENDING; + break; + } + result = 0; + io_status->u.Status = FILE_GetNtStatus(); + goto done; + } + if (result >= 0) + { + io_status->Information = result; + io_status->u.Status = result ? STATUS_SUCCESS : STATUS_END_OF_FILE; + if (hEvent) NtSetEvent( hEvent, NULL ); + if (apc && !io_status->u.Status) apc( apc_user, io_status, io_status->Information ); + goto done; + } + } + else + { + if (lseek( unix_handle, offset->QuadPart, SEEK_SET ) == (off_t)-1) + { + io_status->u.Status = FILE_GetNtStatus(); + goto done; + } + } + } + if (flags & FD_FLAG_RECV_SHUTDOWN) { if (needs_close) close( unix_handle ); @@ -535,14 +563,6 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, } fileio->handle = hFile; fileio->count = length; - if ( offset == NULL ) - fileio->offset = 0; - else - { - fileio->offset = offset->QuadPart; - if (offset->u.HighPart && fileio->offset == offset->u.LowPart) - FIXME("High part of offset is lost\n"); - } fileio->apc = apc; fileio->apc_user = apc_user; fileio->buffer = buffer; @@ -589,27 +609,15 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, return io_status->u.Status; } - if (offset) - { - FILE_POSITION_INFORMATION fpi; - - fpi.CurrentByteOffset = *offset; - io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi), - FilePositionInformation); - if (io_status->u.Status) goto done; - } /* code for synchronous reads */ - while ((io_status->Information = read( unix_handle, buffer, length )) == -1) + while ((result = read( unix_handle, buffer, length )) == -1) { if ((errno == EAGAIN) || (errno == EINTR)) continue; - if (errno == EFAULT) - { - io_status->Information = 0; - io_status->u.Status = STATUS_ACCESS_VIOLATION; - } - else io_status->u.Status = FILE_GetNtStatus(); - break; + io_status->u.Status = FILE_GetNtStatus(); + result = 0; + break; } + io_status->Information = result; if (io_status->u.Status == STATUS_SUCCESS && io_status->Information == 0) { struct stat st; @@ -645,15 +653,7 @@ static void WINAPI FILE_AsyncWriteService(void *ovp, IO_STATUS_BLOCK *iosb, ULON fileio_terminate(fileio, iosb); break; } - if ( fileio->avail_mode ) - result = write(fd, &fileio->buffer[already], fileio->count - already); - else - { - result = pwrite(fd, &fileio->buffer[already], - fileio->count - already, fileio->offset + already); - if ((result < 0) && (errno == ESPIPE)) - result = write(fd, &fileio->buffer[already], fileio->count - already); - } + result = write(fd, &fileio->buffer[already], fileio->count - already); if (needs_close) close( fd ); if (result < 0) @@ -708,7 +708,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, const void* buffer, ULONG length, PLARGE_INTEGER offset, PULONG key) { - int unix_handle, needs_close, flags; + int result, unix_handle, needs_close, flags; + enum server_fd_type type; TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n", hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key); @@ -717,9 +718,46 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, io_status->Information = 0; io_status->u.Status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle, - &needs_close, NULL, &flags ); + &needs_close, &type, &flags ); if (io_status->u.Status) return io_status->u.Status; + if (type == FD_TYPE_FILE && offset) + { + if (flags & FD_FLAG_OVERLAPPED) + { + /* async I/O doesn't make sense on regular files */ + while ((result = pwrite( unix_handle, buffer, length, offset->QuadPart )) == -1) + { + if (errno == EINTR) continue; + if (errno == EAGAIN || errno == ESPIPE) + { + io_status->u.Status = STATUS_PENDING; + break; + } + result = 0; + if (errno == EFAULT) io_status->u.Status = STATUS_INVALID_USER_BUFFER; + else io_status->u.Status = FILE_GetNtStatus(); + goto done; + } + if (result >= 0) + { + io_status->Information = result; + io_status->u.Status = STATUS_SUCCESS; + if (hEvent) NtSetEvent( hEvent, NULL ); + if (apc) apc( apc_user, io_status, io_status->Information ); + goto done; + } + } + else + { + if (lseek( unix_handle, offset->QuadPart, SEEK_SET ) == (off_t)-1) + { + io_status->u.Status = FILE_GetNtStatus(); + goto done; + } + } + } + if (flags & FD_FLAG_SEND_SHUTDOWN) { if (needs_close) close( unix_handle ); @@ -756,16 +794,6 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, } fileio->handle = hFile; fileio->count = length; - if (offset) - { - fileio->offset = offset->QuadPart; - if (offset->u.HighPart && fileio->offset == offset->u.LowPart) - FIXME("High part of offset is lost\n"); - } - else - { - fileio->offset = 0; - } fileio->apc = apc; fileio->apc_user = apc_user; fileio->buffer = (void*)buffer; @@ -812,29 +840,16 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, return io_status->u.Status; } - if (offset) - { - FILE_POSITION_INFORMATION fpi; - - fpi.CurrentByteOffset = *offset; - io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi), - FilePositionInformation); - if (io_status->u.Status) goto done; - } - /* synchronous file write */ - while ((io_status->Information = write( unix_handle, buffer, length )) == -1) + while ((result = write( unix_handle, buffer, length )) == -1) { if ((errno == EAGAIN) || (errno == EINTR)) continue; - if (errno == EFAULT) - { - io_status->Information = 0; - io_status->u.Status = STATUS_INVALID_USER_BUFFER; - } - else if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL; + result = 0; + if (errno == EFAULT) io_status->u.Status = STATUS_INVALID_USER_BUFFER; else io_status->u.Status = FILE_GetNtStatus(); break; } + io_status->Information = result; done: if (needs_close) close( unix_handle ); return io_status->u.Status;