The branch, master has been updated via ae259575c447e61665c8e7070c476914161b953f (commit) from 082ba6a1ad3a68aff118d96f855a2aa65eaeb359 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit ae259575c447e61665c8e7070c476914161b953f Author: Derrell Lipman <derrell.lip...@unwireduniverse.com> Date: Thu Feb 12 10:39:17 2009 -0500 [Bug 6069] Add a fstatvfs function for libsmbclient - port functionality from v3_3_test to master Derrell ----------------------------------------------------------------------- Summary of changes: examples/libsmbclient/Makefile | 10 ++ examples/libsmbclient/testfstatvfs.c | 122 ++++++++++++++++++++++++ examples/libsmbclient/teststatvfs.c | 96 +++++++++++++++++++ source3/include/includes.h | 1 + source3/include/libsmb_internal.h | 14 +++ source3/include/libsmbclient.h | 75 +++++++++++++++ source3/include/proto.h | 15 +++ source3/libsmb/clifsinfo.c | 145 +++++++++++++++++++++++++++++ source3/libsmb/libsmb_compat.c | 15 +++ source3/libsmb/libsmb_context.c | 2 + source3/libsmb/libsmb_setget.c | 24 +++++ source3/libsmb/libsmb_stat.c | 169 ++++++++++++++++++++++++++++++++++ 12 files changed, 688 insertions(+), 0 deletions(-) create mode 100644 examples/libsmbclient/testfstatvfs.c create mode 100644 examples/libsmbclient/teststatvfs.c Changeset truncated at 500 lines: diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile index 047addc..728dbe0 100644 --- a/examples/libsmbclient/Makefile +++ b/examples/libsmbclient/Makefile @@ -24,6 +24,8 @@ TESTS= testsmbc \ teststat \ teststat2 \ teststat3 \ + teststatvfs \ + testfstatvfs \ testtruncate \ testchmod \ testutime \ @@ -74,6 +76,14 @@ 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 + testtruncate: testtruncate.o @echo Linking testtruncate $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt diff --git a/examples/libsmbclient/testfstatvfs.c b/examples/libsmbclient/testfstatvfs.c new file mode 100644 index 0000000..b4dafef --- /dev/null +++ b/examples/libsmbclient/testfstatvfs.c @@ -0,0 +1,122 @@ +#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'; + } + + /* Determine if it's a file or a folder */ + if (smbc_stat(path, &statbuf) < 0) + { + perror("smbc_stat"); + continue; + } + + if (S_ISREG(statbuf.st_mode)) + { + if ((fd = smbc_open(path, O_RDONLY, 0)) < 0) + { + perror("smbc_open"); + continue; + } + } + else + { + if ((fd = smbc_opendir(path)) < 0) + { + perror("smbc_opendir"); + continue; + } + } + + ret = smbc_fstatvfs(fd, &statvfsbuf); + + smbc_close(fd); + + 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/examples/libsmbclient/teststatvfs.c b/examples/libsmbclient/teststatvfs.c new file mode 100644 index 0000000..8812002 --- /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/source3/include/includes.h b/source3/include/includes.h index fc77534..2c033e8 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -396,6 +396,7 @@ typedef sig_atomic_t volatile SIG_ATOMIC_T; #endif #define SBIG_UINT(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), SIVAL(p,(ofs)+4,(v)>>32)) +#define BIG_UINT(p, ofs) ((((uint64_t) IVAL(p,(ofs)+4))<<32)|IVAL(p,ofs)) #define IVAL2_TO_SMB_BIG_UINT(buf,off) ( (((uint64_t)(IVAL((buf),(off)))) & ((uint64_t)0xFFFFFFFF)) | \ (( ((uint64_t)(IVAL((buf),(off+4)))) & ((uint64_t)0xFFFFFFFF) ) << 32 ) ) diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h index 67add07..166685c 100644 --- a/source3/include/libsmb_internal.h +++ b/source3/include/libsmb_internal.h @@ -197,6 +197,8 @@ 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 */ smbc_close_fn close_fn; @@ -501,6 +503,18 @@ SMBC_fstat_ctx(SMBCCTX *context, struct stat *st); +int +SMBC_statvfs_ctx(SMBCCTX *context, + char *path, + struct statvfs *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/source3/include/libsmbclient.h b/source3/include/libsmbclient.h index b2d9483..d35d9de 100644 --- a/source3/include/libsmbclient.h +++ b/source3/include/libsmbclient.h @@ -75,6 +75,7 @@ extern "C" { /* Make sure we have the following includes for now ... */ #include <sys/types.h> #include <sys/stat.h> +#include <sys/statvfs.h> #include <fcntl.h> #include <utime.h> @@ -174,6 +175,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_feature +{ + /* Defined by POSIX or in Linux include files (low-order bits) */ + SMBC_VFS_FEATURE_RDONLY = (1 << 0), + + /* Specific to libsmbclient (high-order bits) */ + SMBC_VFS_FEATURE_DFS = (1 << 29), + SMBC_VFS_FEATURE_CASE_INSENSITIVE = (1 << 30), + SMBC_VFS_FEATURE_NO_UNIXCIFS = (1 << 31) +} smbc_vfs_feature; + typedef int smbc_bool; @@ -853,6 +870,18 @@ 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); +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 +1621,52 @@ 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(), + * 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/source3/include/proto.h b/source3/include/proto.h index 3478ea4..1b17e02 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2606,6 +2606,21 @@ bool cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, u bool cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr); bool cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number); bool cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate); +bool cli_get_fs_full_size_info(struct cli_state *cli, + uint64_t *total_allocation_units, + uint64_t *caller_allocation_units, + uint64_t *actual_allocation_units, + uint64_t *sectors_per_allocation_unit, + uint64_t *bytes_per_sector); +bool cli_get_posix_fs_info(struct cli_state *cli, + uint32 *optimal_transfer_size, + uint32 *block_size, + uint64_t *total_blocks, + uint64_t *blocks_available, + uint64_t *user_blocks_available, + uint64_t *total_file_nodes, + uint64_t *free_file_nodes, + uint64_t *fs_identifier); NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, const char *user, const char *pass, diff --git a/source3/libsmb/clifsinfo.c b/source3/libsmb/clifsinfo.c index 77290d2..e0ae948 100644 --- a/source3/libsmb/clifsinfo.c +++ b/source3/libsmb/clifsinfo.c @@ -305,6 +305,151 @@ cleanup: return ret; } +bool cli_get_fs_full_size_info(struct cli_state *cli, + uint64_t *total_allocation_units, + uint64_t *caller_allocation_units, + uint64_t *actual_allocation_units, + uint64_t *sectors_per_allocation_unit, + uint64_t *bytes_per_sector) +{ + bool ret = False; + uint16 setup; + char param[2]; + char *rparam=NULL, *rdata=NULL; + unsigned int rparam_count=0, rdata_count=0; + + setup = TRANSACT2_QFSINFO; + + SSVAL(param,0,SMB_FS_FULL_SIZE_INFORMATION); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, + 0, 0, + &setup, 1, 0, + param, 2, 0, + NULL, 0, 560)) { + goto cleanup; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, &rparam_count, + &rdata, &rdata_count)) { + goto cleanup; + } + + if (cli_is_error(cli)) { + ret = False; + goto cleanup; + } else { + ret = True; + } + + if (rdata_count != 32) { + goto cleanup; + } + + if (total_allocation_units) { + *total_allocation_units = BIG_UINT(rdata, 0); + } + if (caller_allocation_units) { + *caller_allocation_units = BIG_UINT(rdata,8); + } + if (actual_allocation_units) { + *actual_allocation_units = BIG_UINT(rdata,16); + } + if (sectors_per_allocation_unit) { + *sectors_per_allocation_unit = IVAL(rdata,24); + } + if (bytes_per_sector) { + *bytes_per_sector = IVAL(rdata,28); -- Samba Shared Repository