2002-07-09 16:24:59 +04:00
|
|
|
/* fd.c
|
|
|
|
*
|
|
|
|
* Operations on file descriptors...
|
|
|
|
* see fd.h for the definitions
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ktypes.h>
|
|
|
|
#include <OS.h>
|
|
|
|
#include <fd.h>
|
|
|
|
#include <vfs.h>
|
|
|
|
#include <Errors.h>
|
|
|
|
#include <debug.h>
|
|
|
|
#include <memheap.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define CHECK_USER_ADDR(x) \
|
|
|
|
if ((addr)(x) >= KERNEL_BASE && (addr)(x) <= KERNEL_TOP) \
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
#define CHECK_SYS_ADDR(x) \
|
|
|
|
if ((addr)(x) < KERNEL_BASE && (addr)(x) >= KERNEL_TOP) \
|
|
|
|
return EINVAL;
|
|
|
|
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
#define TRACE_FD 0
|
|
|
|
#if TRACE_FD
|
|
|
|
# define TRACE(x) dprintf x
|
|
|
|
# define PRINT(x) dprintf x
|
|
|
|
#else
|
|
|
|
# define TRACE(x)
|
|
|
|
# define PRINT(x)
|
|
|
|
#endif
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
|
|
|
|
/*** General fd routines ***/
|
|
|
|
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
void dump_fd(int fd, struct file_descriptor *descriptor);
|
|
|
|
|
|
|
|
void
|
|
|
|
dump_fd(int fd,struct file_descriptor *descriptor)
|
|
|
|
{
|
|
|
|
dprintf("fd[%d] = %p: type = %d, ref_count = %d, ops = %p, vnode = %p, cookie = %p, dummy = %x\n",
|
|
|
|
fd,descriptor,descriptor->type,descriptor->ref_count,descriptor->ops,
|
|
|
|
descriptor->vnode,descriptor->cookie,descriptor->dummy);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
/** Allocates and initializes a new file_descriptor */
|
|
|
|
|
|
|
|
struct file_descriptor *
|
|
|
|
alloc_fd(void)
|
|
|
|
{
|
|
|
|
struct file_descriptor *f;
|
|
|
|
|
|
|
|
f = kmalloc(sizeof(struct file_descriptor));
|
2002-07-14 09:15:34 +04:00
|
|
|
if (f) {
|
2002-07-09 16:24:59 +04:00
|
|
|
f->vnode = NULL;
|
|
|
|
f->cookie = NULL;
|
|
|
|
f->ref_count = 1;
|
|
|
|
}
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2002-07-20 04:16:12 +04:00
|
|
|
new_fd(struct io_context *context, struct file_descriptor *descriptor)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
|
|
|
int fd = -1;
|
|
|
|
int i;
|
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
mutex_lock(&context->io_mutex);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
for (i = 0; i < context->table_size; i++) {
|
|
|
|
if (!context->fds[i]) {
|
2002-07-09 16:24:59 +04:00
|
|
|
fd = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fd < 0) {
|
2002-07-12 02:21:56 +04:00
|
|
|
fd = EMFILE;
|
2002-07-09 16:24:59 +04:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
context->fds[fd] = descriptor;
|
|
|
|
context->num_used_fds++;
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
err:
|
2002-07-20 04:16:12 +04:00
|
|
|
mutex_unlock(&context->io_mutex);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2002-07-17 11:55:51 +04:00
|
|
|
put_fd(struct file_descriptor *descriptor)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
|
|
|
/* Run a cleanup (fd_free) routine if there is one and free structure, but only
|
|
|
|
* if we've just removed the final reference to it :)
|
|
|
|
*/
|
2002-07-17 11:55:51 +04:00
|
|
|
if (atomic_add(&descriptor->ref_count, -1) == 1) {
|
|
|
|
if (descriptor->ops->fd_close)
|
|
|
|
descriptor->ops->fd_close(descriptor);
|
|
|
|
if (descriptor->ops->fd_free)
|
|
|
|
descriptor->ops->fd_free(descriptor);
|
|
|
|
|
|
|
|
kfree(descriptor);
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct file_descriptor *
|
2002-07-20 04:16:12 +04:00
|
|
|
get_fd(struct io_context *context, int fd)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
2002-07-20 04:16:12 +04:00
|
|
|
struct file_descriptor *descriptor = NULL;
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
if (fd < 0)
|
|
|
|
return NULL;
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
mutex_lock(&context->io_mutex);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
if (fd < context->table_size)
|
|
|
|
descriptor = context->fds[fd];
|
|
|
|
|
|
|
|
if (descriptor != NULL) // fd is valid
|
|
|
|
atomic_add(&descriptor->ref_count, 1);
|
2002-07-17 11:55:51 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
mutex_unlock(&context->io_mutex);
|
|
|
|
|
|
|
|
return descriptor;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2002-07-20 04:16:12 +04:00
|
|
|
remove_fd(struct io_context *context, int fd)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
2002-07-20 04:16:12 +04:00
|
|
|
struct file_descriptor *descriptor = NULL;
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mutex_lock(&context->io_mutex);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
if (fd < context->table_size)
|
|
|
|
descriptor = context->fds[fd];
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
if (descriptor) { // fd is valid
|
|
|
|
context->fds[fd] = NULL;
|
|
|
|
context->num_used_fds--;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
mutex_unlock(&context->io_mutex);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
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;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// #pragma mark -
|
|
|
|
/*** USER routines ***/
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
user_read(int fd, void *buffer, off_t pos, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
|
|
|
/* This is a user_function, so abort if we have a kernel address */
|
|
|
|
CHECK_USER_ADDR(buffer)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_read) {
|
|
|
|
retval = descriptor->ops->fd_read(descriptor, buffer, pos, &length);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = (ssize_t)length;
|
|
|
|
} else
|
|
|
|
retval = EINVAL;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
user_write(int fd, const void *buffer, off_t pos, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval = 0;
|
|
|
|
|
|
|
|
CHECK_USER_ADDR(buffer)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_write) {
|
|
|
|
retval = descriptor->ops->fd_write(descriptor, buffer, pos, &length);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = (ssize_t)length;
|
|
|
|
} else
|
|
|
|
retval = EINVAL;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
off_t
|
|
|
|
user_seek(int fd, off_t pos, int seekType)
|
2002-07-14 09:15:34 +04:00
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
TRACE(("user_seek(descriptor = %p)\n",descriptor));
|
|
|
|
|
2002-07-14 09:15:34 +04:00
|
|
|
if (descriptor->ops->fd_seek)
|
2002-07-17 11:55:51 +04:00
|
|
|
pos = descriptor->ops->fd_seek(descriptor, pos, seekType);
|
2002-07-14 09:15:34 +04:00
|
|
|
else
|
2002-07-17 11:55:51 +04:00
|
|
|
pos = ESPIPE;
|
2002-07-14 09:15:34 +04:00
|
|
|
|
|
|
|
put_fd(descriptor);
|
2002-07-17 11:55:51 +04:00
|
|
|
return pos;
|
2002-07-14 09:15:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
int
|
|
|
|
user_ioctl(int fd, ulong op, void *buffer, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
CHECK_USER_ADDR(buffer)
|
|
|
|
|
|
|
|
PRINT(("user_ioctl: fd %d\n", fd));
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_ioctl)
|
|
|
|
status = descriptor->ops->fd_ioctl(descriptor, op, buffer, length);
|
|
|
|
else
|
|
|
|
status = EOPNOTSUPP;
|
|
|
|
|
2002-07-14 09:15:34 +04:00
|
|
|
put_fd(descriptor);
|
2002-07-09 16:24:59 +04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
2002-07-11 01:47:38 +04:00
|
|
|
user_read_dir(int fd, struct dirent *buffer,size_t bufferSize,uint32 maxCount)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
|
|
|
CHECK_USER_ADDR(buffer)
|
|
|
|
|
2002-07-11 01:47:38 +04:00
|
|
|
PRINT(("user_read_dir(fd = %d, buffer = 0x%p, bufferSize = %ld, count = %d)\n",fd,buffer,bufferSize,maxCount));
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_read_dir) {
|
2002-07-11 01:47:38 +04:00
|
|
|
uint32 count = maxCount;
|
2002-07-09 16:24:59 +04:00
|
|
|
retval = descriptor->ops->fd_read_dir(descriptor,buffer,bufferSize,&count);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = count;
|
|
|
|
} else
|
|
|
|
retval = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
user_rewind_dir(int fd)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
status_t status;
|
|
|
|
|
|
|
|
PRINT(("user_rewind_dir(fd = %d)\n",fd));
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_rewind_dir)
|
|
|
|
status = descriptor->ops->fd_rewind_dir(descriptor);
|
|
|
|
else
|
|
|
|
status = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
user_fstat(int fd, struct stat *stat)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
|
|
|
/* This is a user_function, so abort if we have a kernel address */
|
|
|
|
CHECK_USER_ADDR(stat)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(false), fd);
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
TRACE(("user_fstat(descriptor = %p)\n",descriptor));
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
if (descriptor->ops->fd_stat) {
|
|
|
|
// we're using the stat buffer on the stack to not have to
|
|
|
|
// lock the given stat buffer in memory
|
|
|
|
struct stat kstat;
|
|
|
|
|
|
|
|
retval = descriptor->ops->fd_stat(descriptor, &kstat);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = user_memcpy(stat, &kstat, sizeof(*stat));
|
|
|
|
} else
|
|
|
|
retval = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
user_close(int fd)
|
|
|
|
{
|
2002-07-17 11:55:51 +04:00
|
|
|
struct io_context *io = get_current_io_context(false);
|
|
|
|
struct file_descriptor *descriptor = get_fd(io, fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
TRACE(("user_close(descriptor = %p)\n",descriptor));
|
|
|
|
|
|
|
|
remove_fd(io, fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
put_fd(descriptor);
|
2002-07-17 11:55:51 +04:00
|
|
|
return B_OK;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
int
|
|
|
|
user_dup(int fd)
|
|
|
|
{
|
|
|
|
return fd_dup(fd, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
user_dup2(int ofd, int nfd)
|
|
|
|
{
|
|
|
|
return fd_dup2(ofd, nfd, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
// #pragma mark -
|
|
|
|
/*** SYSTEM functions ***/
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
sys_read(int fd, void *buffer, off_t pos, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
|
|
|
/* This is a sys_function, so abort if we have a kernel address */
|
|
|
|
// I've removed those checks because we have to be able to load things
|
|
|
|
// into user memory as well -- axeld.
|
|
|
|
//CHECK_SYS_ADDR(buffer)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_read) {
|
|
|
|
retval = descriptor->ops->fd_read(descriptor, buffer, pos, &length);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = (ssize_t)length;
|
|
|
|
} else
|
|
|
|
retval = EINVAL;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
|
|
|
sys_write(int fd, const void *buffer, off_t pos, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
|
|
|
// CHECK_SYS_ADDR(buffer)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_write) {
|
|
|
|
retval = descriptor->ops->fd_write(descriptor, buffer, pos, &length);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = (ssize_t)length;
|
|
|
|
|
|
|
|
PRINT(("sys_write(%d) = %ld (rlen = %ld)\n", fd, retval, length));
|
|
|
|
} else
|
|
|
|
retval = EINVAL;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
off_t
|
|
|
|
sys_seek(int fd, off_t pos, int seekType)
|
2002-07-14 09:15:34 +04:00
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
|
|
|
if (!descriptor)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_seek)
|
2002-07-17 11:55:51 +04:00
|
|
|
pos = descriptor->ops->fd_seek(descriptor, pos, seekType);
|
2002-07-14 09:15:34 +04:00
|
|
|
else
|
2002-07-17 11:55:51 +04:00
|
|
|
pos = ESPIPE;
|
2002-07-14 09:15:34 +04:00
|
|
|
|
|
|
|
put_fd(descriptor);
|
2002-07-17 11:55:51 +04:00
|
|
|
return pos;
|
2002-07-14 09:15:34 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-07-09 16:24:59 +04:00
|
|
|
int
|
|
|
|
sys_ioctl(int fd, ulong op, void *buffer, size_t length)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
PRINT(("sys_ioctl: fd %d\n", fd));
|
|
|
|
|
|
|
|
CHECK_SYS_ADDR(buffer)
|
|
|
|
|
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_ioctl)
|
|
|
|
status = descriptor->ops->fd_ioctl(descriptor, op, buffer, length);
|
|
|
|
else
|
|
|
|
status = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ssize_t
|
2002-07-11 01:47:38 +04:00
|
|
|
sys_read_dir(int fd, struct dirent *buffer,size_t bufferSize,uint32 maxCount)
|
2002-07-09 16:24:59 +04:00
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
ssize_t retval;
|
|
|
|
|
2002-07-11 01:47:38 +04:00
|
|
|
PRINT(("sys_read_dir(fd = %d, buffer = 0x%p, bufferSize = %ld, count = %u)\n",fd,buffer,bufferSize,maxCount));
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-14 09:15:34 +04:00
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_read_dir) {
|
2002-07-11 01:47:38 +04:00
|
|
|
uint32 count = maxCount;
|
2002-07-09 16:24:59 +04:00
|
|
|
retval = descriptor->ops->fd_read_dir(descriptor,buffer,bufferSize,&count);
|
|
|
|
if (retval >= 0)
|
|
|
|
retval = count;
|
|
|
|
} else
|
|
|
|
retval = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t
|
|
|
|
sys_rewind_dir(int fd)
|
|
|
|
{
|
|
|
|
struct file_descriptor *descriptor;
|
|
|
|
status_t status;
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
PRINT(("sys_rewind_dir(fd = %d)\n",fd));
|
2002-07-09 16:24:59 +04:00
|
|
|
|
2002-07-14 09:15:34 +04:00
|
|
|
descriptor = get_fd(get_current_io_context(true), fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
|
|
|
if (descriptor->ops->fd_rewind_dir)
|
|
|
|
status = descriptor->ops->fd_rewind_dir(descriptor);
|
|
|
|
else
|
|
|
|
status = EOPNOTSUPP;
|
|
|
|
|
|
|
|
put_fd(descriptor);
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
sys_close(int fd)
|
|
|
|
{
|
2002-07-17 11:55:51 +04:00
|
|
|
struct io_context *io = get_current_io_context(true);
|
|
|
|
struct file_descriptor *descriptor = get_fd(io, fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
if (descriptor == NULL)
|
|
|
|
return EBADF;
|
|
|
|
|
2002-07-17 11:55:51 +04:00
|
|
|
remove_fd(io, fd);
|
2002-07-09 16:24:59 +04:00
|
|
|
|
|
|
|
put_fd(descriptor);
|
2002-07-17 11:55:51 +04:00
|
|
|
return B_OK;
|
2002-07-09 16:24:59 +04:00
|
|
|
}
|
|
|
|
|
2002-07-20 04:16:12 +04:00
|
|
|
|
|
|
|
int
|
|
|
|
sys_dup(int fd)
|
|
|
|
{
|
|
|
|
return fd_dup(fd, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
sys_dup2(int ofd, int nfd)
|
|
|
|
{
|
|
|
|
return fd_dup2(ofd, nfd, true);
|
|
|
|
}
|
|
|
|
|