* Added fd_ops::set_flags() hook. It's only implemented by socket FDs
ATM. * Changed common_fcntl() to also work for non-vnode-based FDs. Only the operations that require a vnode do fail now. F_SETFL uses the new fd_ops::set_flags() if available, falling back to the vnode respective operation. * Changed some direct accesses to file_descriptor::u::vnode. It was safe in those cases, but might not be anymore if we ever change fd_vnode(). ftp can at least connect to servers again, now, but apparently we still have a problem with syscall restarts -- downloads fail after one second, when the timer goes off. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24917 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,7 @@ struct fd_ops {
|
|||||||
status_t (*fd_write)(struct file_descriptor *, off_t pos, const void *buffer, size_t *length);
|
status_t (*fd_write)(struct file_descriptor *, off_t pos, const void *buffer, size_t *length);
|
||||||
off_t (*fd_seek)(struct file_descriptor *, off_t pos, int seekType);
|
off_t (*fd_seek)(struct file_descriptor *, off_t pos, int seekType);
|
||||||
status_t (*fd_ioctl)(struct file_descriptor *, ulong op, void *buffer, size_t length);
|
status_t (*fd_ioctl)(struct file_descriptor *, ulong op, void *buffer, size_t length);
|
||||||
|
status_t (*fd_set_flags)(struct file_descriptor *, int flags);
|
||||||
status_t (*fd_select)(struct file_descriptor *, uint8 event,
|
status_t (*fd_select)(struct file_descriptor *, uint8 event,
|
||||||
struct selectsync *sync);
|
struct selectsync *sync);
|
||||||
status_t (*fd_deselect)(struct file_descriptor *, uint8 event,
|
status_t (*fd_deselect)(struct file_descriptor *, uint8 event,
|
||||||
|
|||||||
@@ -214,6 +214,17 @@ socket_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
socket_set_flags(struct file_descriptor *descriptor, int flags)
|
||||||
|
{
|
||||||
|
// we ignore O_APPEND, but O_NONBLOCK we need to translate
|
||||||
|
uint32 op = (flags & O_NONBLOCK) != 0
|
||||||
|
? B_SET_NONBLOCKING_IO : B_SET_BLOCKING_IO;
|
||||||
|
|
||||||
|
return sStackInterface->ioctl(descriptor->u.socket, op, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
socket_select(struct file_descriptor *descriptor, uint8 event,
|
socket_select(struct file_descriptor *descriptor, uint8 event,
|
||||||
struct selectsync *sync)
|
struct selectsync *sync)
|
||||||
@@ -272,6 +283,7 @@ static struct fd_ops sSocketFDOps = {
|
|||||||
&socket_write,
|
&socket_write,
|
||||||
NULL, // fd_seek
|
NULL, // fd_seek
|
||||||
&socket_ioctl,
|
&socket_ioctl,
|
||||||
|
&socket_set_flags,
|
||||||
&socket_select,
|
&socket_select,
|
||||||
&socket_deselect,
|
&socket_deselect,
|
||||||
NULL, // fd_read_dir
|
NULL, // fd_read_dir
|
||||||
|
|||||||
@@ -292,6 +292,7 @@ static struct fd_ops sFileOps = {
|
|||||||
file_write,
|
file_write,
|
||||||
file_seek,
|
file_seek,
|
||||||
common_ioctl,
|
common_ioctl,
|
||||||
|
NULL, // set_flags
|
||||||
file_select,
|
file_select,
|
||||||
file_deselect,
|
file_deselect,
|
||||||
NULL, // read_dir()
|
NULL, // read_dir()
|
||||||
@@ -307,6 +308,7 @@ static struct fd_ops sDirectoryOps = {
|
|||||||
NULL, // write()
|
NULL, // write()
|
||||||
NULL, // seek()
|
NULL, // seek()
|
||||||
common_ioctl,
|
common_ioctl,
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
dir_read,
|
dir_read,
|
||||||
@@ -322,6 +324,7 @@ static struct fd_ops sAttributeDirectoryOps = {
|
|||||||
NULL, // write()
|
NULL, // write()
|
||||||
NULL, // seek()
|
NULL, // seek()
|
||||||
common_ioctl,
|
common_ioctl,
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
attr_dir_read,
|
attr_dir_read,
|
||||||
@@ -337,6 +340,7 @@ static struct fd_ops sAttributeOps = {
|
|||||||
attr_write,
|
attr_write,
|
||||||
attr_seek,
|
attr_seek,
|
||||||
common_ioctl,
|
common_ioctl,
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
NULL, // read_dir()
|
NULL, // read_dir()
|
||||||
@@ -352,6 +356,7 @@ static struct fd_ops sIndexDirectoryOps = {
|
|||||||
NULL, // write()
|
NULL, // write()
|
||||||
NULL, // seek()
|
NULL, // seek()
|
||||||
NULL, // ioctl()
|
NULL, // ioctl()
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
index_dir_read,
|
index_dir_read,
|
||||||
@@ -368,6 +373,7 @@ static struct fd_ops sIndexOps = {
|
|||||||
NULL, // write()
|
NULL, // write()
|
||||||
NULL, // seek()
|
NULL, // seek()
|
||||||
NULL, // ioctl()
|
NULL, // ioctl()
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
NULL, // dir_read()
|
NULL, // dir_read()
|
||||||
@@ -384,6 +390,7 @@ static struct fd_ops sQueryOps = {
|
|||||||
NULL, // write()
|
NULL, // write()
|
||||||
NULL, // seek()
|
NULL, // seek()
|
||||||
NULL, // ioctl()
|
NULL, // ioctl()
|
||||||
|
NULL, // set_flags
|
||||||
NULL, // select()
|
NULL, // select()
|
||||||
NULL, // deselect()
|
NULL, // deselect()
|
||||||
query_read,
|
query_read,
|
||||||
@@ -2435,7 +2442,8 @@ get_fd_and_vnode(int fd, struct vnode **_vnode, bool kernel)
|
|||||||
if (descriptor == NULL)
|
if (descriptor == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (fd_vnode(descriptor) == NULL) {
|
struct vnode* vnode = fd_vnode(descriptor);
|
||||||
|
if (vnode == NULL) {
|
||||||
put_fd(descriptor);
|
put_fd(descriptor);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -2443,7 +2451,7 @@ get_fd_and_vnode(int fd, struct vnode **_vnode, bool kernel)
|
|||||||
// ToDo: when we can close a file descriptor at any point, investigate
|
// ToDo: when we can close a file descriptor at any point, investigate
|
||||||
// if this is still valid to do (accessing the vnode without ref_count
|
// if this is still valid to do (accessing the vnode without ref_count
|
||||||
// or locking)
|
// or locking)
|
||||||
*_vnode = descriptor->u.vnode;
|
*_vnode = vnode;
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5121,17 +5129,18 @@ common_ioctl(struct file_descriptor *descriptor, ulong op, void *buffer,
|
|||||||
static status_t
|
static status_t
|
||||||
common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
||||||
{
|
{
|
||||||
struct file_descriptor *descriptor;
|
|
||||||
struct vnode *vnode;
|
|
||||||
struct flock flock;
|
struct flock flock;
|
||||||
|
|
||||||
FUNCTION(("common_fcntl(fd = %d, op = %d, argument = %lx, %s)\n",
|
FUNCTION(("common_fcntl(fd = %d, op = %d, argument = %lx, %s)\n",
|
||||||
fd, op, argument, kernel ? "kernel" : "user"));
|
fd, op, argument, kernel ? "kernel" : "user"));
|
||||||
|
|
||||||
descriptor = get_fd_and_vnode(fd, &vnode, kernel);
|
struct file_descriptor *descriptor = get_fd(get_current_io_context(kernel),
|
||||||
|
fd);
|
||||||
if (descriptor == NULL)
|
if (descriptor == NULL)
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
|
|
||||||
|
struct vnode* vnode = fd_vnode(descriptor);
|
||||||
|
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) {
|
if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) {
|
||||||
@@ -5175,19 +5184,23 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
|||||||
|
|
||||||
case F_SETFL:
|
case F_SETFL:
|
||||||
// Set file descriptor open mode
|
// Set file descriptor open mode
|
||||||
if (HAS_FS_CALL(vnode, set_flags)) {
|
|
||||||
// we only accept changes to O_APPEND and O_NONBLOCK
|
|
||||||
argument &= O_APPEND | O_NONBLOCK;
|
|
||||||
|
|
||||||
|
// we only accept changes to O_APPEND and O_NONBLOCK
|
||||||
|
argument &= O_APPEND | O_NONBLOCK;
|
||||||
|
if (descriptor->ops->fd_set_flags != NULL) {
|
||||||
|
status = descriptor->ops->fd_set_flags(descriptor, argument);
|
||||||
|
} else if (vnode != NULL && HAS_FS_CALL(vnode, set_flags)) {
|
||||||
status = FS_CALL(vnode, set_flags, descriptor->cookie,
|
status = FS_CALL(vnode, set_flags, descriptor->cookie,
|
||||||
(int)argument);
|
(int)argument);
|
||||||
if (status == B_OK) {
|
|
||||||
// update this descriptor's open_mode field
|
|
||||||
descriptor->open_mode = (descriptor->open_mode
|
|
||||||
& ~(O_APPEND | O_NONBLOCK)) | argument;
|
|
||||||
}
|
|
||||||
} else
|
} else
|
||||||
status = EOPNOTSUPP;
|
status = EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (status == B_OK) {
|
||||||
|
// update this descriptor's open_mode field
|
||||||
|
descriptor->open_mode = (descriptor->open_mode
|
||||||
|
& ~(O_APPEND | O_NONBLOCK)) | argument;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_GETFL:
|
case F_GETFL:
|
||||||
@@ -5211,12 +5224,15 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case F_GETLK:
|
case F_GETLK:
|
||||||
status = get_advisory_lock(descriptor->u.vnode, &flock);
|
if (vnode != NULL) {
|
||||||
if (status == B_OK) {
|
status = get_advisory_lock(vnode, &flock);
|
||||||
// copy back flock structure
|
if (status == B_OK) {
|
||||||
status = user_memcpy((struct flock *)argument, &flock,
|
// copy back flock structure
|
||||||
sizeof(struct flock));
|
status = user_memcpy((struct flock *)argument, &flock,
|
||||||
}
|
sizeof(struct flock));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
status = B_BAD_VALUE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case F_SETLK:
|
case F_SETLK:
|
||||||
@@ -5225,9 +5241,11 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
|||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (flock.l_type == F_UNLCK)
|
if (vnode == NULL) {
|
||||||
status = release_advisory_lock(descriptor->u.vnode, &flock);
|
status = B_BAD_VALUE;
|
||||||
else {
|
} else if (flock.l_type == F_UNLCK) {
|
||||||
|
status = release_advisory_lock(vnode, &flock);
|
||||||
|
} else {
|
||||||
// the open mode must match the lock type
|
// the open mode must match the lock type
|
||||||
if ((descriptor->open_mode & O_RWMASK) == O_RDONLY
|
if ((descriptor->open_mode & O_RWMASK) == O_RDONLY
|
||||||
&& flock.l_type == F_WRLCK
|
&& flock.l_type == F_WRLCK
|
||||||
@@ -5235,7 +5253,7 @@ common_fcntl(int fd, int op, uint32 argument, bool kernel)
|
|||||||
&& flock.l_type == F_RDLCK)
|
&& flock.l_type == F_RDLCK)
|
||||||
status = B_FILE_ERROR;
|
status = B_FILE_ERROR;
|
||||||
else {
|
else {
|
||||||
status = acquire_advisory_lock(descriptor->u.vnode, -1,
|
status = acquire_advisory_lock(vnode, -1,
|
||||||
&flock, op == F_SETLKW);
|
&flock, op == F_SETLKW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8023,9 +8041,9 @@ _user_flock(int fd, int op)
|
|||||||
flock.l_type = (op & LOCK_SH) != 0 ? F_RDLCK : F_WRLCK;
|
flock.l_type = (op & LOCK_SH) != 0 ? F_RDLCK : F_WRLCK;
|
||||||
|
|
||||||
if ((op & LOCK_UN) != 0)
|
if ((op & LOCK_UN) != 0)
|
||||||
status = release_advisory_lock(descriptor->u.vnode, &flock);
|
status = release_advisory_lock(vnode, &flock);
|
||||||
else {
|
else {
|
||||||
status = acquire_advisory_lock(descriptor->u.vnode,
|
status = acquire_advisory_lock(vnode,
|
||||||
thread_get_current_thread()->team->session_id, &flock,
|
thread_get_current_thread()->team->session_id, &flock,
|
||||||
(op & LOCK_NB) == 0);
|
(op & LOCK_NB) == 0);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user