The branch, v3-3-test has been updated
       via  eeeceea8b92b8b814209f496a7ab953dcd0a8367 (commit)
      from  0acc962e3968253a3f64b5a92def177ced44994d (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-3-test


- Log -----------------------------------------------------------------
commit eeeceea8b92b8b814209f496a7ab953dcd0a8367
Author: Derrell Lipman <[email protected]>
Date:   Tue Feb 10 15:03:32 2009 -0500

    [Bug 6069] Add a fstatvfs function for libsmbclient
    
    - Fill in the remainder of the data (or at least as much as we can get) for
      the fstatvfs return value.
    
    Derrell

-----------------------------------------------------------------------

Summary of changes:
 examples/libsmbclient/testfstatvfs.c |   15 +++-
 source/include/includes.h            |    2 +
 source/include/proto.h               |   15 ++++
 source/libsmb/clifsinfo.c            |  145 ++++++++++++++++++++++++++++++++++
 source/libsmb/libsmb_stat.c          |   64 +++++++++++++++
 5 files changed, 240 insertions(+), 1 deletions(-)


Changeset truncated at 500 lines:

diff --git a/examples/libsmbclient/testfstatvfs.c 
b/examples/libsmbclient/testfstatvfs.c
index fbb51f1..f8a6870 100644
--- a/examples/libsmbclient/testfstatvfs.c
+++ b/examples/libsmbclient/testfstatvfs.c
@@ -72,7 +72,20 @@ int main(int argc, char * argv[])
         }
         else
         {
-            printf("Features: ");
+            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)
             {
diff --git a/source/include/includes.h b/source/include/includes.h
index d130171..65b4242 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -470,10 +470,12 @@ typedef int VOLATILE SIG_ATOMIC_T;
 #define SMB_BIG_UINT unsigned long long
 #define SMB_BIG_INT long long
 #define SBIG_UINT(p, ofs, v) (SIVAL(p,ofs,(v)&0xFFFFFFFF), 
SIVAL(p,(ofs)+4,(v)>>32))
+#define BIG_UINT(p, ofs) ((((SMB_BIG_UINT) IVAL(p,(ofs)+4))<<32)|IVAL(p,ofs))
 #else
 #define SMB_BIG_UINT unsigned long
 #define SMB_BIG_INT long
 #define SBIG_UINT(p, ofs, v) (SIVAL(p,ofs,v),SIVAL(p,(ofs)+4,0))
+#define BIG_UINT(p, ofs) (IVAL(p,ofs))
 #endif
 
 #define SMB_BIG_UINT_BITS (sizeof(SMB_BIG_UINT)*8)
diff --git a/source/include/proto.h b/source/include/proto.h
index 226f7be..04ceb83 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -4333,6 +4333,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,
+                               SMB_BIG_UINT *total_allocation_units,
+                               SMB_BIG_UINT *caller_allocation_units,
+                               SMB_BIG_UINT *actual_allocation_units,
+                               SMB_BIG_UINT *sectors_per_allocation_unit,
+                               SMB_BIG_UINT *bytes_per_sector);
+bool cli_get_posix_fs_info(struct cli_state *cli,
+                           uint32 *optimal_transfer_size,
+                           uint32 *block_size,
+                           SMB_BIG_UINT *total_blocks,
+                           SMB_BIG_UINT *blocks_available,
+                           SMB_BIG_UINT *user_blocks_available,
+                           SMB_BIG_UINT *total_file_nodes,
+                           SMB_BIG_UINT *free_file_nodes,
+                           SMB_BIG_UINT *fs_identifier);
 NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, 
                                const char *user,
                                const char *pass,
diff --git a/source/libsmb/clifsinfo.c b/source/libsmb/clifsinfo.c
index 5e73b61..dd56f30 100644
--- a/source/libsmb/clifsinfo.c
+++ b/source/libsmb/clifsinfo.c
@@ -303,6 +303,151 @@ cleanup:
        return ret;
 }
 
