Major code cleanup and reorganisation.
Fixed many bugs. Now, the vfs_ prefix is for functions that are called by other parts of the kernel. file_ is for file related stuff, dir_ for directory related, and common_ for both, fs_ for general file system stuff. Put all prefixed functions together in the source. Implemented (currently without a user/sys call) opening/creating of entry_refs, and node_refs (the latter for opening directories only). Moved vfs_dup(), and vfs_dup2() to fd.c, fd_dup(), and fd_dup2(). git-svn-id: file:///srv/svn/repos/haiku/trunk/current@351 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6ec6552ee4
commit
071f62bc36
@ -162,8 +162,6 @@ int sys_rename(const char *oldpath, const char *newpath);
|
||||
int sys_write_stat(const char *path, struct stat *stat, int stat_mask);
|
||||
char *sys_getcwd(char *buf, size_t size);
|
||||
int sys_setcwd(const char* path);
|
||||
int sys_dup(int fd);
|
||||
int sys_dup2(int ofd, int nfd);
|
||||
|
||||
/* calls the syscall dispatcher should use for user file I/O */
|
||||
int user_mount(const char *path, const char *device, const char *fs_name, void *args);
|
||||
@ -181,8 +179,6 @@ int user_read_stat(const char *path, struct stat *stat);
|
||||
int user_write_stat(const char *path, struct stat *stat, int stat_mask);
|
||||
int user_getcwd(char *buf, size_t size);
|
||||
int user_setcwd(const char* path);
|
||||
int user_dup(int fd);
|
||||
int user_dup2(int ofd, int nfd);
|
||||
|
||||
/* fd kernel prototypes (implementation located in fd.c) */
|
||||
extern ssize_t sys_read(int fd, void *buf, off_t pos, size_t len);
|
||||
@ -192,7 +188,8 @@ extern ssize_t sys_read_dir(int fd, struct dirent *buffer, size_t bufferSize, ui
|
||||
extern status_t sys_rewind_dir(int fd);
|
||||
extern int sys_read_stat(const char *path, struct stat *stat);
|
||||
extern int sys_close(int fd);
|
||||
|
||||
extern int sys_dup(int fd);
|
||||
extern int sys_dup2(int ofd, int nfd);
|
||||
|
||||
/* fd user prototypes (implementation located in fd.c) */
|
||||
extern ssize_t user_read(int fd, void *buf, off_t pos, size_t len);
|
||||
@ -202,6 +199,8 @@ extern ssize_t user_read_dir(int fd, struct dirent *buffer, size_t bufferSize, u
|
||||
extern status_t user_rewind_dir(int fd);
|
||||
extern int user_fstat(int, struct stat *);
|
||||
extern int user_close(int fd);
|
||||
extern int user_dup(int fd);
|
||||
extern int user_dup2(int ofd, int nfd);
|
||||
|
||||
/* vfs entry points... */
|
||||
|
||||
@ -209,5 +208,4 @@ extern int user_close(int fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL_VFS_H */
|
||||
|
@ -66,15 +66,15 @@ alloc_fd(void)
|
||||
|
||||
|
||||
int
|
||||
new_fd(struct io_context *ioctx, struct file_descriptor *f)
|
||||
new_fd(struct io_context *context, struct file_descriptor *descriptor)
|
||||
{
|
||||
int fd = -1;
|
||||
int i;
|
||||
|
||||
mutex_lock(&ioctx->io_mutex);
|
||||
mutex_lock(&context->io_mutex);
|
||||
|
||||
for (i = 0; i < ioctx->table_size; i++) {
|
||||
if (!ioctx->fds[i]) {
|
||||
for (i = 0; i < context->table_size; i++) {
|
||||
if (!context->fds[i]) {
|
||||
fd = i;
|
||||
break;
|
||||
}
|
||||
@ -84,11 +84,11 @@ new_fd(struct io_context *ioctx, struct file_descriptor *f)
|
||||
goto err;
|
||||
}
|
||||
|
||||
ioctx->fds[fd] = f;
|
||||
ioctx->num_used_fds++;
|
||||
context->fds[fd] = descriptor;
|
||||
context->num_used_fds++;
|
||||
|
||||
err:
|
||||
mutex_unlock(&ioctx->io_mutex);
|
||||
mutex_unlock(&context->io_mutex);
|
||||
|
||||
return fd;
|
||||
}
|
||||
@ -112,46 +112,117 @@ put_fd(struct file_descriptor *descriptor)
|
||||
|
||||
|
||||
struct file_descriptor *
|
||||
get_fd(struct io_context *ioctx, int fd)
|
||||
get_fd(struct io_context *context, int fd)
|
||||
{
|
||||
struct file_descriptor *f;
|
||||
struct file_descriptor *descriptor = NULL;
|
||||
|
||||
mutex_lock(&ioctx->io_mutex);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
|
||||
if (fd >= 0 && fd < ioctx->table_size && ioctx->fds[fd]) {
|
||||
// valid fd
|
||||
f = ioctx->fds[fd];
|
||||
atomic_add(&f->ref_count, 1);
|
||||
} else {
|
||||
f = NULL;
|
||||
}
|
||||
mutex_lock(&context->io_mutex);
|
||||
|
||||
mutex_unlock(&ioctx->io_mutex);
|
||||
if (fd < context->table_size)
|
||||
descriptor = context->fds[fd];
|
||||
|
||||
if (descriptor != NULL) // fd is valid
|
||||
atomic_add(&descriptor->ref_count, 1);
|
||||
|
||||
return f;
|
||||
mutex_unlock(&context->io_mutex);
|
||||
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
remove_fd(struct io_context *ioctx, int fd)
|
||||
remove_fd(struct io_context *context, int fd)
|
||||
{
|
||||
struct file_descriptor *f;
|
||||
struct file_descriptor *descriptor = NULL;
|
||||
|
||||
mutex_lock(&ioctx->io_mutex);
|
||||
if (fd < 0)
|
||||
return;
|
||||
|
||||
if (fd >= 0 && fd < ioctx->table_size && ioctx->fds[fd]) {
|
||||
// valid fd
|
||||
f = ioctx->fds[fd];
|
||||
ioctx->fds[fd] = NULL;
|
||||
ioctx->num_used_fds--;
|
||||
} else {
|
||||
f = NULL;
|
||||
mutex_lock(&context->io_mutex);
|
||||
|
||||
if (fd < context->table_size)
|
||||
descriptor = context->fds[fd];
|
||||
|
||||
if (descriptor) { // fd is valid
|
||||
context->fds[fd] = NULL;
|
||||
context->num_used_fds--;
|
||||
}
|
||||
|
||||
mutex_unlock(&ioctx->io_mutex);
|
||||
mutex_unlock(&context->io_mutex);
|
||||
|
||||
if (f)
|
||||
put_fd(f);
|
||||
if (descriptor)
|
||||
put_fd(descriptor);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fd_dup(int fd, bool kernel)
|
||||
{
|
||||
struct io_context *context = get_current_io_context(kernel);
|
||||
struct file_descriptor *descriptor;
|
||||
int status;
|
||||
|
||||
TRACE(("fd_dup: fd = %d\n", fd));
|
||||
|
||||
// Try to get the fd structure
|
||||
descriptor = get_fd(context, fd);
|
||||
if (descriptor == NULL)
|
||||
return EBADF;
|
||||
|
||||
// now put the fd in place
|
||||
status = new_fd(context, descriptor);
|
||||
if (status < 0)
|
||||
put_fd(descriptor);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
fd_dup2(int oldfd, int newfd, bool kernel)
|
||||
{
|
||||
struct file_descriptor *evicted = NULL;
|
||||
struct io_context *context;
|
||||
|
||||
TRACE(("fd_dup2: ofd = %d, nfd = %d\n", oldfd, newfd));
|
||||
|
||||
// quick check
|
||||
if (oldfd < 0 || newfd < 0)
|
||||
return EBADF;
|
||||
|
||||
// Get current I/O context and lock it
|
||||
context = get_current_io_context(kernel);
|
||||
mutex_lock(&context->io_mutex);
|
||||
|
||||
// Check if the fds are valid (mutex must be locked because
|
||||
// the table size could be changed)
|
||||
if (oldfd >= context->table_size
|
||||
|| newfd >= context->table_size
|
||||
|| context->fds[oldfd] == NULL) {
|
||||
mutex_unlock(&context->io_mutex);
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
// Check for identity, note that it cannot be made above
|
||||
// because we always want to return an error on invalid
|
||||
// handles
|
||||
if (oldfd != newfd) {
|
||||
// Now do the work
|
||||
evicted = context->fds[newfd];
|
||||
context->fds[newfd] = context->fds[oldfd];
|
||||
atomic_add(&context->fds[oldfd]->ref_count, 1);
|
||||
}
|
||||
|
||||
mutex_unlock(&context->io_mutex);
|
||||
|
||||
// Say bye bye to the evicted fd
|
||||
if (evicted)
|
||||
put_fd(evicted);
|
||||
|
||||
return newfd;
|
||||
}
|
||||
|
||||
|
||||
@ -351,6 +422,20 @@ user_close(int fd)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_dup(int fd)
|
||||
{
|
||||
return fd_dup(fd, false);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_dup2(int ofd, int nfd)
|
||||
{
|
||||
return fd_dup2(ofd, nfd, false);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
/*** SYSTEM functions ***/
|
||||
|
||||
@ -513,3 +598,17 @@ sys_close(int fd)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_dup(int fd)
|
||||
{
|
||||
return fd_dup(fd, true);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_dup2(int ofd, int nfd)
|
||||
{
|
||||
return fd_dup2(ofd, nfd, true);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user