Commit ce613493 authored by Alexandre Julliard's avatar Alexandre Julliard

Implemented file locking functions (partly based on my old Corel

patch). Added a few regression tests.
parent 6fb02776
......@@ -674,6 +674,79 @@ void test_offset_in_overlapped_structure(void)
ok(DeleteFileA(temp_fname), "DeleteFileA error %ld\n", GetLastError());
}
static void test_LockFile(void)
{
HANDLE handle;
DWORD written;
OVERLAPPED overlapped;
handle = CreateFileA( filename, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, 0, 0 );
if (handle == INVALID_HANDLE_VALUE)
{
ok(0,"couldn't create file \"%s\" (err=%ld)",filename,GetLastError());
return;
}
ok( WriteFile( handle, sillytext, strlen(sillytext), &written, NULL ), "write failed" );
ok( LockFile( handle, 0, 0, 0, 0 ), "LockFile failed" );
ok( UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile failed" );
ok( !UnlockFile( handle, 0, 0, 0, 0 ), "UnlockFile succeeded" );
ok( LockFile( handle, 10, 0, 20, 0 ), "LockFile 10,20 failed" );
/* overlapping locks must fail */
ok( !LockFile( handle, 12, 0, 10, 0 ), "LockFile 12,10 succeeded" );
ok( !LockFile( handle, 5, 0, 6, 0 ), "LockFile 5,6 succeeded" );
/* non-overlapping locks must succeed */
ok( LockFile( handle, 5, 0, 5, 0 ), "LockFile 5,5 failed" );
ok( !UnlockFile( handle, 10, 0, 10, 0 ), "UnlockFile 10,10 succeeded" );
ok( UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 failed" );
ok( !UnlockFile( handle, 10, 0, 20, 0 ), "UnlockFile 10,20 again succeeded" );
ok( UnlockFile( handle, 5, 0, 5, 0 ), "UnlockFile 5,5 failed" );
overlapped.Offset = 100;
overlapped.OffsetHigh = 0;
overlapped.hEvent = 0;
ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 100,100 failed" );
/* overlapping shared locks are OK */
overlapped.Offset = 150;
ok( LockFileEx( handle, 0, 0, 100, 0, &overlapped ), "LockFileEx 150,100 failed" );
/* but exclusive is not */
ok( !LockFileEx( handle, LOCKFILE_EXCLUSIVE_LOCK|LOCKFILE_FAIL_IMMEDIATELY, 0, 50, 0, &overlapped ),
"LockFileEx exclusive 150,50 succeeded" );
ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 150,100 failed" );
ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 150,100 again succeeded" );
overlapped.Offset = 100;
ok( UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 100,100 failed" );
ok( !UnlockFileEx( handle, 0, 100, 0, &overlapped ), "UnlockFileEx 100,100 again succeeded" );
ok( LockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "LockFile failed" );
ok( !LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 succeeded" );
ok( !LockFile( handle, 0, 0x20000000, 20, 0 ), "LockFile 0x20000000,20 succeeded" );
ok( UnlockFile( handle, 0, 0x10000000, 0, 0xf0000000 ), "UnlockFile failed" );
/* wrap-around lock should not do anything */
/* (but still succeeds on NT4 so we don't check result) */
LockFile( handle, 0, 0x10000000, 0, 0xf0000001 );
ok( LockFile( handle, ~0, ~0, 1, 0 ), "LockFile ~0,1 failed" );
ok( UnlockFile( handle, ~0, ~0, 1, 0 ), "Unlockfile ~0,1 failed" );
/* zero-byte lock */
ok( LockFile( handle, 100, 0, 0, 0 ), "LockFile 100,0 failed" );
ok( !LockFile( handle, 98, 0, 4, 0 ), "LockFile 98,4 succeeded" );
ok( LockFile( handle, 90, 0, 10, 0 ), "LockFile 90,10 failed" );
ok( LockFile( handle, 100, 0, 10, 0 ), "LockFile 100,10 failed" );
ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed" );
ok( UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 failed" );
ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed" );
CloseHandle( handle );
DeleteFileA( filename );
}
START_TEST(file)
{
test__hread( );
......@@ -690,5 +763,6 @@ START_TEST(file)
test_CreateFileW();
test_DeleteFileA();
test_DeleteFileW();
test_LockFile();
test_offset_in_overlapped_structure();
}
......@@ -293,6 +293,8 @@ typedef struct _PROCESS_HEAP_ENTRY
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#define LOCKFILE_FAIL_IMMEDIATELY 1
#define LOCKFILE_EXCLUSIVE_LOCK 2
#define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
......
......@@ -899,10 +899,14 @@ struct lock_file_request
unsigned int offset_high;
unsigned int count_low;
unsigned int count_high;
int shared;
int wait;
};
struct lock_file_reply
{
struct reply_header __header;
obj_handle_t handle;
int overlapped;
};
......@@ -3551,6 +3555,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply;
};
#define SERVER_PROTOCOL_VERSION 99
#define SERVER_PROTOCOL_VERSION 100
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -453,6 +453,7 @@ void file_set_error(void)
case ESPIPE: set_error( 0xc0010000 | ERROR_SEEK /* FIXME */ ); break;
case ENOTEMPTY: set_error( STATUS_DIRECTORY_NOT_EMPTY ); break;
case EIO: set_error( STATUS_ACCESS_VIOLATION ); break;
case EOVERFLOW: set_error( STATUS_INVALID_PARAMETER ); break;
default: perror("file_set_error"); set_error( ERROR_UNKNOWN /* FIXME */ ); break;
}
}
......@@ -581,20 +582,6 @@ static int set_file_time( obj_handle_t handle, time_t access_time, time_t write_
return 0;
}
static int file_lock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low )
{
/* FIXME: implement this */
return 1;
}
static int file_unlock( struct file *file, int offset_high, int offset_low,
int count_high, int count_low )
{
/* FIXME: implement this */
return 1;
}
/* create a file */
DECL_HANDLER(create_file)
{
......@@ -661,11 +648,13 @@ DECL_HANDLER(set_file_time)
DECL_HANDLER(lock_file)
{
struct file *file;
file_pos_t offset = ((file_pos_t)req->offset_high << 32) | req->offset_low;
file_pos_t count = ((file_pos_t)req->count_high << 32) | req->count_low;
if ((file = get_file_obj( current->process, req->handle, 0 )))
{
file_lock( file, req->offset_high, req->offset_low,
req->count_high, req->count_low );
reply->handle = lock_fd( file->fd, offset, count, req->shared, req->wait );
reply->overlapped = (file->flags & FILE_FLAG_OVERLAPPED) != 0;
release_object( file );
}
}
......@@ -674,11 +663,12 @@ DECL_HANDLER(lock_file)
DECL_HANDLER(unlock_file)
{
struct file *file;
file_pos_t offset = ((file_pos_t)req->offset_high << 32) | req->offset_low;
file_pos_t count = ((file_pos_t)req->count_high << 32) | req->count_low;
if ((file = get_file_obj( current->process, req->handle, 0 )))
{
file_unlock( file, req->offset_high, req->offset_low,
req->count_high, req->count_low );
unlock_fd( file->fd, offset, count );
release_object( file );
}
}
......@@ -25,6 +25,8 @@
struct fd;
typedef unsigned __int64 file_pos_t;
/* operations valid on file descriptor objects */
struct fd_ops
{
......@@ -51,6 +53,8 @@ extern int get_unix_fd( struct fd *fd );
extern void fd_poll_event( struct fd *fd, int event );
extern int check_fd_events( struct fd *fd, int events );
extern void set_fd_events( struct fd *fd, int events );
extern obj_handle_t lock_fd( struct fd *fd, file_pos_t offset, file_pos_t count, int shared, int wait );
extern void unlock_fd( struct fd *fd, file_pos_t offset, file_pos_t count );
extern int default_fd_add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void default_fd_remove_queue( struct object *obj, struct wait_queue_entry *entry );
......
......@@ -80,6 +80,12 @@ inline static struct list *list_tail( struct list *list )
return list_prev( list, list );
}
/* check if a list is empty */
inline static int list_empty( struct list *list )
{
return list->next == list;
}
/* initialize a list */
inline static void list_init( struct list *list )
{
......
......@@ -296,6 +296,7 @@ struct thread *create_process( int fd )
process->exe.namelen = 0;
process->exe.filename = NULL;
process->group_id = 0;
list_init( &process->locks );
gettimeofday( &process->start_time, NULL );
if ((process->next = first_process) != NULL) process->next->prev = process;
......
......@@ -67,6 +67,7 @@ struct process
int affinity; /* process affinity mask */
int suspend; /* global process suspend count */
int create_flags; /* process creation flags */
struct list locks; /* list of file locks owned by the process */
struct console_input*console; /* console input */
enum startup_state startup_state; /* startup state */
struct startup_info *startup_info; /* startup info while init is in progress */
......
......@@ -681,6 +681,11 @@ enum fd_type
unsigned int offset_high; /* offset of start of lock */
unsigned int count_low; /* count of bytes to lock */
unsigned int count_high; /* count of bytes to lock */
int shared; /* shared or exclusive lock? */
int wait; /* do we want to wait? */
@REPLY
obj_handle_t handle; /* handle to wait on */
int overlapped; /* is it an overlapped I/O handle? */
@END
......
......@@ -889,7 +889,15 @@ static void dump_lock_file_request( const struct lock_file_request *req )
fprintf( stderr, " offset_low=%08x,", req->offset_low );
fprintf( stderr, " offset_high=%08x,", req->offset_high );
fprintf( stderr, " count_low=%08x,", req->count_low );
fprintf( stderr, " count_high=%08x", req->count_high );
fprintf( stderr, " count_high=%08x,", req->count_high );
fprintf( stderr, " shared=%d,", req->shared );
fprintf( stderr, " wait=%d", req->wait );
}
static void dump_lock_file_reply( const struct lock_file_reply *req )
{
fprintf( stderr, " handle=%p,", req->handle );
fprintf( stderr, " overlapped=%d", req->overlapped );
}
static void dump_unlock_file_request( const struct unlock_file_request *req )
......@@ -2632,7 +2640,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)0,
(dump_func)dump_get_file_info_reply,
(dump_func)0,
(dump_func)dump_lock_file_reply,
(dump_func)0,
(dump_func)dump_create_pipe_reply,
(dump_func)dump_create_socket_reply,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment