Added an inode object to keep track of all file descriptors open for a
given file.
Plugged a couple of potential file descriptor leaks.
diff --git a/server/file.c b/server/file.c
index 2544bba..ba853e9 100644
--- a/server/file.c
+++ b/server/file.c
@@ -149,7 +149,7 @@
init_async_queue (&file->read_q);
init_async_queue (&file->write_q);
}
- if (!(file->fd = alloc_fd( &file_fd_ops, fd, &file->obj )))
+ if (!(file->fd = create_anonymous_fd( &file_fd_ops, fd, &file->obj )))
{
release_object( file );
return NULL;
@@ -165,9 +165,7 @@
{
struct file *file;
int hash, flags;
- struct stat st;
char *name;
- int fd = -1;
mode_t mode;
if (!(name = mem_alloc( len + 1 ))) return NULL;
@@ -200,31 +198,38 @@
(!strcasecmp( name + len - 4, ".exe" ) || !strcasecmp( name + len - 4, ".com" )))
mode |= 0111;
- /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
- if ((fd = open( name, flags | O_NONBLOCK | O_LARGEFILE, mode )) == -1 )
- goto file_error;
- /* refuse to open a directory */
- if (fstat( fd, &st ) == -1) goto file_error;
- if (S_ISDIR(st.st_mode))
+ if (!(file = alloc_object( &file_ops ))) goto error;
+
+ file->access = access;
+ file->flags = attrs;
+ file->sharing = sharing;
+ file->drive_type = drive_type;
+ file->name = name;
+ file->next = file_hash[hash];
+ file_hash[hash] = file;
+ if (file->flags & FILE_FLAG_OVERLAPPED)
{
- set_error( STATUS_ACCESS_DENIED );
- goto error;
+ init_async_queue (&file->read_q);
+ init_async_queue (&file->write_q);
}
- if (!(file = create_file_for_fd( fd, access, sharing, attrs, drive_type )))
+ /* FIXME: should set error to STATUS_OBJECT_NAME_COLLISION if file existed before */
+ if (!(file->fd = alloc_fd( &file_fd_ops, &file->obj )) ||
+ !(file->fd = open_fd( file->fd, name, flags | O_NONBLOCK | O_LARGEFILE, &mode )))
{
- free( name );
+ release_object( file );
return NULL;
}
- file->name = name;
- file->next = file_hash[hash];
- file_hash[hash] = file;
+ /* refuse to open a directory */
+ if (S_ISDIR(mode))
+ {
+ set_error( STATUS_ACCESS_DENIED );
+ release_object( file );
+ return NULL;
+ }
return file;
- file_error:
- file_set_error();
error:
- if (fd != -1) close( fd );
free( name );
return NULL;
}
@@ -241,29 +246,20 @@
return file->drive_type;
}
-/* Create an anonymous Unix file */
-int create_anonymous_file(void)
+/* create a temp file for anonymous mappings */
+struct file *create_temp_file( int access )
{
- char tmpfn[21];
+ char tmpfn[16];
int fd;
- sprintf(tmpfn,"/tmp/anonmap.XXXXXX");
+ sprintf( tmpfn, "anonmap.XXXXXX" ); /* create it in the server directory */
fd = mkstemp(tmpfn);
if (fd == -1)
{
file_set_error();
- return -1;
+ return NULL;
}
unlink( tmpfn );
- return fd;
-}
-
-/* Create a temp file for anonymous mappings */
-struct file *create_temp_file( int access )
-{
- int fd;
-
- if ((fd = create_anonymous_file()) == -1) return NULL;
return create_file_for_fd( fd, access, 0, 0, DRIVE_FIXED );
}