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 status_t
user_read_stat(int fd, struct stat *userStat) _user_read_stat(int fd, struct stat *userStat, size_t statSize)
{ {
struct file_descriptor *descriptor; struct file_descriptor *descriptor;
status_t status; 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 */ /* This is a user_function, so abort if we have a kernel address */
CHECK_USER_ADDR(userStat) CHECK_USER_ADDR(userStat)
@ -461,7 +464,7 @@ user_read_stat(int fd, struct stat *userStat)
if (descriptor == NULL) if (descriptor == NULL)
return B_FILE_ERROR; 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) { if (descriptor->ops->fd_read_stat) {
// we're using the stat buffer on the stack to not have to // 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); status = descriptor->ops->fd_read_stat(descriptor, &stat);
if (status >= 0) if (status >= 0)
status = user_memcpy(userStat, &stat, sizeof(stat)); status = user_memcpy(userStat, &stat, statSize);
} else } else
status = EOPNOTSUPP; status = EOPNOTSUPP;
@ -479,25 +482,31 @@ user_read_stat(int fd, struct stat *userStat)
} }
int status_t
user_write_stat(int fd, const struct stat *userStat, int statMask) _user_write_stat(int fd, const struct stat *userStat, size_t statSize, int statMask)
{ {
struct file_descriptor *descriptor; struct file_descriptor *descriptor;
status_t status; status_t status;
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
CHECK_USER_ADDR(userStat) CHECK_USER_ADDR(userStat)
descriptor = get_fd(get_current_io_context(false), fd); descriptor = get_fd(get_current_io_context(false), fd);
if (descriptor == NULL) if (descriptor == NULL)
return B_FILE_ERROR; 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) { if (descriptor->ops->fd_write_stat) {
// we're using the stat buffer on the stack to not have to // we're using the stat buffer on the stack to not have to
// lock the given stat buffer in memory // lock the given stat buffer in memory
struct stat stat; 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) if (status == B_OK)
status = descriptor->ops->fd_write_stat(descriptor, &stat, statMask); status = descriptor->ops->fd_write_stat(descriptor, &stat, statMask);
} else } else
@ -678,21 +687,35 @@ sys_rewind_dir(int fd)
} }
int status_t
sys_read_stat(int fd, struct stat *stat) _kern_read_stat(int fd, struct stat *stat, size_t statSize)
{ {
struct file_descriptor *descriptor; struct file_descriptor *descriptor;
status_t status; status_t status;
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
descriptor = get_fd(get_current_io_context(true), fd); descriptor = get_fd(get_current_io_context(true), fd);
if (descriptor == NULL) if (descriptor == NULL)
return B_FILE_ERROR; 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); status = descriptor->ops->fd_read_stat(descriptor, stat);
else
if (originalStat != NULL)
memcpy(originalStat, stat, statSize);
} else
status = EOPNOTSUPP; status = EOPNOTSUPP;
put_fd(descriptor); put_fd(descriptor);
@ -700,21 +723,32 @@ sys_read_stat(int fd, struct stat *stat)
} }
int status_t
sys_write_stat(int fd, const struct stat *stat, int statMask) _kern_write_stat(int fd, const struct stat *stat, size_t statSize, int statMask)
{ {
struct file_descriptor *descriptor; struct file_descriptor *descriptor;
status_t status; status_t status;
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
descriptor = get_fd(get_current_io_context(true), fd); descriptor = get_fd(get_current_io_context(true), fd);
if (descriptor == NULL) if (descriptor == NULL)
return B_FILE_ERROR; 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); status = descriptor->ops->fd_write_stat(descriptor, stat, statMask);
else } else
status = EOPNOTSUPP; status = EOPNOTSUPP;
put_fd(descriptor); put_fd(descriptor);

View File

@ -3731,22 +3731,52 @@ sys_access(const char *path, int mode)
} }
int status_t
sys_read_path_stat(const char *path, bool traverseLeafLink, struct stat *stat) _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]; 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); 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 status_t
sys_write_path_stat(const char *path, bool traverseLeafLink, const struct stat *stat, int statMask) _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]; char pathBuffer[SYS_MAX_PATH_LEN + 1];
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
strlcpy(pathBuffer, path, SYS_MAX_PATH_LEN - 1); 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); return common_path_write_stat(pathBuffer, traverseLeafLink, stat, statMask, true);
} }
@ -4281,38 +4311,50 @@ user_access(const char *userPath, int mode)
} }
int status_t
user_read_path_stat(const char *userPath, bool traverseLink, struct stat *userStat) _user_read_path_stat(const char *userPath, bool traverseLink, struct stat *userStat,
size_t statSize)
{ {
char path[SYS_MAX_PATH_LEN + 1]; char path[SYS_MAX_PATH_LEN + 1];
struct stat stat; struct stat stat;
int status; int status;
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userPath) if (!IS_USER_ADDRESS(userPath)
|| !IS_USER_ADDRESS(userStat) || !IS_USER_ADDRESS(userStat)
|| user_strlcpy(path, userPath, SYS_MAX_PATH_LEN) < B_OK) || user_strlcpy(path, userPath, SYS_MAX_PATH_LEN) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status = common_path_read_stat(path, traverseLink, &stat, false); status = common_path_read_stat(path, traverseLink, &stat, false);
if (status < 0) if (status < B_OK)
return status; return status;
return user_memcpy(userStat, &stat, sizeof(struct stat)); return user_memcpy(userStat, &stat, statSize);
} }
int status_t
user_write_path_stat(const char *userPath, bool traverseLeafLink, const struct stat *userStat, int statMask) _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]; char path[SYS_MAX_PATH_LEN + 1];
struct stat stat; struct stat stat;
if (statSize > sizeof(struct stat))
return B_BAD_VALUE;
if (!IS_USER_ADDRESS(userStat) if (!IS_USER_ADDRESS(userStat)
|| !IS_USER_ADDRESS(userPath) || !IS_USER_ADDRESS(userPath)
|| user_strlcpy(path, userPath, SYS_MAX_PATH_LEN) < B_OK || 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; 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); 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); *call_ret = user_rename((const char *)arg0, (const char *)arg1);
break; break;
case SYSCALL_READ_PATH_STAT: 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; break;
case SYSCALL_WRITE_PATH_STAT: 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; break;
case SYSCALL_READ_STAT: 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; break;
case SYSCALL_WRITE_STAT: 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; break;
case SYSCALL_ACCESS: case SYSCALL_ACCESS:
*call_ret = user_access((const char *)arg0, (int)arg1); *call_ret = user_access((const char *)arg0, (int)arg1);