diff options
author | Derrell Lipman <derrell.lipman@unwireduniverse.com> | 2009-02-12 09:16:48 -0500 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2009-02-16 09:57:02 +0100 |
commit | 6e4efa3a31567a1f136e4ba4537b25e55765535a (patch) | |
tree | d207287ba06c9174537c1580e13308d208c5a16b | |
parent | 962acaf800014913794cbbc1df381f619f63a6ca (diff) | |
download | samba-6e4efa3a31567a1f136e4ba4537b25e55765535a.tar.gz samba-6e4efa3a31567a1f136e4ba4537b25e55765535a.tar.xz samba-6e4efa3a31567a1f136e4ba4537b25e55765535a.zip |
[Bug 6069] Add a fstatvfs function for libsmbclient
- DFS is not a POSIX feature, so the state of that bit should be zero if DFS
is *not* supported. Bit feature reversed.
- Added smbc_statvfs function
Derrell
(cherry picked from commit 0697cffe211a922c816b6c75230c4186328498ed)
-rw-r--r-- | examples/libsmbclient/Makefile | 5 | ||||
-rw-r--r-- | examples/libsmbclient/testfstatvfs.c | 6 | ||||
-rw-r--r-- | examples/libsmbclient/teststatvfs.c | 96 | ||||
-rw-r--r-- | source/include/libsmb_internal.h | 7 | ||||
-rw-r--r-- | source/include/libsmbclient.h | 31 | ||||
-rw-r--r-- | source/libsmb/libsmb_compat.c | 7 | ||||
-rw-r--r-- | source/libsmb/libsmb_context.c | 1 | ||||
-rw-r--r-- | source/libsmb/libsmb_setget.c | 12 | ||||
-rw-r--r-- | source/libsmb/libsmb_stat.c | 56 |
9 files changed, 215 insertions, 6 deletions
diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile index 7ad28dcea0f..728dbe0edbc 100644 --- a/examples/libsmbclient/Makefile +++ b/examples/libsmbclient/Makefile @@ -24,6 +24,7 @@ TESTS= testsmbc \ teststat \ teststat2 \ teststat3 \ + teststatvfs \ testfstatvfs \ testtruncate \ testchmod \ @@ -75,6 +76,10 @@ teststat3: teststat3.o @echo Linking teststat3 $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt +teststatvfs: teststatvfs.o + @echo Linking teststatvfs + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + testfstatvfs: testfstatvfs.o @echo Linking testfstatvfs $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt diff --git a/examples/libsmbclient/testfstatvfs.c b/examples/libsmbclient/testfstatvfs.c index f8a6870a921..b4dafefff60 100644 --- a/examples/libsmbclient/testfstatvfs.c +++ b/examples/libsmbclient/testfstatvfs.c @@ -105,13 +105,13 @@ int main(int argc, char * argv[]) printf("case_sensitive "); } - if (statvfsbuf.f_flag & SMBC_VFS_FEATURE_NO_DFS) + if (statvfsbuf.f_flag & SMBC_VFS_FEATURE_DFS) { - printf("NO_DFS "); + printf("DFS "); } else { - printf("dfs "); + printf("no_dfs "); } printf("\n"); diff --git a/examples/libsmbclient/teststatvfs.c b/examples/libsmbclient/teststatvfs.c new file mode 100644 index 00000000000..8812002d5ce --- /dev/null +++ b/examples/libsmbclient/teststatvfs.c @@ -0,0 +1,96 @@ +#include <sys/types.h> +#include <sys/statvfs.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <libsmbclient.h> +#include "get_auth_data_fn.h" + + +int main(int argc, char * argv[]) +{ + int i; + int fd; + int ret; + int debug = 0; + char * p; + char path[2048]; + struct stat statbuf; + struct statvfs statvfsbuf; + + smbc_init(get_auth_data_fn, debug); + + for (;;) + { + fprintf(stdout, "Path: "); + *path = '\0'; + fgets(path, sizeof(path) - 1, stdin); + if (strlen(path) == 0) + { + return 0; + } + + p = path + strlen(path) - 1; + if (*p == '\n') + { + *p = '\0'; + } + + ret = smbc_statvfs(path, &statvfsbuf); + + if (ret < 0) + { + perror("fstatvfs"); + } + else + { + printf("\n"); + printf("Block Size: %lu\n", statvfsbuf.f_bsize); + printf("Fragment Size: %lu\n", statvfsbuf.f_frsize); + printf("Blocks: %llu\n", statvfsbuf.f_blocks); + printf("Free Blocks: %llu\n", statvfsbuf.f_bfree); + printf("Available Blocks: %llu\n", statvfsbuf.f_bavail); + printf("Files : %llu\n", statvfsbuf.f_files); + printf("Free Files: %llu\n", statvfsbuf.f_ffree); + printf("Available Files: %llu\n", statvfsbuf.f_favail); + printf("File System ID: %lu\n", statvfsbuf.f_fsid); + printf("\n"); + + printf("Flags: 0x%lx\n", statvfsbuf.f_flag); + printf("Extended Features: "); + + if (statvfsbuf.f_flag & SMBC_VFS_FEATURE_NO_UNIXCIFS) + { + printf("NO_UNIXCIFS "); + } + else + { + printf("unixcifs "); + } + + if (statvfsbuf.f_flag & SMBC_VFS_FEATURE_CASE_INSENSITIVE) + { + printf("CASE_INSENSITIVE "); + } + else + { + printf("case_sensitive "); + } + + if (statvfsbuf.f_flag & SMBC_VFS_FEATURE_DFS) + { + printf("DFS "); + } + else + { + printf("no_dfs "); + } + + printf("\n"); + } + } + + return 0; +} diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h index edf3a6ed088..166685c3801 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_statvfs_fn statvfs_fn; smbc_fstatvfs_fn fstatvfs_fn; smbc_ftruncate_fn ftruncate_fn; #if 0 /* Left in libsmbclient.h for backward compatibility */ @@ -503,6 +504,12 @@ SMBC_fstat_ctx(SMBCCTX *context, int +SMBC_statvfs_ctx(SMBCCTX *context, + char *path, + struct statvfs *st); + + +int SMBC_fstatvfs_ctx(SMBCCTX *context, SMBCFILE *file, struct statvfs *st); diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h index ec7e74287f0..67010a5bfe5 100644 --- a/source/include/libsmbclient.h +++ b/source/include/libsmbclient.h @@ -185,7 +185,7 @@ typedef enum smbc_vfs_feature SMBC_VFS_FEATURE_RDONLY = (1 << 0), /* Specific to libsmbclient (high-order bits) */ - SMBC_VFS_FEATURE_NO_DFS = (1 << 29), + SMBC_VFS_FEATURE_DFS = (1 << 29), SMBC_VFS_FEATURE_CASE_INSENSITIVE = (1 << 30), SMBC_VFS_FEATURE_NO_UNIXCIFS = (1 << 31) } smbc_vfs_feature; @@ -869,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_statvfs_fn)(SMBCCTX *c, + char *path, + struct statvfs *st); +smbc_statvfs_fn smbc_getFunctionStatVFS(SMBCCTX *c); +void smbc_setFunctionStatVFS(SMBCCTX *c, smbc_statvfs_fn fn); + typedef int (*smbc_fstatvfs_fn)(SMBCCTX *c, SMBCFILE *file, struct statvfs *st); @@ -1614,6 +1620,28 @@ int smbc_fstat(int fd, struct stat *st); /**@ingroup attribute + * Get file system information for a specified path. + * + * @param url The smb url to get information for + * + * @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_statvfs(char *url, + struct statvfs *st); + +/**@ingroup attribute * Get file system information via an file descriptor. * * @param fd Open file handle from smbc_open(), smbc_creat(), @@ -1636,6 +1664,7 @@ int smbc_fstatvfs(int fd, struct statvfs *st); + /**@ingroup attribute * Truncate a file given a file descriptor * diff --git a/source/libsmb/libsmb_compat.c b/source/libsmb/libsmb_compat.c index 5bebc5ef87d..56d113f31a2 100644 --- a/source/libsmb/libsmb_compat.c +++ b/source/libsmb/libsmb_compat.c @@ -330,6 +330,13 @@ smbc_fstat(int fd, } int +smbc_statvfs(char *path, + struct statvfs *st) +{ + return smbc_getFunctionStatVFS(statcont)(statcont, path, st); +} + +int smbc_fstatvfs(int fd, struct statvfs *st) { diff --git a/source/libsmb/libsmb_context.c b/source/libsmb/libsmb_context.c index fa0de246395..3f8e0c573cb 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_setFunctionStatVFS(context, SMBC_statvfs_ctx); smbc_setFunctionFstatVFS(context, SMBC_fstatvfs_ctx); smbc_setFunctionFstat(context, SMBC_fstat_ctx); smbc_setFunctionOpendir(context, SMBC_opendir_ctx); diff --git a/source/libsmb/libsmb_setget.c b/source/libsmb/libsmb_setget.c index 9fb608b30e7..3493e4f8dd2 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_statvfs_fn +smbc_getFunctionStatVFS(SMBCCTX *c) +{ + return c->internal->posix_emu.statvfs_fn; +} + +void +smbc_setFunctionStatVFS(SMBCCTX *c, smbc_statvfs_fn fn) +{ + c->internal->posix_emu.statvfs_fn = fn; +} + smbc_fstatvfs_fn smbc_getFunctionFstatVFS(SMBCCTX *c) { diff --git a/source/libsmb/libsmb_stat.c b/source/libsmb/libsmb_stat.c index 02088c368bb..bfcacdc87a0 100644 --- a/source/libsmb/libsmb_stat.c +++ b/source/libsmb/libsmb_stat.c @@ -301,6 +301,58 @@ SMBC_fstat_ctx(SMBCCTX *context, } + +/* + * Routine to obtain file system information given a path + */ +int +SMBC_statvfs_ctx(SMBCCTX *context, + char *path, + struct statvfs *st) +{ + int ret; + bool bIsDir; + struct stat statbuf; + SMBCFILE * pFile; + + /* Determine if the provided path is a file or a folder */ + if (SMBC_stat_ctx(context, path, &statbuf) < 0) { + return -1; + } + + /* Is it a file or a directory? */ + if (S_ISDIR(statbuf.st_mode)) { + /* It's a directory. */ + if ((pFile = SMBC_opendir_ctx(context, path)) < 0) { + return -1; + } + bIsDir = true; + } else if (S_ISREG(statbuf.st_mode)) { + /* It's a file. */ + if ((pFile = SMBC_open_ctx(context, path, O_RDONLY, 0)) < 0) { + return -1; + } + bIsDir = false; + } else { + /* It's neither a file nor a directory. Not supported. */ + errno = ENOSYS; + return -1; + } + + /* Now we have an open file handle, so just use SMBC_fstatvfs */ + ret = SMBC_fstatvfs_ctx(context, pFile, st); + + /* Close the file or directory */ + if (bIsDir) { + SMBC_closedir_ctx(context, pFile); + } else { + SMBC_close_ctx(context, pFile); + } + + return ret; +} + + /* * Routine to obtain file system information given an fd */ @@ -411,8 +463,8 @@ SMBC_fstatvfs_ctx(SMBCCTX *context, } /* See if DFS is supported */ - if (! (cli->capabilities & CAP_DFS) || ! cli->dfsroot) { - st->f_flag |= SMBC_VFS_FEATURE_NO_DFS; + if ((cli->capabilities & CAP_DFS) && cli->dfsroot) { + st->f_flag |= SMBC_VFS_FEATURE_DFS; } return 0; |