- factored out [f]pathconf().
- *pathconf() now uses statvfs and fs_info data when appropriate. It should also check for file type though, some only apply to directory or others. - added confstr(_CS_PATH) with a sensible default. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25625 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -87,6 +87,9 @@
|
|||||||
#define _SC_SEMAPHORES 30
|
#define _SC_SEMAPHORES 30
|
||||||
#define _SC_THREADS 31
|
#define _SC_THREADS 31
|
||||||
|
|
||||||
|
/* confstr() constants */
|
||||||
|
#define _CS_PATH 1
|
||||||
|
|
||||||
/* lseek() constants */
|
/* lseek() constants */
|
||||||
#ifndef SEEK_SET
|
#ifndef SEEK_SET
|
||||||
# define SEEK_SET 0
|
# define SEEK_SET 0
|
||||||
|
|||||||
@@ -11,9 +11,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <fs_info.h>
|
||||||
#include <libroot_private.h>
|
#include <libroot_private.h>
|
||||||
#include <posix/realtime_sem_defs.h>
|
#include <posix/realtime_sem_defs.h>
|
||||||
#include <user_group.h>
|
#include <user_group.h>
|
||||||
@@ -77,17 +79,45 @@ sysconf(int name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long
|
enum {
|
||||||
fpathconf(int fd, int name)
|
FS_BFS,
|
||||||
|
FS_FAT,
|
||||||
|
FS_EXT,
|
||||||
|
FS_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
fstype(const char *fsh_name)
|
||||||
{
|
{
|
||||||
if (fd < 0) {
|
if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH))
|
||||||
errno = EBADF;
|
return FS_BFS;
|
||||||
|
if (!strncmp(fsh_name, "dos", B_OS_NAME_LENGTH))
|
||||||
|
return FS_FAT;
|
||||||
|
if (!strncmp(fsh_name, "fat", B_OS_NAME_LENGTH))
|
||||||
|
return FS_FAT;
|
||||||
|
if (!strncmp(fsh_name, "ext2", B_OS_NAME_LENGTH))
|
||||||
|
return FS_EXT;
|
||||||
|
if (!strncmp(fsh_name, "ext3", B_OS_NAME_LENGTH))
|
||||||
|
return FS_EXT;
|
||||||
|
return FS_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static long
|
||||||
|
__pathconf_common(struct statvfs *fs, struct stat *st,
|
||||||
|
int name)
|
||||||
|
{
|
||||||
|
fs_info info;
|
||||||
|
int ret;
|
||||||
|
ret = fs_stat_dev(fs->f_fsid, &info);
|
||||||
|
if (ret < 0) {
|
||||||
|
errno = ret;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: should query the underlying filesystem
|
// TODO: many cases should check for file type from st.
|
||||||
// for correct value, as most are fs-dependant
|
|
||||||
// (which is why it's a different call than sysconf() btw).
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case _PC_CHOWN_RESTRICTED:
|
case _PC_CHOWN_RESTRICTED:
|
||||||
return _POSIX_CHOWN_RESTRICTED;
|
return _POSIX_CHOWN_RESTRICTED;
|
||||||
@@ -99,7 +129,8 @@ fpathconf(int fd, int name)
|
|||||||
return MAX_INPUT;
|
return MAX_INPUT;
|
||||||
|
|
||||||
case _PC_NAME_MAX:
|
case _PC_NAME_MAX:
|
||||||
return NAME_MAX;
|
return fs->f_namemax;
|
||||||
|
//return NAME_MAX;
|
||||||
|
|
||||||
case _PC_NO_TRUNC:
|
case _PC_NO_TRUNC:
|
||||||
return _POSIX_NO_TRUNC;
|
return _POSIX_NO_TRUNC;
|
||||||
@@ -117,15 +148,53 @@ fpathconf(int fd, int name)
|
|||||||
return _POSIX_VDISABLE;
|
return _POSIX_VDISABLE;
|
||||||
|
|
||||||
case _PC_FILESIZEBITS:
|
case _PC_FILESIZEBITS:
|
||||||
|
{
|
||||||
|
int type = fstype(info.fsh_name);
|
||||||
|
switch (type) {
|
||||||
|
case FS_BFS:
|
||||||
|
case FS_EXT:
|
||||||
return 64;
|
return 64;
|
||||||
|
case FS_FAT:
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
// XXX: add fs ? add to statvfs/fs_info ?
|
||||||
|
return 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
case _PC_SYMLINK_MAX:
|
||||||
|
return SYMLINK_MAX;
|
||||||
|
|
||||||
|
case _PC_2_SYMLINKS:
|
||||||
|
{
|
||||||
|
int type = fstype(info.fsh_name);
|
||||||
|
switch (type) {
|
||||||
|
case FS_BFS:
|
||||||
|
case FS_EXT:
|
||||||
|
return 1;
|
||||||
|
case FS_FAT:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// XXX: there should be an HAS_SYMLINKS flag
|
||||||
|
// to fs_info...
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case _PC_XATTR_EXISTS:
|
case _PC_XATTR_EXISTS:
|
||||||
case _PC_XATTR_ENABLED:
|
case _PC_XATTR_ENABLED:
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
/* those seem to be Solaris specific,
|
/* those seem to be Solaris specific,
|
||||||
* else we should return 1 I suppose.
|
* else we should return 1 I suppose.
|
||||||
|
* we don't yet map POSIX xattrs
|
||||||
|
* to BFS ones anyway.
|
||||||
*/
|
*/
|
||||||
|
if (info.flags & B_FS_HAS_ATTR)
|
||||||
|
return 1;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
case _PC_SYNC_IO:
|
case _PC_SYNC_IO:
|
||||||
case _PC_ASYNC_IO:
|
case _PC_ASYNC_IO:
|
||||||
@@ -136,8 +205,6 @@ fpathconf(int fd, int name)
|
|||||||
case _PC_REC_MIN_XFER_SIZE:
|
case _PC_REC_MIN_XFER_SIZE:
|
||||||
case _PC_REC_XFER_ALIGN:
|
case _PC_REC_XFER_ALIGN:
|
||||||
case _PC_ALLOC_SIZE_MIN:
|
case _PC_ALLOC_SIZE_MIN:
|
||||||
case _PC_SYMLINK_MAX:
|
|
||||||
case _PC_2_SYMLINKS:
|
|
||||||
/* not yet supported */
|
/* not yet supported */
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -149,39 +216,72 @@ fpathconf(int fd, int name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long
|
||||||
|
fpathconf(int fd, int name)
|
||||||
|
{
|
||||||
|
struct statvfs fs;
|
||||||
|
struct stat st;
|
||||||
|
int ret;
|
||||||
|
if (fd < 0) {
|
||||||
|
errno = EBADF;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ret = fstat(fd, &st);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
ret = fstatvfs(fd, &fs);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return __pathconf_common(&fs, &st, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
long
|
long
|
||||||
pathconf(const char *path, int name)
|
pathconf(const char *path, int name)
|
||||||
{
|
{
|
||||||
int fd;
|
struct statvfs fs;
|
||||||
long value;
|
struct stat st;
|
||||||
//XXX: some names shouldn't require openning,
|
int ret;
|
||||||
// just statfs
|
if (path == NULL) {
|
||||||
fd = open(path, O_RDONLY | O_NOCTTY | O_NOTRAVERSE);
|
errno = EFAULT;
|
||||||
if (fd < 0)
|
return -1;
|
||||||
return fd;
|
}
|
||||||
|
ret = lstat(path, &st);
|
||||||
value = fpathconf(fd, name);
|
if (ret < 0)
|
||||||
close(fd);
|
return ret;
|
||||||
return value;
|
ret = statvfs(path, &fs);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
return __pathconf_common(&fs, &st, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
confstr(int name, char *buffer, size_t length)
|
confstr(int name, char *buffer, size_t length)
|
||||||
{
|
{
|
||||||
size_t stringLength = 1;
|
size_t stringLength = 0;
|
||||||
char *string = "";
|
char *string = "";
|
||||||
|
|
||||||
|
if (!length || !buffer) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 0:
|
case _CS_PATH:
|
||||||
|
string = "/bin:/boot/beos/apps:" \
|
||||||
|
"/boot/common/bin:/boot/develop/bin";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer != NULL)
|
if (buffer != NULL) {
|
||||||
strlcpy(buffer, string, min_c(length, stringLength));
|
stringLength = strlen(string) + 1;
|
||||||
|
strlcpy(buffer, string,
|
||||||
|
min_c(length - 1, stringLength));
|
||||||
|
}
|
||||||
|
|
||||||
return stringLength;
|
return stringLength;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user