Big commit: Added symlink support to the kernel.
- added needed syscalls to access symlink support from userland - implemented lstat(), symlink(), and readlink() - added dev_t to ktypes.h (for now - should be in a public header anyway) - added symlink support to the "ls" command (now calls lstat() and shows the link target with the -l option) - changed the sys_read_stat() call to support symlinks, and updated files using that function (it gets an extra argument: bool traverseLink) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
409a1aeacd
commit
ae372703ce
@ -37,8 +37,6 @@ off_t sys_seek(int fd, off_t pos, int seek_type);
|
||||
int sys_ioctl(int fd, ulong op, void *buf, size_t length);
|
||||
int sys_unlink(const char *path);
|
||||
int sys_rename(const char *oldpath, const char *newpath);
|
||||
int sys_rstat(const char *path, struct stat *stat);
|
||||
int sys_wstat(const char *path, struct stat *stat, int stat_mask);
|
||||
int sys_fstat(int, struct stat *);
|
||||
char *sys_getcwd(char* buf, size_t size);
|
||||
int sys_setcwd(const char* path);
|
||||
|
@ -10,7 +10,7 @@
|
||||
// This file should reside in headers/posix, not here...
|
||||
// needs ino_t (int64), and dev_t (long)
|
||||
#include <ktypes.h>
|
||||
typedef long dev_t;
|
||||
|
||||
|
||||
typedef struct dirent {
|
||||
dev_t d_dev;
|
||||
|
@ -1,246 +1,102 @@
|
||||
/*-
|
||||
* Copyright (c) 1982, 1986, 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* (c) UNIX System Laboratories, Inc.
|
||||
* All or some portions of this file are derived from material licensed
|
||||
* to the University of California by American Telephone and Telegraph
|
||||
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
|
||||
* the permission of UNIX System Laboratories, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)stat.h 8.9 (Berkeley) 8/17/94
|
||||
*/
|
||||
|
||||
#ifndef _SYS_STAT_H_
|
||||
#define _SYS_STAT_H_
|
||||
#define _SYS_STAT_H_
|
||||
|
||||
//#include <sys/time.h>
|
||||
#include <OS.h>
|
||||
//#include <sys/types.h>
|
||||
#include <ktypes.h>
|
||||
|
||||
/**
|
||||
* @file stat.h
|
||||
* @brief Stat structures and defines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup OpenBeOS_POSIX POSIX Headers
|
||||
* @brief Headers to provide the POSIX layer
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup Stat sys/stat.h
|
||||
* @brief Structures and prototypes for stat operations
|
||||
* @ingroup OpenBeOS_POSIX
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* XXX - some types we don't yet have in sys/types.h (because we don't yet
|
||||
* have a sys/types.h and these aren't in ktypes.h!)
|
||||
/*
|
||||
* stat structure
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
struct ostat {
|
||||
mode_t st_mode; /* inode protection mode */
|
||||
ino_t st_ino; /* inode's number */
|
||||
uint16 st_dev; /* inode's device */
|
||||
nlink_t st_nlink; /* number of hard links */
|
||||
uid_t st_uid; /* user ID of the file's owner */
|
||||
gid_t st_gid; /* group ID of the file's group */
|
||||
off_t st_size; /* file size, in bytes */
|
||||
time_t st_atime; /* time of last access */
|
||||
time_t st_mtime; /* time of last data modification */
|
||||
time_t st_ctime; /* time of last file status change */
|
||||
int64 st_blocks; /* blocks allocated for file */
|
||||
int32 st_blksize; /* optimal blocksize for I/O */
|
||||
};
|
||||
#endif /* _KERNEL_MODE */
|
||||
|
||||
/* XXX - The stat structure, as defined by POSIX.
|
||||
* Just implement what we can for the time being.
|
||||
*/
|
||||
struct stat {
|
||||
mode_t st_mode; /* File mode */
|
||||
ino_t st_ino; /* vnode_id */
|
||||
// dev_t st_dev; /* inode's device */
|
||||
nlink_t st_nlink; /* number of hard links */
|
||||
uid_t st_uid; /* user ID of the file's owner */
|
||||
gid_t st_gid; /* group ID of the file's group */
|
||||
off_t st_size; /* file size, in bytes */
|
||||
time_t st_atime; /* time of last access */
|
||||
time_t st_mtime; /* time of last data modification */
|
||||
time_t st_ctime; /* time of last file status change */
|
||||
int64 st_blocks; /* blocks allocated for file */
|
||||
uint32 st_blksize; /* optimal blocksize for I/O */
|
||||
dev_t st_dev; /* "device" that this file resides on */
|
||||
ino_t st_ino; /* this file's inode #, unique per device */
|
||||
mode_t st_mode; /* mode bits (rwx for user, group, etc) */
|
||||
nlink_t st_nlink; /* number of hard links to this file */
|
||||
uid_t st_uid; /* user id of the owner of this file */
|
||||
gid_t st_gid; /* group id of the owner of this file */
|
||||
off_t st_size; /* size in bytes of this file */
|
||||
dev_t st_rdev; /* device type (not used) */
|
||||
size_t st_blksize; /* preferred block size for i/o */
|
||||
time_t st_atime; /* last access time */
|
||||
time_t st_mtime; /* last modification time */
|
||||
time_t st_ctime; /* last change time, not creation time */
|
||||
time_t st_crtime; /* creation time */
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup POSIX_filemodes File mode defines
|
||||
* @brief Defines of the file modes we allow
|
||||
* @ingroup Stat
|
||||
*@{
|
||||
*/
|
||||
/** @def S_ISUID set user id on execution */
|
||||
/** @def S_ISGID set group id on execution */
|
||||
/** @def S_ISTXT sticky bit */
|
||||
#define S_ISUID 0004000
|
||||
#define S_ISGID 0002000
|
||||
#define S_ISTXT 0001000
|
||||
/* extended file types */
|
||||
#define S_ATTR_DIR 01000000000 /* attribute directory */
|
||||
#define S_ATTR 02000000000 /* attribute */
|
||||
#define S_INDEX_DIR 04000000000 /* index (or index directory) */
|
||||
#define S_STR_INDEX 00100000000 /* string index */
|
||||
#define S_INT_INDEX 00200000000 /* int32 index */
|
||||
#define S_UINT_INDEX 00400000000 /* uint32 index */
|
||||
#define S_LONG_LONG_INDEX 00010000000 /* int64 index */
|
||||
#define S_ULONG_LONG_INDEX 00020000000 /* uint64 index */
|
||||
#define S_FLOAT_INDEX 00040000000 /* float index */
|
||||
#define S_DOUBLE_INDEX 00001000000 /* double index */
|
||||
#define S_ALLOW_DUPS 00002000000 /* allow duplicate entries (currently unused) */
|
||||
|
||||
/** @def S_IRWXU RWX mask for owner */
|
||||
/** @def S_IRUSR R for owner */
|
||||
/** @def S_IWUSR W for owner */
|
||||
/** @def S_IXUSR X for owner */
|
||||
#define S_IRWXU 0000700
|
||||
#define S_IRUSR 0000400
|
||||
#define S_IWUSR 0000200
|
||||
#define S_IXUSR 0000100
|
||||
/* standard file types */
|
||||
#define S_IFMT 00000170000 /* type of file */
|
||||
#define S_IFLNK 00000120000 /* symbolic link */
|
||||
#define S_IFREG 00000100000 /* regular */
|
||||
#define S_IFBLK 00000060000 /* block special */
|
||||
#define S_IFDIR 00000040000 /* directory */
|
||||
#define S_IFCHR 00000020000 /* character special */
|
||||
#define S_IFIFO 00000010000 /* fifo */
|
||||
|
||||
/** @def S_IRWXG RWX mask for group */
|
||||
/** @def S_IWGRP W for group */
|
||||
/** @def S_IRGRP R for group */
|
||||
/** @def S_IXGRP X for group */
|
||||
#define S_IRWXG 0000070
|
||||
#define S_IRGRP 0000040
|
||||
#define S_IWGRP 0000020
|
||||
#define S_IXGRP 0000010
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
|
||||
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
|
||||
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
|
||||
#define S_ISINDEX(m) (((m) & S_INDEX_DIR) == S_INDEX_DIR)
|
||||
|
||||
/** @def S_IXOTH RWX mask for other */
|
||||
/** @def S_IROTH R for other */
|
||||
/** @def S_IWOTH W for other */
|
||||
/** @def S_IXOTH X for other */
|
||||
#define S_IRWXO 0000007
|
||||
#define S_IROTH 0000004
|
||||
#define S_IWOTH 0000002
|
||||
#define S_IXOTH 0000001
|
||||
#define S_IUMSK 07777 /* user settable bits */
|
||||
|
||||
#define S_IFMT 0170000
|
||||
#define S_IFSOCK 0140000
|
||||
#define S_IFIFO 0010000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFBLK 0060000
|
||||
#define S_IFREG 0100000
|
||||
#define S_IFLNK 0120000
|
||||
#define S_IFWHT 0160000
|
||||
#define S_ISVTX 0001000
|
||||
#define S_ISUID 04000 /* set user id on execution */
|
||||
#define S_ISGID 02000 /* set group id on execution */
|
||||
|
||||
/**
|
||||
* @defgroup stat_tests Stat Macro's
|
||||
* @ingroup POSIX_filemodes
|
||||
* @brief macro's that should be used to test for the type of device
|
||||
* @{
|
||||
*/
|
||||
/** @def S_ISDIR(m) it's a directory */
|
||||
/** @def S_ISREG(m) it's a regular file */
|
||||
/** @def S_ISCHR(m) it's a character device */
|
||||
/** @def S_ISBLK(m) it's a block device */
|
||||
/** @def S_ISFIFO(m) it's a fifo device */
|
||||
/** @def S_ISLNK(m) it's a symbolic link */
|
||||
/** @def S_ISSOCK(m) it's a socket */
|
||||
/** @def S_ISWHT(m) whiteout? */
|
||||
#define S_ISDIR(m) ((m & 0170000) == 0040000)
|
||||
#define S_ISREG(m) ((m & 0170000) == 0100000)
|
||||
#define S_ISCHR(m) ((m & 0170000) == 0020000)
|
||||
#define S_ISBLK(m) ((m & 0170000) == 0060000)
|
||||
#define S_ISFIFO(m) ((m & 0170000) == 0010000)
|
||||
#define S_ISLNK(m) ((m & 0170000) == 0120000)
|
||||
#define S_ISSOCK(m) ((m & 0170000) == 0140000)
|
||||
#define S_ISWHT(m) ((m & 0170000) == 0160000)
|
||||
/** @} */
|
||||
#define S_ISVTX 01000 /* save swapped text even after use */
|
||||
|
||||
#define S_IRWXU 00700 /* read, write, execute: owner */
|
||||
#define S_IRUSR 00400 /* read permission: owner */
|
||||
#define S_IWUSR 00200 /* write permission: owner */
|
||||
#define S_IXUSR 00100 /* execute permission: owner */
|
||||
#define S_IRWXG 00070 /* read, write, execute: group */
|
||||
#define S_IRGRP 00040 /* read permission: group */
|
||||
#define S_IWGRP 00020 /* write permission: group */
|
||||
#define S_IXGRP 00010 /* execute permission: group */
|
||||
#define S_IRWXO 00007 /* read, write, execute: other */
|
||||
#define S_IROTH 00004 /* read permission: other */
|
||||
#define S_IWOTH 00002 /* write permission: other */
|
||||
#define S_IXOTH 00001 /* execute permission: other */
|
||||
|
||||
/** @def ACCESSPERMS 00777 */
|
||||
/** @def ALLPERMS 07777 */
|
||||
/** @def DEFFILEMODE 00666 default file mode, everyone can read/write*/
|
||||
#define ACCESSPERMS (S_IRWXU | S_IRWXG | S_IRWXO)
|
||||
/** @def ALLPERMS 07777 */
|
||||
#define ALLPERMS (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO)
|
||||
/** @def DEFFILEMODE 00666 default file mode, everyone can read/write*/
|
||||
#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
|
||||
|
||||
/** @} */
|
||||
|
||||
/*
|
||||
* Definitions of flags stored in file flags word.
|
||||
*
|
||||
* Super-user and owner changeable flags.
|
||||
*/
|
||||
#define UF_SETTABLE 0x0000ffff /* mask of owner changeable flags */
|
||||
#define UF_NODUMP 0x00000001 /* do not dump file */
|
||||
#define UF_IMMUTABLE 0x00000002 /* file may not be changed */
|
||||
#define UF_APPEND 0x00000004 /* writes to file may only append */
|
||||
#define UF_OPAQUE 0x00000008 /* directory is opaque wrt. union */
|
||||
/*
|
||||
* Super-user changeable flags.
|
||||
*/
|
||||
#define SF_SETTABLE 0xffff0000 /* mask of superuser changeable flags */
|
||||
#define SF_ARCHIVED 0x00010000 /* file is archived */
|
||||
#define SF_IMMUTABLE 0x00020000 /* file may not be changed */
|
||||
#define SF_APPEND 0x00040000 /* writes to file may only append */
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
/*
|
||||
* Shorthand abbreviations of above.
|
||||
*/
|
||||
#define OPAQUE (UF_OPAQUE)
|
||||
#define APPEND (UF_APPEND | SF_APPEND)
|
||||
#define IMMUTABLE (UF_IMMUTABLE | SF_IMMUTABLE)
|
||||
#endif /* _KERNEL_MODE */
|
||||
|
||||
#ifndef _KERNEL_MODE_
|
||||
//#include <sys/cdefs.h>
|
||||
|
||||
/** @fn int chmod(const char *path, mode_t mode)
|
||||
* Changes the file protection modes to those given by mode
|
||||
*
|
||||
* @ref POISX_filemodes
|
||||
*/
|
||||
int chmod (const char *, mode_t);
|
||||
/** @fn int fstat(int fd, struct stat *stat)
|
||||
* get file information on a file identified by descriptor fd
|
||||
*
|
||||
* @ref stat
|
||||
*/
|
||||
int fstat (int, struct stat *);
|
||||
//int mknod (const char *, mode_t, dev_t);
|
||||
int mkdir (const char *, mode_t);
|
||||
int mkfifo (const char *, mode_t);
|
||||
/** @fn int stat(const char *path, struct stat *stat)
|
||||
* Get file information for file path and store it in the structure
|
||||
* stat
|
||||
*
|
||||
* @ref stat
|
||||
*/
|
||||
int stat (const char *, struct stat *);
|
||||
mode_t umask (mode_t);
|
||||
int fchmod (int, mode_t);
|
||||
int lstat (const char *, struct stat *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
extern int chmod(const char *path, mode_t mode);
|
||||
extern int fchmod(int fd, mode_t mode);
|
||||
extern int stat(const char *path, struct stat *buf);
|
||||
extern int fstat(int fd, struct stat *buf);
|
||||
extern int lstat(const char *path, struct stat *st);
|
||||
extern int mkdir(const char *path, mode_t mode);
|
||||
extern int mkfifo(const char *path, mode_t mode);
|
||||
extern mode_t umask(mode_t cmask);
|
||||
|
||||
#endif /* !_SYS_STAT_H_ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _SYS_STAT_H_ */
|
||||
|
@ -22,8 +22,8 @@ enum {
|
||||
SYSCALL_CREATE,
|
||||
SYSCALL_UNLINK,
|
||||
SYSCALL_RENAME,
|
||||
SYSCALL_RSTAT,
|
||||
SYSCALL_WSTAT,
|
||||
SYSCALL_READ_STAT,
|
||||
SYSCALL_WRITE_STAT,
|
||||
SYSCALL_SYSTEM_TIME,
|
||||
SYSCALL_SNOOZE,
|
||||
SYSCALL_SEM_CREATE,
|
||||
@ -82,7 +82,7 @@ enum {
|
||||
SYSCALL_SYSCTL,
|
||||
SYSCALL_SOCKET,
|
||||
SYSCALL_GETDTABLESIZE,
|
||||
SYSCALL_FSTAT,
|
||||
SYSCALL_FD_STAT,
|
||||
SYSCALL_READ_DIR,
|
||||
SYSCALL_REWIND_DIR,
|
||||
SYSCALL_OPEN_DIR,
|
||||
@ -93,7 +93,9 @@ enum {
|
||||
SYSCALL_OPEN_DIR_ENTRY_REF,
|
||||
SYSCALL_OPEN_DIR_NODE_REF,
|
||||
SYSCALL_CREATE_ENTRY_REF,
|
||||
SYSCALL_CREATE_DIR_ENTRY_REF
|
||||
SYSCALL_CREATE_DIR_ENTRY_REF,
|
||||
SYSCALL_CREATE_SYMLINK,
|
||||
SYSCALL_READ_LINK,
|
||||
};
|
||||
|
||||
int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_ret);
|
||||
|
@ -20,15 +20,14 @@ typedef int team_id;
|
||||
typedef int sem_id;
|
||||
typedef int port_id;
|
||||
typedef int image_id;
|
||||
typedef uint32 dev_t;
|
||||
typedef uint64 ino_t;
|
||||
typedef uint64 vnode_id;
|
||||
typedef uint32 fs_id;
|
||||
typedef uint16 nlink_t;
|
||||
typedef uint32 uid_t;
|
||||
typedef uint32 gid_t;
|
||||
|
||||
/* compat with beos (was int32 on beos) */
|
||||
typedef int status_t;
|
||||
typedef int32 status_t;
|
||||
|
||||
|
||||
#ifdef _OBOS_TIME_T_
|
||||
|
@ -41,6 +41,9 @@ extern int optreset;
|
||||
|
||||
extern char **environ;
|
||||
|
||||
int readlink(const char *path, char *buffer, size_t bufferSize);
|
||||
int symlink(const char *path, const char *toPath);
|
||||
|
||||
off_t lseek(int, off_t, int);
|
||||
ssize_t read(int, void *, size_t);
|
||||
ssize_t pread(int, void *, size_t, off_t);
|
||||
|
@ -158,10 +158,12 @@ int sys_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omode
|
||||
int sys_create(const char *path, int omode, int perms);
|
||||
int sys_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms);
|
||||
int sys_create_dir(const char *path, int perms);
|
||||
int sys_symlink(const char *path, const char *toPath);
|
||||
int sys_read_link(const char *path, char *buffer, size_t bufferSize);
|
||||
int sys_create_symlink(const char *path, const char *toPath);
|
||||
int sys_unlink(const char *path);
|
||||
int sys_rename(const char *oldpath, const char *newpath);
|
||||
int sys_write_stat(const char *path, struct stat *stat, int stat_mask);
|
||||
int sys_read_stat(const char *path, bool traverseLink, struct stat *stat);
|
||||
int sys_write_stat(const char *path, bool traverseLink, struct stat *stat, int statMask);
|
||||
char *sys_getcwd(char *buf, size_t size);
|
||||
int sys_setcwd(const char* path);
|
||||
|
||||
@ -180,11 +182,12 @@ int user_create_entry_ref(dev_t device, ino_t inode, const char *uname, int omod
|
||||
int user_create(const char *path, int omode, int perms);
|
||||
int user_create_dir_entry_ref(dev_t device, ino_t inode, const char *name, int perms);
|
||||
int user_create_dir(const char *path, int perms);
|
||||
int user_symlink(const char *path, const char *toPath);
|
||||
int user_read_link(const char *path, char *buffer, size_t bufferSize);
|
||||
int user_create_symlink(const char *path, const char *toPath);
|
||||
int user_unlink(const char *path);
|
||||
int user_rename(const char *oldpath, const char *newpath);
|
||||
int user_read_stat(const char *path, struct stat *stat);
|
||||
int user_write_stat(const char *path, struct stat *stat, int stat_mask);
|
||||
int user_read_stat(const char *path, bool traverseLink, struct stat *stat);
|
||||
int user_write_stat(const char *path, bool traverseLink, struct stat *stat, int statMask);
|
||||
int user_getcwd(char *buf, size_t size);
|
||||
int user_setcwd(const char* path);
|
||||
|
||||
@ -194,7 +197,6 @@ extern ssize_t sys_write(int fd, const void *buf, off_t pos, size_t len);
|
||||
extern int sys_ioctl(int fd, ulong cmd, void *data, size_t length);
|
||||
extern ssize_t sys_read_dir(int fd, struct dirent *buffer, size_t bufferSize, uint32 maxCount);
|
||||
extern status_t sys_rewind_dir(int fd);
|
||||
extern int sys_read_stat(const char *path, struct stat *stat);
|
||||
extern int sys_close(int fd);
|
||||
extern int sys_dup(int fd);
|
||||
extern int sys_dup2(int ofd, int nfd);
|
||||
|
@ -351,6 +351,7 @@ KernelStaticLibraryObjects libc.a :
|
||||
<$(SOURCE_GRIST)!libc!unistd>lseek.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>open.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>opendir.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>link.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>pread.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>pwrite.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>read.o
|
||||
@ -467,6 +468,7 @@ KernelLd libc.so :
|
||||
<$(SOURCE_GRIST)!libc!unistd>lseek.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>open.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>opendir.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>link.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>pread.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>pwrite.o
|
||||
<$(SOURCE_GRIST)!libc!unistd>read.o
|
||||
@ -585,6 +587,19 @@ KernelLd ls :
|
||||
bin/ls
|
||||
;
|
||||
|
||||
KernelLd symlink :
|
||||
libglue2.o
|
||||
<$(SOURCE_GRIST)!apps!symlink>main.o
|
||||
libc.so
|
||||
libm.so
|
||||
:
|
||||
$(SUBDIR)/ldscripts/$(OBOS_ARCH)/app.ld
|
||||
:
|
||||
:
|
||||
:
|
||||
bin/symlink
|
||||
;
|
||||
|
||||
# Note: shell is a built in target, thus we need the grist.
|
||||
KernelLd obos_shell :
|
||||
libglue2.o
|
||||
|
@ -7,6 +7,7 @@ SubInclude OBOS_TOP src kernel apps filetest ;
|
||||
SubInclude OBOS_TOP src kernel apps fortune ;
|
||||
SubInclude OBOS_TOP src kernel apps hostname ;
|
||||
SubInclude OBOS_TOP src kernel apps ls ;
|
||||
SubInclude OBOS_TOP src kernel apps symlink ;
|
||||
SubInclude OBOS_TOP src kernel apps ps ;
|
||||
SubInclude OBOS_TOP src kernel apps rld ;
|
||||
SubInclude OBOS_TOP src kernel apps shell ;
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
extern char *__progname;
|
||||
|
||||
void (*disp_func)(const char *, struct stat *) = NULL;
|
||||
void (*disp_func)(const char *, const char *, struct stat *) = NULL;
|
||||
static int show_all = 0;
|
||||
|
||||
mode_t perms [9] = {
|
||||
@ -27,7 +27,9 @@ mode_t perms [9] = {
|
||||
S_IXOTH
|
||||
};
|
||||
|
||||
static void display_l(const char *filename, struct stat *stat)
|
||||
|
||||
static void
|
||||
display_l(const char *path, const char *filename, struct stat *stat)
|
||||
{
|
||||
const char *type;
|
||||
char perm[11];
|
||||
@ -51,16 +53,32 @@ static void display_l(const char *filename, struct stat *stat)
|
||||
}
|
||||
if (S_ISDIR(stat->st_mode))
|
||||
perm[0] = 'd';
|
||||
|
||||
printf("%10s %12lld %s\n" ,perm ,stat->st_size ,filename);
|
||||
else if (S_ISLNK(stat->st_mode))
|
||||
perm[0] = 'l';
|
||||
else if (S_ISCHR(stat->st_mode))
|
||||
perm[0] = 'c';
|
||||
|
||||
printf("%10s %12lld %s" ,perm ,stat->st_size ,filename);
|
||||
|
||||
if (S_ISLNK(stat->st_mode)) {
|
||||
char buffer[1024];
|
||||
if (readlink(path, buffer, sizeof(buffer)) != 0)
|
||||
strcpy(buffer, "???");
|
||||
printf(" (-> %s)\n", buffer);
|
||||
} else
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void display(const char *filename, struct stat *stat)
|
||||
|
||||
static void
|
||||
display(const char *path, const char *filename, struct stat *stat)
|
||||
{
|
||||
printf("%s\n", filename);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int rc;
|
||||
int rc2;
|
||||
@ -85,14 +103,13 @@ int main(int argc, char *argv[])
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if(*argv == NULL) {
|
||||
if (*argv == NULL)
|
||||
arg = ".";
|
||||
} else {
|
||||
else
|
||||
arg = *argv;
|
||||
}
|
||||
|
||||
rc = stat(arg, &st);
|
||||
if(rc < 0) {
|
||||
if (rc < 0) {
|
||||
printf("%s: %s: %s\n", __progname,
|
||||
arg, strerror(rc));
|
||||
goto err_ls;
|
||||
@ -109,7 +126,7 @@ int main(int argc, char *argv[])
|
||||
/* process the '.' entry */
|
||||
rc = stat(arg, &st);
|
||||
if (rc == 0) {
|
||||
(*disp_func)(".", &st);
|
||||
(*disp_func)(arg, ".", &st);
|
||||
totbytes += st.st_size;
|
||||
}
|
||||
}
|
||||
@ -128,9 +145,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
strlcat(buf2, de->d_name, sizeof(buf2));
|
||||
|
||||
rc2 = stat(buf2, &st);
|
||||
rc2 = lstat(buf2, &st);
|
||||
if (rc2 == 0) {
|
||||
(*disp_func)(de->d_name, &st);
|
||||
(*disp_func)(buf2, de->d_name, &st);
|
||||
totbytes += st.st_size;
|
||||
}
|
||||
count++;
|
||||
@ -140,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
printf("%lld bytes in %d files\n", totbytes, count);
|
||||
} else {
|
||||
(*disp_func)(arg, &st);
|
||||
(*disp_func)(arg, arg, &st);
|
||||
}
|
||||
|
||||
err_ls:
|
||||
|
@ -2,6 +2,7 @@
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <syscalls.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -168,13 +169,13 @@ int cmd_stat(int argc, char *argv[])
|
||||
int rc;
|
||||
struct stat stat;
|
||||
|
||||
if(argc < 2) {
|
||||
if (argc < 2) {
|
||||
printf("not enough arguments to stat\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = sys_read_stat(argv[1], &stat);
|
||||
if(rc >= 0) {
|
||||
rc = sys_read_stat(argv[1], true, &stat);
|
||||
if (rc >= 0) {
|
||||
printf("stat of file '%s': \n", argv[1]);
|
||||
printf("vnid 0x%x\n", (unsigned int)stat.st_ino);
|
||||
// printf("type %d\n", stat.type);
|
||||
|
@ -99,7 +99,7 @@ static int bus_find_device_recurse(int *n, char *base_path, int max_path_len, in
|
||||
dirent->d_name[dirent->d_reclen] = '\0';
|
||||
strlcat(base_path, dirent->d_name, max_path_len);
|
||||
|
||||
err = sys_read_stat(base_path, &stat);
|
||||
err = sys_read_stat(base_path, true, &stat);
|
||||
if (err < 0)
|
||||
continue;
|
||||
|
||||
|
@ -499,14 +499,10 @@ get_vnode_from_fd(struct io_context *ioContext, int fd)
|
||||
return NULL;
|
||||
|
||||
vnode = descriptor->vnode;
|
||||
if (vnode == NULL)
|
||||
goto out;
|
||||
if (vnode != NULL)
|
||||
inc_vnode_ref_count(vnode);
|
||||
|
||||
inc_vnode_ref_count(vnode);
|
||||
|
||||
out:
|
||||
put_fd(descriptor);
|
||||
|
||||
return vnode;
|
||||
}
|
||||
|
||||
@ -562,7 +558,7 @@ entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode
|
||||
|
||||
|
||||
static int
|
||||
vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int count)
|
||||
vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink, struct vnode **_vnode, int count)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
@ -624,45 +620,64 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int
|
||||
return ERR_VFS_PATH_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If the new node is a symbolic link, resolve it (if we've been told to do it)
|
||||
if (S_ISLNK(type) && !(!traverseLeafLink && nextPath[0] == '\0')) {
|
||||
char *buffer;
|
||||
|
||||
// it's not exactly nice style using goto in this way, but hey, it works :-/
|
||||
if (count + 1 > MAX_SYM_LINKS) {
|
||||
status = B_LINK_LIMIT;
|
||||
goto resolve_link_error;
|
||||
}
|
||||
|
||||
buffer = kmalloc(SYS_MAX_PATH_LEN);
|
||||
if (buffer == NULL) {
|
||||
status = B_NO_MEMORY;
|
||||
goto resolve_link_error;
|
||||
}
|
||||
|
||||
status = FS_CALL(nextVnode,fs_read_link)(nextVnode->mount->cookie, nextVnode->private_node, buffer, SYS_MAX_PATH_LEN);
|
||||
if (status < B_OK) {
|
||||
kfree(buffer);
|
||||
|
||||
resolve_link_error:
|
||||
put_vnode(vnode);
|
||||
put_vnode(nextVnode);
|
||||
|
||||
return status;
|
||||
}
|
||||
put_vnode(nextVnode);
|
||||
|
||||
// Check if we start from the root directory or the current
|
||||
// directory ("vnode" still points to that one).
|
||||
// Cut off all leading slashes if it's the root directory
|
||||
path = buffer;
|
||||
if (path[0] == '/') {
|
||||
// we don't need the old directory anymore
|
||||
put_vnode(vnode);
|
||||
|
||||
while (*++path == '/')
|
||||
;
|
||||
vnode = root_vnode;
|
||||
inc_vnode_ref_count(vnode);
|
||||
}
|
||||
|
||||
status = vnode_path_to_vnode(vnode, path, traverseLeafLink, &nextVnode, count + 1);
|
||||
|
||||
kfree(buffer);
|
||||
|
||||
if (status < B_OK) {
|
||||
put_vnode(vnode);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// decrease the ref count on the old dir we just looked up into
|
||||
put_vnode(vnode);
|
||||
|
||||
path = nextPath;
|
||||
vnode = nextVnode;
|
||||
|
||||
// If the new node is a symbolic link, resolve it
|
||||
if (S_ISLNK(type)) {
|
||||
char *buffer;
|
||||
|
||||
if (count + 1 > MAX_SYM_LINKS) {
|
||||
put_vnode(vnode);
|
||||
return B_LINK_LIMIT;
|
||||
}
|
||||
|
||||
buffer = kmalloc(SYS_MAX_PATH_LEN);
|
||||
if (buffer == NULL) {
|
||||
put_vnode(vnode);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = FS_CALL(vnode,fs_read_link)(vnode->mount->cookie, vnode->private_node, buffer, SYS_MAX_PATH_LEN);
|
||||
if (status < B_OK) {
|
||||
put_vnode(vnode);
|
||||
kfree(buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = vnode_path_to_vnode(vnode, buffer, &nextVnode, count + 1);
|
||||
|
||||
put_vnode(vnode);
|
||||
kfree(buffer);
|
||||
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
vnode = nextVnode;
|
||||
}
|
||||
|
||||
// see if we hit a mount point
|
||||
if (vnode->covered_by) {
|
||||
nextVnode = vnode->covered_by;
|
||||
@ -678,7 +693,7 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int
|
||||
|
||||
|
||||
static int
|
||||
path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
||||
path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel)
|
||||
{
|
||||
struct vnode *start;
|
||||
int linkCount = 0;
|
||||
@ -702,7 +717,7 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
|
||||
mutex_unlock(&context->io_mutex);
|
||||
}
|
||||
|
||||
return vnode_path_to_vnode(start, path, _vnode, 0);
|
||||
return vnode_path_to_vnode(start, path, traverseLink, _vnode, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -730,7 +745,7 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel
|
||||
p[1] = '\0';
|
||||
}
|
||||
}
|
||||
return path_to_vnode(path, _vnode, kernel);
|
||||
return path_to_vnode(path, true, _vnode, kernel);
|
||||
}
|
||||
|
||||
|
||||
@ -1013,9 +1028,9 @@ vfs_get_vnode_from_fd(int fd, bool kernel, void **vnode)
|
||||
|
||||
|
||||
int
|
||||
vfs_get_vnode_from_path(const char *path, bool kernel, void **vnode)
|
||||
vfs_get_vnode_from_path(const char *path, bool kernel, void **_vnode)
|
||||
{
|
||||
struct vnode *v;
|
||||
struct vnode *vnode;
|
||||
int err;
|
||||
char buf[SYS_MAX_PATH_LEN+1];
|
||||
|
||||
@ -1024,13 +1039,10 @@ vfs_get_vnode_from_path(const char *path, bool kernel, void **vnode)
|
||||
strncpy(buf, path, SYS_MAX_PATH_LEN);
|
||||
buf[SYS_MAX_PATH_LEN] = 0;
|
||||
|
||||
err = path_to_vnode(buf, &v, kernel);
|
||||
if (err < 0)
|
||||
goto err;
|
||||
err = path_to_vnode(buf, true, &vnode, kernel);
|
||||
if (err >= 0)
|
||||
*_vnode = vnode;
|
||||
|
||||
*vnode = v;
|
||||
|
||||
err:
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -1731,7 +1743,7 @@ file_open(char *path, int omode, bool kernel)
|
||||
FUNCTION(("file_open: entry. path = '%s', omode %d, kernel %d\n", path, omode, kernel));
|
||||
|
||||
// get the vnode matching the path
|
||||
status = path_to_vnode(path, &vnode, kernel);
|
||||
status = path_to_vnode(path, true, &vnode, kernel);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
@ -1884,7 +1896,7 @@ dir_open(char *path, bool kernel)
|
||||
|
||||
FUNCTION(("dir_open: path = '%s', kernel %d\n", path, kernel));
|
||||
|
||||
status = path_to_vnode(path, &vnode, kernel);
|
||||
status = path_to_vnode(path, true, &vnode, kernel);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
@ -1979,6 +1991,27 @@ common_sync(int fd, bool kernel)
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
common_read_link(char *path, char *buffer, size_t bufferSize, bool kernel)
|
||||
{
|
||||
struct vnode *vnode;
|
||||
int status;
|
||||
|
||||
status = path_to_vnode(path, false, &vnode, kernel);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
if (FS_CALL(vnode,fs_read_link) != NULL)
|
||||
status = FS_CALL(vnode,fs_read_link)(vnode->mount->cookie, vnode->private_node, buffer, bufferSize);
|
||||
else
|
||||
status = B_BAD_VALUE;
|
||||
|
||||
put_vnode(vnode);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
common_symlink(char *path, const char *toPath, bool kernel)
|
||||
{
|
||||
@ -1987,6 +2020,8 @@ common_symlink(char *path, const char *toPath, bool kernel)
|
||||
struct vnode *vnode;
|
||||
int status;
|
||||
|
||||
FUNCTION(("common_symlink(path = %s, toPath = %s, kernel = %d)\n", path, toPath, kernel));
|
||||
|
||||
status = path_to_dir_vnode(path, &vnode, name, kernel);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
@ -2009,7 +2044,7 @@ common_unlink(char *path, bool kernel)
|
||||
struct vnode *vnode;
|
||||
int status;
|
||||
|
||||
FUNCTION(("vfs_unlink: path '%s', kernel %d\n", path, kernel));
|
||||
FUNCTION(("common_unlink: path '%s', kernel %d\n", path, kernel));
|
||||
|
||||
status = path_to_dir_vnode(path, &vnode, filename, kernel);
|
||||
if (status < 0)
|
||||
@ -2027,18 +2062,20 @@ common_unlink(char *path, bool kernel)
|
||||
|
||||
|
||||
static int
|
||||
common_rename(char *path, char *newpath, bool kernel)
|
||||
common_rename(char *path, char *newPath, bool kernel)
|
||||
{
|
||||
struct vnode *vnode1, *vnode2;
|
||||
char filename1[SYS_MAX_NAME_LEN];
|
||||
char filename2[SYS_MAX_NAME_LEN];
|
||||
int status;
|
||||
|
||||
FUNCTION(("common_rename(path = %s, newPath = %s, kernel = %d)\n", path, newPath, kernel));
|
||||
|
||||
status = path_to_dir_vnode(path, &vnode1, filename1, kernel);
|
||||
if (status < 0)
|
||||
goto err;
|
||||
|
||||
status = path_to_dir_vnode(newpath, &vnode2, filename2, kernel);
|
||||
status = path_to_dir_vnode(newPath, &vnode2, filename2, kernel);
|
||||
if (status < 0)
|
||||
goto err1;
|
||||
|
||||
@ -2062,14 +2099,14 @@ err:
|
||||
|
||||
|
||||
static int
|
||||
common_write_stat(char *path, const struct stat *stat, int statMask, bool kernel)
|
||||
common_write_stat(char *path, bool traverseLeafLink, const struct stat *stat, int statMask, bool kernel)
|
||||
{
|
||||
struct vnode *vnode;
|
||||
int status;
|
||||
|
||||
FUNCTION(("vfs_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel));
|
||||
FUNCTION(("common_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel));
|
||||
|
||||
status = path_to_vnode(path, &vnode, kernel);
|
||||
status = path_to_vnode(path, traverseLeafLink, &vnode, kernel);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
@ -2137,7 +2174,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
|
||||
|
||||
mount->covers_vnode = NULL; // this is the root mount
|
||||
} else {
|
||||
err = path_to_vnode(path,&covered_vnode,kernel);
|
||||
err = path_to_vnode(path, true, &covered_vnode, kernel);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
@ -2210,7 +2247,7 @@ fs_unmount(char *path, bool kernel)
|
||||
|
||||
FUNCTION(("vfs_unmount: entry. path = '%s', kernel %d\n", path, kernel));
|
||||
|
||||
err = path_to_vnode(path, &vnode, kernel);
|
||||
err = path_to_vnode(path, true, &vnode, kernel);
|
||||
if (err < 0)
|
||||
return ERR_VFS_PATH_NOT_FOUND;
|
||||
|
||||
@ -2395,10 +2432,10 @@ set_cwd(char *path, bool kernel)
|
||||
struct stat stat;
|
||||
int rc;
|
||||
|
||||
FUNCTION(("vfs_set_cwd: path = \'%s\'\n", path));
|
||||
FUNCTION(("set_cwd: path = \'%s\'\n", path));
|
||||
|
||||
// Get vnode for passed path, and bail if it failed
|
||||
rc = path_to_vnode(path, &vnode, kernel);
|
||||
rc = path_to_vnode(path, true, &vnode, kernel);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
@ -2580,7 +2617,20 @@ sys_create_dir(const char *path, int perms)
|
||||
|
||||
|
||||
int
|
||||
sys_symlink(const char *userPath, const char *userToPath)
|
||||
sys_read_link(const char *path, char *buffer, size_t bufferSize)
|
||||
{
|
||||
char pathCopy[SYS_MAX_PATH_LEN + 1];
|
||||
int status;
|
||||
|
||||
strncpy(pathCopy, path, SYS_MAX_PATH_LEN);
|
||||
pathCopy[SYS_MAX_PATH_LEN] = '\0';
|
||||
|
||||
return common_read_link(pathCopy, buffer, bufferSize, true);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_create_symlink(const char *userPath, const char *userToPath)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
char toPath[SYS_MAX_PATH_LEN + 1];
|
||||
@ -2629,37 +2679,37 @@ sys_rename(const char *oldpath, const char *newpath)
|
||||
|
||||
|
||||
int
|
||||
sys_read_stat(const char *path, struct stat *stat)
|
||||
sys_read_stat(const char *path, bool traverseLeafLink, struct stat *stat)
|
||||
{
|
||||
char buf[SYS_MAX_PATH_LEN+1];
|
||||
char buffer[SYS_MAX_PATH_LEN + 1];
|
||||
struct vnode *vnode;
|
||||
int status;
|
||||
|
||||
strncpy(buf, path, SYS_MAX_PATH_LEN);
|
||||
buf[SYS_MAX_PATH_LEN] = 0;
|
||||
strncpy(buffer, path, SYS_MAX_PATH_LEN);
|
||||
buffer[SYS_MAX_PATH_LEN] = 0;
|
||||
|
||||
FUNCTION(("sys_read_stat: path '%s', stat %p,\n", path, stat));
|
||||
|
||||
status = path_to_vnode(buf, &vnode, true);
|
||||
status = path_to_vnode(buffer, traverseLeafLink, &vnode, true);
|
||||
if (status < 0)
|
||||
return status;
|
||||
|
||||
status = FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->private_node, stat);
|
||||
|
||||
dec_vnode_ref_count(vnode, false);
|
||||
put_vnode(vnode);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
sys_write_stat(const char *path, struct stat *stat, int stat_mask)
|
||||
sys_write_stat(const char *path, bool traverseLeafLink, struct stat *stat, int statMask)
|
||||
{
|
||||
char buf[SYS_MAX_PATH_LEN+1];
|
||||
char buffer[SYS_MAX_PATH_LEN + 1];
|
||||
|
||||
strncpy(buf, path, SYS_MAX_PATH_LEN);
|
||||
buf[SYS_MAX_PATH_LEN] = 0;
|
||||
strncpy(buffer, path, SYS_MAX_PATH_LEN);
|
||||
buffer[SYS_MAX_PATH_LEN] = 0;
|
||||
|
||||
return common_write_stat(buf, stat, stat_mask, true);
|
||||
return common_write_stat(buffer, traverseLeafLink, stat, statMask, true);
|
||||
}
|
||||
|
||||
|
||||
@ -2901,15 +2951,15 @@ user_create_dir_entry_ref(dev_t device, ino_t inode, const char *uname, int perm
|
||||
|
||||
|
||||
int
|
||||
user_create_dir(const char *upath, int perms)
|
||||
user_create_dir(const char *userPath, int perms)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
int status;
|
||||
|
||||
if (!CHECK_USER_ADDRESS(upath))
|
||||
if (!CHECK_USER_ADDRESS(userPath))
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
status = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
|
||||
status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
|
||||
if (status < 0)
|
||||
return status;
|
||||
path[SYS_MAX_PATH_LEN] = '\0';
|
||||
@ -2919,7 +2969,31 @@ user_create_dir(const char *upath, int perms)
|
||||
|
||||
|
||||
int
|
||||
user_symlink(const char *userPath, const char *userToPath)
|
||||
user_read_link(const char *userPath, char *userBuffer, size_t bufferSize)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
char buffer[SYS_MAX_PATH_LEN + 1];
|
||||
int status;
|
||||
|
||||
if (!CHECK_USER_ADDRESS(userPath)
|
||||
|| !CHECK_USER_ADDRESS(userBuffer))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
|
||||
if (status < 0)
|
||||
return status;
|
||||
path[SYS_MAX_PATH_LEN] = '\0';
|
||||
|
||||
status = common_read_link(path, buffer, bufferSize, false);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return user_strncpy(userBuffer, buffer, SYS_MAX_PATH_LEN);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_create_symlink(const char *userPath, const char *userToPath)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
char toPath[SYS_MAX_PATH_LEN + 1];
|
||||
@ -2993,25 +3067,25 @@ user_rename(const char *uoldpath, const char *unewpath)
|
||||
|
||||
|
||||
int
|
||||
user_read_stat(const char *upath, struct stat *ustat)
|
||||
user_read_stat(const char *userPath, bool traverseLink, struct stat *userStat)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN];
|
||||
char path[SYS_MAX_PATH_LEN + 1];
|
||||
struct vnode *vnode = NULL;
|
||||
struct stat stat;
|
||||
int rc;
|
||||
|
||||
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
if (!CHECK_USER_ADDRESS(userPath)
|
||||
|| !CHECK_USER_ADDRESS(userStat))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1);
|
||||
rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
path[SYS_MAX_PATH_LEN-1] = 0;
|
||||
path[SYS_MAX_PATH_LEN] = 0;
|
||||
|
||||
rc = path_to_vnode(path, &vnode, false);
|
||||
FUNCTION(("user_read_stat(path = %s, traverseLeafLink = %d)\n", path, traverseLink));
|
||||
|
||||
rc = path_to_vnode(path, traverseLink, &vnode, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
@ -3023,35 +3097,31 @@ user_read_stat(const char *upath, struct stat *ustat)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
rc = user_memcpy(ustat, &stat, sizeof(struct stat));
|
||||
|
||||
return rc;
|
||||
return user_memcpy(userStat, &stat, sizeof(struct stat));
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
user_write_stat(const char *upath, struct stat *ustat, int stat_mask)
|
||||
user_write_stat(const char *userPath, bool traverseLeafLink, struct stat *userStat, int statMask)
|
||||
{
|
||||
char path[SYS_MAX_PATH_LEN+1];
|
||||
struct stat stat;
|
||||
int rc;
|
||||
|
||||
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
if (!CHECK_USER_ADDRESS(userPath)
|
||||
|| !CHECK_USER_ADDRESS(userStat))
|
||||
return B_BAD_ADDRESS;
|
||||
|
||||
if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP)
|
||||
return ERR_VM_BAD_USER_MEMORY;
|
||||
|
||||
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
|
||||
rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
path[SYS_MAX_PATH_LEN] = 0;
|
||||
|
||||
rc = user_memcpy(&stat, ustat, sizeof(struct stat));
|
||||
rc = user_memcpy(&stat, userStat, sizeof(struct stat));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return common_write_stat(path, &stat, stat_mask, false);
|
||||
return common_write_stat(path, traverseLeafLink, &stat, statMask, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -415,7 +415,7 @@ static int recurse_directory(const char *path, const char *match)
|
||||
strlcat(newpath, "/", slen);
|
||||
strlcat(newpath, dirent->d_name, slen);
|
||||
|
||||
if ((res = sys_read_stat(newpath, &stat)) != B_NO_ERROR) {
|
||||
if ((res = sys_read_stat(newpath, true, &stat)) != B_NO_ERROR) {
|
||||
kfree(newpath);
|
||||
break;
|
||||
}
|
||||
@ -758,7 +758,7 @@ static inline int module_traverse_dir(module_iterator *iter)
|
||||
iter->cur_header = NULL;
|
||||
iter->module_pos = 0;
|
||||
|
||||
if ((res = sys_read_stat(path, &stat)) != B_NO_ERROR)
|
||||
if ((res = sys_read_stat(path, true, &stat)) != B_NO_ERROR)
|
||||
return res;
|
||||
|
||||
if (S_ISREG(stat.st_mode)) {
|
||||
|
@ -111,20 +111,26 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
|
||||
case SYSCALL_CREATE_DIR:
|
||||
*call_ret = user_create_dir((const char *)arg0, (int)arg1);
|
||||
break;
|
||||
case SYSCALL_CREATE_SYMLINK:
|
||||
*call_ret = user_create_symlink((const char *)arg0, (const char *)arg1);
|
||||
break;
|
||||
case SYSCALL_READ_LINK:
|
||||
*call_ret = user_read_link((const char *)arg0, (char *)arg1, (size_t)arg2);
|
||||
break;
|
||||
case SYSCALL_UNLINK:
|
||||
*call_ret = user_unlink((const char *)arg0);
|
||||
break;
|
||||
case SYSCALL_RENAME:
|
||||
*call_ret = user_rename((const char *)arg0, (const char *)arg1);
|
||||
break;
|
||||
case SYSCALL_RSTAT:
|
||||
*call_ret = user_read_stat((const char *)arg0, (struct stat *)arg1);
|
||||
case SYSCALL_READ_STAT:
|
||||
*call_ret = user_read_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2);
|
||||
break;
|
||||
case SYSCALL_FSTAT:
|
||||
case SYSCALL_FD_STAT:
|
||||
*call_ret = user_fstat((int)arg0, (struct stat*)arg1);
|
||||
break;
|
||||
case SYSCALL_WSTAT:
|
||||
*call_ret = user_write_stat((const char *)arg0, (struct stat *)arg1, (int)arg2);
|
||||
case SYSCALL_WRITE_STAT:
|
||||
*call_ret = user_write_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2, (int)arg3);
|
||||
break;
|
||||
case SYSCALL_SYSTEM_TIME:
|
||||
*call_ret = system_time();
|
||||
|
Loading…
Reference in New Issue
Block a user