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:
Axel Dörfler 2004-05-10 14:33:17 +00:00
parent 5ac1540121
commit c396c39fc5
3 changed files with 110 additions and 34 deletions

View File

@ -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);

View File

@ -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);
}

View File

@ -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);