1
0
mirror of https://github.com/samba-team/samba.git synced 2025-08-03 04:22:09 +03:00

Many bug fixes to the libsmbclient.c code plus

- an implementation of smbc_readdir
  - extensions to tree.c to show files in a second window
  - changes to auth_fn to provide buffers for username, password, etc
    from caller rather than callee
(This used to be commit 7f559c1a73)
This commit is contained in:
Richard Sharpe
2001-01-12 05:10:45 +00:00
parent 78b2616049
commit fb40134446
4 changed files with 382 additions and 69 deletions

View File

@ -26,30 +26,36 @@
#include <libsmbclient.h>
void auth_fn(char *server, char *share,
char **workgroup, char **username, char **password)
char *workgroup, int wgmaxlen, char *username, int unmaxlen,
char *password, int pwmaxlen)
{
static char wg[128], un[128], pw[128];
/* DO nothing for now ... change later */
char temp[128];
fprintf(stdout, "Enter workgroup: ");
fgets(wg, sizeof(wg), stdin);
fprintf(stdout, "Need password for //%s/%s\n", server, share);
if (wg[strlen(wg) - 1] == 0x0a) /* A new line? */
wg[strlen(wg) - 1] = 0x00;
fprintf(stdout, "Enter workgroup: [%s] ", workgroup);
fgets(temp, sizeof(temp), stdin);
fprintf(stdout, "Enter username: ");
fgets(un, sizeof(un), stdin);
if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */
temp[strlen(temp) - 1] = 0x00;
if (un[strlen(un) - 1] == 0x0a) /* A new line? */
un[strlen(un) - 1] = 0x00;
if (temp[0]) strncpy(workgroup, temp, wgmaxlen - 1);
fprintf(stdout, "Enter password: ");
fgets(pw, sizeof(pw), stdin);
fprintf(stdout, "Enter username: [%s] ", username);
fgets(temp, sizeof(temp), stdin);
if (pw[strlen(pw) - 1] == 0x0a) /* A new line? */
pw[strlen(pw) - 1] = 0x00;
if (temp[strlen(temp) - 1] == 0x0a) /* A new line? */
temp[strlen(temp) - 1] = 0x00;
*workgroup = wg; *password = pw; *username = un;
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);
}
@ -122,7 +128,7 @@ int main(int argc, char *argv[])
while (dirc > 0) {
dsize = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
dsize = dirp->dirlen;
fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
dirp->smbc_type, dirp->name, dirp->comment);
@ -148,7 +154,7 @@ int main(int argc, char *argv[])
while (dirc > 0) {
dsize = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
dsize = dirp->dirlen;
fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
dirp->smbc_type, dirp->name, dirp->comment);
@ -174,7 +180,7 @@ int main(int argc, char *argv[])
while (dirc > 0) {
dsize = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
dsize = dirp->dirlen;
fprintf(stdout, "\nDir Ent, Type: %u, Name: %s, Comment: %s\n",
dirp->smbc_type, dirp->name, dirp->comment);
@ -330,7 +336,9 @@ int main(int argc, char *argv[])
fprintf(stdout, "Stat'ed file: %s. Size = %d, mode = %04X\n", file2,
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,
st1.st_size, st1.st_mode);
fprintf(stdout, " time: %s\n", ctime(&st1.st_atime));
}

View File

