diff options
Diffstat (limited to 'examples/libsmbclient')
24 files changed, 3371 insertions, 0 deletions
diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile new file mode 100644 index 0000000..08ff19a --- /dev/null +++ b/examples/libsmbclient/Makefile @@ -0,0 +1,116 @@ +# +CC = gcc + +SAMBA_INCL = -I/usr/local/samba/include +EXTLIB_INCL = -I/usr/include/gtk-1.2 \ + -I/usr/include/glib-1.2 \ + -I/usr/lib/glib/include +EXTLIB_INCL = `gtk-config --cflags` + +DEFS = -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE +CFLAGS = -O0 -g $(SAMBA_INCL) $(EXTLIB_INCL) $(DEFS) + +LDFLAGS = -L/usr/local/samba/lib \ + -lldap -lkrb5 -lgssapi_krb5 +#LIBSMBCLIENT = /usr/local/samba/lib/libsmbclient.so +LIBSMBCLIENT = -lwbclient -lsmbclient -ltalloc -ltdb -ldl -lresolv + +TESTS= testsmbc \ + testacl \ + testacl2 \ + testacl3 \ + testbrowse \ + testbrowse2 \ + teststat \ + teststat2 \ + teststat3 \ + teststatvfs \ + testfstatvfs \ + testtruncate \ + testchmod \ + testutime \ + testread \ + testwrite + +# tree \ + +all: $(TESTS) smbsh + +testsmbc: testsmbc.o + @echo Linking testsmbc + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) + +tree: tree.o + @echo Linking tree + $(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ $< `gtk-config --libs` $(LIBSMBCLIENT) + +testacl: testacl.o + @echo Linking testacl + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testacl2: testacl2.o + @echo Linking testacl2 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testacl3: testacl3.o + @echo Linking testacl3 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testbrowse: testbrowse.o + @echo Linking testbrowse + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testbrowse2: testbrowse2.o + @echo Linking testbrowse2 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +teststat: teststat.o + @echo Linking teststat + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +teststat2: teststat2.o + @echo Linking teststat2 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +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 + +testchmod: testchmod.o + @echo Linking testchmod + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testutime: testutime.o + @echo Linking testutime + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testread: testread.o + @echo Linking testread + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testwrite: testwrite.o + @echo Linking testwrite + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +testctx: testctx.o + @echo Linking testctx + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< $(LIBSMBCLIENT) -lpopt + +smbsh: + make -C smbwrapper + +clean: + @rm -f *.o *~ $(TESTS) + @make -C smbwrapper clean diff --git a/examples/libsmbclient/Makefile.internal.in b/examples/libsmbclient/Makefile.internal.in new file mode 100644 index 0000000..d9f0fd3 --- /dev/null +++ b/examples/libsmbclient/Makefile.internal.in @@ -0,0 +1,138 @@ +# Makefile.internal.in for building the libsmbclient examples +# from within a samba build. +# +# Use Makfile for building the examples with a libsmbclient +# installed to /usr/local/samba + +CC = @CC@ + +SAMBA_DIR = ../../source3 +SAMBA_INCLUDES = -I$(SAMBA_DIR)/include +SAMBA_LIBPATH = -L$(SAMBA_DIR)/bin + +GTK_CFLAGS = `gtk-config --cflags` +GTK_LIBS = `gtk-config --libs` + +#GTK_CFLAGS = `pkg-config gtk+-2.0 --cflags` +#GTK_LIBS = `pkg-config gtk+-2.0 --libs` + +CCFLAGS = @CPPFLAGS@ @CFLAGS@ $(GTK_CFLAGS) $(SAMBA_INCLUDES) + +PICFLAG=@PICFLAG@ +LDFLAGS= $(SAMBA_LIBPATH) @PIE_LDFLAGS@ @LDFLAGS@ + +EXTERNAL_LIBS = @LIBS@ @LDAP_LIBS@ @KRB5_LIBS@ @NSCD_LIBS@ +LIBSMBCLIENT_LIBS = -lwbclient -lsmbclient -ltalloc -ltdb -ldl -lresolv +CMDLINE_LIBS = @POPTLIBS@ +LIBS = $(EXTERNAL_LIBS) $(LIBSMBCLIENT_LIBS) + +# Compile a source file. (.c --> .o) +COMPILE_CC = $(CC) -I. $(CCFLAGS) $(PICFLAG) -c $< -o $@ +COMPILE = $(COMPILE_CC) + +MAKEDIR = || exec false; \ + if test -d "$$dir"; then :; else \ + echo mkdir "$$dir"; \ + mkdir -p "$$dir" >/dev/null 2>&1 || \ + test -d "$$dir" || \ + mkdir "$$dir" || \ + exec false; fi || exec false + +TESTS= testsmbc \ + testacl \ + testacl2 \ + testacl3 \ + testbrowse \ + testbrowse2 \ + teststat \ + teststat2 \ + teststat3 \ + testtruncate \ + testchmod \ + testutime \ + testread \ + testwrite + +# tree \ + +all: $(TESTS) smbsh + +.c.o: + @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ + dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi + @echo Compiling $*.c + @$(COMPILE) && exit 0;\ + echo "The following command failed:" 1>&2;\ + echo "$(COMPILE_CC)" 1>&2;\ + $(COMPILE_CC) >/dev/null 2>&1 + +testsmbc: testsmbc.o + @echo Linking testsmbc + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) + +tree: tree.o + @echo Linking tree + @$(CC) $(GTK_CFLAGS) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(GTK_LIBS) $(LIBS) + +testacl: testacl.o + @echo Linking testacl + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testacl2: testacl2.o + @echo Linking testacl2 + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testacl3: testacl3.o + @echo Linking testacl3 + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testbrowse: testbrowse.o + @echo Linking testbrowse + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testbrowse2: testbrowse2.o + @echo Linking testbrowse2 + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +teststat: teststat.o + @echo Linking teststat + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +teststat2: teststat2.o + @echo Linking teststat2 + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +teststat3: teststat3.o + @echo Linking teststat3 + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testtruncate: testtruncate.o + @echo Linking testtruncate + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testchmod: testchmod.o + @echo Linking testchmod + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testutime: testutime.o + @echo Linking testutime + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testread: testread.o + @echo Linking testread + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testwrite: testwrite.o + @echo Linking testwrite + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +testctx: testctx.o + @echo Linking testctx + @$(CC) $(CCFLAGS) $(LDFLAGS) -o $@ $< $(LIBS) $(CMDLINE_LIBS) + +smbsh: + make -C smbwrapper + +clean: + @rm -f *.o *~ $(TESTS) + @make -C smbwrapper clean diff --git a/examples/libsmbclient/README b/examples/libsmbclient/README new file mode 100644 index 0000000..c45dd8b --- /dev/null +++ b/examples/libsmbclient/README @@ -0,0 +1,17 @@ +Some simple example programs for libsmbclient ... + +testsmbc.c is kinda broken as it has many hardcoded bits in it + +testbrowse.c opens a remote folder and displays its contents + +teststat.c allows comparing the results of smbc_stat() against a local stat() of +the same file. + +tree.c is an example of how you might do some of these things with GTK+ +It needs lots of work but shows you some ways to use libsmbclient. + +smbwrapper implements the old smbsh/smbwrapper mechanism using libsmbclient, in +such a way that it works on Linux + +Richard Sharpe, 17 May 2001 +Derrell Lipman, 30 Mar 2005 diff --git a/examples/libsmbclient/get_auth_data_fn.h b/examples/libsmbclient/get_auth_data_fn.h new file mode 100644 index 0000000..9adb745 --- /dev/null +++ b/examples/libsmbclient/get_auth_data_fn.h @@ -0,0 +1,92 @@ +#include <stdlib.h> + +static void +get_auth_data_fn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) +{ + char temp[128]; + char server[256] = { '\0' }; + char share[256] = { '\0' }; + char workgroup[256] = { '\0' }; + char username[256] = { '\0' }; + char password[256] = { '\0' }; + char *ret; + + static int krb5_set = 1; + + if (strcmp(server, pServer) == 0 && + strcmp(share, pShare) == 0 && + *workgroup != '\0' && + *username != '\0') + { + strncpy(pWorkgroup, workgroup, maxLenWorkgroup - 1); + strncpy(pUsername, username, maxLenUsername - 1); + strncpy(pPassword, password, maxLenPassword - 1); + return; + } + + if (krb5_set && getenv("KRB5CCNAME")) { + krb5_set = 0; + return; + } + + fprintf(stdout, "Workgroup: [%s] ", pWorkgroup); + ret = fgets(temp, sizeof(temp), stdin); + if (ret == NULL) { + return; + } + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pWorkgroup, temp, maxLenWorkgroup - 1); + } + + fprintf(stdout, "Username: [%s] ", pUsername); + ret = fgets(temp, sizeof(temp), stdin); + if (ret == NULL) { + return; + } + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pUsername, temp, maxLenUsername - 1); + } + + fprintf(stdout, "Password: "); + ret = fgets(temp, sizeof(temp), stdin); + if (ret == NULL) { + return; + } + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pPassword, temp, maxLenPassword - 1); + } + + strncpy(workgroup, pWorkgroup, sizeof(workgroup) - 1); + strncpy(username, pUsername, sizeof(username) - 1); + strncpy(password, pPassword, sizeof(password) - 1); + + krb5_set = 1; +} diff --git a/examples/libsmbclient/testacl.c b/examples/libsmbclient/testacl.c new file mode 100644 index 0000000..e0e4eeb --- /dev/null +++ b/examples/libsmbclient/testacl.c @@ -0,0 +1,333 @@ +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <popt.h> +#include "libsmbclient.h" +#include "get_auth_data_fn.h" + +enum acl_mode +{ + SMB_ACL_LIST, + SMB_ACL_GET, + SMB_ACL_SET, + SMB_ACL_DELETE, + SMB_ACL_MODIFY, + SMB_ACL_ADD, + SMB_ACL_CHOWN, + SMB_ACL_CHGRP +}; + + +int main(int argc, const char *argv[]) +{ + int opt; + int flags = 0; + int debug = 0; + int numeric = 0; + int stat_and_retry = 0; + int full_time_names = 0; + enum acl_mode mode = SMB_ACL_LIST; + static const char *the_acl = NULL; + int ret; + char *p; + const char *debugstr; + char path[1024]; + char value[1024]; + poptContext pc; + struct stat st; + struct poptOption long_options[] = + { + POPT_AUTOHELP + { + .longName = "numeric", + .shortName = 'n', + .argInfo = POPT_ARG_NONE, + .arg = &numeric, + .val = 1, + .descrip = "Don't resolve sids or masks to names" + }, + { + .longName = "debug", + .shortName = 'd', + .argInfo = POPT_ARG_INT, + .arg = &debug, + .val = 0, + .descrip = "Set debug level (0-100)" + }, + { + .longName = "full_time_names", + .shortName = 'f', + .argInfo = POPT_ARG_NONE, + .arg = &full_time_names, + .val = 1, + .descrip = "Use new style xattr names, which include CREATE_TIME" + }, + { + .longName = "delete", + .shortName = 'D', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'D', + .descrip = "Delete an acl", + .argDescrip = "ACL" + }, + { + .longName = "modify", + .shortName = 'M', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'M', + .descrip = "Modify an acl", + .argDescrip = "ACL" + }, + { + .longName = "add", + .shortName = 'a', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'a', + .descrip = "Add an acl", + .argDescrip = "ACL" + }, + { + .longName = "set", + .shortName = 'S', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'S', + .descrip = "Set acls", + .argDescrip = "ACLS" + }, + { + .longName = "chown", + .shortName = 'C', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'C', + .descrip = "Change ownership of a file", + .argDescrip = "USERNAME" + }, + { + .longName = "chgrp", + .shortName = 'G', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'G', + .descrip = "Change group ownership of a file", + .argDescrip = "GROUPNAME" + }, + { + .longName = "get", + .shortName = 'g', + .argInfo = POPT_ARG_STRING, + .arg = NULL, + .val = 'g', + .descrip = "Get a specific acl attribute", + .argDescrip = "ACL" + }, + { + .longName = "stat_and_retry", + .shortName = 'R', + .argInfo = POPT_ARG_NONE, + .arg = &stat_and_retry, + .val = 1, + .descrip = "After 'get' do 'stat' and another 'get'" + }, + POPT_TABLEEND + }; + + setbuf(stdout, NULL); + + pc = poptGetContext("smbcacls", argc, argv, long_options, 0); + + poptSetOtherOptionHelp(pc, "smb://server1/share1/filename"); + + while ((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + case 'S': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_SET; + break; + + case 'D': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_DELETE; + break; + + case 'M': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_MODIFY; + break; + + case 'a': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_ADD; + break; + + case 'g': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_GET; + break; + + case 'C': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_CHOWN; + break; + + case 'G': + the_acl = strdup(poptGetOptArg(pc)); + mode = SMB_ACL_CHGRP; + break; + } + } + + /* Make connection to server */ + if(!poptPeekArg(pc)) { + poptPrintUsage(pc, stderr, 0); + return 1; + } + + strncpy(path, poptGetArg(pc), sizeof(path)); + path[sizeof(path)-1] = '\0'; + + if (smbc_init(get_auth_data_fn, debug) != 0) + { + printf("Could not initialize smbc_ library\n"); + return 1; + } + + if (full_time_names) { + SMBCCTX *context = smbc_set_context(NULL); + smbc_setOptionFullTimeNames(context, 1); + } + + /* Perform requested action */ + + switch(mode) + { + case SMB_ACL_LIST: + ret = smbc_listxattr(path, value, sizeof(value)-2); + if (ret < 0) + { + printf("Could not get attribute list for [%s] %d: %s\n", + path, errno, strerror(errno)); + return 1; + } + + /* + * The list of attributes has a series of null-terminated strings. + * The list of strings terminates with an extra null byte, thus two in + * a row. Ensure that our buffer, which is conceivably shorter than + * the list of attributes, actually ends with two null bytes in a row. + */ + value[sizeof(value) - 2] = '\0'; + value[sizeof(value) - 1] = '\0'; + printf("Supported attributes:\n"); + for (p = value; *p; p += strlen(p) + 1) + { + printf("\t%s\n", p); + } + break; + + case SMB_ACL_GET: + do + { + if (the_acl == NULL) + { + if (numeric) + { + the_acl = "system.*"; + } + else + { + the_acl = "system.*+"; + } + } + ret = smbc_getxattr(path, the_acl, value, sizeof(value)); + if (ret < 0) + { + printf("Could not get attributes for [%s] %d: %s\n", + path, errno, strerror(errno)); + return 1; + } + + printf("Attributes for [%s] are:\n%s\n", path, value); + + if (stat_and_retry) + { + if (smbc_stat(path, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + } + + --stat_and_retry; + } while (stat_and_retry >= 0); + break; + + case SMB_ACL_ADD: + flags = SMBC_XATTR_FLAG_CREATE; + debugstr = "add attributes"; + goto do_set; + + case SMB_ACL_MODIFY: + flags = SMBC_XATTR_FLAG_REPLACE; + debugstr = "modify attributes"; + goto do_set; + + case SMB_ACL_CHOWN: + snprintf(value, sizeof(value), + "system.nt_sec_desc.owner%s:%s", + numeric ? "" : "+", the_acl); + the_acl = value; + debugstr = "chown owner"; + goto do_set; + + case SMB_ACL_CHGRP: + snprintf(value, sizeof(value), + "system.nt_sec_desc.group%s:%s", + numeric ? "" : "+", the_acl); + the_acl = value; + debugstr = "change group"; + goto do_set; + + case SMB_ACL_SET: + flags = 0; + debugstr = "set attributes"; + + do_set: + if ((p = strchr(the_acl, ':')) == NULL) + { + printf("Missing value. ACL must be name:value pair\n"); + return 1; + } + + *p++ = '\0'; + + ret = smbc_setxattr(path, the_acl, p, strlen(p), flags); + if (ret < 0) + { + printf("Could not %s for [%s] %d: %s\n", + debugstr, path, errno, strerror(errno)); + return 1; + } + break; + + case SMB_ACL_DELETE: + ret = smbc_removexattr(path, the_acl); + if (ret < 0) + { + printf("Could not remove attribute %s for [%s] %d:%s\n", + the_acl, path, errno, strerror(errno)); + return 1; + } + break; + + default: + printf("operation not yet implemented\n"); + break; + } + + return 0; +} diff --git a/examples/libsmbclient/testacl2.c b/examples/libsmbclient/testacl2.c new file mode 100644 index 0000000..ee48b7b --- /dev/null +++ b/examples/libsmbclient/testacl2.c @@ -0,0 +1,73 @@ +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <popt.h> +#include "libsmbclient.h" +#include "get_auth_data_fn.h" + +enum acl_mode +{ + SMB_ACL_GET, + SMB_ACL_SET, + SMB_ACL_DELETE, + SMB_ACL_MODIFY, + SMB_ACL_ADD, + SMB_ACL_CHOWN, + SMB_ACL_CHGRP +}; + + +int main(int argc, const char *argv[]) +{ + int flags; + int debug = 0; + static char *the_acl = NULL; + int ret; + const char *debugstr; + char value[1024]; + SMBCCTX *context; + + if (smbc_init(get_auth_data_fn, debug) != 0) + { + printf("Could not initialize smbc_ library\n"); + return 1; + } + + context = smbc_set_context(NULL); + smbc_setOptionFullTimeNames(context, 1); + + the_acl = strdup("system.nt_sec_desc.*"); + ret = smbc_getxattr(argv[1], the_acl, value, sizeof(value)); + if (ret < 0) + { + printf("Could not get attributes for [%s] %d: %s\n", + argv[1], errno, strerror(errno)); + return 1; + } + + printf("Attributes for [%s] are:\n%s\n", argv[1], value); + + flags = 0; + debugstr = "set attributes (1st time)"; + + ret = smbc_setxattr(argv[1], the_acl, value, strlen(value), flags); + if (ret < 0) + { + printf("Could not %s for [%s] %d: %s\n", + debugstr, argv[1], errno, strerror(errno)); + return 1; + } + + flags = 0; + debugstr = "set attributes (2nd time)"; + + ret = smbc_setxattr(argv[1], the_acl, value, strlen(value), flags); + if (ret < 0) + { + printf("Could not %s for [%s] %d: %s\n", + debugstr, argv[1], errno, strerror(errno)); + return 1; + } + + return 0; +} diff --git a/examples/libsmbclient/testacl3.c b/examples/libsmbclient/testacl3.c new file mode 100644 index 0000000..e5ec2c8 --- /dev/null +++ b/examples/libsmbclient/testacl3.c @@ -0,0 +1,59 @@ +#include <sys/types.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 ret; + int debug = 0; + char value[2048]; + char path[2048]; + char * the_acl; + char * p; + SMBCCTX * context; + + smbc_init(get_auth_data_fn, debug); + + context = smbc_set_context(NULL); + smbc_setOptionFullTimeNames(context, 1); + + for (;;) + { + fprintf(stdout, "Path: "); + *path = '\0'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + printf("Error reading from stdin\n"); + return 1; + } + if (strlen(path) == 0) + { + return 0; + } + + p = path + strlen(path) - 1; + if (*p == '\n') + { + *p = '\0'; + } + + the_acl = strdup("system.nt_sec_desc.*+"); + ret = smbc_getxattr(path, the_acl, value, sizeof(value)); + if (ret < 0) + { + printf("Could not get attributes for [%s] %d: %s\n", + path, errno, strerror(errno)); + return 1; + } + + printf("Attributes for [%s] are:\n%s\n", path, value); + } + + return 0; +} diff --git a/examples/libsmbclient/testbrowse.c b/examples/libsmbclient/testbrowse.c new file mode 100644 index 0000000..2f2f54e --- /dev/null +++ b/examples/libsmbclient/testbrowse.c @@ -0,0 +1,281 @@ +#include <sys/types.h> +#include <unistd.h> +#include <dirent.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <popt.h> +#include <stdlib.h> +#include <libsmbclient.h> +#include "get_auth_data_fn.h" + +static void browse(char * path, + int scan, + int indent); + + +static void +get_auth_data_with_context_fn(SMBCCTX * context, + const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword); + +int main(int argc, const char *argv[]) +{ + int debug = 0; + int debug_stderr = 0; + int no_auth = 0; + int context_auth = 0; + int scan = 0; + int iterations = -1; + int opt; + char * p; + char buf[1024]; + poptContext pc; + SMBCCTX * context; + struct poptOption long_options[] = + { + POPT_AUTOHELP + { + "debug", 'd', POPT_ARG_INT, &debug, + 0, "Set debug level", "integer" + }, + { + "stderr", 'e', POPT_ARG_NONE, &debug_stderr, + 0, "Debug log to stderr instead of stdout", "integer" + }, + { + "scan", 's', POPT_ARG_NONE, &scan, + 0, "Scan for servers and shares", "integer" + }, + { + "iterations", 'i', POPT_ARG_INT, &iterations, + 0, "Iterations", "integer" + }, + { + "noauth", 'A', POPT_ARG_NONE, &no_auth, + 0, "Do not request authentication data", "integer" + }, + { + "contextauth", 'C', POPT_ARG_NONE, &context_auth, + 0, "Use new authentication function with context", "integer" + }, + {0} + }; + + setbuf(stdout, NULL); + + pc = poptGetContext("opendir", argc, argv, long_options, 0); + + poptSetOtherOptionHelp(pc, ""); + + while ((opt = poptGetNextOpt(pc)) != -1) { + printf("Got option %d = %c\n", opt, opt); + switch (opt) { + } + } + + /* Allocate a new context */ + context = smbc_new_context(); + if (!context) { + printf("Could not allocate new smbc context\n"); + return 1; + } + + /* If we're scanning, do no requests for authentication data */ + if (scan) { + no_auth = 1; + } + + /* Set mandatory options (is that a contradiction in terms?) */ + smbc_setDebug(context, debug); + if (context_auth) { + smbc_setFunctionAuthDataWithContext(context, + get_auth_data_with_context_fn); + smbc_setOptionUserData(context, strdup("hello world")); + } else { + smbc_setFunctionAuthData(context, get_auth_data_fn); + } + + smbc_setOptionUseKerberos(context, 1); + smbc_setOptionFallbackAfterKerberos(context, 1); + + /* If we've been asked to log to stderr instead of stdout, ... */ + if (debug_stderr) { + /* ... then set the option to do so */ + smbc_setOptionDebugToStderr(context, 1); + } + + /* Initialize the context using the previously specified options */ + if (!smbc_init_context(context)) { + smbc_free_context(context, 0); + printf("Could not initialize smbc context\n"); + return 1; + } + + /* Tell the compatibility layer to use this context */ + smbc_set_context(context); + + if (scan) + { + for (; iterations != 0;) { + if (iterations > 0) { + iterations--; + } + + snprintf(buf, sizeof(buf), "smb://"); + browse(buf, scan, 0); + } + } + else + { + for (; iterations != 0;) { + if (iterations > 0) { + iterations--; + } + + fputs("url: ", stdout); + p = fgets(buf, sizeof(buf), stdin); + if (! p) + { + break; + } + + if ((p = strchr(buf, '\n')) != NULL) + { + *p = '\0'; + } + + browse(buf, scan, 0); + } + } + + exit(0); +} + +static void +get_auth_data_with_context_fn(SMBCCTX * context, + const char * pServer, + const char * pShare, + char * pWorkgroup, + int maxLenWorkgroup, + char * pUsername, + int maxLenUsername, + char * pPassword, + int maxLenPassword) +{ + printf("Authenticating with context %p", context); + if (context != NULL) { + char *user_data = smbc_getOptionUserData(context); + printf(" with user data %s", user_data); + } + printf("\n"); + + get_auth_data_fn(pServer, pShare, pWorkgroup, maxLenWorkgroup, + pUsername, maxLenUsername, pPassword, maxLenPassword); +} + +static void browse(char * path, int scan, int indent) +{ + char * p; + char buf[1024]; + int dir; + struct stat st; + struct smbc_dirent * dirent; + + if (! scan) + { + printf("Opening (%s)...\n", path); + } + + if ((dir = smbc_opendir(path)) < 0) + { + printf("Could not open directory [%s] (%d:%s)\n", + path, errno, strerror(errno)); + return; + } + + while ((dirent = smbc_readdir(dir)) != NULL) + { + printf("%*.*s%-30s", indent, indent, "", dirent->name); + + switch(dirent->smbc_type) + { + case SMBC_WORKGROUP: + printf("WORKGROUP"); + break; + + case SMBC_SERVER: + printf("SERVER"); + break; + + case SMBC_FILE_SHARE: + printf("FILE_SHARE"); + break; + + case SMBC_PRINTER_SHARE: + printf("PRINTER_SHARE"); + break; + + case SMBC_COMMS_SHARE: + printf("COMMS_SHARE"); + break; + + case SMBC_IPC_SHARE: + printf("IPC_SHARE"); + break; + + case SMBC_DIR: + printf("DIR"); + break; + + case SMBC_FILE: + printf("FILE"); + + p = path + strlen(path); + strcat(p, "/"); + strcat(p+1, dirent->name); + if (smbc_stat(path, &st) < 0) + { + printf(" unknown size (reason %d: %s)", + errno, strerror(errno)); + } + else + { + printf(" size %lu", (unsigned long) st.st_size); + } + *p = '\0'; + + break; + + case SMBC_LINK: + printf("LINK"); + break; + } + + printf("\n"); + + if (scan && + (dirent->smbc_type == SMBC_WORKGROUP || + dirent->smbc_type == SMBC_SERVER)) + { + /* + * don't append server name to workgroup; what we want is: + * + * smb://workgroup_name + * or + * smb://server_name + * + */ + snprintf(buf, sizeof(buf), "smb://%s", dirent->name); + browse(buf, scan, indent + 2); + } + } + + smbc_closedir(dir); +} diff --git a/examples/libsmbclient/testbrowse2.c b/examples/libsmbclient/testbrowse2.c new file mode 100644 index 0000000..c1d5644 --- /dev/null +++ b/examples/libsmbclient/testbrowse2.c @@ -0,0 +1,169 @@ +/* + * Alternate testbrowse utility provided by Mikhail Kshevetskiy. + * This version tests use of multiple contexts. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <libsmbclient.h> + +int debuglevel = 0; +const char *workgroup = "NT"; +const char *username = "guest"; +const char *password = ""; + +typedef struct smbitem smbitem; +typedef int(*qsort_cmp)(const void *, const void *); + +struct smbitem{ + smbitem *next; + int type; + char name[1]; +}; + +static void smbc_auth_fn( + const char *server, + const char *share, + char *wrkgrp, int wrkgrplen, + char *user, int userlen, + char *passwd, int passwdlen){ + + (void) server; + (void) share; + (void) wrkgrp; + (void) wrkgrplen; + + strncpy(wrkgrp, workgroup, wrkgrplen - 1); wrkgrp[wrkgrplen - 1] = 0; + strncpy(user, username, userlen - 1); user[userlen - 1] = 0; + strncpy(passwd, password, passwdlen - 1); passwd[passwdlen - 1] = 0; +} + +static SMBCCTX* create_smbctx(void){ + SMBCCTX *ctx; + + if ((ctx = smbc_new_context()) == NULL) return NULL; + + smbc_setDebug(ctx, debuglevel); + smbc_setFunctionAuthData(ctx, smbc_auth_fn); + + if (smbc_init_context(ctx) == NULL){ + smbc_free_context(ctx, 1); + return NULL; + } + + return ctx; +} + +static void delete_smbctx(SMBCCTX* ctx){ + smbc_getFunctionPurgeCachedServers(ctx)(ctx); + smbc_free_context(ctx, 1); +} + +static smbitem* get_smbitem_list(SMBCCTX *ctx, char *smb_path){ + SMBCFILE *fd; + struct smbc_dirent *dirent; + smbitem *list = NULL, *item; + + if ((fd = smbc_getFunctionOpendir(ctx)(ctx, smb_path)) == NULL) + return NULL; + while((dirent = smbc_getFunctionReaddir(ctx)(ctx, fd)) != NULL){ + size_t slen; + if (strcmp(dirent->name, "") == 0) continue; + if (strcmp(dirent->name, ".") == 0) continue; + if (strcmp(dirent->name, "..") == 0) continue; + + slen = strlen(dirent->name)+1; + if ((item = malloc(sizeof(smbitem) + slen)) == NULL) + continue; + + item->next = list; + item->type = dirent->smbc_type; + memcpy(item->name, dirent->name, slen); + list = item; + } + smbc_getFunctionClose(ctx)(ctx, fd); + return /* smbitem_list_sort */ (list); +} + +static void print_smb_path(const char *group, const char *path){ + if ((strlen(group) == 0) && (strlen(path) == 0)) printf("/\n"); + else if (strlen(path) == 0) printf("/%s\n", group); + else{ + if (strlen(group) == 0) group = "(unknown_group)"; + printf("/%s/%s\n", group, path); + } +} + +static void recurse(SMBCCTX *ctx, const char *smb_group, char *smb_path, int maxlen){ + int len; + smbitem *list, *item; + SMBCCTX *ctx1; + + len = strlen(smb_path); + + list = get_smbitem_list(ctx, smb_path); + while(list != NULL){ + switch(list->type){ + case SMBC_WORKGROUP: + case SMBC_SERVER: + if (list->type == SMBC_WORKGROUP){ + print_smb_path(list->name, ""); + smb_group = list->name; + } + else print_smb_path(smb_group, list->name); + + if (maxlen < 7 + strlen(list->name)) break; + strncpy(smb_path + 6, list->name, maxlen - 6); + smb_path[maxlen-1] = '\0'; + if ((ctx1 = create_smbctx()) != NULL){ + recurse(ctx1, smb_group, smb_path, maxlen); + delete_smbctx(ctx1); + }else{ + recurse(ctx, smb_group, smb_path, maxlen); + smbc_getFunctionPurgeCachedServers(ctx)(ctx); + } + break; + case SMBC_FILE_SHARE: + case SMBC_DIR: + case SMBC_FILE: + if (maxlen < len + strlen(list->name) + 2) break; + + smb_path[len] = '/'; + strncpy(smb_path + len + 1, list->name, maxlen - len - 1); + smb_path[maxlen-1] = '\0'; + print_smb_path(smb_group, smb_path + 6); + if (list->type != SMBC_FILE){ + recurse(ctx, smb_group, smb_path, maxlen); + if (list->type == SMBC_FILE_SHARE) + smbc_getFunctionPurgeCachedServers(ctx)(ctx); + } + break; + } + item = list; + list = list->next; + free(item); + } + smb_path[len] = '\0'; +} + +int main(int argc, char *argv[]){ + int i; + SMBCCTX *ctx; + char smb_path[32768] = "smb://"; + + if ((ctx = create_smbctx()) == NULL){ + perror("Can't create samba context."); + return 1; + } + + if (argc == 1) recurse(ctx, "", smb_path, sizeof(smb_path)); + else for(i = 1; i < argc; i++){ + strncpy(smb_path + 6, argv[i], sizeof(smb_path) - 7); + smb_path[sizeof(smb_path) - 1] = '\0'; + recurse(ctx, "", smb_path, sizeof(smb_path)); + } + + delete_smbctx(ctx); + return 0; +} diff --git a/examples/libsmbclient/testchmod.c b/examples/libsmbclient/testchmod.c new file mode 100644 index 0000000..2341e81 --- /dev/null +++ b/examples/libsmbclient/testchmod.c @@ -0,0 +1,62 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <libsmbclient.h> +#include "get_auth_data_fn.h" + + +int main(int argc, char * argv[]) +{ + int debug = 0; + int mode = 0666; + const char * pSmbPath = NULL; + struct stat st; + + if (argc == 1) + { + pSmbPath = "smb://RANDOM/Public/small"; + } + else if (argc == 2) + { + pSmbPath = argv[1]; + } + else if (argc == 3) + { + pSmbPath = argv[1]; + mode = (int) strtol(argv[2], NULL, 8); + } + else + { + printf("usage: " + "%s [ smb://path/to/file [ octal_mode ] ]\n", + argv[0]); + return 1; + } + + smbc_init(get_auth_data_fn, debug); + + if (smbc_stat(pSmbPath, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("\nBefore chmod: mode = %04o\n", (unsigned int)st.st_mode); + + if (smbc_chmod(pSmbPath, mode) < 0) + { + perror("smbc_chmod"); + return 1; + } + + if (smbc_stat(pSmbPath, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("After chmod: mode = %04o\n", (unsigned int)st.st_mode); + + return 0; +} diff --git a/examples/libsmbclient/testctx.c b/examples/libsmbclient/testctx.c new file mode 100644 index 0000000..e410731 --- /dev/null +++ b/examples/libsmbclient/testctx.c @@ -0,0 +1,33 @@ +#include <libsmbclient.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static void create_and_destroy_context (void) +{ + int i; + SMBCCTX *ctx; + ctx = smbc_new_context (); + /* Both should do the same thing */ + smbc_setOptionDebugToStderr(ctx, 1); + smbc_option_set(ctx, strdup("debug_to_stderr"), 1); + smbc_setDebug(ctx, 1); + i = smbc_getDebug(ctx); + if (i != 1) { + printf("smbc_getDebug() did not return debug level set\n"); + exit(1); + } + if (!smbc_getOptionDebugToStderr(ctx)) { + printf("smbc_setOptionDebugToStderr() did not stick\n"); + exit(1); + } + smbc_init_context (ctx); + smbc_free_context (ctx, 1); +} + +int main (int argc, char **argv) +{ + create_and_destroy_context (); + create_and_destroy_context (); + return 0; +} diff --git a/examples/libsmbclient/testfstatvfs.c b/examples/libsmbclient/testfstatvfs.c new file mode 100644 index 0000000..9a4063e --- /dev/null +++ b/examples/libsmbclient/testfstatvfs.c @@ -0,0 +1,134 @@ +#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 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'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + fprintf(stderr, "failed to read from stdin\n"); + return 1; + } + 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", + (unsigned long long) statvfsbuf.f_blocks); + printf("Free Blocks: %llu\n", + (unsigned long long) statvfsbuf.f_bfree); + printf("Available Blocks: %llu\n", + (unsigned long long) statvfsbuf.f_bavail); + printf("Files : %llu\n", + (unsigned long long) statvfsbuf.f_files); + printf("Free Files: %llu\n", + (unsigned long long) statvfsbuf.f_ffree); + printf("Available Files: %llu\n", + (unsigned long long) statvfsbuf.f_favail); +#ifdef HAVE_FSID_INT + printf("File System ID: %lu\n", + (unsigned long) statvfsbuf.f_fsid); +#endif + 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/testnotify.c b/examples/libsmbclient/testnotify.c new file mode 100644 index 0000000..8760cf0 --- /dev/null +++ b/examples/libsmbclient/testnotify.c @@ -0,0 +1,82 @@ +#include <sys/types.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <libsmbclient.h> +#include <inttypes.h> +#include "get_auth_data_fn.h" + +static int notify_cb(const struct smbc_notify_callback_action *actions, + size_t num_actions, void *private_data) +{ + int *count = private_data; + size_t i; + + printf("%zu\n", num_actions); + + for (i=0; i<num_actions; i++) { + const struct smbc_notify_callback_action *a = &actions[i]; + printf("%s: %"PRIu32"\n", a->filename, a->action); + } + + *count -= 1; + if (*count < 0) { + return 1; + } + + return 0; +} + +int main(int argc, char * argv[]) +{ + int fd; + int ret; + int debug = 0; + int saved_errno; + char path[2048]; + char * p; + int count = 1000; + + smbc_init(get_auth_data_fn, debug); + + fprintf(stdout, "Path: "); + *path = '\0'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + fprintf(stderr, "error reading from stdin\n"); + return 1; + } + if (strlen(path) == 0) { + return 0; + } + + p = path + strlen(path) - 1; + if (*p == '\n') { + *p = '\0'; + } + + fd = smbc_opendir(path); + if (fd < 0) { + perror("smbc_open"); + return 1; + } + + ret = smbc_notify(fd, 1, + SMBC_NOTIFY_CHANGE_SECURITY| + SMBC_NOTIFY_CHANGE_FILE_NAME, + 1000, notify_cb, &count); + if (ret < 0) { + saved_errno = errno; + } + + smbc_close(fd); + + if (ret < 0) { + errno = saved_errno; + perror("notify"); + } + + return 0; +} diff --git a/examples/libsmbclient/testread.c b/examples/libsmbclient/testread.c new file mode 100644 index 0000000..d9722ad --- /dev/null +++ b/examples/libsmbclient/testread.c @@ -0,0 +1,66 @@ +#include <sys/types.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 fd; + int ret; + int debug = 0; + int savedErrno; + char buffer[2048]; + char path[2048]; + char * p; + + smbc_init(get_auth_data_fn, debug); + + for (;;) + { + fprintf(stdout, "Path: "); + *path = '\0'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + fprintf(stderr, "failed to read from stdin\n"); + return 1; + } + if (strlen(path) == 0) + { + return 0; + } + + p = path + strlen(path) - 1; + if (*p == '\n') + { + *p = '\0'; + } + + if ((fd = smbc_open(path, O_RDONLY, 0)) < 0) + { + perror("smbc_open"); + continue; + } + + do + { + ret = smbc_read(fd, buffer, sizeof(buffer)); + savedErrno = errno; + if (ret > 0) fwrite(buffer, 1, ret, stdout); + } while (ret > 0); + + smbc_close(fd); + + if (ret < 0) + { + errno = savedErrno; + perror("read"); + } + } + + return 0; +} diff --git a/examples/libsmbclient/testsmbc.c b/examples/libsmbclient/testsmbc.c new file mode 100644 index 0000000..a61d38e --- /dev/null +++ b/examples/libsmbclient/testsmbc.c @@ -0,0 +1,291 @@ +/* + Unix SMB/CIFS implementation. + SMB client library test program + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2000 + Copyright (C) John Terpsra 2000 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <errno.h> +#include <time.h> +#include <sys/time.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include "libsmbclient.h" +#include "get_auth_data_fn.h" + +int main(int argc, char *argv[]) +{ + int err, fd, dh1, dsize, dirc; + const char *file = "smb://samba/public/testfile.txt"; + const char *file2 = "smb://samba/public/testfile2.txt"; + char buff[256]; + char dirbuf[512]; + char *dirp; + struct stat st1, st2; + + err = smbc_init(get_auth_data_fn, 10); /* Initialize things */ + + if (err < 0) { + + fprintf(stderr, "Initializing the smbclient library ...: %s\n", strerror(errno)); + + } + + if (argc > 1) { + + if ((dh1 = smbc_opendir(argv[1]))<1) { + + fprintf(stderr, "Could not open directory: %s: %s\n", + argv[1], strerror(errno)); + + exit(1); + + } + + fprintf(stdout, "Directory handle: %u\n", dh1); + + /* Now, list those directories, but in funny ways ... */ + + dirp = (char *)dirbuf; + + if ((dirc = smbc_getdents(dh1, (struct smbc_dirent *)dirp, + sizeof(dirbuf))) < 0) { + + fprintf(stderr, "Problems getting directory entries: %s\n", + strerror(errno)); + + exit(1); + + } + + /* Now, process the list of names ... */ + + fprintf(stdout, "Directory listing, size = %u\n", dirc); + + while (dirc > 0) { + + dsize = ((struct smbc_dirent *)dirp)->dirlen; + fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n", + ((struct smbc_dirent *)dirp)->smbc_type, + ((struct smbc_dirent *)dirp)->name, + ((struct smbc_dirent *)dirp)->comment); + + dirp += dsize; + dirc -= dsize; + + } + + dirp = (char *)dirbuf; + + exit(1); + + } + + /* For now, open a file on a server that is hard coded ... later will + * read from the command line ... + */ + + fd = smbc_open(file, O_RDWR | O_CREAT | O_TRUNC, 0666); + + if (fd < 0) { + + fprintf(stderr, "Creating file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Opened or created file: %s\n", file); + + /* Now, write some date to the file ... */ + + memset(buff, '\0', sizeof(buff)); + snprintf(buff, sizeof(buff), "%s", "Some test data for the moment ..."); + + err = smbc_write(fd, buff, sizeof(buff)); + + if (err < 0) { + + fprintf(stderr, "writing file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Wrote %lu bytes to file: %s\n", + (unsigned long) sizeof(buff), buff); + + /* Now, seek the file back to offset 0 */ + + err = smbc_lseek(fd, SEEK_SET, 0); + + if (err < 0) { + + fprintf(stderr, "Seeking file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Completed lseek on file: %s\n", file); + + /* Now, read the file contents back ... */ + + err = smbc_read(fd, buff, sizeof(buff)); + + if (err < 0) { + + fprintf(stderr, "Reading file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Read file: %s\n", buff); /* Should check the contents */ + + fprintf(stdout, "Now fstat'ing file: %s\n", file); + + err = smbc_fstat(fd, &st1); + + if (err < 0) { + + fprintf(stderr, "Fstat'ing file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + + /* Now, close the file ... */ + + err = smbc_close(fd); + + if (err < 0) { + + fprintf(stderr, "Closing file: %s: %s\n", file, strerror(errno)); + + } + + /* Now, rename the file ... */ + + err = smbc_rename(file, file2); + + if (err < 0) { + + fprintf(stderr, "Renaming file: %s to %s: %s\n", file, file2, strerror(errno)); + + } + + fprintf(stdout, "Renamed file %s to %s\n", file, file2); + + /* Now, create a file and delete it ... */ + + fprintf(stdout, "Now, creating file: %s so we can delete it.\n", file); + + fd = smbc_open(file, O_RDWR | O_CREAT, 0666); + + if (fd < 0) { + + fprintf(stderr, "Creating file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Opened or created file: %s\n", file); + + err = smbc_close(fd); + + if (err < 0) { + + fprintf(stderr, "Closing file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + /* Now, delete the file ... */ + + fprintf(stdout, "File %s created, now deleting ...\n", file); + + err = smbc_unlink(file); + + if (err < 0) { + + fprintf(stderr, "Deleting file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + /* Now, stat the file, file 2 ... */ + + fprintf(stdout, "Now stat'ing file: %s\n", file); + + err = smbc_stat(file2, &st2); + + if (err < 0) { + + fprintf(stderr, "Stat'ing file: %s: %s\n", file, strerror(errno)); + exit(0); + + } + + fprintf(stdout, "Stat'ed file: %s. Size = %d, mode = %04X\n", file2, + (int)st2.st_size, (unsigned int)st2.st_mode); + fprintf(stdout, " time: %s\n", ctime(&st2.st_atime)); + fprintf(stdout, "Earlier stat: %s, Size = %d, mode = %04X\n", file, + (int)st1.st_size, (unsigned int)st1.st_mode); + fprintf(stdout, " time: %s\n", ctime(&st1.st_atime)); + + /* Now, make a directory ... */ + + fprintf(stdout, "Making directory smb://samba/public/make-dir\n"); + + if (smbc_mkdir("smb://samba/public/make-dir", 0666) < 0) { + + fprintf(stderr, "Error making directory: smb://samba/public/make-dir: %s\n", + strerror(errno)); + + if (errno == EEXIST) { /* Try to delete the directory */ + + fprintf(stdout, "Trying to delete directory: smb://samba/public/make-dir\n"); + + if (smbc_rmdir("smb://samba/public/make-dir") < 0) { /* Error */ + + fprintf(stderr, "Error removing directory: smb://samba/public/make-dir: %s\n", strerror(errno)); + + exit(0); + + } + + fprintf(stdout, "Making directory: smb://samba/public/make-dir\n"); + + if (smbc_mkdir("smb://samba/public/make-dir", 666) < 0) { + + fprintf(stderr, "Error making directory: smb://samba/public/make-dir: %s\n", + strerror(errno)); + + fprintf(stderr, "I give up!\n"); + + exit(1); + + } + + } + + exit(0); + + } + + fprintf(stdout, "Made dir: make-dir\n"); + return 0; +} diff --git a/examples/libsmbclient/teststat.c b/examples/libsmbclient/teststat.c new file mode 100644 index 0000000..079ac89 --- /dev/null +++ b/examples/libsmbclient/teststat.c @@ -0,0 +1,110 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <libsmbclient.h> +#include <stdbool.h> +#include "get_auth_data_fn.h" + +static const char *filetypestr(mode_t mode) +{ + if (S_ISREG(mode)) { + return "regular file"; + } + if (S_ISDIR(mode)) { + return "directory"; + } + if (S_ISFIFO(mode)) { + return "fifo"; + } + if (S_ISLNK(mode)) { + return "symbolic link"; + } + if (S_ISSOCK(mode)) { + return "socket"; + } + if (S_ISCHR(mode)) { + return "character special file"; + } + if (S_ISBLK(mode)) { + return "block special file"; + } + return "unknown file type"; +} + +int main(int argc, char * argv[]) +{ + SMBCCTX *ctx = NULL; + int debug = 0; + char m_time[32]; + char c_time[32]; + char a_time[32]; + const char * pSmbPath = NULL; + const char * pLocalPath = NULL; + struct stat st; + int ret; + + if (argc == 1) { + pSmbPath = "smb://RANDOM/Public/small"; + pLocalPath = "/random/home/samba/small"; + } + else if (argc == 2) { + pSmbPath = argv[1]; + pLocalPath = NULL; + } + else if (argc == 3) { + pSmbPath = argv[1]; + pLocalPath = argv[2]; + } else { + printf("usage: %s [ smb://path/to/file " + "[ /nfs/or/local/path/to/file ] ]\n", + argv[0]); + return 1; + } + + ctx = smbc_new_context(); + if (ctx == NULL) { + perror("smbc_new_context failed"); + return 1; + } + + smbc_setOptionDebugToStderr(ctx, 1); + smbc_setDebug(ctx, debug); + smbc_init_context(ctx); + smbc_setFunctionAuthData(ctx, get_auth_data_fn); + smbc_setOptionPosixExtensions(ctx, true); + + ret = smbc_getFunctionStat(ctx)(ctx, pSmbPath, &st); + if (ret < 0) { + perror("smbc_stat"); + return 1; + } + + printf("\nSAMBA\n mtime:%jd/%s ctime:%jd/%s atime:%jd/%s %s\n", + (intmax_t)st.st_mtime, + ctime_r(&st.st_mtime, m_time), + (intmax_t)st.st_ctime, + ctime_r(&st.st_ctime, c_time), + (intmax_t)st.st_atime, + ctime_r(&st.st_atime, a_time), + filetypestr(st.st_mode)); + + if (pLocalPath != NULL) { + ret = stat(pLocalPath, &st); + if (ret < 0) { + perror("stat"); + return 1; + } + + printf("LOCAL\n mtime:%jd/%s ctime:%jd/%s atime:%jd/%s %s\n", + (intmax_t)st.st_mtime, + ctime_r(&st.st_mtime, m_time), + (intmax_t)st.st_ctime, + ctime_r(&st.st_ctime, c_time), + (intmax_t)st.st_atime, + ctime_r(&st.st_atime, a_time), + filetypestr(st.st_mode)); + } + + return 0; +} diff --git a/examples/libsmbclient/teststat2.c b/examples/libsmbclient/teststat2.c new file mode 100644 index 0000000..04994b7 --- /dev/null +++ b/examples/libsmbclient/teststat2.c @@ -0,0 +1,70 @@ +#include <libsmbclient.h> +#include <sys/stat.h> +#include <string.h> +#include <stdio.h> +#include <time.h> +#include "get_auth_data_fn.h" + +/* + * This test is intended to ensure that the timestamps returned by + * libsmbclient are the same as timestamps returned by the local system. To + * test this, we assume a working Samba environment, and access the same + * file via SMB and locally (or NFS). + * + */ + + +static int gettime(const char * pUrl, + const char * pLocalPath); + + +int main(int argc, char* argv[]) +{ + if(argc != 3) + { + printf("usage: %s <file_url> <file_localpath>\n", argv[0]); + return 1; + } + + gettime(argv[1], argv[2]); + return 0; +} + + +static int gettime(const char * pUrl, + const char * pLocalPath) +{ + struct stat st; + char m_time[32]; + char c_time[32]; + char a_time[32]; + + smbc_init(get_auth_data_fn, 0); + + if (smbc_stat(pUrl, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("SAMBA\n mtime:%lld/%s ctime:%lld/%s atime:%lld/%s\n", + (long long)st.st_mtime, ctime_r(&st.st_mtime, m_time), + (long long)st.st_ctime, ctime_r(&st.st_ctime, c_time), + (long long)st.st_atime, ctime_r(&st.st_atime, a_time)); + + + /* check the stat on this file */ + if (stat(pLocalPath, &st) < 0) + { + perror("stat"); + return 1; + } + + printf("LOCAL\n mtime:%lld/%s ctime:%lld/%s atime:%lld/%s\n", + (long long)st.st_mtime, ctime_r(&st.st_mtime, m_time), + (long long)st.st_ctime, ctime_r(&st.st_ctime, c_time), + (long long)st.st_atime, ctime_r(&st.st_atime, a_time)); + + + return 0; +} diff --git a/examples/libsmbclient/teststat3.c b/examples/libsmbclient/teststat3.c new file mode 100644 index 0000000..3669d70 --- /dev/null +++ b/examples/libsmbclient/teststat3.c @@ -0,0 +1,74 @@ +#include <libsmbclient.h> +#include <sys/stat.h> +#include <string.h> +#include <stdio.h> +#include <time.h> +#include "get_auth_data_fn.h" + +/* + * This test is intended to ensure that the timestamps returned by + * libsmbclient using smbc_stat() are the same as those returned by + * smbc_fstat(). + */ + + +int main(int argc, char* argv[]) +{ + int fd; + struct stat st1; + struct stat st2; + char * pUrl = argv[1]; + + if(argc != 2) + { + printf("usage: %s <file_url>\n", argv[0]); + return 1; + } + + + smbc_init(get_auth_data_fn, 0); + + if (smbc_stat(pUrl, &st1) < 0) + { + perror("smbc_stat"); + return 1; + } + + if ((fd = smbc_open(pUrl, O_RDONLY, 0)) < 0) + { + perror("smbc_open"); + return 1; + } + + if (smbc_fstat(fd, &st2) < 0) + { + perror("smbc_fstat"); + return 1; + } + + smbc_close(fd); + +#define COMPARE(name, field) \ + if (st1.field != st2.field) \ + { \ + printf("Field " name " MISMATCH: st1=%lu, st2=%lu\n", \ + (unsigned long) st1.field, \ + (unsigned long) st2.field); \ + } + + COMPARE("st_dev", st_dev); + COMPARE("st_ino", st_ino); + COMPARE("st_mode", st_mode); + COMPARE("st_nlink", st_nlink); + COMPARE("st_uid", st_uid); + COMPARE("st_gid", st_gid); + COMPARE("st_rdev", st_rdev); + COMPARE("st_size", st_size); + COMPARE("st_blksize", st_blksize); + COMPARE("st_blocks", st_blocks); + COMPARE("st_atime", st_atime); + COMPARE("st_mtime", st_mtime); + COMPARE("st_ctime", st_ctime); + + return 0; +} diff --git a/examples/libsmbclient/teststatvfs.c b/examples/libsmbclient/teststatvfs.c new file mode 100644 index 0000000..44d4ed2 --- /dev/null +++ b/examples/libsmbclient/teststatvfs.c @@ -0,0 +1,106 @@ +#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 ret; + int debug = 0; + char * p; + char path[2048]; + struct statvfs statvfsbuf; + + smbc_init(get_auth_data_fn, debug); + + for (;;) + { + fprintf(stdout, "Path: "); + *path = '\0'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + fprintf(stderr, "failed to read from stdin\n"); + return 1; + } + 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", + (unsigned long long) statvfsbuf.f_blocks); + printf("Free Blocks: %llu\n", + (unsigned long long) statvfsbuf.f_bfree); + printf("Available Blocks: %llu\n", + (unsigned long long) statvfsbuf.f_bavail); + printf("Files : %llu\n", + (unsigned long long) statvfsbuf.f_files); + printf("Free Files: %llu\n", + (unsigned long long) statvfsbuf.f_ffree); + printf("Available Files: %llu\n", + (unsigned long long) statvfsbuf.f_favail); +#ifdef HAVE_FSID_INT + printf("File System ID: %lu\n", + (unsigned long) statvfsbuf.f_fsid); +#endif + 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/testtruncate.c b/examples/libsmbclient/testtruncate.c new file mode 100644 index 0000000..bbc70e9 --- /dev/null +++ b/examples/libsmbclient/testtruncate.c @@ -0,0 +1,80 @@ +#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 fd; + int ret; + int debug = 0; + int savedErrno; + char buffer[128]; + struct stat st; + + if (argc != 2) + { + printf("usage: " + "%s smb://path/to/file\n", + argv[0]); + return 1; + } + + smbc_init(get_auth_data_fn, debug); + + if ((fd = smbc_open(argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0)) < 0) + { + perror("smbc_open"); + return 1; + } + + snprintf(buffer, sizeof(buffer), "%s", "Hello world.\nThis is a test.\n"); + + ret = smbc_write(fd, buffer, strlen(buffer)); + savedErrno = errno; + smbc_close(fd); + + if (ret < 0) + { + errno = savedErrno; + perror("write"); + } + + if (smbc_stat(argv[1], &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("Original size: %lu\n", (unsigned long) st.st_size); + + if ((fd = smbc_open(argv[1], O_WRONLY, 0)) < 0) + { + perror("smbc_open"); + return 1; + } + + ret = smbc_ftruncate(fd, 13); + savedErrno = errno; + smbc_close(fd); + if (ret < 0) + { + errno = savedErrno; + perror("smbc_ftruncate"); + return 1; + } + + if (smbc_stat(argv[1], &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("New size: %lu\n", (unsigned long) st.st_size); + + return 0; +} diff --git a/examples/libsmbclient/testutime.c b/examples/libsmbclient/testutime.c new file mode 100644 index 0000000..378b0e9 --- /dev/null +++ b/examples/libsmbclient/testutime.c @@ -0,0 +1,75 @@ +#include "config.h" +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <time.h> +#include <libsmbclient.h> +#include "get_auth_data_fn.h" + + +int main(int argc, char * argv[]) +{ + int debug = 0; + char m_time[32]; + char c_time[32]; + char a_time[32]; + const char * pSmbPath = NULL; + time_t t = time(NULL); + struct stat st; + struct utimbuf utimbuf; + + if (argc == 1) + { + pSmbPath = "smb://RANDOM/Public/small"; + } + else if (argc == 2) + { + pSmbPath = argv[1]; + } + else if (argc == 3) + { + pSmbPath = argv[1]; + t = (time_t) strtol(argv[2], NULL, 10); + } + else + { + printf("usage: " + "%s [ smb://path/to/file [ mtime ] ]\n", + argv[0]); + return 1; + } + + smbc_init(get_auth_data_fn, debug); + + if (smbc_stat(pSmbPath, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("Before\n mtime:%lld/%s ctime:%lld/%s atime:%lld/%s\n", + (long long)st.st_mtime, ctime_r(&st.st_mtime, m_time), + (long long)st.st_ctime, ctime_r(&st.st_ctime, c_time), + (long long)st.st_atime, ctime_r(&st.st_atime, a_time)); + + utimbuf.actime = t; /* unchangeable (won't change) */ + utimbuf.modtime = t; /* this one should succeed */ + if (smbc_utime(pSmbPath, &utimbuf) < 0) + { + perror("smbc_utime"); + return 1; + } + + if (smbc_stat(pSmbPath, &st) < 0) + { + perror("smbc_stat"); + return 1; + } + + printf("After\n mtime:%lld/%s ctime:%lld/%s atime:%lld/%s\n", + (long long)st.st_mtime, ctime_r(&st.st_mtime, m_time), + (long long)st.st_ctime, ctime_r(&st.st_ctime, c_time), + (long long)st.st_atime, ctime_r(&st.st_atime, a_time)); + + return 0; +} diff --git a/examples/libsmbclient/testwrite.c b/examples/libsmbclient/testwrite.c new file mode 100644 index 0000000..0e728e0 --- /dev/null +++ b/examples/libsmbclient/testwrite.c @@ -0,0 +1,72 @@ +#include <sys/types.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 fd; + int ret; + int debug = 0; + int savedErrno; + char buffer[2048]; + char path[2048]; + char * p; + + smbc_init(get_auth_data_fn, debug); + + printf("CAUTION: This program will overwrite a file. " + "Press ENTER to continue."); + p = fgets(buffer, sizeof(buffer), stdin); + if (p == NULL) { + fprintf(stderr, "failed to read from stdin\n"); + return 1; + } + + + for (;;) + { + fprintf(stdout, "\nPath: "); + *path = '\0'; + p = fgets(path, sizeof(path) - 1, stdin); + if (p == NULL) { + fprintf(stderr, "failed to read from stdin\n"); + return 1; + } + if (strlen(path) == 0) + { + return 0; + } + + p = path + strlen(path) - 1; + if (*p == '\n') + { + *p = '\0'; + } + + if ((fd = smbc_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0)) < 0) + { + perror("smbc_open"); + continue; + } + + snprintf(buffer, sizeof(buffer), "%s", "Hello world\n"); + + ret = smbc_write(fd, buffer, strlen(buffer)); + savedErrno = errno; + smbc_close(fd); + + if (ret < 0) + { + errno = savedErrno; + perror("write"); + } + } + + return 0; +} diff --git a/examples/libsmbclient/tree.c b/examples/libsmbclient/tree.c new file mode 100644 index 0000000..07847c8 --- /dev/null +++ b/examples/libsmbclient/tree.c @@ -0,0 +1,812 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + SMB client GTK+ tree-based application + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Richard Sharpe 2001 + Copyright (C) John Terpstra 2001 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/* example-gtk+ application, ripped off from the gtk+ tree.c sample */ + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <gtk/gtk.h> +#include "libsmbclient.h" + +static GtkWidget *clist; + +struct tree_data { + + guint32 type; /* Type of tree item, an SMBC_TYPE */ + char name[256]; /* May need to change this later */ + +}; + +void error_message(gchar *message) { + + GtkWidget *dialog, *label, *okay_button; + + /* Create the widgets */ + + dialog = gtk_dialog_new(); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + label = gtk_label_new (message); + okay_button = gtk_button_new_with_label("Okay"); + + /* Ensure that the dialog box is destroyed when the user clicks ok. */ + + gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), + okay_button); + + /* Add the label, and show everything we've added to the dialog. */ + + gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), + label); + gtk_widget_show_all (dialog); +} + +/* + * We are given a widget, and we want to retrieve its URL so we + * can do a directory listing. + * + * We walk back up the tree, picking up pieces until we hit a server or + * workgroup type and return a path from there + */ + +static char path_string[1024]; + +char *get_path(GtkWidget *item) +{ + GtkWidget *p = item; + struct tree_data *pd; + char *comps[1024]; /* We keep pointers to the components here */ + int i = 0, j, level,type; + + /* Walk back up the tree, getting the private data */ + + level = GTK_TREE(item->parent)->level; + + /* Pick up this item's component info */ + + pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(item)); + + comps[i++] = pd->name; + type = pd->type; + + while (level > 0 && type != SMBC_SERVER && type != SMBC_WORKGROUP) { + + /* Find the parent and extract the data etc ... */ + + p = GTK_WIDGET(p->parent); + p = GTK_WIDGET(GTK_TREE(p)->tree_owner); + + pd = (struct tree_data *)gtk_object_get_user_data(GTK_OBJECT(p)); + + level = GTK_TREE(item->parent)->level; + + comps[i++] = pd->name; + type = pd->type; + + } + + /* + * Got a list of comps now, should check that we did not hit a workgroup + * when we got other things as well ... Later + * + * Now, build the path + */ + + snprintf(path_string, sizeof(path_string), "smb:/"); + + for (j = i - 1; j >= 0; j--) { + + strncat(path_string, "/", sizeof(path_string) - strlen(path_string)); + strncat(path_string, comps[j], sizeof(path_string) - strlen(path_string)); + + } + + fprintf(stdout, "Path string = %s\n", path_string); + + return path_string; + +} + +struct tree_data *make_tree_data(guint32 type, const char *name) +{ + struct tree_data *p = (struct tree_data *)malloc(sizeof(struct tree_data)); + + if (p) { + + p->type = type; + strncpy(p->name, name, sizeof(p->name)); + + } + + return p; + +} + +/* Note that this is called every time the user clicks on an item, + whether it is already selected or not. */ +static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, + GtkWidget *subtree) +{ + gint dh, err, dirlen; + char dirbuf[512]; + struct smbc_dirent *dirp; + struct stat st1; + char path[1024], path1[1024]; + + g_print ("select_child called for root tree %p, subtree %p, child %p\n", + root_tree, subtree, child); + + /* Now, figure out what it is, and display it in the clist ... */ + + gtk_clist_clear(GTK_CLIST(clist)); /* Clear the CLIST */ + + /* Now, get the private data for the subtree */ + + strncpy(path, get_path(child), 1024); + + if ((dh = smbc_opendir(path)) < 0) { /* Handle error */ + + g_print("cb_select_child: Could not open dir %s, %s\n", path, + strerror(errno)); + + gtk_main_quit(); + + return; + + } + + while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, + sizeof(dirbuf))) != 0) { + + if (err < 0) { + + g_print("cb_select_child: Could not read dir %s, %s\n", path, + strerror(errno)); + + gtk_main_quit(); + + return; + + } + + dirp = (struct smbc_dirent *)dirbuf; + + while (err > 0) { + gchar col1[128], col2[128], col3[128], col4[128]; + gchar *rowdata[4] = {col1, col2, col3, col4}; + + dirlen = dirp->dirlen; + + /* Format each of the items ... */ + + strncpy(col1, dirp->name, 128); + + col2[0] = col3[0] = col4[0] = (char)0; + + switch (dirp->smbc_type) { + + case SMBC_WORKGROUP: + + break; + + case SMBC_SERVER: + + strncpy(col2, (dirp->comment?dirp->comment:""), 128); + + break; + + case SMBC_FILE_SHARE: + + strncpy(col2, (dirp->comment?dirp->comment:""), 128); + + break; + + case SMBC_PRINTER_SHARE: + + strncpy(col2, (dirp->comment?dirp->comment:""), 128); + break; + + case SMBC_COMMS_SHARE: + + break; + + case SMBC_IPC_SHARE: + + break; + + case SMBC_DIR: + case SMBC_FILE: + + /* Get stats on the file/dir and see what we have */ + + if ((strcmp(dirp->name, ".") != 0) && + (strcmp(dirp->name, "..") != 0)) { + + strncpy(path1, path, sizeof(path1)); + strncat(path1, "/", sizeof(path) - strlen(path)); + strncat(path1, dirp->name, sizeof(path) - strlen(path)); + + if (smbc_stat(path1, &st1) < 0) { + + if (errno != EBUSY) { + + g_print("cb_select_child: Could not stat file %s, %s\n", path1, + strerror(errno)); + + gtk_main_quit(); + + return; + + } + else { + + strncpy(col2, "Device or resource busy", sizeof(col2)); + + } + } + else { + /* Now format each of the relevant things ... */ + + snprintf(col2, sizeof(col2), "%c%c%c%c%c%c%c%c%c(%0X)", + (st1.st_mode&S_IRUSR?'r':'-'), + (st1.st_mode&S_IWUSR?'w':'-'), + (st1.st_mode&S_IXUSR?'x':'-'), + (st1.st_mode&S_IRGRP?'r':'-'), + (st1.st_mode&S_IWGRP?'w':'-'), + (st1.st_mode&S_IXGRP?'x':'-'), + (st1.st_mode&S_IROTH?'r':'-'), + (st1.st_mode&S_IWOTH?'w':'-'), + (st1.st_mode&S_IXOTH?'x':'-'), + st1.st_mode); + snprintf(col3, sizeof(col3), "%u", st1.st_size); + snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_mtime)); + } + } + + break; + + default: + + break; + } + + gtk_clist_append(GTK_CLIST(clist), rowdata); + + dirp = (struct smbc_dirent *) ((char *) dirp + dirlen); + err -= dirlen; + + } + + } + +} + +/* Note that this is never called */ +static void cb_unselect_child( GtkWidget *root_tree, + GtkWidget *child, + GtkWidget *subtree ) +{ + g_print ("unselect_child called for root tree %p, subtree %p, child %p\n", + root_tree, subtree, child); +} + +/* for all the GtkItem:: and GtkTreeItem:: signals */ +static void cb_itemsignal( GtkWidget *item, + gchar *signame ) +{ + GtkWidget *real_tree, *aitem, *subtree; + gchar *name; + GtkLabel *label; + gint dh, err, dirlen, level; + char dirbuf[512]; + struct smbc_dirent *dirp; + + label = GTK_LABEL (GTK_BIN (item)->child); + /* Get the text of the label */ + gtk_label_get (label, &name); + + level = GTK_TREE(item->parent)->level; + + /* Get the level of the tree which the item is in */ + g_print ("%s called for item %s->%p, level %d\n", signame, name, + item, GTK_TREE (item->parent)->level); + + real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */ + + if (strncmp(signame, "expand", 6) == 0) { /* Expand called */ + char server[128]; + + if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */ + gchar errmsg[256]; + + g_print("cb_itemsignal: Could not open dir %s, %s\n", get_path(item), + strerror(errno)); + + snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno)); + + error_message(errmsg); + + /* gtk_main_quit();*/ + + return; + + } + + while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, + sizeof(dirbuf))) != 0) { + + if (err < 0) { /* An error, report it */ + gchar errmsg[256]; + + g_print("cb_itemsignal: Could not read dir smbc://, %s\n", + strerror(errno)); + + snprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno)); + + error_message(errmsg); + + /* gtk_main_quit();*/ + + return; + + } + + dirp = (struct smbc_dirent *)dirbuf; + + while (err > 0) { + struct tree_data *my_data; + + dirlen = dirp->dirlen; + + my_data = make_tree_data(dirp->smbc_type, dirp->name); + + if (!my_data) { + + g_print("Could not allocate space for tree_data: %s\n", + dirp->name); + + gtk_main_quit(); + return; + + } + + aitem = gtk_tree_item_new_with_label(dirp->name); + + /* Connect all GtkItem:: and GtkTreeItem:: signals */ + gtk_signal_connect (GTK_OBJECT(aitem), "select", + GTK_SIGNAL_FUNC(cb_itemsignal), "select"); + gtk_signal_connect (GTK_OBJECT(aitem), "deselect", + GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); + gtk_signal_connect (GTK_OBJECT(aitem), "toggle", + GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); + gtk_signal_connect (GTK_OBJECT(aitem), "expand", + GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); + gtk_signal_connect (GTK_OBJECT(aitem), "collapse", + GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); + /* Add it to the parent tree */ + gtk_tree_append (GTK_TREE(real_tree), aitem); + + gtk_widget_show (aitem); + + gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data); + + fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); + + if (dirp->smbc_type != SMBC_FILE && + dirp->smbc_type != SMBC_IPC_SHARE && + (strcmp(dirp->name, ".") != 0) && + (strcmp(dirp->name, "..") !=0)){ + + subtree = gtk_tree_new(); + gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree); + + gtk_signal_connect(GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), real_tree); + gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); + + } + + dirp = (struct smbc_dirent *) ((char *) dirp + dirlen); + err -= dirlen; + + } + + } + + smbc_closedir(dh); + + } + else if (strncmp(signame, "collapse", 8) == 0) { + GtkWidget *subtree = gtk_tree_new(); + + gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children); + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); + + gtk_signal_connect (GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), real_tree); + gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); + + } + +} + +static void cb_selection_changed( GtkWidget *tree ) +{ + GList *i; + + g_print ("selection_change called for tree %p\n", tree); + g_print ("selected objects are:\n"); + + i = GTK_TREE_SELECTION(tree); + while (i){ + gchar *name; + GtkLabel *label; + GtkWidget *item; + + /* Get a GtkWidget pointer from the list node */ + item = GTK_WIDGET (i->data); + label = GTK_LABEL (GTK_BIN (item)->child); + gtk_label_get (label, &name); + g_print ("\t%s on level %d\n", name, GTK_TREE + (item->parent)->level); + i = i->next; + } +} + +/* + * Expand or collapse the whole network ... + */ +static void cb_wholenet(GtkWidget *item, gchar *signame) +{ + GtkWidget *real_tree, *aitem, *subtree; + gchar *name; + GtkLabel *label; + gint dh, err, dirlen; + char dirbuf[512]; + struct smbc_dirent *dirp; + + label = GTK_LABEL (GTK_BIN (item)->child); + gtk_label_get (label, &name); + g_print ("%s called for item %s->%p, level %d\n", signame, name, + item, GTK_TREE (item->parent)->level); + + real_tree = GTK_TREE_ITEM_SUBTREE(item); /* Get the subtree */ + + if (strncmp(signame, "expand", 6) == 0) { /* Expand called */ + + if ((dh = smbc_opendir("smb://")) < 0) { /* Handle error */ + + g_print("cb_wholenet: Could not open dir smbc://, %s\n", + strerror(errno)); + + gtk_main_quit(); + + return; + + } + + while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, + sizeof(dirbuf))) != 0) { + + if (err < 0) { /* An error, report it */ + + g_print("cb_wholenet: Could not read dir smbc://, %s\n", + strerror(errno)); + + gtk_main_quit(); + + return; + + } + + dirp = (struct smbc_dirent *)dirbuf; + + while (err > 0) { + struct tree_data *my_data; + + dirlen = dirp->dirlen; + + my_data = make_tree_data(dirp->smbc_type, dirp->name); + + aitem = gtk_tree_item_new_with_label(dirp->name); + + /* Connect all GtkItem:: and GtkTreeItem:: signals */ + gtk_signal_connect (GTK_OBJECT(aitem), "select", + GTK_SIGNAL_FUNC(cb_itemsignal), "select"); + gtk_signal_connect (GTK_OBJECT(aitem), "deselect", + GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); + gtk_signal_connect (GTK_OBJECT(aitem), "toggle", + GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); + gtk_signal_connect (GTK_OBJECT(aitem), "expand", + GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); + gtk_signal_connect (GTK_OBJECT(aitem), "collapse", + GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); + + gtk_tree_append (GTK_TREE(real_tree), aitem); + /* Show it - this can be done at any time */ + gtk_widget_show (aitem); + + gtk_object_set_user_data(GTK_OBJECT(aitem), (gpointer)my_data); + + fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); + + subtree = gtk_tree_new(); + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(aitem), subtree); + + gtk_signal_connect(GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), real_tree); + gtk_signal_connect(GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); + + dirp = (struct smbc_dirent *) ((char *) dirp + dirlen); + err -= dirlen; + + } + + } + + smbc_closedir(dh); + + } + else { /* Must be collapse ... FIXME ... */ + GtkWidget *subtree = gtk_tree_new(); + + gtk_tree_remove_items(GTK_TREE(real_tree), GTK_TREE(real_tree)->children); + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); + + gtk_signal_connect (GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), real_tree); + gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), real_tree); + + + } + +} + +/* Should put up a dialog box to ask the user for username and password */ + +static void +auth_fn(const char *server, const char *share, + char *workgroup, int wgmaxlen, char *username, int unmaxlen, + char *password, int pwmaxlen) +{ + strncpy(username, "test", unmaxlen); + strncpy(password, "test", pwmaxlen); +} + +static char *col_titles[] = { + "Name", "Attributes", "Size", "Modification Date", +}; + +int main( int argc, + char *argv[] ) +{ + GtkWidget *window, *scrolled_win, *scrolled_win2, *tree; + GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane; + gint err, dh; + gint i; + char dirbuf[512]; + struct smbc_dirent *dirp; + + gtk_init (&argc, &argv); + + /* Init the smbclient library */ + + err = smbc_init(auth_fn, 10); + + /* Print an error response ... */ + + if (err < 0) { + + fprintf(stderr, "smbc_init returned %s (%i)\nDo you have a ~/.smb/smb.conf file?\n", strerror(errno), errno); + exit(1); + + } + + /* a generic toplevel window */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_widget_set_name(window, "main browser window"); + gtk_signal_connect (GTK_OBJECT(window), "delete_event", + GTK_SIGNAL_FUNC (gtk_main_quit), NULL); + gtk_window_set_title(GTK_WINDOW(window), "The Linux Windows Network Browser"); + gtk_widget_set_usize(GTK_WIDGET(window), 750, -1); + gtk_container_set_border_width (GTK_CONTAINER(window), 5); + + gtk_widget_show (window); + + /* A container for the two panes ... */ + + main_hbox = gtk_hbox_new(FALSE, 1); + gtk_container_border_width(GTK_CONTAINER(main_hbox), 1); + gtk_container_add(GTK_CONTAINER(window), main_hbox); + + gtk_widget_show(main_hbox); + + l_pane = gtk_hpaned_new(); + gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size); + r_pane = gtk_hpaned_new(); + gtk_paned_gutter_size(GTK_PANED(r_pane), (GTK_PANED(r_pane))->handle_size); + gtk_container_add(GTK_CONTAINER(main_hbox), l_pane); + gtk_widget_show(l_pane); + + /* A generic scrolled window */ + scrolled_win = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize (scrolled_win, 150, 200); + gtk_container_add (GTK_CONTAINER(l_pane), scrolled_win); + gtk_widget_show (scrolled_win); + + /* Another generic scrolled window */ + scrolled_win2 = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win2), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_widget_set_usize (scrolled_win2, 150, 200); + gtk_paned_add2 (GTK_PANED(l_pane), scrolled_win2); + gtk_widget_show (scrolled_win2); + + /* Create the root tree */ + tree = gtk_tree_new(); + g_print ("root tree is %p\n", tree); + /* connect all GtkTree:: signals */ + gtk_signal_connect (GTK_OBJECT(tree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), tree); + gtk_signal_connect (GTK_OBJECT(tree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), tree); + gtk_signal_connect (GTK_OBJECT(tree), "selection_changed", + GTK_SIGNAL_FUNC(cb_selection_changed), tree); + /* Add it to the scrolled window */ + gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled_win), + tree); + /* Set the selection mode */ + gtk_tree_set_selection_mode (GTK_TREE(tree), + GTK_SELECTION_MULTIPLE); + /* Show it */ + gtk_widget_show (tree); + + /* Now, create a clist and attach it to the second pane */ + + clist = gtk_clist_new_with_titles(4, col_titles); + + gtk_container_add (GTK_CONTAINER(scrolled_win2), clist); + + gtk_widget_show(clist); + + /* Now, build the top level display ... */ + + if ((dh = smbc_opendir("smb://")) < 0) { + + fprintf(stderr, "Could not list workgroups: smb://: %s\n", + strerror(errno)); + + exit(1); + + } + + /* Create a tree item for Whole Network */ + + item = gtk_tree_item_new_with_label ("Whole Network"); + /* Connect all GtkItem:: and GtkTreeItem:: signals */ + gtk_signal_connect (GTK_OBJECT(item), "select", + GTK_SIGNAL_FUNC(cb_itemsignal), "select"); + gtk_signal_connect (GTK_OBJECT(item), "deselect", + GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); + gtk_signal_connect (GTK_OBJECT(item), "toggle", + GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); + gtk_signal_connect (GTK_OBJECT(item), "expand", + GTK_SIGNAL_FUNC(cb_wholenet), "expand"); + gtk_signal_connect (GTK_OBJECT(item), "collapse", + GTK_SIGNAL_FUNC(cb_wholenet), "collapse"); + /* Add it to the parent tree */ + gtk_tree_append (GTK_TREE(tree), item); + /* Show it - this can be done at any time */ + gtk_widget_show (item); + + subtree = gtk_tree_new(); /* A subtree for Whole Network */ + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); + + gtk_signal_connect (GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), tree); + gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), tree); + + /* Now, get the items in smb:/// and add them to the tree */ + + while ((err = smbc_getdents(dh, (struct smbc_dirent *)dirbuf, + sizeof(dirbuf))) != 0) { + + if (err < 0) { /* Handle the error */ + + fprintf(stderr, "Could not read directory for smbc:///: %s\n", + strerror(errno)); + + exit(1); + + } + + dirp = (struct smbc_dirent *)dirbuf; + + fprintf(stdout, "Dir len: %u\n", err); + + while (err > 0) { /* Extract each entry and make a sub-tree */ + struct tree_data *my_data; + int dirlen = dirp->dirlen; + + my_data = make_tree_data(dirp->smbc_type, dirp->name); + + item = gtk_tree_item_new_with_label(dirp->name); + /* Connect all GtkItem:: and GtkTreeItem:: signals */ + gtk_signal_connect (GTK_OBJECT(item), "select", + GTK_SIGNAL_FUNC(cb_itemsignal), "select"); + gtk_signal_connect (GTK_OBJECT(item), "deselect", + GTK_SIGNAL_FUNC(cb_itemsignal), "deselect"); + gtk_signal_connect (GTK_OBJECT(item), "toggle", + GTK_SIGNAL_FUNC(cb_itemsignal), "toggle"); + gtk_signal_connect (GTK_OBJECT(item), "expand", + GTK_SIGNAL_FUNC(cb_itemsignal), "expand"); + gtk_signal_connect (GTK_OBJECT(item), "collapse", + GTK_SIGNAL_FUNC(cb_itemsignal), "collapse"); + /* Add it to the parent tree */ + gtk_tree_append (GTK_TREE(tree), item); + /* Show it - this can be done at any time */ + gtk_widget_show (item); + + gtk_object_set_user_data(GTK_OBJECT(item), (gpointer)my_data); + + fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen); + + subtree = gtk_tree_new(); + + gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), subtree); + + gtk_signal_connect (GTK_OBJECT(subtree), "select_child", + GTK_SIGNAL_FUNC(cb_select_child), tree); + gtk_signal_connect (GTK_OBJECT(subtree), "unselect_child", + GTK_SIGNAL_FUNC(cb_unselect_child), tree); + + dirp = (struct smbc_dirent *) ((char *) dirp + dirlen); + err -= dirlen; + + } + + } + + smbc_closedir(dh); /* FIXME, check for error :-) */ + + /* Show the window and loop endlessly */ + gtk_main(); + return 0; +} +/* example-end */ diff --git a/examples/libsmbclient/wscript_build b/examples/libsmbclient/wscript_build new file mode 100644 index 0000000..c58a5b9 --- /dev/null +++ b/examples/libsmbclient/wscript_build @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +names = ['testsmbc', + 'testacl', + 'testacl2', + 'testacl3', + 'testbrowse', + 'testbrowse2', + 'testnotify', + 'teststat', + 'teststat2', + 'teststat3', + 'teststatvfs', + 'testfstatvfs', + 'testtruncate', + 'testchmod', + 'testutime', + 'testread', + 'testwrite', + 'testctx'] + +for name in names: + bld.SAMBA_BINARY(name, + source='%s.c' % name, + deps='popt smbclient', + install=False) |