- 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:
François Revol
2008-05-23 00:33:08 +00:00
parent 15ebab7616
commit 3a17a548da
2 changed files with 128 additions and 25 deletions
+3
View File
@@ -87,6 +87,9 @@
#define _SC_SEMAPHORES 30
#define _SC_THREADS 31
/* confstr() constants */
#define _CS_PATH 1
/* lseek() constants */
#ifndef SEEK_SET
# define SEEK_SET 0
+125 -25
View File
@@ -11,9 +11,11 @@
#include <stdlib.h>
#include <string.h>
#include <sys/resource.h>
#include <sys/statvfs.h>
#include <SupportDefs.h>
#include <fs_info.h>
#include <libroot_private.h>
#include <posix/realtime_sem_defs.h>
#include <user_group.h>
@@ -77,17 +79,45 @@ sysconf(int name)
}
long
fpathconf(int fd, int name)
enum {
FS_BFS,
FS_FAT,
FS_EXT,
FS_UNKNOWN
};
static int
fstype(const char *fsh_name)
{
if (fd < 0) {
errno = EBADF;
if (!strncmp(fsh_name, "bfs", B_OS_NAME_LENGTH))
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;
}
// TODO: should query the underlying filesystem
// for correct value, as most are fs-dependant
// (which is why it's a different call than sysconf() btw).
// TODO: many cases should check for file type from st.
switch (name) {
case _PC_CHOWN_RESTRICTED:
return _POSIX_CHOWN_RESTRICTED;
@@ -99,7 +129,8 @@ fpathconf(int fd, int name)
return MAX_INPUT;
case _PC_NAME_MAX:
return NAME_MAX;
return fs->f_namemax;
//return NAME_MAX;
case _PC_NO_TRUNC:
return _POSIX_NO_TRUNC;
@@ -117,15 +148,53 @@ fpathconf(int fd, int name)
return _POSIX_VDISABLE;
case _PC_FILESIZEBITS:
{
int type = fstype(info.fsh_name);
switch (type) {
case FS_BFS:
case FS_EXT:
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_ENABLED:
{
#if 0
/* those seem to be Solaris specific,
* 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;
return -1;
}
case _PC_SYNC_IO:
case _PC_ASYNC_IO:
@@ -136,8 +205,6 @@ fpathconf(int fd, int name)
case _PC_REC_MIN_XFER_SIZE:
case _PC_REC_XFER_ALIGN:
case _PC_ALLOC_SIZE_MIN:
case _PC_SYMLINK_MAX:
case _PC_2_SYMLINKS:
/* not yet supported */
errno = EINVAL;
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
pathconf(const char *path, int name)
{
int fd;
long value;
//XXX: some names shouldn't require openning,
// just statfs
fd = open(path, O_RDONLY | O_NOCTTY | O_NOTRAVERSE);
if (fd < 0)
return fd;
value = fpathconf(fd, name);
close(fd);
return value;
struct statvfs fs;
struct stat st;
int ret;
if (path == NULL) {
errno = EFAULT;
return -1;
}
ret = lstat(path, &st);
if (ret < 0)
return ret;
ret = statvfs(path, &fs);
if (ret < 0)
return ret;
return __pathconf_common(&fs, &st, name);
}
size_t
confstr(int name, char *buffer, size_t length)
{
size_t stringLength = 1;
size_t stringLength = 0;
char *string = "";
if (!length || !buffer) {
errno = EINVAL;
return 0;
}
switch (name) {
case 0:
case _CS_PATH:
string = "/bin:/boot/beos/apps:" \
"/boot/common/bin:/boot/develop/bin";
break;
default:
errno = EINVAL;
return 0;
}
if (buffer != NULL)
strlcpy(buffer, string, min_c(length, stringLength));
if (buffer != NULL) {
stringLength = strlen(string) + 1;
strlcpy(buffer, string,
min_c(length - 1, stringLength));
}
return stringLength;
}