@ -28,6 +28,8 @@
#include <gtk/gtk.h>
#include "libsmbclient.h"
static GtkWidget *clist;
struct tree_data {
guint32 type; /* Type of tree item, an SMBC_TYPE */
@ -142,7 +144,7 @@ static void cb_itemsignal( GtkWidget *item,
if ((dh = smbc_opendir(get_path(item))) < 0) { /* Handle error */
g_print("cb_wholenet: Could not open dir %s, %s\n", server,
g_print("cb_wholenet: Could not open dir %s, %s\n", get_path(item),
strerror(errno));
gtk_main_quit();
@ -208,7 +210,10 @@ static void cb_itemsignal( GtkWidget *item,
fprintf(stdout, "Added: %s, len: %u\n", dirp->name, dirlen);
if (dirp->smbc_type != SMBC_FILE && dirp->smbc_type != SMBC_IPC_SHARE){
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);
@ -242,8 +247,147 @@ static void cb_unselect_child( GtkWidget *root_tree,
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) {
g_print("cb_select_child: Could not stat file %s, %s\n", path1,
strerror(errno));
gtk_main_quit();
return;
}
/* Now format each of the relevant things ... */
snprintf(col2, sizeof(col2), "%s%s%s%s%s%s(%0X)",
(st1.st_mode&0x20?"A":""),
(st1.st_mode&0x10?"D":""),
(st1.st_mode&0x08?"V":""),
(st1.st_mode&0x04?"S":""),
(st1.st_mode&0x02?"H":""),
(st1.st_mode&0x01?"R":""),
st1.st_mode);
snprintf(col3, sizeof(col3), "%u", st1.st_size);
snprintf(col4, sizeof(col4), "%s", ctime(&st1.st_ctime));
}
break;
default:
break;
}
gtk_clist_append(GTK_CLIST(clist), rowdata);
(char *)dirp += dirlen;
err -= dirlen;
}
}
}
static void cb_selection_changed( GtkWidget *tree )
@ -363,22 +507,28 @@ static void cb_wholenet(GtkWidget *item, gchar *signame)
}
/* Should put up a dialog box to ask the user for username and password */
static void
auth_fn(char *server, char *share,
char **workgroup, char **username, char **password)
char *workgroup, int wgmaxlen, char *username, int unmaxlen,
char *password, int pwmaxlen)
{
*workgroup = "";
*username = "test";
*password = "test";
strncpy(username, "test", unmaxlen);
strncpy(password, "test", pwmaxlen);
}
static char *col_titles[] = {
"Name", "Attributes", "Size", "Creation Date",
};
int main( int argc,
char *argv[] )
{
GtkWidget *window, *scrolled_win, *tree;
GtkWidget *subtree, *item;
GtkWidget *window, *scrolled_win, *scrolled_win2, *tree;
GtkWidget *subtree, *item, *main_hbox, *r_pane, *l_pane;
gint err, dh;
gint i;
char dirbuf[512];
@ -392,18 +542,50 @@ int main( int argc,
/* 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);
/*gtk_container_add(GTK_CONTAINER(main_hbox), r_pane);
gtk_widget_show(r_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(window), scrolled_win);
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();
@ -424,6 +606,14 @@ int main( int argc,
/* 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) {
@ -458,6 +648,11 @@ int main( int argc,
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 */
dirp = (struct smbc_dirent *)dirbuf;
@ -507,6 +702,11 @@ int main( int argc,
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;
@ -517,7 +717,6 @@ int main( int argc,
smbc_closedir(dh); /* FIXME, check for error :-) */
/* Show the window and loop endlessly */
gtk_widget_show (window);
gtk_main();
return 0;
}

View File

@ -60,8 +60,9 @@ struct smbc_dirent {
#define SMBC_DIR_MODE (S_IFDIR | 0555)
typedef void (*smbc_get_auth_data_fn)(char *server, char *share,
char **workgroup, char **username,
char **password);
char *workgroup, int wgmaxlen,
char *username, int unmaxlen,
char *password, int pwmaxlen);
/*
* Init the smbc package
@ -160,6 +161,12 @@ int smbc_closedir(int fd);
int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count);
/*
* Read a dirent in the old way
*/
struct smbc_dirent *smbc_readdir(unsigned int fd);
/*
* Create a directory on a server, share, dir in fname URL
*/

View File

@ -65,6 +65,7 @@ static int smbc_max_fd = 10000;
static struct smbc_file **smbc_file_table;
static struct smbc_server *smbc_srvs;
static pstring my_netbios_name;
static pstring smbc_user;
/*
* Clean up a filename by removing redundent stuff
@ -174,14 +175,15 @@ smbc_clean_fname(char *name)
static const char *smbc_prefix = "smb:";
static int
smbc_parse_path(const char *fname, char *server, char *share, char *path)
smbc_parse_path(const char *fname, char *server, char *share, char *path,
char *user, char *password) /* FIXME, lengths of strings */
{
static pstring s;
char *p;
int len;
fstring workgroup;
server[0] = share[0] = path[0] = (char)0;
server[0] = share[0] = path[0] = user[0] = password[0] = (char)0;
pstrcpy(s, fname);
/* clean_fname(s); causing problems ... */
@ -257,15 +259,21 @@ int smbc_errno(struct cli_state *c)
/*
* Connect to a server, possibly on an existing connection
*
* Here, what we want to do is: If the server and username
* match an existing connection, reuse that, otherwise, establish a
* new connection.
*
* If we have to create a new connection, call the auth_fn to get the
* info we need, unless the username and password were passed in.
*/
struct smbc_server *smbc_server(char *server, char *share)
struct smbc_server *smbc_server(char *server, char *share,
char *workgroup, char *username,
char *password)
{
struct smbc_server *srv=NULL;
struct cli_state c;
char *username = NULL;
char *password = NULL;
char *workgroup = NULL;
struct nmb_name called, calling;
char *p, *server_n = server;
fstring group;
@ -276,16 +284,6 @@ struct smbc_server *smbc_server(char *server, char *share)
ip = ipzero;
ZERO_STRUCT(c);
if (strncmp(share, "IPC$", 4)) /* IPC$ should not need a pwd ... */
smbc_auth_fn(server, share, &workgroup, &username, &password);
else {
workgroup = lp_workgroup(); /* Is this relevant here? */
username = "";
password = "";
}
/* try to use an existing connection */
for (srv=smbc_srvs;srv;srv=srv->next) {
if (strcmp(server,srv->server_name)==0 &&
@ -300,6 +298,24 @@ struct smbc_server *smbc_server(char *server, char *share)
return NULL;
}
/* Pick up the auth info here, once we know we need to connect */
smbc_auth_fn(server, share, workgroup, sizeof(fstring),
username, sizeof(fstring), password, sizeof(fstring));
/*
* However, smbc_auth_fn may have picked up info relating to an
* existing connection, so try for and existing connection again ...
*/
for (srv=smbc_srvs;srv;srv=srv->next) {
if (strcmp(server,srv->server_name)==0 &&
strcmp(share,srv->share_name)==0 &&
strcmp(workgroup,srv->workgroup)==0 &&
strcmp(username, srv->username) == 0)
return srv;
}
make_nmb_name(&calling, my_netbios_name, 0x0);
make_nmb_name(&called , server, 0x20);
@ -443,7 +459,12 @@ int smbc_init(smbc_get_auth_data_fn fn, const char *wgroup, int debug)
*/
user = getenv("USER");
if (!user) user = "";
if (!user) user = ""; /* FIXME: What to do about this? */
/*
* FIXME: Is this the best way to get the user info? */
pstrcpy(smbc_user, user); /* Save for use elsewhere */
pid = getpid();
@ -533,7 +554,7 @@ int smbc_init(smbc_get_auth_data_fn fn, const char *wgroup, int debug)
int smbc_open(const char *fname, int flags, mode_t mode)
{
fstring server, share;
fstring server, share, user, password;
pstring path;
struct smbc_server *srv = NULL;
struct smbc_file *file = NULL;
@ -553,9 +574,11 @@ int smbc_open(const char *fname, int flags, mode_t mode)
}
smbc_parse_path(fname, server, share, path); /* FIXME, check errors */
smbc_parse_path(fname, server, share, path, user, password); /* FIXME, check errors */
srv = smbc_server(server, share);
if (user[0] == (char)0) pstrcpy(user, smbc_user);
srv = smbc_server(server, share, lp_workgroup(), user, password);
if (!srv) {
@ -787,7 +810,7 @@ int smbc_close(int fd)
int smbc_unlink(const char *fname)
{
fstring server, share;
fstring server, share, user, password;
pstring path;
struct smbc_server *srv = NULL;
@ -805,9 +828,11 @@ int smbc_unlink(const char *fname)
}
smbc_parse_path(fname, server, share, path); /* FIXME, check errors */
smbc_parse_path(fname, server, share, path, user, password); /* FIXME, check errors */
srv = smbc_server(server, share);
if (user[0] == (char)0) pstrcpy(user, smbc_user);
srv = smbc_server(server, share, lp_workgroup(), user, password);
if (!srv) {
@ -847,7 +872,7 @@ int smbc_unlink(const char *fname)
int smbc_rename(const char *oname, const char *nname)
{
fstring server1, share1, server2, share2;
fstring server1, share1, server2, share2, user1, user2, password1, password2;
pstring path1, path2;
struct smbc_server *srv = NULL;
@ -867,19 +892,25 @@ int smbc_rename(const char *oname, const char *nname)
DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname));
smbc_parse_path(oname, server1, share1, path1);
smbc_parse_path(nname, server2, share2, path2);
smbc_parse_path(oname, server1, share1, path1, user1, password1);
if (strcmp(server1, server2) || strcmp(share1, share2)) {
if (user1[0] == (char)0) pstrcpy(user1, smbc_user);
/* Can't rename across file systems */
smbc_parse_path(nname, server2, share2, path2, user2, password2);
if (user2[0] == (char)0) pstrcpy(user2, smbc_user);
if (strcmp(server1, server2) || strcmp(share1, share2) ||
strcmp(user1, user2)) {
/* Can't rename across file systems, or users?? */
errno = EXDEV;
return -1;
}
srv = smbc_server(server1, share1);
srv = smbc_server(server1, share1, lp_workgroup(), user1, password1);
if (!srv) {
return -1;
@ -1059,7 +1090,7 @@ BOOL smbc_getatr(struct smbc_server *srv, char *path,
int smbc_stat(const char *fname, struct stat *st)
{
struct smbc_server *srv;
fstring server, share;
fstring server, share, user, password;
pstring path;
time_t m_time = 0, a_time = 0, c_time = 0;
size_t size = 0;
@ -1082,9 +1113,11 @@ int smbc_stat(const char *fname, struct stat *st)
DEBUG(4, ("stat(%s)\n", fname));
smbc_parse_path(fname, server, share, path);
smbc_parse_path(fname, server, share, path, user, password); /*FIXME, errors*/
srv = smbc_server(server, share);
if (user[0] == (char)0) pstrcpy(user, smbc_user);
srv = smbc_server(server, share, lp_workgroup(), user, password);
if (!srv) {
@ -1353,7 +1386,7 @@ dir_list_fn(file_info *finfo, const char *mask, void *state)
int smbc_opendir(const char *fname)
{
struct in_addr addr;
fstring server, share;
fstring server, share, user, password;
pstring path;
struct smbc_server *srv = NULL;
struct in_addr rem_ip;
@ -1373,13 +1406,15 @@ int smbc_opendir(const char *fname)
}
if (smbc_parse_path(fname, server, share, path)) {
if (smbc_parse_path(fname, server, share, path, user, password)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) pstrcpy(user, smbc_user);
/* Get a file entry ... */
slot = 0;
@ -1433,7 +1468,7 @@ int smbc_opendir(const char *fname)
* Get a connection to IPC$ on the server if we do not already have one
*/
srv = smbc_server(server, "IPC$");
srv = smbc_server(server, "IPC$", lp_workgroup(), user, password);
if (!srv) {
@ -1486,7 +1521,7 @@ int smbc_opendir(const char *fname)
* Get a connection to IPC$ on the server if we do not already have one
*/
srv = smbc_server(buserver, "IPC$");
srv = smbc_server(buserver, "IPC$", lp_workgroup(), user, password);
if (!srv) {
@ -1518,7 +1553,7 @@ int smbc_opendir(const char *fname)
smbc_file_table[slot]->dir_type = SMBC_FILE_SHARE;
srv = smbc_server(server, "IPC$");
srv = smbc_server(server, "IPC$", lp_workgroup(), user, password);
if (!srv) {
@ -1560,7 +1595,7 @@ int smbc_opendir(const char *fname)
smbc_file_table[slot]->dir_type = SMBC_FILE_SHARE;
srv = smbc_server(server, share);
srv = smbc_server(server, share, lp_workgroup(), user, password);
if (!srv) {
@ -1638,6 +1673,70 @@ int smbc_closedir(int fd)
* Routine to get a directory entry
*/
static char smbc_local_dirent[512]; /* Make big enough */
struct smbc_dirent *smbc_readdir(unsigned int fd)
{
struct smbc_file *fe;
struct smbc_dirent *dirp, *dirent;
/* Check that all is ok first ... */
if (!smbc_initialized) {
errno = EUCLEAN;
return NULL;
}
if (fd < smbc_start_fd || fd >= (smbc_start_fd + smbc_max_fd)) {
errno = EBADF;
return NULL;
}
fe = smbc_file_table[fd - smbc_start_fd];
if (fe->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
return NULL;
}
if (!fe->dir_next)
return NULL;
else {
dirent = fe->dir_next->dirent;
if (!dirent) {
errno = ENOENT;
return NULL;
}
/* Hmmm, do I even need to copy it? */
bcopy(dirent, smbc_local_dirent, dirent->dirlen); /* Copy the dirent */
dirp = (struct smbc_dirent *)smbc_local_dirent;
dirp->comment = (char *)(&dirp->name + dirent->namelen + 1);
fe->dir_next = fe->dir_next->next;
return (struct smbc_dirent *)smbc_local_dirent;
}
}
/*
* Routine to get directory entries
*/
int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
{
struct smbc_file *fe;