mirror of
https://github.com/samba-team/samba.git
synced 2025-03-25 14:50:24 +03:00
[Bug 6069] Add a fstatvfs function for libsmbclient
- port functionality from v3_3_test to master Derrell
This commit is contained in:
parent
082ba6a1ad
commit
ae259575c4
@ -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
|
||||
|
122
examples/libsmbclient/testfstatvfs.c
Normal file
122
examples/libsmbclient/testfstatvfs.c
Normal file
@ -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;
|
||||
}
|
96
examples/libsmbclient/teststatvfs.c
Normal file
96
examples/libsmbclient/teststatvfs.c
Normal file
@ -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;
|
||||
}
|
@ -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 ) )
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
@ -1591,6 +1620,52 @@ int smbc_stat(const char *url, struct stat *st);
|
||||
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
|
||||
*
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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,
|
||||
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)
|
||||
{
|
||||
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.
|
||||
******************************************************************************/
|
||||
|
@ -329,6 +329,21 @@ smbc_fstat(int fd,
|
||||
return smbc_getFunctionFstat(statcont)(statcont, file, st);
|
||||
}
|
||||
|
||||
int
|
||||
smbc_statvfs(char *path,
|
||||
struct statvfs *st)
|
||||
{
|
||||
return smbc_getFunctionStatVFS(statcont)(statcont, path, st);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -94,6 +94,8 @@ 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);
|
||||
smbc_setFunctionClosedir(context, SMBC_closedir_ctx);
|
||||
|
@ -659,6 +659,30 @@ 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -300,3 +300,172 @@ SMBC_fstat_ctx(SMBCCTX *context,
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
int
|
||||
SMBC_fstatvfs_ctx(SMBCCTX *context,
|
||||
SMBCFILE *file,
|
||||
struct statvfs *st)
|
||||
{
|
||||
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));
|
||||
|
||||
/*
|
||||
* The state of each flag is such that the same bits are unset as
|
||||
* would typically be unset on a local file system on a POSIX OS. Thus
|
||||
* the bit is on, for example, only for case-insensitive file systems
|
||||
* since most POSIX file systems are case sensitive and fstatvfs()
|
||||
* would typically return zero in these bits on such a local file
|
||||
* system.
|
||||
*/
|
||||
|
||||
/* See if the server has UNIX CIFS support */
|
||||
if (! SERVER_HAS_UNIX_CIFS(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;
|
||||
|
||||
/* Nope. If size data is available... */
|
||||
if (cli_get_fs_full_size_info(cli,
|
||||
&total_allocation_units,
|
||||
&caller_allocation_units,
|
||||
&actual_allocation_units,
|
||||
§ors_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;
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
if (!cli_get_fs_attr_info(cli, &fs_attrs)) {
|
||||
/*
|
||||
* We can't determine the case sensitivity of
|
||||
* the share. We have no choice but to use the
|
||||
* user-specified case sensitivity setting.
|
||||
*/
|
||||
if (! smbc_getOptionCaseSensitive(context)) {
|
||||
st->f_flag |= SMBC_VFS_FEATURE_CASE_INSENSITIVE;
|
||||
}
|
||||
} else {
|
||||
if (! (fs_attrs & FILE_CASE_SENSITIVE_SEARCH)) {
|
||||
st->f_flag |= SMBC_VFS_FEATURE_CASE_INSENSITIVE;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if DFS is supported */
|
||||
if ((cli->capabilities & CAP_DFS) && cli->dfsroot) {
|
||||
st->f_flag |= SMBC_VFS_FEATURE_DFS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user