Changed the "stat" related syscalls to have an additional parameter that specified
the size of the stat structure to allow extensions of that structure. Renamed those syscalls to the new naming scheme. Updated the syscalls to support stat extensions. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7494 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
5ac1540121
commit
c396c39fc5
@ -448,12 +448,15 @@ user_rewind_dir(int fd)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_read_stat(int fd, struct stat *userStat)
|
||||
status_t
|
||||
_user_read_stat(int fd, struct stat *userStat, size_t statSize)
|
||||
{
|
||||
struct file_descriptor *descriptor;
|
||||
status_t status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
/* This is a user_function, so abort if we have a kernel address */
|
||||
CHECK_USER_ADDR(userStat)
|
||||
|
||||
@ -461,7 +464,7 @@ user_read_stat(int fd, struct stat *userStat)
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
TRACE(("user_read_stat(descriptor = %p)\n", descriptor));
|
||||
TRACE(("_user_read_stat(descriptor = %p)\n", descriptor));
|
||||
|
||||
if (descriptor->ops->fd_read_stat) {
|
||||
// we're using the stat buffer on the stack to not have to
|
||||
@ -470,7 +473,7 @@ user_read_stat(int fd, struct stat *userStat)
|
||||
|
||||
status = descriptor->ops->fd_read_stat(descriptor, &stat);
|
||||
if (status >= 0)
|
||||
status = user_memcpy(userStat, &stat, sizeof(stat));
|
||||
status = user_memcpy(userStat, &stat, statSize);
|
||||
} else
|
||||
status = EOPNOTSUPP;
|
||||
|
||||
@ -479,25 +482,31 @@ user_read_stat(int fd, struct stat *userStat)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_write_stat(int fd, const struct stat *userStat, int statMask)
|
||||
status_t
|
||||
_user_write_stat(int fd, const struct stat *userStat, size_t statSize, int statMask)
|
||||
{
|
||||
struct file_descriptor *descriptor;
|
||||
status_t status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
CHECK_USER_ADDR(userStat)
|
||||
|
||||
descriptor = get_fd(get_current_io_context(false), fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
TRACE(("user_write_stat(descriptor = %p)\n", descriptor));
|
||||
TRACE(("_user_write_stat(descriptor = %p)\n", descriptor));
|
||||
|
||||
if (descriptor->ops->fd_write_stat) {
|
||||
// we're using the stat buffer on the stack to not have to
|
||||
// lock the given stat buffer in memory
|
||||
struct stat stat;
|
||||
status = user_memcpy(&stat, userStat, sizeof(stat));
|
||||
if (sizeof(struct stat) != statSize)
|
||||
memset((uint8 *)&stat + statSize, 0, sizeof(struct stat) - statSize);
|
||||
|
||||
status = user_memcpy(&stat, userStat, statSize);
|
||||
if (status == B_OK)
|
||||
status = descriptor->ops->fd_write_stat(descriptor, &stat, statMask);
|
||||
} else
|
||||
@ -678,21 +687,35 @@ sys_rewind_dir(int fd)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_read_stat(int fd, struct stat *stat)
|
||||
status_t
|
||||
_kern_read_stat(int fd, struct stat *stat, size_t statSize)
|
||||
{
|
||||
struct file_descriptor *descriptor;
|
||||
status_t status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
descriptor = get_fd(get_current_io_context(true), fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
TRACE(("sys_read_stat(descriptor = %p)\n", descriptor));
|
||||
TRACE(("_kern_read_stat(descriptor = %p)\n", descriptor));
|
||||
|
||||
if (descriptor->ops->fd_read_stat)
|
||||
if (descriptor->ops->fd_read_stat) {
|
||||
// this supports different stat extensions
|
||||
struct stat completeStat;
|
||||
struct stat *originalStat = NULL;
|
||||
|
||||
if (statSize < sizeof(struct stat)) {
|
||||
originalStat = stat;
|
||||
stat = &completeStat;
|
||||
}
|
||||
status = descriptor->ops->fd_read_stat(descriptor, stat);
|
||||
else
|
||||
|
||||
if (originalStat != NULL)
|
||||
memcpy(originalStat, stat, statSize);
|
||||
} else
|
||||
status = EOPNOTSUPP;
|
||||
|
||||
put_fd(descriptor);
|
||||
@ -700,21 +723,32 @@ sys_read_stat(int fd, struct stat *stat)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_write_stat(int fd, const struct stat *stat, int statMask)
|
||||
status_t
|
||||
_kern_write_stat(int fd, const struct stat *stat, size_t statSize, int statMask)
|
||||
{
|
||||
struct file_descriptor *descriptor;
|
||||
status_t status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
descriptor = get_fd(get_current_io_context(true), fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
TRACE(("sys_write_stat(descriptor = %p)\n", descriptor));
|
||||
TRACE(("_kern_write_stat(descriptor = %p)\n", descriptor));
|
||||
|
||||
if (descriptor->ops->fd_write_stat)
|
||||
if (descriptor->ops->fd_write_stat) {
|
||||
// this supports different stat extensions
|
||||
struct stat completeStat;
|
||||
|
||||
if (statSize < sizeof(struct stat)) {
|
||||
memset((uint8 *)&completeStat + statSize, 0, sizeof(struct stat) - statSize);
|
||||
memcpy(&completeStat, stat, statSize);
|
||||
stat = &completeStat;
|
||||
}
|
||||
status = descriptor->ops->fd_write_stat(descriptor, stat, statMask);
|
||||
else
|
||||
} else
|
||||
status = EOPNOTSUPP;
|
||||
|
||||
put_fd(descriptor);
|
||||
|
@ -3731,22 +3731,52 @@ sys_access(const char *path, int mode)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_read_path_stat(const char *path, bool traverseLeafLink, struct stat *stat)
|
||||
status_t
|
||||
_kern_read_path_stat(const char *path, bool traverseLeafLink, struct stat *stat, size_t statSize)
|
||||
{
|
||||
struct stat completeStat;
|
||||
struct stat *originalStat = NULL;
|
||||
char pathBuffer[SYS_MAX_PATH_LEN + 1];
|
||||
status_t status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1);
|
||||
|
||||
return common_path_read_stat(pathBuffer, traverseLeafLink, stat, true);
|
||||
// this supports different stat extensions
|
||||
if (statSize < sizeof(struct stat)) {
|
||||
originalStat = stat;
|
||||
stat = &completeStat;
|
||||
}
|
||||
|
||||
status = common_path_read_stat(pathBuffer, traverseLeafLink, stat, true);
|
||||
if (status == B_OK && originalStat != NULL)
|
||||
memcpy(originalStat, stat, statSize);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_write_path_stat(const char *path, bool traverseLeafLink, const struct stat *stat, int statMask)
|
||||
status_t
|
||||
_kern_write_path_stat(const char *path, bool traverseLeafLink, const struct stat *stat, size_t statSize, int statMask)
|
||||
{
|
||||
struct stat completeStat;
|
||||
char pathBuffer[SYS_MAX_PATH_LEN + 1];
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1);
|
||||
|
||||
// this supports different stat extensions
|
||||
|
||||
if (statSize < sizeof(struct stat)) {
|
||||
memset((uint8 *)&completeStat + statSize, 0, sizeof(struct stat) - statSize);
|
||||
memcpy(&completeStat, stat, statSize);
|
||||
stat = &completeStat;
|
||||
}
|
||||
|
||||
return common_path_write_stat(pathBuffer, traverseLeafLink, stat, statMask, true);
|
||||
}
|
||||
|
||||
@ -4281,38 +4311,50 @@ user_access(const char *userPath, int mode)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_read_path_stat(const char *userPath, bool traverseLink, struct stat *userStat)
|
||||
status_t
|
||||
_user_read_path_stat(const char *userPath, bool traverseLink, struct stat *userStat,
|
||||
size_t statSize)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
struct stat stat;
|
||||
int status;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!IS_USER_ADDRESS(userPath)
|
||||
|| !IS_USER_ADDRESS(userStat)
|
||||
|| user_strlcpy(path, userPath, SYS_MAX_PATH_LEN) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = common_path_read_stat(path, traverseLink, &stat, false);
|
||||
if (status < 0)
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return user_memcpy(userStat, &stat, sizeof(struct stat));
|
||||
return user_memcpy(userStat, &stat, statSize);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_write_path_stat(const char *userPath, bool traverseLeafLink, const struct stat *userStat, int statMask)
|
||||
status_t
|
||||
_user_write_path_stat(const char *userPath, bool traverseLeafLink, const struct stat *userStat,
|
||||
size_t statSize, int statMask)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
struct stat stat;
|
||||
|
||||
if (statSize > sizeof(struct stat))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (!IS_USER_ADDRESS(userStat)
|
||||
|| !IS_USER_ADDRESS(userPath)
|
||||
|| user_strlcpy(path, userPath, SYS_MAX_PATH_LEN) < B_OK
|
||||
|| user_memcpy(&stat, userStat, sizeof(struct stat)) < B_OK)
|
||||
|| user_memcpy(&stat, userStat, statSize) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
// clear additional stat fields
|
||||
if (statSize < sizeof(struct stat))
|
||||
memset((uint8 *)&stat + statSize, 0, sizeof(struct stat) - statSize);
|
||||
|
||||
return common_path_write_stat(path, traverseLeafLink, &stat, statMask, false);
|
||||
}
|
||||
|
||||
|
@ -140,16 +140,16 @@ syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret)
|
||||
*call_ret = user_rename((const char *)arg0, (const char *)arg1);
|
||||
break;
|
||||
case SYSCALL_READ_PATH_STAT:
|
||||
*call_ret = user_read_path_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2);
|
||||
*call_ret = _user_read_path_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2, (size_t)arg3);
|
||||
break;
|
||||
case SYSCALL_WRITE_PATH_STAT:
|
||||
*call_ret = user_write_path_stat((const char *)arg0, (bool)arg1, (const struct stat *)arg2, (int)arg3);
|
||||
*call_ret = _user_write_path_stat((const char *)arg0, (bool)arg1, (const struct stat *)arg2, (size_t)arg3, (int)arg4);
|
||||
break;
|
||||
case SYSCALL_READ_STAT:
|
||||
*call_ret = user_read_stat((int)arg0, (struct stat*)arg1);
|
||||
*call_ret = _user_read_stat((int)arg0, (struct stat *)arg1, (size_t)arg2);
|
||||
break;
|
||||
case SYSCALL_WRITE_STAT:
|
||||
*call_ret = user_write_stat((int)arg0, (const struct stat *)arg1, (int)arg2);
|
||||
*call_ret = _user_write_stat((int)arg0, (const struct stat *)arg1, (size_t)arg2, (int)arg3);
|
||||
break;
|
||||
case SYSCALL_ACCESS:
|
||||
*call_ret = user_access((const char *)arg0, (int)arg1);
|
||||
|
Loading…
Reference in New Issue
Block a user