diff options
author | CVS Import User <samba-bugs@samba.org> | 2004-04-04 09:21:52 +0000 |
---|---|---|
committer | CVS Import User <samba-bugs@samba.org> | 2004-04-04 09:21:52 +0000 |
commit | 9f765b7406282904ce56f2535dcd929a9aefc5ca (patch) | |
tree | dbdff78b624ac7c1afcb8851f395df3d99eb1f84 /examples/libsmbclient | |
parent | 111b4e05ab96eafc4212f38dc5977538907187c7 (diff) | |
download | samba-9f765b7406282904ce56f2535dcd929a9aefc5ca.tar.gz samba-9f765b7406282904ce56f2535dcd929a9aefc5ca.tar.xz samba-9f765b7406282904ce56f2535dcd929a9aefc5ca.zip |
r2: import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
metze
Diffstat (limited to 'examples/libsmbclient')
-rw-r--r-- | examples/libsmbclient/Makefile | 36 | ||||
-rw-r--r-- | examples/libsmbclient/README | 8 | ||||
-rw-r--r-- | examples/libsmbclient/testacl.c | 280 | ||||
-rw-r--r-- | examples/libsmbclient/testbrowse.c | 91 | ||||
-rw-r--r-- | examples/libsmbclient/testsmbc.c | 335 | ||||
-rw-r--r-- | examples/libsmbclient/tree.c | 813 |
6 files changed, 1563 insertions, 0 deletions
diff --git a/examples/libsmbclient/Makefile b/examples/libsmbclient/Makefile new file mode 100644 index 00000000000..fcd5ef29003 --- /dev/null +++ b/examples/libsmbclient/Makefile @@ -0,0 +1,36 @@ +# +CC = gcc + +SAMBA_INCL = ../../source/include +EXTLIB_INCL = -I/usr/include/gtk-1.2 \ + -I/usr/include/glib-1.2 \ + -I/usr/lib/glib/include + +CFLAGS = -I$(SAMBA_INCL) $(EXTLIB_INCL) + +LDFLAGS = -L/usr/lib + +all: testsmbc tree testacl testbrowse + +testsmbc: testsmbc.o + @echo Linking testsmbc + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lsmbclient -L/usr/local/lib + +testsmbc-static: testsmbc.o + @echo Linking testsmbc + @$(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $< -lsmbclient -ldl -lnsl + +tree: tree.o + @echo Linking tree + @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient $< + +testacl: testacl.o + @echo Linking testacl + @$(CC) `gtk-config --cflags` $(CFLAGS) $(LDFLAGS) -o $@ `gtk-config --libs` -lsmbclient -lpopt $< + +testbrowse: testbrowse.o + @echo Linking testbrowse + @$(CC) $(CFLAGS) $(LDFLAGS) -o $@ -lsmbclient -lpopt $< + +clean: + @rm -f *.o *~ diff --git a/examples/libsmbclient/README b/examples/libsmbclient/README new file mode 100644 index 00000000000..d9a9f829174 --- /dev/null +++ b/examples/libsmbclient/README @@ -0,0 +1,8 @@ +Some simple example programs for libsmbclient ... + +testsmbc.c is kinda broken as it has many hardcoded bits in it + +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. + +Richard Sharpe, 17-May-2001 ... diff --git a/examples/libsmbclient/testacl.c b/examples/libsmbclient/testacl.c new file mode 100644 index 00000000000..47668f7c9c4 --- /dev/null +++ b/examples/libsmbclient/testacl.c @@ -0,0 +1,280 @@ +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <popt.h> +#include "libsmbclient.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 +}; + +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]; + + fprintf(stdout, "Workgroup: [%s] ", pWorkgroup); + fgets(temp, sizeof(temp), stdin); + + 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); + fgets(temp, sizeof(temp), stdin); + + 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: "); + fgets(temp, sizeof(temp), stdin); + + if (temp[strlen(temp) - 1] == '\n') /* A new line? */ + { + temp[strlen(temp) - 1] = '\0'; + } + + if (temp[0] != '\0') + { + strncpy(pPassword, temp, maxLenPassword - 1); + } +} + + +int main(int argc, const char *argv[]) +{ + int opt; + int flags; + int debug = 0; + int numeric = 0; + enum acl_mode mode = SMB_ACL_GET; + static char *the_acl = NULL; + int ret; + char *p; + char *debugstr; + char path[1024]; + char value[1024]; + poptContext pc; + struct poptOption long_options[] = + { + POPT_AUTOHELP + { + "numeric", 'n', POPT_ARG_NONE, &numeric, + 1, "Don't resolve sids or masks to names" + }, + { + "debug", 'd', POPT_ARG_INT, &debug, + 0, "Set debug level (0-100)" + }, + { + "delete", 'D', POPT_ARG_STRING, NULL, + 'D', "Delete an acl", "ACL" + }, + { + "modify", 'M', POPT_ARG_STRING, NULL, + 'M', "Modify an acl", "ACL" + }, + { + "add", 'a', POPT_ARG_STRING, NULL, + 'a', "Add an acl", "ACL" + }, + { + "set", 'S', POPT_ARG_STRING, NULL, + 'S', "Set acls", "ACLS" + }, + { + "chown", 'C', POPT_ARG_STRING, NULL, + 'C', "Change ownership of a file", "USERNAME" + }, + { + "chgrp", 'G', POPT_ARG_STRING, NULL, + 'G', "Change group ownership of a file", "GROUPNAME" + }, + { + "get", 'g', POPT_ARG_STRING, NULL, + 'g', "Get a specific acl attribute", "ACL" + }, + { + NULL + } + }; + + 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; + } + + strcpy(path, poptGetArg(pc)); + + if (smbc_init(get_auth_data_fn, debug) != 0) + { + printf("Could not initialize smbc_ library\n"); + return 1; + } + + /* Perform requested action */ + + switch(mode) + { + case SMB_ACL_GET: + if (the_acl == NULL) + { + if (numeric) + { + the_acl = "system.nt_sec_desc.*"; + } + else + { + the_acl = "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); + 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/testbrowse.c b/examples/libsmbclient/testbrowse.c new file mode 100644 index 00000000000..d2472230a20 --- /dev/null +++ b/examples/libsmbclient/testbrowse.c @@ -0,0 +1,91 @@ +/* + Unix SMB/CIFS implementation. + SMB client library test program for browsing with different master browsers + Copyright (C) Derrell Lipman 2004 + + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stdio.h> +#include <errno.h> +#include <sys/time.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <libsmbclient.h> + +static void +auth_fn(const char * pServer, + const char * pShare, + char * pWorkgroup, + int workgroup_len, + char * pUsername, + int username_len, + char * pPassword, + int password_len) + +{ + strncpy(pUsername, "anonymous", username_len); /* doesn't matter what */ + strncpy(pPassword, "password", password_len); /* ditto */ +} + + +int +main(int argc, char * argv[]) +{ + int debug = 4; + int opt; + char * p; + char buf[1024]; + int dir; + struct smbc_dirent * dirent; + char ** ppUrl; + char * urlList[] = + { + "smb://", + "smb://?mb=.any", + "smb://?mb=.all", + "smb://?mb=xx", /* this one is suupposed to fail */ + NULL + }; + + if (smbc_init(auth_fn, debug) != 0) + { + printf("Could not initialize smbc_ library\n"); + return 1; + } + + for (ppUrl = urlList; *ppUrl != NULL; ppUrl++) + { + printf("Opening (%s)...\n", *ppUrl); + + if ((dir = smbc_opendir(*ppUrl)) < 0) + { + printf("Could not open [%s] (%d:%s)\n", + *ppUrl, errno, strerror(errno)); + continue; + } + + while ((dirent = smbc_readdir(dir)) != NULL) + { + printf("%s\n", dirent->name); + } + + smbc_closedir(dir); + } + + exit(0); +} + diff --git a/examples/libsmbclient/testsmbc.c b/examples/libsmbclient/testsmbc.c new file mode 100644 index 00000000000..888a9c0d4f9 --- /dev/null +++ b/examples/libsmbclient/testsmbc.c @@ -0,0 +1,335 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <stdio.h> +#include <errno.h> +#include <sys/time.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <libsmbclient.h> + +void auth_fn(const char *server, const char *share, + char *workgroup, int wgmaxlen, char *username, int unmaxlen, + char *password, int pwmaxlen) +{ + char temp[128]; + + fprintf(stdout, "Need password for //%s/%s\n", server, share); + + fprintf(stdout, "Enter workgroup: [%s] ", workgroup); + fgets(temp, sizeof(temp), stdin); + + if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */ + temp[strlen(temp) - 1] = 0x00; + + if (temp[0]) strncpy(workgroup, temp, wgmaxlen - 1); + + fprintf(stdout, "Enter username: [%s] ", username); + fgets(temp, sizeof(temp), stdin); + + if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */ + temp[strlen(temp) - 1] = 0x00; + + if (temp[0]) strncpy(username, temp, unmaxlen - 1); + + fprintf(stdout, "Enter password: [%s] ", password); + fgets(temp, sizeof(temp), stdin); + + if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */ + temp[strlen(temp) - 1] = 0x00; + + if (temp[0]) strncpy(password, temp, pwmaxlen - 1); + +} + +int global_id = 0; + +void print_list_fn(struct print_job_info *pji) +{ + + fprintf(stdout, "Print job: ID: %u, Prio: %u, Size: %u, User: %s, Name: %s\n", + pji->id, pji->priority, pji->size, pji->user, pji->name); + + global_id = pji->id; + +} + +int main(int argc, char *argv[]) +{ + int err, fd, dh1, dh2, dh3, 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(auth_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 handles: %u, %u, %u\n", dh1, dh2, dh3); + + /* 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; + (char *)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 ... */ + + bzero(buff, sizeof(buff)); + strcpy(buff, "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 %d bytes to file: %s\n", 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, 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, 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/tree.c b/examples/libsmbclient/tree.c new file mode 100644 index 00000000000..f50b3670cff --- /dev/null +++ b/examples/libsmbclient/tree.c @@ -0,0 +1,813 @@ +/* + 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 2 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, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* example-gtk+ application, ripped off from the gtk+ tree.c sample */ + +#include <stdio.h> +#include <errno.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); + + (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); + + } + + (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); + + (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); + + (char *)dirp += dirlen; + err -= dirlen; + + } + + } + + smbc_closedir(dh); /* FIXME, check for error :-) */ + + /* Show the window and loop endlessly */ + gtk_main(); + return 0; +} +/* example-end */ |