* Introduced dedicated syscalls for the deprecated BeOS fs_attr API. Before,

each attribute access needed 3 syscalls, now only one as it should.
* Renamed the new Haiku call fs_open_attr() to fs_fopen_attr(), and added a new
  function fs_open_attr() that takes a path (same semantics as the
  fs_[f]open_attr_dir() functions already present in BeOS).
* Merged former _kern_open_attr(), and _kern_create_attr() into one syscall.
* Cleaned up vfs.h.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31881 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-07-29 00:34:44 +00:00
parent b237fdf90a
commit 8ae594ffd4
7 changed files with 357 additions and 276 deletions
+14 -11
View File
@@ -1,7 +1,7 @@
/* File System attributes /*
** * Copyright 2004-2009, Haiku Inc. All Rights Reserved.
** Distributed under the terms of the OpenBeOS License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _FS_ATTR_H #ifndef _FS_ATTR_H
#define _FS_ATTR_H #define _FS_ATTR_H
@@ -20,15 +20,18 @@ typedef struct attr_info {
extern "C" { extern "C" {
#endif #endif
extern ssize_t fs_read_attr(int fd, const char *attribute, uint32 type, off_t pos, void *buffer, size_t readBytes); extern ssize_t fs_read_attr(int fd, const char *attribute, uint32 type,
extern ssize_t fs_write_attr(int fd, const char *attribute, uint32 type, off_t pos, const void *buffer, size_t readBytes); off_t pos, void *buffer, size_t readBytes);
extern ssize_t fs_write_attr(int fd, const char *attribute, uint32 type,
off_t pos, const void *buffer, size_t readBytes);
extern int fs_remove_attr(int fd, const char *attribute); extern int fs_remove_attr(int fd, const char *attribute);
extern int fs_stat_attr(int fd, const char *attribute, struct attr_info *attrInfo); extern int fs_stat_attr(int fd, const char *attribute,
struct attr_info *attrInfo);
// ToDo: the following three functions are not part of the R5 API, and extern int fs_open_attr(const char *path, const char *attribute,
// are only preliminary - they may change or be removed at any point uint32 type, int openMode);
//extern int fs_open_attr(const char *path, const char *attribute, uint32 type, int openMode); extern int fs_fopen_attr(int fd, const char *attribute, uint32 type,
extern int fs_open_attr(int fd, const char *attribute, uint32 type, int openMode); int openMode);
extern int fs_close_attr(int fd); extern int fs_close_attr(int fd);
extern DIR *fs_open_attr_dir(const char *path); extern DIR *fs_open_attr_dir(const char *path);
+187 -171
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2002-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -31,10 +31,12 @@
#define B_UNMOUNT_BUSY_PARTITION 0x80000000 #define B_UNMOUNT_BUSY_PARTITION 0x80000000
struct attr_info;
struct file_descriptor; struct file_descriptor;
struct kernel_args; struct kernel_args;
struct net_stat; struct net_stat;
struct pollfd; struct pollfd;
struct rlimit;
struct selectsync; struct selectsync;
struct select_info; struct select_info;
struct VMCache; struct VMCache;
@@ -67,191 +69,206 @@ typedef struct io_context {
extern "C" { extern "C" {
#endif #endif
status_t vfs_init(struct kernel_args *args); status_t vfs_init(struct kernel_args *args);
status_t vfs_bootstrap_file_systems(void); status_t vfs_bootstrap_file_systems(void);
void vfs_mount_boot_file_system(struct kernel_args *args); void vfs_mount_boot_file_system(struct kernel_args *args);
void vfs_exec_io_context(io_context *context); void vfs_exec_io_context(io_context *context);
io_context *vfs_new_io_context(io_context *parentContext); io_context *vfs_new_io_context(io_context *parentContext);
void vfs_get_io_context(io_context *context); void vfs_get_io_context(io_context *context);
void vfs_put_io_context(io_context *context); void vfs_put_io_context(io_context *context);
struct rlimit; int vfs_getrlimit(int resource, struct rlimit *rlp);
int vfs_getrlimit(int resource, struct rlimit * rlp); int vfs_setrlimit(int resource, const struct rlimit *rlp);
int vfs_setrlimit(int resource, const struct rlimit * rlp);
/* calls needed by the VM for paging and by the file cache */ /* calls needed by the VM for paging and by the file cache */
int vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode); int vfs_get_vnode_from_fd(int fd, bool kernel, struct vnode **_vnode);
status_t vfs_get_vnode_from_path(const char *path, bool kernel, status_t vfs_get_vnode_from_path(const char *path, bool kernel,
struct vnode **_vnode); struct vnode **_vnode);
status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait, status_t vfs_get_vnode(dev_t mountID, ino_t vnodeID, bool canWait,
struct vnode **_vnode); struct vnode **_vnode);
status_t vfs_entry_ref_to_vnode(dev_t mountID, ino_t directoryID, status_t vfs_entry_ref_to_vnode(dev_t mountID, ino_t directoryID,
const char *name, struct vnode **_vnode); const char *name, struct vnode **_vnode);
void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID, void vfs_vnode_to_node_ref(struct vnode *vnode, dev_t *_mountID,
ino_t *_vnodeID); ino_t *_vnodeID);
status_t vfs_lookup_vnode(dev_t mountID, ino_t vnodeID, struct vnode **_vnode); status_t vfs_lookup_vnode(dev_t mountID, ino_t vnodeID,
void vfs_put_vnode(struct vnode *vnode); struct vnode **_vnode);
void vfs_acquire_vnode(struct vnode *vnode); void vfs_put_vnode(struct vnode *vnode);
status_t vfs_get_cookie_from_fd(int fd, void **_cookie); void vfs_acquire_vnode(struct vnode *vnode);
bool vfs_can_page(struct vnode *vnode, void *cookie); status_t vfs_get_cookie_from_fd(int fd, void **_cookie);
status_t vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos, bool vfs_can_page(struct vnode *vnode, void *cookie);
const iovec *vecs, size_t count, uint32 flags, size_t *_numBytes); status_t vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos,
status_t vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos, const iovec *vecs, size_t count, uint32 flags,
const iovec *vecs, size_t count, uint32 flags, size_t *_numBytes); size_t *_numBytes);
status_t vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request); status_t vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos,
status_t vfs_synchronous_io(io_request* request, const iovec *vecs, size_t count, uint32 flags,
status_t (*doIO)(void* cookie, off_t offset, void* buffer, size_t *_numBytes);
status_t vfs_vnode_io(struct vnode* vnode, void* cookie,
io_request* request);
status_t vfs_synchronous_io(io_request* request,
status_t (*doIO)(void* cookie, off_t offset, void* buffer,
size_t* length), size_t* length),
void* cookie); void* cookie);
status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache, status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache,
bool allocate); bool allocate);
status_t vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size, status_t vfs_get_file_map(struct vnode *vnode, off_t offset, size_t size,
struct file_io_vec *vecs, size_t *_count); struct file_io_vec *vecs, size_t *_count);
status_t vfs_get_fs_node_from_path(fs_volume *volume, const char *path, status_t vfs_get_fs_node_from_path(fs_volume *volume, const char *path,
bool kernel, void **_node); bool kernel, void **_node);
status_t vfs_stat_vnode(struct vnode *vnode, struct stat *stat); status_t vfs_stat_vnode(struct vnode *vnode, struct stat *stat);
status_t vfs_stat_node_ref(dev_t device, ino_t inode, struct stat *stat); status_t vfs_stat_node_ref(dev_t device, ino_t inode, struct stat *stat);
status_t vfs_get_vnode_name(struct vnode *vnode, char *name, size_t nameSize); status_t vfs_get_vnode_name(struct vnode *vnode, char *name,
status_t vfs_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, size_t nameSize);
char *path, size_t pathLength); status_t vfs_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf,
status_t vfs_get_cwd(dev_t *_mountID, ino_t *_vnodeID); char *path, size_t pathLength);
void vfs_unlock_vnode_if_locked(struct file_descriptor *descriptor); status_t vfs_get_cwd(dev_t *_mountID, ino_t *_vnodeID);
status_t vfs_unmount(dev_t mountID, uint32 flags); void vfs_unlock_vnode_if_locked(struct file_descriptor *descriptor);
status_t vfs_disconnect_vnode(dev_t mountID, ino_t vnodeID); status_t vfs_unmount(dev_t mountID, uint32 flags);
void vfs_free_unused_vnodes(int32 level); status_t vfs_disconnect_vnode(dev_t mountID, ino_t vnodeID);
void vfs_free_unused_vnodes(int32 level);
status_t vfs_read_stat(int fd, const char *path, bool traverseLeafLink, status_t vfs_read_stat(int fd, const char *path, bool traverseLeafLink,
struct stat *stat, bool kernel); struct stat *stat, bool kernel);
/* special module convenience call */ /* special module convenience call */
status_t vfs_get_module_path(const char *basePath, const char *moduleName, status_t vfs_get_module_path(const char *basePath, const char *moduleName,
char *pathBuffer, size_t bufferSize); char *pathBuffer, size_t bufferSize);
/* service call for whoever needs a normalized path */ /* service call for whoever needs a normalized path */
status_t vfs_normalize_path(const char *path, char *buffer, size_t bufferSize, status_t vfs_normalize_path(const char *path, char *buffer,
bool traverseLink, bool kernel); size_t bufferSize, bool traverseLink, bool kernel);
/* service call for whoever wants to create a special node */ /* service call for whoever wants to create a special node */
status_t vfs_create_special_node(const char *path, fs_vnode *subVnode, status_t vfs_create_special_node(const char *path, fs_vnode *subVnode,
mode_t mode, uint32 flags, bool kernel, fs_vnode *_superVnode, mode_t mode, uint32 flags, bool kernel, fs_vnode *_superVnode,
struct vnode **_createdVnode); struct vnode **_createdVnode);
/* service call for the node monitor */ /* service call for the node monitor */
status_t resolve_mount_point_to_volume_root(dev_t mountID, ino_t nodeID, status_t resolve_mount_point_to_volume_root(dev_t mountID, ino_t nodeID,
dev_t *resolvedMountID, ino_t *resolvedNodeID); dev_t *resolvedMountID, ino_t *resolvedNodeID);
/* calls the syscall dispatcher should use for user file I/O */ /* calls the syscall dispatcher should use for user file I/O */
dev_t _user_mount(const char *path, const char *device, const char *fs_name, dev_t _user_mount(const char *path, const char *device,
uint32 flags, const char *args, size_t argsLength); const char *fs_name, uint32 flags, const char *args,
status_t _user_unmount(const char *path, uint32 flags); size_t argsLength);
status_t _user_read_fs_info(dev_t device, struct fs_info *info); status_t _user_unmount(const char *path, uint32 flags);
status_t _user_write_fs_info(dev_t device, const struct fs_info *info, int mask); status_t _user_read_fs_info(dev_t device, struct fs_info *info);
dev_t _user_next_device(int32 *_cookie); status_t _user_write_fs_info(dev_t device, const struct fs_info *info,
status_t _user_sync(void); int mask);
status_t _user_get_next_fd_info(team_id team, uint32 *cookie, struct fd_info *info, dev_t _user_next_device(int32 *_cookie);
size_t infoSize); status_t _user_sync(void);
status_t _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf, status_t _user_get_next_fd_info(team_id team, uint32 *cookie,
char *userPath, size_t pathLength); struct fd_info *info, size_t infoSize);
status_t _user_normalize_path(const char* userPath, bool traverseLink, status_t _user_entry_ref_to_path(dev_t device, ino_t inode, const char *leaf,
char* buffer); char *userPath, size_t pathLength);
int _user_open_entry_ref(dev_t device, ino_t inode, const char *name, int openMode, int perms); status_t _user_normalize_path(const char* userPath, bool traverseLink,
int _user_open(int fd, const char *path, int openMode, int perms); char* buffer);
int _user_open_dir_node_ref(dev_t device, ino_t inode); int _user_open_entry_ref(dev_t device, ino_t inode, const char *name,
int _user_open_dir_entry_ref(dev_t device, ino_t inode, const char *uname); int openMode, int perms);
int _user_open_dir(int fd, const char *path); int _user_open(int fd, const char *path, int openMode, int perms);
int _user_open_parent_dir(int fd, char *name, size_t nameLength); int _user_open_dir_node_ref(dev_t device, ino_t inode);
status_t _user_fcntl(int fd, int op, uint32 argument); int _user_open_dir_entry_ref(dev_t device, ino_t inode,
status_t _user_fsync(int fd); const char *name);
status_t _user_flock(int fd, int op); int _user_open_dir(int fd, const char *path);
status_t _user_read_stat(int fd, const char *path, bool traverseLink, int _user_open_parent_dir(int fd, char *name, size_t nameLength);
struct stat *stat, size_t statSize); status_t _user_fcntl(int fd, int op, uint32 argument);
status_t _user_write_stat(int fd, const char *path, bool traverseLink, status_t _user_fsync(int fd);
const struct stat *stat, size_t statSize, int statMask); status_t _user_flock(int fd, int op);
off_t _user_seek(int fd, off_t pos, int seekType); status_t _user_read_stat(int fd, const char *path, bool traverseLink,
status_t _user_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms); struct stat *stat, size_t statSize);
status_t _user_create_dir(int fd, const char *path, int perms); status_t _user_write_stat(int fd, const char *path, bool traverseLink,
status_t _user_remove_dir(int fd, const char *path); const struct stat *stat, size_t statSize, int statMask);
status_t _user_read_link(int fd, const char *path, char *buffer, size_t *_bufferSize); off_t _user_seek(int fd, off_t pos, int seekType);
status_t _user_write_link(const char *path, const char *toPath); status_t _user_create_dir_entry_ref(dev_t device, ino_t inode,
status_t _user_create_symlink(int fd, const char *path, const char *toPath, const char *name, int perms);
int mode); status_t _user_create_dir(int fd, const char *path, int perms);
status_t _user_create_link(const char *path, const char *toPath); status_t _user_remove_dir(int fd, const char *path);
status_t _user_unlink(int fd, const char *path); status_t _user_read_link(int fd, const char *path, char *buffer,
status_t _user_rename(int oldFD, const char *oldpath, int newFD, size_t *_bufferSize);
const char *newpath); status_t _user_write_link(const char *path, const char *toPath);
status_t _user_create_fifo(const char *path, mode_t perms); status_t _user_create_symlink(int fd, const char *path, const char *toPath,
status_t _user_create_pipe(int *fds); int mode);
status_t _user_access(const char *path, int mode); status_t _user_create_link(const char *path, const char *toPath);
ssize_t _user_select(int numfds, fd_set *readSet, fd_set *writeSet, fd_set *errorSet, status_t _user_unlink(int fd, const char *path);
bigtime_t timeout, const sigset_t *sigMask); status_t _user_rename(int oldFD, const char *oldpath, int newFD,
ssize_t _user_poll(struct pollfd *fds, int numfds, bigtime_t timeout); const char *newpath);
int _user_open_attr_dir(int fd, const char *path); status_t _user_create_fifo(const char *path, mode_t perms);
int _user_create_attr(int fd, const char *name, uint32 type, int openMode); status_t _user_create_pipe(int *fds);
int _user_open_attr(int fd, const char *name, int openMode); status_t _user_access(const char *path, int mode);
status_t _user_remove_attr(int fd, const char *name); ssize_t _user_select(int numfds, fd_set *readSet, fd_set *writeSet,
status_t _user_rename_attr(int fromFile, const char *fromName, int toFile, const char *toName); fd_set *errorSet, bigtime_t timeout, const sigset_t *sigMask);
int _user_open_index_dir(dev_t device); ssize_t _user_poll(struct pollfd *fds, int numfds, bigtime_t timeout);
status_t _user_create_index(dev_t device, const char *name, uint32 type, uint32 flags); int _user_open_attr_dir(int fd, const char *path);
status_t _user_read_index_stat(dev_t device, const char *name, struct stat *stat); ssize_t _user_read_attr(int fd, const char *attribute, off_t pos,
status_t _user_remove_index(dev_t device, const char *name); void *buffer, size_t readBytes);
status_t _user_getcwd(char *buffer, size_t size); ssize_t _user_write_attr(int fd, const char *attribute, uint32 type,
status_t _user_setcwd(int fd, const char *path); off_t pos, const void *buffer, size_t readBytes);
status_t _user_change_root(const char *path); status_t _user_stat_attr(int fd, const char *attribute,
int _user_open_query(dev_t device, const char *query, size_t queryLength, uint32 flags, struct attr_info *attrInfo);
port_id port, int32 token); int _user_open_attr(int fd, const char* path, const char *name,
uint32 type, int openMode);
status_t _user_remove_attr(int fd, const char *name);
status_t _user_rename_attr(int fromFile, const char *fromName, int toFile,
const char *toName);
int _user_open_index_dir(dev_t device);
status_t _user_create_index(dev_t device, const char *name, uint32 type,
uint32 flags);
status_t _user_read_index_stat(dev_t device, const char *name,
struct stat *stat);
status_t _user_remove_index(dev_t device, const char *name);
status_t _user_getcwd(char *buffer, size_t size);
status_t _user_setcwd(int fd, const char *path);
status_t _user_change_root(const char *path);
int _user_open_query(dev_t device, const char *query,
size_t queryLength, uint32 flags, port_id port, int32 token);
/* fd user prototypes (implementation located in fd.cpp) */ /* fd user prototypes (implementation located in fd.cpp) */
extern ssize_t _user_read(int fd, off_t pos, void *buffer, size_t bufferSize); ssize_t _user_read(int fd, off_t pos, void *buffer, size_t bufferSize);
extern ssize_t _user_readv(int fd, off_t pos, const iovec *vecs, size_t count); ssize_t _user_readv(int fd, off_t pos, const iovec *vecs, size_t count);
extern ssize_t _user_write(int fd, off_t pos, const void *buffer, size_t bufferSize); ssize_t _user_write(int fd, off_t pos, const void *buffer,
extern ssize_t _user_writev(int fd, off_t pos, const iovec *vecs, size_t count); size_t bufferSize);
extern status_t _user_ioctl(int fd, ulong cmd, void *data, size_t length); ssize_t _user_writev(int fd, off_t pos, const iovec *vecs, size_t count);
extern ssize_t _user_read_dir(int fd, struct dirent *buffer, size_t bufferSize, uint32 maxCount); status_t _user_ioctl(int fd, ulong cmd, void *data, size_t length);
extern status_t _user_rewind_dir(int fd); ssize_t _user_read_dir(int fd, struct dirent *buffer, size_t bufferSize,
extern status_t _user_close(int fd); uint32 maxCount);
extern int _user_dup(int fd); status_t _user_rewind_dir(int fd);
extern int _user_dup2(int ofd, int nfd); status_t _user_close(int fd);
extern status_t _user_lock_node(int fd); int _user_dup(int fd);
extern status_t _user_unlock_node(int fd); int _user_dup2(int ofd, int nfd);
status_t _user_lock_node(int fd);
status_t _user_unlock_node(int fd);
/* socket user prototypes (implementation in socket.cpp) */ /* socket user prototypes (implementation in socket.cpp) */
extern int _user_socket(int family, int type, int protocol); int _user_socket(int family, int type, int protocol);
extern status_t _user_bind(int socket, const struct sockaddr *address, status_t _user_bind(int socket, const struct sockaddr *address,
socklen_t addressLength); socklen_t addressLength);
extern status_t _user_shutdown_socket(int socket, int how); status_t _user_shutdown_socket(int socket, int how);
extern status_t _user_connect(int socket, const struct sockaddr *address, status_t _user_connect(int socket, const struct sockaddr *address,
socklen_t addressLength); socklen_t addressLength);
extern status_t _user_listen(int socket, int backlog); status_t _user_listen(int socket, int backlog);
extern int _user_accept(int socket, struct sockaddr *address, int _user_accept(int socket, struct sockaddr *address,
socklen_t *_addressLength); socklen_t *_addressLength);
extern ssize_t _user_recv(int socket, void *data, size_t length, ssize_t _user_recv(int socket, void *data, size_t length, int flags);
int flags); ssize_t _user_recvfrom(int socket, void *data, size_t length, int flags,
extern ssize_t _user_recvfrom(int socket, void *data, size_t length, struct sockaddr *address, socklen_t *_addressLength);
int flags, struct sockaddr *address, ssize_t _user_recvmsg(int socket, struct msghdr *message, int flags);
socklen_t *_addressLength); ssize_t _user_send(int socket, const void *data, size_t length, int flags);
extern ssize_t _user_recvmsg(int socket, struct msghdr *message, ssize_t _user_sendto(int socket, const void *data, size_t length, int flags,
int flags); const struct sockaddr *address, socklen_t addressLength);
extern ssize_t _user_send(int socket, const void *data, size_t length, ssize_t _user_sendmsg(int socket, const struct msghdr *message, int flags);
int flags); status_t _user_getsockopt(int socket, int level, int option, void *value,
extern ssize_t _user_sendto(int socket, const void *data, size_t length, socklen_t *_length);
int flags, const struct sockaddr *address, status_t _user_setsockopt(int socket, int level, int option,
socklen_t addressLength); const void *value, socklen_t length);
extern ssize_t _user_sendmsg(int socket, const struct msghdr *message, status_t _user_getpeername(int socket, struct sockaddr *address,
int flags); socklen_t *_addressLength);
extern status_t _user_getsockopt(int socket, int level, int option, status_t _user_getsockname(int socket, struct sockaddr *address,
void *value, socklen_t *_length); socklen_t *_addressLength);
extern status_t _user_setsockopt(int socket, int level, int option, int _user_sockatmark(int socket);
const void *value, socklen_t length); status_t _user_socketpair(int family, int type, int protocol,
extern status_t _user_getpeername(int socket, struct sockaddr *address, int *socketVector);
socklen_t *_addressLength); status_t _user_get_next_socket_stat(int family, uint32 *cookie,
extern status_t _user_getsockname(int socket, struct sockaddr *address, struct net_stat *stat);
socklen_t *_addressLength);
extern int _user_sockatmark(int socket);
extern status_t _user_socketpair(int family, int type, int protocol,
int *socketVector);
extern status_t _user_get_next_socket_stat(int family, uint32 *cookie,
struct net_stat *stat);
#ifdef __cplusplus #ifdef __cplusplus
} }
@@ -286,14 +303,13 @@ protected:
}; };
status_t vfs_asynchronous_read_pages(struct vnode* vnode, void* cookie, status_t vfs_asynchronous_read_pages(struct vnode* vnode, void* cookie,
off_t pos, const iovec* vecs, size_t count, size_t numBytes, off_t pos, const iovec* vecs, size_t count, size_t numBytes,
uint32 flags, AsyncIOCallback* callback); uint32 flags, AsyncIOCallback* callback);
status_t vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie,
off_t pos, const iovec* vecs, size_t count, size_t numBytes,
uint32 flags, AsyncIOCallback* callback);
status_t vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie,
off_t pos, const iovec* vecs, size_t count, size_t numBytes,
uint32 flags, AsyncIOCallback* callback);
#endif // __cplusplus #endif // __cplusplus
+10 -3
View File
@@ -19,6 +19,7 @@
extern "C" { extern "C" {
#endif #endif
struct attr_info;
struct dirent; struct dirent;
struct Elf32_Sym; struct Elf32_Sym;
struct fd_info; struct fd_info;
@@ -250,10 +251,16 @@ extern ssize_t _kern_select(int numfds, struct fd_set *readSet,
bigtime_t timeout, const sigset_t *sigMask); bigtime_t timeout, const sigset_t *sigMask);
extern ssize_t _kern_poll(struct pollfd *fds, int numFDs, extern ssize_t _kern_poll(struct pollfd *fds, int numFDs,
bigtime_t timeout); bigtime_t timeout);
extern int _kern_open_attr_dir(int fd, const char *path); extern int _kern_open_attr_dir(int fd, const char *path);
extern int _kern_create_attr(int fd, const char *name, uint32 type, extern ssize_t _kern_read_attr(int fd, const char *attribute, off_t pos,
int openMode); void *buffer, size_t readBytes);
extern int _kern_open_attr(int fd, const char *name, int openMode); extern ssize_t _kern_write_attr(int fd, const char *attribute, uint32 type,
off_t pos, const void *buffer, size_t readBytes);
extern status_t _kern_stat_attr(int fd, const char *attribute,
struct attr_info *attrInfo);
extern int _kern_open_attr(int fd, const char* path, const char *name,
uint32 type, int openMode);
extern status_t _kern_remove_attr(int fd, const char *name); extern status_t _kern_remove_attr(int fd, const char *name);
extern status_t _kern_rename_attr(int fromFile, const char *fromName, extern status_t _kern_rename_attr(int fromFile, const char *fromName,
int toFile, const char *toName); int toFile, const char *toName);
+1 -1
View File
@@ -1202,7 +1202,7 @@ AboutView::_AddCopyrightsFromAttribute()
} }
// open the attribute // open the attribute
int attrFD = fs_open_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY); int attrFD = fs_fopen_attr(appFD, "COPYRIGHTS", B_STRING_TYPE, O_RDONLY);
close(appFD); close(appFD);
if (attrFD < 0) if (attrFD < 0)
return; return;
+1 -1
View File
@@ -168,7 +168,7 @@ sv_rewind(struct irs_sv *sv)
return; return;
// open the attribute // open the attribute
int attrFD = fs_open_attr(libraryFD, "services", B_STRING_TYPE, O_RDONLY); int attrFD = fs_fopen_attr(libraryFD, "services", B_STRING_TYPE, O_RDONLY);
close(libraryFD); close(libraryFD);
if (attrFD < 0) if (attrFD < 0)
return; return;
+128 -41
View File
@@ -21,6 +21,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fs_attr.h>
#include <fs_info.h> #include <fs_info.h>
#include <fs_interface.h> #include <fs_interface.h>
#include <fs_volume.h> #include <fs_volume.h>
@@ -1251,7 +1252,8 @@ static status_t
get_vnode(dev_t mountID, ino_t vnodeID, struct vnode** _vnode, bool canWait, get_vnode(dev_t mountID, ino_t vnodeID, struct vnode** _vnode, bool canWait,
int reenter) int reenter)
{ {
FUNCTION(("get_vnode: mountid %ld vnid 0x%Lx %p\n", mountID, vnodeID, _vnode)); FUNCTION(("get_vnode: mountid %ld vnid 0x%Lx %p\n", mountID, vnodeID,
_vnode));
mutex_lock(&sVnodeMutex); mutex_lock(&sVnodeMutex);
@@ -1263,7 +1265,8 @@ restart:
mutex_unlock(&sVnodeMutex); mutex_unlock(&sVnodeMutex);
if (!canWait || --tries < 0) { if (!canWait || --tries < 0) {
// vnode doesn't seem to become unbusy // vnode doesn't seem to become unbusy
dprintf("vnode %ld:%Ld is not becoming unbusy!\n", mountID, vnodeID); dprintf("vnode %ld:%Ld is not becoming unbusy!\n", mountID,
vnodeID);
return B_BUSY; return B_BUSY;
} }
snooze(10000); // 10 ms snooze(10000); // 10 ms
@@ -5155,7 +5158,8 @@ file_create(int fd, char* path, int openMode, int perms, bool kernel)
struct vnode* directory; struct vnode* directory;
int status; int status;
FUNCTION(("file_create: path '%s', omode %x, perms %d, kernel %d\n", path, openMode, perms, kernel)); FUNCTION(("file_create: path '%s', omode %x, perms %d, kernel %d\n", path,
openMode, perms, kernel));
// get directory to put the new file in // get directory to put the new file in
status = fd_and_path_to_dir_vnode(fd, path, &directory, name, kernel); status = fd_and_path_to_dir_vnode(fd, path, &directory, name, kernel);
@@ -6247,30 +6251,33 @@ attr_dir_rewind(struct file_descriptor* descriptor)
static int static int
attr_create(int fd, const char* name, uint32 type, int openMode, bool kernel) attr_create(int fd, char* path, const char* name, uint32 type,
int openMode, bool kernel)
{ {
struct vnode* vnode;
void* cookie;
int status;
if (name == NULL || *name == '\0') if (name == NULL || *name == '\0')
return B_BAD_VALUE; return B_BAD_VALUE;
vnode = get_vnode_from_fd(fd, kernel); struct vnode* vnode;
if (vnode == NULL) status_t status = fd_and_path_to_vnode(fd, path,
return B_FILE_ERROR; (openMode & O_NOTRAVERSE) != 0, &vnode, NULL, kernel);
if (status != B_OK)
return status;
if (!HAS_FS_CALL(vnode, create_attr)) { if (!HAS_FS_CALL(vnode, create_attr)) {
status = EROFS; status = EROFS;
goto err; goto err;
} }
void* cookie;
status = FS_CALL(vnode, create_attr, name, type, openMode, &cookie); status = FS_CALL(vnode, create_attr, name, type, openMode, &cookie);
if (status < B_OK) if (status != B_OK)
goto err; goto err;
if ((status = get_new_fd(FDTYPE_ATTR, NULL, vnode, cookie, openMode, kernel)) >= 0) fd = get_new_fd(FDTYPE_ATTR, NULL, vnode, cookie, openMode, kernel);
return status; if (fd >= 0)
return fd;
status = fd;
FS_CALL(vnode, close_attr, cookie); FS_CALL(vnode, close_attr, cookie);
FS_CALL(vnode, free_attr_cookie, cookie); FS_CALL(vnode, free_attr_cookie, cookie);
@@ -6285,31 +6292,33 @@ err:
static int static int
attr_open(int fd, const char* name, int openMode, bool kernel) attr_open(int fd, char* path, const char* name, int openMode, bool kernel)
{ {
struct vnode* vnode;
void* cookie;
int status;
if (name == NULL || *name == '\0') if (name == NULL || *name == '\0')
return B_BAD_VALUE; return B_BAD_VALUE;
vnode = get_vnode_from_fd(fd, kernel); struct vnode* vnode;
if (vnode == NULL) status_t status = fd_and_path_to_vnode(fd, path,
return B_FILE_ERROR; (openMode & O_NOTRAVERSE) != 0, &vnode, NULL, kernel);
if (status != B_OK)
return status;
if (!HAS_FS_CALL(vnode, open_attr)) { if (!HAS_FS_CALL(vnode, open_attr)) {
status = EOPNOTSUPP; status = EOPNOTSUPP;
goto err; goto err;
} }
void* cookie;
status = FS_CALL(vnode, open_attr, name, openMode, &cookie); status = FS_CALL(vnode, open_attr, name, openMode, &cookie);
if (status < B_OK) if (status != B_OK)
goto err; goto err;
// now we only need a file descriptor for this attribute and we're done // now we only need a file descriptor for this attribute and we're done
if ((status = get_new_fd(FDTYPE_ATTR, NULL, vnode, cookie, openMode, kernel)) >= 0) fd = get_new_fd(FDTYPE_ATTR, NULL, vnode, cookie, openMode, kernel);
return status; if (fd >= 0)
return fd;
status = fd;
FS_CALL(vnode, close_attr, cookie); FS_CALL(vnode, close_attr, cookie);
FS_CALL(vnode, free_attr_cookie, cookie); FS_CALL(vnode, free_attr_cookie, cookie);
@@ -8105,16 +8114,19 @@ _kern_open_attr_dir(int fd, const char* path)
int int
_kern_create_attr(int fd, const char* name, uint32 type, int openMode) _kern_open_attr(int fd, const char* path, const char* name, uint32 type,
int openMode)
{ {
return attr_create(fd, name, type, openMode, true); KPath pathBuffer(path, false, B_PATH_NAME_LENGTH + 1);
} if (pathBuffer.InitCheck() != B_OK)
return B_NO_MEMORY;
if ((openMode & O_CREAT) != 0) {
return attr_create(fd, pathBuffer.LockBuffer(), name, type, openMode,
true);
}
int return attr_open(fd, pathBuffer.LockBuffer(), name, openMode, true);
_kern_open_attr(int fd, const char* name, int openMode)
{
return attr_open(fd, name, openMode, true);
} }
@@ -9069,21 +9081,79 @@ _user_open_attr_dir(int fd, const char* userPath)
} }
int ssize_t
_user_create_attr(int fd, const char* userName, uint32 type, int openMode) _user_read_attr(int fd, const char* attribute, off_t pos, void* userBuffer,
size_t readBytes)
{ {
char name[B_FILE_NAME_LENGTH]; int attr = attr_open(fd, NULL, attribute, O_RDONLY, false);
if (attr < 0)
return attr;
if (!IS_USER_ADDRESS(userName) ssize_t bytes = _user_read(attr, pos, userBuffer, readBytes);
|| user_strlcpy(name, userName, B_FILE_NAME_LENGTH) < B_OK) _user_close(attr);
return B_BAD_ADDRESS;
return attr_create(fd, name, type, openMode, false); return bytes;
}
ssize_t
_user_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
const void* buffer, size_t writeBytes)
{
// Try to support the BeOS typical truncation as well as the position
// argument
int attr = attr_create(fd, NULL, attribute, type,
O_CREAT | O_WRONLY | (pos != 0 ? 0 : O_TRUNC), false);
if (attr < 0)
return attr;
ssize_t bytes = _user_write(attr, pos, buffer, writeBytes);
_user_close(attr);
return bytes;
}
status_t
_user_stat_attr(int fd, const char* attribute, struct attr_info* userAttrInfo)
{
int attr = attr_open(fd, NULL, attribute, O_RDONLY, false);
if (attr < 0)
return attr;
struct file_descriptor* descriptor
= get_fd(get_current_io_context(false), attr);
if (descriptor == NULL) {
_user_close(attr);
return B_FILE_ERROR;
}
struct stat stat;
status_t status;
if (descriptor->ops->fd_read_stat)
status = descriptor->ops->fd_read_stat(descriptor, &stat);
else
status = EOPNOTSUPP;
put_fd(descriptor);
_user_close(attr);
if (status == B_OK) {
attr_info info;
info.type = stat.st_type;
info.size = stat.st_size;
if (user_memcpy(userAttrInfo, &info, sizeof(struct attr_info)) != B_OK)
return B_BAD_ADDRESS;
}
return status;
} }
int int
_user_open_attr(int fd, const char* userName, int openMode) _user_open_attr(int fd, const char* userPath, const char* userName,
uint32 type, int openMode)
{ {
char name[B_FILE_NAME_LENGTH]; char name[B_FILE_NAME_LENGTH];
@@ -9091,7 +9161,24 @@ _user_open_attr(int fd, const char* userName, int openMode)
|| user_strlcpy(name, userName, B_FILE_NAME_LENGTH) < B_OK) || user_strlcpy(name, userName, B_FILE_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
return attr_open(fd, name, openMode, false); KPath pathBuffer(B_PATH_NAME_LENGTH + 1);
if (pathBuffer.InitCheck() != B_OK)
return B_NO_MEMORY;
char* path = pathBuffer.LockBuffer();
if (userPath != NULL) {
if (!IS_USER_ADDRESS(userPath)
|| user_strlcpy(path, userPath, B_PATH_NAME_LENGTH) < B_OK)
return B_BAD_ADDRESS;
}
if ((openMode & O_CREAT) != 0) {
return attr_create(fd, userPath ? path : NULL, name, type, openMode,
false);
}
return attr_open(fd, userPath ? path : NULL, name, openMode, false);
} }
+16 -48
View File
@@ -59,13 +59,7 @@ extern "C" ssize_t
fs_read_attr(int fd, const char* attribute, uint32 /*type*/, off_t pos, fs_read_attr(int fd, const char* attribute, uint32 /*type*/, off_t pos,
void* buffer, size_t readBytes) void* buffer, size_t readBytes)
{ {
int attr = _kern_open_attr(fd, attribute, O_RDONLY); ssize_t bytes = _kern_read_attr(fd, attribute, pos, buffer, readBytes);
if (attr < 0)
RETURN_AND_SET_ERRNO(attr);
ssize_t bytes = _kern_read(attr, pos, buffer, readBytes);
_kern_close(attr);
RETURN_AND_SET_ERRNO(bytes); RETURN_AND_SET_ERRNO(bytes);
} }
@@ -74,14 +68,15 @@ extern "C" ssize_t
fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos, fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
const void* buffer, size_t writeBytes) const void* buffer, size_t writeBytes)
{ {
// TODO: move this documentation into the Haiku book!
// NOTE: This call is deprecated in Haiku and has a number of problems: // NOTE: This call is deprecated in Haiku and has a number of problems:
// On BeOS, it was documented that the "pos" argument is ignored. // On BeOS, it was documented that the "pos" argument is ignored, however,
// However, a number of programs tried to use this call to write large // that did not actually happen if the attribute was backed up by a real
// attributes in a loop anyways. These programs all relied on the broken // file.
// or at least inconsistent behaviour to truncate/clobber an existing // Also, it will truncate any existing attribute, disregarding the specified
// attribute. In other words, writing 5 bytes at position 0 into an // position.
// attribute that was already 10 bytes long resulted in an attribute of
// only 5 bytes length.
// The implementation of this function tries to stay compatible with // The implementation of this function tries to stay compatible with
// BeOS in that it clobbers the existing attribute when you write at offset // BeOS in that it clobbers the existing attribute when you write at offset
// 0, but it also tries to support programs which continue to write more // 0, but it also tries to support programs which continue to write more
@@ -91,14 +86,8 @@ fs_write_attr(int fd, const char* attribute, uint32 type, off_t pos,
// see from this implementation, it saves 2 syscalls per writing a chunk // see from this implementation, it saves 2 syscalls per writing a chunk
// of data. // of data.
int attr = _kern_create_attr(fd, attribute, type, ssize_t bytes = _kern_write_attr(fd, attribute, type, pos, buffer,
O_WRONLY | (pos != 0 ? 0 : O_TRUNC)); writeBytes);
if (attr < 0)
RETURN_AND_SET_ERRNO(attr);
ssize_t bytes = _kern_write(attr, pos, buffer, writeBytes);
_kern_close(attr);
RETURN_AND_SET_ERRNO(bytes); RETURN_AND_SET_ERRNO(bytes);
} }
@@ -115,44 +104,23 @@ fs_remove_attr(int fd, const char* attribute)
extern "C" int extern "C" int
fs_stat_attr(int fd, const char* attribute, struct attr_info* attrInfo) fs_stat_attr(int fd, const char* attribute, struct attr_info* attrInfo)
{ {
int attr = _kern_open_attr(fd, attribute, O_RDONLY); status_t status = _kern_stat_attr(fd, attribute, attrInfo);
if (attr < 0)
RETURN_AND_SET_ERRNO(attr);
struct stat stat;
status_t status = _kern_read_stat(attr, NULL, false, &stat,
sizeof(struct stat));
if (status == B_OK) {
attrInfo->type = stat.st_type;
attrInfo->size = stat.st_size;
}
_kern_close(attr);
RETURN_AND_SET_ERRNO(status); RETURN_AND_SET_ERRNO(status);
} }
/*
int int
fs_open_attr(const char *path, const char *attribute, uint32 type, int openMode) fs_open_attr(const char *path, const char *attribute, uint32 type, int openMode)
{ {
// TODO: implement fs_open_attr() - or remove it completely status_t status = _kern_open_attr(-1, path, attribute, type, openMode);
// if it will be implemented, rename the current fs_open_attr() to fs_fopen_attr() RETURN_AND_SET_ERRNO(status);
return B_ERROR;
} }
*/
extern "C" int extern "C" int
fs_open_attr(int fd, const char* attribute, uint32 type, int openMode) fs_fopen_attr(int fd, const char* attribute, uint32 type, int openMode)
{ {
status_t status; status_t status = _kern_open_attr(fd, NULL, attribute, type, openMode);
if ((openMode & O_CREAT) != 0)
status = _kern_create_attr(fd, attribute, type, openMode);
else
status = _kern_open_attr(fd, attribute, openMode);
RETURN_AND_SET_ERRNO(status); RETURN_AND_SET_ERRNO(status);
} }