+bool cli_get_fs_full_size_info(struct cli_state *cli,
+                               SMB_BIG_UINT *total_allocation_units,
+                               SMB_BIG_UINT *caller_allocation_units,
+                               SMB_BIG_UINT *actual_allocation_units,
+                               SMB_BIG_UINT *sectors_per_allocation_unit,
+                               SMB_BIG_UINT *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);
+       }
+
+cleanup:
+       SAFE_FREE(rparam);
+       SAFE_FREE(rdata);
+
+       return ret;
+}
+
+bool cli_get_posix_fs_info(struct cli_state *cli,
+                           uint32 *optimal_transfer_size,
+                           uint32 *block_size,
+                           SMB_BIG_UINT *total_blocks,
+                           SMB_BIG_UINT *blocks_available,
+                           SMB_BIG_UINT *user_blocks_available,
+                           SMB_BIG_UINT *total_file_nodes,
+                           SMB_BIG_UINT *free_file_nodes,
+                           SMB_BIG_UINT *fs_identifier)
+{
+       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_QUERY_POSIX_FS_INFO);
+
+       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 != 56) {
+               goto cleanup;
+       }
+
+       if (optimal_transfer_size) {
+                *optimal_transfer_size = IVAL(rdata, 0);
+       }
+       if (block_size) {
+               *block_size = IVAL(rdata,4);
+       }
+       if (total_blocks) {
+               *total_blocks = BIG_UINT(rdata,8);
+       }
+       if (blocks_available) {
+               *blocks_available = BIG_UINT(rdata,16);
+       }
+       if (user_blocks_available) {
+               *user_blocks_available = BIG_UINT(rdata,24);
+       }
+       if (total_file_nodes) {
+               *total_file_nodes = BIG_UINT(rdata,32);
+       }
+       if (free_file_nodes) {
+               *free_file_nodes = BIG_UINT(rdata,40);
+       }
+       if (fs_identifier) {
+               *fs_identifier = BIG_UINT(rdata,48);
+       }
+
+cleanup:
+       SAFE_FREE(rparam);
+       SAFE_FREE(rdata);
+
+       return ret;
+}
+
+
 /******************************************************************************
  Send/receive the request encryption blob.
 ******************************************************************************/
diff --git a/source/libsmb/libsmb_stat.c b/source/libsmb/libsmb_stat.c
index e5eac59..02088c3 100644
--- a/source/libsmb/libsmb_stat.c
+++ b/source/libsmb/libsmb_stat.c
@@ -312,6 +312,7 @@ SMBC_fstatvfs_ctx(SMBCCTX *context,
 {
        uint32 fs_attrs = 0;
        struct cli_state *cli = file->srv->cli;
+                
 
         /* Initialize all fields (at least until we actually use them) */
         memset(st, 0, sizeof(*st));
@@ -327,7 +328,70 @@ SMBC_fstatvfs_ctx(SMBCCTX *context,
 
         /* See if the server has UNIX CIFS support */
         if (! SERVER_HAS_UNIX_CIFS(cli)) {
+                SMB_BIG_UINT total_allocation_units;
+                SMB_BIG_UINT caller_allocation_units;
+                SMB_BIG_UINT actual_allocation_units;
+                SMB_BIG_UINT sectors_per_allocation_unit;
+                SMB_BIG_UINT bytes_per_sector;
+                
+                /* Nope. If size data is available... */
+                if (cli_get_fs_full_size_info(cli,
+                                              &total_allocation_units,
+                                              &caller_allocation_units,
+                                              &actual_allocation_units,
+                                              &sectors_per_allocation_unit,
+                                              &bytes_per_sector)) {
+
+                        /* ... then provide it */
+                        st->f_bsize =
+                                (unsigned long) bytes_per_sector;
+                        st->f_frsize =
+                                (unsigned long) sectors_per_allocation_unit;
+                        st->f_blocks =
+                                (fsblkcnt_t) total_allocation_units;
+                        st->f_bfree =
+                                (fsblkcnt_t) actual_allocation_units;
+                }
+
                 st->f_flag |= SMBC_VFS_FEATURE_NO_UNIXCIFS;
+        } else {
+                uint32 optimal_transfer_size;
+                uint32 block_size;
+                SMB_BIG_UINT total_blocks;
+                SMB_BIG_UINT blocks_available;
+                SMB_BIG_UINT user_blocks_available;
+                SMB_BIG_UINT total_file_nodes;
+                SMB_BIG_UINT free_file_nodes;
+                SMB_BIG_UINT fs_identifier;
+
+                /* Has UNIXCIFS. If POSIX filesystem info is available... */
+                if (cli_get_posix_fs_info(cli,
+                                          &optimal_transfer_size,
+                                          &block_size,
+                                          &total_blocks,
+                                          &blocks_available,
+                                          &user_blocks_available,
+                                          &total_file_nodes,
+                                          &free_file_nodes,
+                                          &fs_identifier)) {
+
+                        /* ... then what's provided here takes precedence. */
+                        st->f_bsize =
+                                (unsigned long) block_size;
+                        st->f_blocks =
+                                (fsblkcnt_t) total_blocks;
+                        st->f_bfree =
+                                (fsblkcnt_t) blocks_available;
+                        st->f_bavail =
+                                (fsblkcnt_t) user_blocks_available;
+                        st->f_files =
+                                (fsfilcnt_t) total_file_nodes;
+                        st->f_ffree =
+                                (fsfilcnt_t) free_file_nodes;
+                        st->f_fsid =
+                                (unsigned long) fs_identifier;
+                        
+                }
         }
 
         /* See if the share is case sensitive */


-- 
Samba Shared Repository

Reply via email to