From 0c8044736287d38893198455e2a4cdc9aaf55a43 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 9 Feb 2009 12:41:29 -0500 Subject: [PATCH] [Bug 6069] Add a fstatvfs function for libsmbclient - Add initial test implementation. This works on a Linux client to determine whether a connection's server supports UNIX CIFS. I'm eager to see what the build farm has to say about this, specifically how many, if any, hosts don't provide a statvfs.h file with the requisite struct statvfs. Derrell (cherry picked from commit ff6a1bebd589637a4aecb9c76b4e33f579d7b0df) --- examples/libsmbclient/Makefile | 5 +++++ source/include/libsmb_internal.h | 7 +++++++ source/include/libsmbclient.h | 45 ++++++++++++++++++++++++++++++++++++++++ source/libsmb/libsmb_compat.c | 8 +++++++ source/libsmb/libsmb_context.c | 1 + source/libsmb/libsmb_setget.c | 12 +++++++++++ source/libsmb/libsmb_stat.c | 21 +++++++++++++++++++ 7 files changed, 99 insertions(+) diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile index 047addc8f7a..7ad28dcea0f 100644 --- a/examples/libsmbclient/Makefile +++ b/examples/libsmbclient/Makefile @@ -24,6 +24,7 @@ TESTS= testsmbc \ teststat \ teststat2 \ teststat3 \ + testfstatvfs \ testtruncate \ testchmod \ testutime \ @@ -74,6 +75,10 @@ teststat3: teststat3.o @echo Linking teststat3 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt +testfstatvfs: testfstatvfs.o + @echo Linking testfstatvfs + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + testtruncate: testtruncate.o @echo Linking testtruncate $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h index 67add074bfc..edf3a6ed088 100644 --- a/source/include/libsmb_internal.h +++ b/source/include/libsmb_internal.h @@ -197,6 +197,7 @@ struct SMBC_internal_data { smbc_stat_fn stat_fn; smbc_fstat_fn fstat_fn; #endif + smbc_fstatvfs_fn fstatvfs_fn; smbc_ftruncate_fn ftruncate_fn; #if 0 /* Left in libsmbclient.h for backward compatibility */ smbc_close_fn close_fn; @@ -501,6 +502,12 @@ SMBC_fstat_ctx(SMBCCTX *context, struct stat *st); +int +SMBC_fstatvfs_ctx(SMBCCTX *context, + SMBCFILE *file, + struct statvfs *st); + + /* Functions in libsmb_xattr.c */ int SMBC_setxattr_ctx(SMBCCTX *context, diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h index b2d9483a0b9..575bef691c4 100644 --- a/source/include/libsmbclient.h +++ b/source/include/libsmbclient.h @@ -174,6 +174,22 @@ typedef enum smbc_smb_encrypt_level } smbc_smb_encrypt_level; +/** + * Capabilities set in the f_flag field of struct statvfs, from + * smbc_statvfs(). These may be OR-ed together to reflect a full set of + * available capabilities. + */ +typedef enum smbc_vfs_capability +{ + /* Defined by POSIX or in Linux include files (low-order bits) */ + SMBC_VFS_CAP_RDONLY = (1 << 0), + + /* Specific to libsmbclient (high-order bits) */ + SMBC_VFS_CAP_DFS = (1 << 29), + SMBC_VFS_CAP_CASE_SENSITIVE = (1 << 30), + SMBC_VFS_CAP_UNIXCIFS = (1 << 31) +} smbc_vfs_capability; + typedef int smbc_bool; @@ -853,6 +869,12 @@ typedef int (*smbc_fstat_fn)(SMBCCTX *c, smbc_fstat_fn smbc_getFunctionFstat(SMBCCTX *c); void smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn); +typedef int (*smbc_fstatvfs_fn)(SMBCCTX *c, + SMBCFILE *file, + struct statvfs *st); +smbc_fstatvfs_fn smbc_getFunctionFstatVFS(SMBCCTX *c); +void smbc_setFunctionFstatVFS(SMBCCTX *c, smbc_fstatvfs_fn fn); + typedef int (*smbc_ftruncate_fn)(SMBCCTX *c, SMBCFILE *f, off_t size); @@ -1592,6 +1614,29 @@ int smbc_fstat(int fd, struct stat *st); /**@ingroup attribute + * Get file system information via an file descriptor. + * + * @param fd Open file handle from smbc_open(), smbc_creat(), + * or smbc_opendir() + * + * @param st pointer to a buffer that will be filled with + * standard Unix struct statvfs information. + * + * @return EBADF filedes is bad. + * - EACCES Permission denied. + * - EBADF fd is not a valid file descriptor + * - EINVAL Problems occurred in the underlying routines + * or smbc_init not called. + * - ENOMEM Out of memory + * + * @see Unix fstatvfs() + * + */ +int +smbc_fstatvfs(int fd, + struct statvfs *st); + +/**@ingroup attribute * Truncate a file given a file descriptor * * @param fd Open file handle from smbc_open() or smbc_creat() diff --git a/source/libsmb/libsmb_compat.c b/source/libsmb/libsmb_compat.c index ad8fd922db2..5bebc5ef87d 100644 --- a/source/libsmb/libsmb_compat.c +++ b/source/libsmb/libsmb_compat.c @@ -330,6 +330,14 @@ smbc_fstat(int fd, } int +smbc_fstatvfs(int fd, + struct statvfs *st) +{ + SMBCFILE * file = find_fd(fd); + return smbc_getFunctionFstatVFS(statcont)(statcont, file, st); +} + +int smbc_ftruncate(int fd, off_t size) { diff --git a/source/libsmb/libsmb_context.c b/source/libsmb/libsmb_context.c index c9e9c34995d..fa0de246395 100644 --- a/source/libsmb/libsmb_context.c +++ b/source/libsmb/libsmb_context.c @@ -94,6 +94,7 @@ smbc_new_context(void) smbc_setFunctionLseek(context, SMBC_lseek_ctx); smbc_setFunctionFtruncate(context, SMBC_ftruncate_ctx); smbc_setFunctionStat(context, SMBC_stat_ctx); + smbc_setFunctionFstatVFS(context, SMBC_fstatvfs_ctx); smbc_setFunctionFstat(context, SMBC_fstat_ctx); smbc_setFunctionOpendir(context, SMBC_opendir_ctx); smbc_setFunctionClosedir(context, SMBC_closedir_ctx); diff --git a/source/libsmb/libsmb_setget.c b/source/libsmb/libsmb_setget.c index 9de49a5b3f6..9fb608b30e7 100644 --- a/source/libsmb/libsmb_setget.c +++ b/source/libsmb/libsmb_setget.c @@ -659,6 +659,18 @@ smbc_setFunctionFstat(SMBCCTX *c, smbc_fstat_fn fn) c->fstat = fn; } +smbc_fstatvfs_fn +smbc_getFunctionFstatVFS(SMBCCTX *c) +{ + return c->internal->posix_emu.fstatvfs_fn; +} + +void +smbc_setFunctionFstatVFS(SMBCCTX *c, smbc_fstatvfs_fn fn) +{ + c->internal->posix_emu.fstatvfs_fn = fn; +} + smbc_ftruncate_fn smbc_getFunctionFtruncate(SMBCCTX *c) { diff --git a/source/libsmb/libsmb_stat.c b/source/libsmb/libsmb_stat.c index 27546f687ed..a9c36475239 100644 --- a/source/libsmb/libsmb_stat.c +++ b/source/libsmb/libsmb_stat.c @@ -300,3 +300,24 @@ SMBC_fstat_ctx(SMBCCTX *context, return 0; } + +/* + * Routine to obtain file system information given an fd + */ + +int +SMBC_fstatvfs_ctx(SMBCCTX *context, + SMBCFILE *file, + struct statvfs *st) +{ + /* Initialize all fields (at least until we actually use them) */ + memset(st, 0, sizeof(*st)); + + /* See if the server has UNIX CIFS support */ + if (SERVER_HAS_UNIX_CIFS(file->srv->cli)) + { + st->f_flag |= SMBC_VFS_CAP_UNIXCIFS; + } + + return 0; +} -- 2.11.4.GIT