mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
The latest changes to libsmbclient ...
It can now do a directory listing for workgroups, servers, and shares, and,
with a bit more effort, it will be able to list directories and files.
I also does not request a username and password for the IPC$ share, but it
should if the first attempt to connect fails.
(This used to be commit 38ff91c505
)
This commit is contained in:
parent
dca808cbc4
commit
b6e811b90b
@ -55,11 +55,13 @@ void auth_fn(char *server, char *share,
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int err, fd;
|
||||
int err, fd, dh1, dh2, dh3, dsize, dirc;
|
||||
const char *file = "smb://samba/public/testfile.txt";
|
||||
const char *file2 = "smb://samba/public/testfile2.txt";
|
||||
const char *workgroup = "sambanet";
|
||||
char buff[256];
|
||||
char dirbuf[512];
|
||||
struct smbc_dirent *dirp;
|
||||
struct stat st1, st2;
|
||||
|
||||
err = smbc_init(auth_fn, workgroup, 10); /* Initialize things */
|
||||
@ -70,6 +72,121 @@ int main(int argc, char *argv[])
|
||||
|
||||
}
|
||||
|
||||
if (argc > 1) {
|
||||
|
||||
if ((dh1 = smbc_opendir("smb://"))<1) {
|
||||
|
||||
fprintf(stderr, "Could not open directory: smb://: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
if ((dh2 = smbc_opendir("smb://sambanet")) < 0) {
|
||||
|
||||
fprintf(stderr, "Could not open directory: smb://sambanet: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
if ((dh3 = smbc_opendir("smb://samba")) < 0) {
|
||||
|
||||
fprintf(stderr, "Could not open directory: smb://samba: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
fprintf(stdout, "Directory handles: %u, %u, %u\n", dh1, dh2, dh3);
|
||||
|
||||
/* Now, list those directories, but in funny ways ... */
|
||||
|
||||
dirp = (struct smbc_dirent *)dirbuf;
|
||||
|
||||
if ((dirc = smbc_getdents(dh1, 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 = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
|
||||
fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
|
||||
dirp->smbc_type, dirp->name, dirp->comment);
|
||||
|
||||
(char *)dirp += dsize;
|
||||
(char *)dirc -= dsize;
|
||||
|
||||
}
|
||||
|
||||
dirp = (struct smbc_dirent *)dirbuf;
|
||||
|
||||
if ((dirc = smbc_getdents(dh2, dirp, sizeof(dirbuf))) < 0) {
|
||||
|
||||
fprintf(stderr, "Problems getting directory entries: %s\n",
|
||||
strerror(errno));
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
/* Now, process the list of names ... */
|
||||
|
||||
fprintf(stdout, "\nDirectory listing, size = %u\n", dirc);
|
||||
|
||||
while (dirc > 0) {
|
||||
|
||||
dsize = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
|
||||
fprintf(stdout, "Dir Ent, Type: %u, Name: %s, Comment: %s\n",
|
||||
dirp->smbc_type, dirp->name, dirp->comment);
|
||||
|
||||
(char *)dirp += dsize;
|
||||
(char *)dirc -= dsize;
|
||||
|
||||
}
|
||||
|
||||
dirp = (struct smbc_dirent *)dirbuf;
|
||||
|
||||
if ((dirc = smbc_getdents(dh3, 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 = sizeof(struct smbc_dirent) + dirp->namelen + dirp->commentlen + 1;
|
||||
fprintf(stdout, "\nDir Ent, Type: %u, Name: %s, Comment: %s\n",
|
||||
dirp->smbc_type, dirp->name, dirp->comment);
|
||||
|
||||
(char *)dirp += dsize;
|
||||
(char *)dirc -= dsize;
|
||||
|
||||
}
|
||||
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
/* For now, open a file on a server that is hard coded ... later will
|
||||
* read from the command line ...
|
||||
*/
|
||||
|
@ -29,7 +29,28 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#define SMBC_MAX_NAME 1023
|
||||
|
||||
struct smbc_dirent {
|
||||
|
||||
uint smbc_type; /* Type of entity, see below */
|
||||
uint namelen;
|
||||
uint commentlen;
|
||||
char *comment; /* Points to the comment futher down */
|
||||
char name[1];
|
||||
|
||||
};
|
||||
|
||||
#define SMBC_WORKGROUP 1
|
||||
#define SMBC_SERVER 2
|
||||
#define SMBC_FILE_SHARE 3
|
||||
#define SMBC_PRINTER_SHARE 4
|
||||
#define SMBC_COMMS_SHARE 5
|
||||
#define SMBC_IPC_SHARE 6
|
||||
#define SMBC_DIR 7
|
||||
#define SMBC_FILE 8
|
||||
#define SMBC_LINK 9
|
||||
|
||||
#define SMBC_FILE_MODE (S_IFREG | 0444)
|
||||
#define SMBC_DIR_MODE (S_IFDIR | 0555)
|
||||
@ -133,7 +154,7 @@ int smbc_closedir(int fd);
|
||||
* Get a directory entry
|
||||
*/
|
||||
|
||||
int smbc_getdents(unsigned int fd, struct dirent *dirp, int count);
|
||||
int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count);
|
||||
|
||||
/*
|
||||
* Create a directory on a server, share, dir in fname URL
|
||||
|
@ -39,6 +39,12 @@ struct smbc_server {
|
||||
BOOL no_pathinfo2;
|
||||
};
|
||||
|
||||
/* Keep directory entries in a list */
|
||||
struct smbc_dir_list {
|
||||
struct smbc_dir_list *next;
|
||||
struct smbc_dirent *dirent;
|
||||
};
|
||||
|
||||
struct smbc_file {
|
||||
int cli_fd;
|
||||
int smbc_fd;
|
||||
@ -46,21 +52,26 @@ struct smbc_file {
|
||||
off_t offset;
|
||||
struct smbc_server *srv;
|
||||
BOOL file;
|
||||
struct smbc_dir_list *dir_list, *dir_end, *dir_next;
|
||||
int dir_type, dir_error;
|
||||
};
|
||||
|
||||
extern BOOL in_client;
|
||||
static int smbc_initialized = 0;
|
||||
static smbc_get_auth_data_fn smbc_auth_fn = NULL;
|
||||
static int smbc_debug;
|
||||
static int smbc_start_fd;
|
||||
static int smbc_max_fd = 10000;
|
||||
static struct smbc_file **smbc_file_table;
|
||||
static struct smbc_server *smbc_srvs;
|
||||
static pstring my_netbios_name;
|
||||
|
||||
/*
|
||||
* Clean up a filename by removing redundent stuff
|
||||
*/
|
||||
|
||||
static void
|
||||
clean_fname(char *name)
|
||||
smbc_clean_fname(char *name)
|
||||
{
|
||||
char *p, *p2;
|
||||
int l;
|
||||
@ -153,8 +164,11 @@ clean_fname(char *name)
|
||||
/*
|
||||
* Function to parse a path and turn it into components
|
||||
*
|
||||
* We accept smb://server/share/path...
|
||||
* We also accept //server/share/path ...
|
||||
* We accept smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]]
|
||||
*
|
||||
* smb:// means show all the workgroups
|
||||
* smb://name/ means, if name<1D> exists, list servers in workgroup,
|
||||
* else, if name<20> exists, list all shares for server ...
|
||||
*/
|
||||
|
||||
static const char *smbc_prefix = "smb:";
|
||||
@ -167,6 +181,7 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path)
|
||||
int len;
|
||||
fstring workgroup;
|
||||
|
||||
server[0] = share[0] = path[0] = (char)0;
|
||||
pstrcpy(s, fname);
|
||||
|
||||
/* clean_fname(s); causing problems ... */
|
||||
@ -186,7 +201,10 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path)
|
||||
|
||||
}
|
||||
|
||||
p += 2; /* Skip the // or \\ */
|
||||
p += 2; /* Skip the // or \\ */
|
||||
|
||||
if (*p == (char)0)
|
||||
return 0;
|
||||
|
||||
/* ok, its for us. Now parse out the server, share etc. */
|
||||
|
||||
@ -195,13 +213,15 @@ smbc_parse_path(const char *fname, char *server, char *share, char *path)
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (*p == (char)0) return 0; /* That's it ... */
|
||||
|
||||
if (!next_token(&p, share, "/", sizeof(fstring))) {
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
pstrcpy(path, p);
|
||||
|
||||
all_string_sub(path, "/", "\\", 0);
|
||||
@ -232,9 +252,6 @@ int smbc_errno(struct cli_state *c)
|
||||
* Connect to a server, possibly on an existing connection
|
||||
*/
|
||||
|
||||
static struct smbc_server *smbc_srvs;
|
||||
static pstring my_netbios_name;
|
||||
|
||||
struct smbc_server *smbc_server(char *server, char *share)
|
||||
{
|
||||
struct smbc_server *srv=NULL;
|
||||
@ -252,7 +269,15 @@ struct smbc_server *smbc_server(char *server, char *share)
|
||||
ip = ipzero;
|
||||
ZERO_STRUCT(c);
|
||||
|
||||
smbc_auth_fn(server, share, &workgroup, &username, &password);
|
||||
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) {
|
||||
@ -394,8 +419,9 @@ struct smbc_server *smbc_server(char *server, char *share)
|
||||
int smbc_init(smbc_get_auth_data_fn fn, const char *wgroup, int debug)
|
||||
{
|
||||
static pstring workgroup;
|
||||
pstring conf;
|
||||
int p, pid;
|
||||
char *user = NULL, *host = NULL;
|
||||
char *user = NULL, *host = NULL, *home = NULL;
|
||||
|
||||
smbc_initialized = 1;
|
||||
smbc_auth_fn = fn;
|
||||
@ -421,7 +447,28 @@ int smbc_init(smbc_get_auth_data_fn fn, const char *wgroup, int debug)
|
||||
|
||||
/* Here we would open the smb.conf file if needed ... */
|
||||
|
||||
/* To do soon ... try $HOME/.smb/smb.conf first ... */
|
||||
home = getenv("HOME");
|
||||
|
||||
slprintf(conf, sizeof(conf), "%s/.smb/smb.conf", home);
|
||||
|
||||
load_interfaces(); /* Load the list of interfaces ... */
|
||||
|
||||
in_client = True; /* FIXME, make a param */
|
||||
|
||||
|
||||
|
||||
if (!lp_load(conf, True, False, False)) {
|
||||
|
||||
/*
|
||||
* Hmmm, what the hell do we do here ... we could not parse the
|
||||
* config file ... We must return an error ... and keep info around
|
||||
* about why we failed
|
||||
*/
|
||||
/*
|
||||
errno = ENOENT; /* Hmmm, what error resp does lp_load return ? */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Now initialize the file descriptor array and figure out what the
|
||||
@ -463,8 +510,6 @@ int smbc_init(smbc_get_auth_data_fn fn, const char *wgroup, int debug)
|
||||
if (!smbc_file_table)
|
||||
return ENOMEM;
|
||||
|
||||
smbc_start_fd = 100000; /* FIXME: Figure it out */
|
||||
|
||||
return 0; /* Success */
|
||||
|
||||
}
|
||||
@ -519,12 +564,21 @@ int smbc_open(const char *fname, int flags, mode_t mode)
|
||||
while (smbc_file_table[slot])
|
||||
slot++;
|
||||
|
||||
if (slot > smbc_max_fd) return ENOMEM; /* FIXME, is this best? */
|
||||
if (slot > smbc_max_fd) {
|
||||
|
||||
errno = ENOMEM; /* FIXME, is this best? */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot] = malloc(sizeof(struct smbc_file));
|
||||
|
||||
if (!smbc_file_table[slot])
|
||||
return ENOMEM;
|
||||
if (!smbc_file_table[slot]) {
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
fd = cli_open(&srv->cli, path, flags, DENY_NONE);
|
||||
|
||||
@ -547,7 +601,7 @@ int smbc_open(const char *fname, int flags, mode_t mode)
|
||||
int eno = 0;
|
||||
|
||||
eno = smbc_errno(&srv->cli);
|
||||
fd = smbc_dir_open(fname);
|
||||
fd = smbc_opendir(fname);
|
||||
if (fd < 0) errno = eno;
|
||||
return fd;
|
||||
|
||||
@ -648,7 +702,7 @@ ssize_t smbc_write(int fd, void *buf, size_t count)
|
||||
|
||||
return ret; /* Success, 0 bytes of data ... */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Routine to close() a file ...
|
||||
*/
|
||||
@ -1077,15 +1131,324 @@ int smbc_fstat(int fd, struct stat *st)
|
||||
|
||||
/*
|
||||
* Routine to open a directory
|
||||
*
|
||||
* We want to allow:
|
||||
*
|
||||
* smb: which should list all the workgroups available
|
||||
* smb:workgroup
|
||||
* smb:workgroup//server
|
||||
* smb://server
|
||||
* smb://server/share
|
||||
*/
|
||||
|
||||
int smbc_dir_open(const char *fname)
|
||||
static void smbc_remove_dir(struct smbc_file *dir)
|
||||
{
|
||||
for (dir->dir_next = dir->dir_list;
|
||||
dir->dir_next != NULL;
|
||||
dir->dir_next = dir->dir_next->next) {
|
||||
|
||||
if (dir->dir_next->dirent) free(dir->dir_next->dirent);
|
||||
free(dir->dir_next);
|
||||
|
||||
}
|
||||
|
||||
dir->dir_list = dir->dir_end = dir->dir_next = NULL;
|
||||
|
||||
}
|
||||
|
||||
static int add_dirent(struct smbc_file *dir, const char *name, const char *comment, uint32 type)
|
||||
{
|
||||
struct smbc_dirent *dirent;
|
||||
|
||||
/*
|
||||
* Allocate space for the dirent, which must be increased by the
|
||||
* size of the name and the comment and 1 for the null on the comment.
|
||||
* The null on the name is already accounted for.
|
||||
*/
|
||||
|
||||
dirent = malloc(sizeof(struct smbc_dirent) + (name?strlen(name):0) +
|
||||
(comment?strlen(comment):0) + 1);
|
||||
|
||||
if (!dirent) {
|
||||
|
||||
dir->dir_error = ENOMEM;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (dir->dir_list == NULL) {
|
||||
|
||||
dir->dir_list = malloc(sizeof(struct smbc_dir_list));
|
||||
if (!dir->dir_list) {
|
||||
|
||||
free(dirent);
|
||||
dir->dir_error = ENOMEM;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
dir->dir_end = dir->dir_next = dir->dir_list;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
dir->dir_end->next = malloc(sizeof(struct smbc_dir_list));
|
||||
|
||||
if (!dir->dir_end) {
|
||||
|
||||
free(dirent);
|
||||
dir->dir_error = ENOMEM;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
dir->dir_end = dir->dir_end->next;
|
||||
dir->dir_end->next = NULL;
|
||||
|
||||
}
|
||||
|
||||
dir->dir_end->dirent = dirent;
|
||||
|
||||
dirent->smbc_type = dir->dir_type;
|
||||
dirent->namelen = (name?strlen(name):0);
|
||||
dirent->commentlen = (comment?strlen(comment):0);
|
||||
|
||||
strncpy(dirent->name, (name?name:""), dirent->namelen + 1);
|
||||
|
||||
dirent->comment = (char *)(&dirent->name + dirent->namelen + 1);
|
||||
strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
list_fn(const char *name, uint32 type, const char *comment, void *state)
|
||||
{
|
||||
|
||||
if (add_dirent((struct smbc_file *)state, name, comment, type) < 0) {
|
||||
|
||||
/* An error occurred, what do we do? */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int smbc_opendir(const char *fname)
|
||||
{
|
||||
struct in_addr addr;
|
||||
fstring server, share;
|
||||
pstring path;
|
||||
struct smbc_server *srv = NULL;
|
||||
struct in_addr rem_ip;
|
||||
int slot = 0;
|
||||
|
||||
if (!smbc_initialized) {
|
||||
|
||||
errno = EUCLEAN;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (!fname) {
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (smbc_parse_path(fname, server, share, path)) {
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* Get a file entry ... */
|
||||
|
||||
slot = 0;
|
||||
|
||||
while (smbc_file_table[slot])
|
||||
slot++;
|
||||
|
||||
if (slot > smbc_max_fd) {
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1; /* FIXME, ... move into a func */
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot] = malloc(sizeof(struct smbc_file));
|
||||
|
||||
if (!smbc_file_table[slot]) {
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot]->cli_fd = 0;
|
||||
smbc_file_table[slot]->smbc_fd = slot + smbc_start_fd;
|
||||
smbc_file_table[slot]->fname = strdup(fname);
|
||||
smbc_file_table[slot]->srv = NULL;
|
||||
smbc_file_table[slot]->offset = 0;
|
||||
smbc_file_table[slot]->file = False;
|
||||
smbc_file_table[slot]->dir_list = NULL;
|
||||
|
||||
if (server[0] == (char)0) {
|
||||
|
||||
if (share[0] != (char)0 || path[0] != (char)0) {
|
||||
|
||||
errno = EINVAL;
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* We have server and share and path empty ... so list the workgroups */
|
||||
|
||||
/* fprintf(stderr, "Workgroup is: %s\n", lp_workgroup()); */
|
||||
cli_get_backup_server(my_netbios_name, lp_workgroup(), server, sizeof(server));
|
||||
|
||||
smbc_file_table[slot]->dir_type = SMBC_WORKGROUP;
|
||||
|
||||
/*
|
||||
* Get a connection to IPC$ on the server if we do not already have one
|
||||
*/
|
||||
|
||||
srv = smbc_server(server, "IPC$");
|
||||
|
||||
if (!srv) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot]->srv = srv;
|
||||
|
||||
/* Now, list the stuff ... */
|
||||
|
||||
if (!cli_NetServerEnum(&srv->cli, lp_workgroup(), 0x80000000, list_fn,
|
||||
(void *)smbc_file_table[slot])) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
}
|
||||
else { /* Server not an empty string ... Check the rest and see what gives */
|
||||
|
||||
if (share[0] == (char)0) {
|
||||
|
||||
if (path[0] != (char)0) { /* Should not have empty share with path */
|
||||
|
||||
errno = EINVAL;
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/* Check to see if <server><1D> translates, or <server><20> translates */
|
||||
|
||||
if (resolve_name(server, &rem_ip, 0x1d)) { /* Found LMB */
|
||||
|
||||
smbc_file_table[slot]->dir_type = SMBC_SERVER;
|
||||
|
||||
/*
|
||||
* Get the backup list ...
|
||||
*/
|
||||
|
||||
cli_get_backup_server(my_netbios_name, server, server, sizeof(server));
|
||||
|
||||
/*
|
||||
* Get a connection to IPC$ on the server if we do not already have one
|
||||
*/
|
||||
|
||||
srv = smbc_server(server, "IPC$");
|
||||
|
||||
if (!srv) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL; /* FIXME: Memory leaks ... */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot]->srv = srv;
|
||||
|
||||
/* Now, list the servers ... */
|
||||
|
||||
if (!cli_NetServerEnum(&srv->cli, lp_workgroup(), 0x0000FFFE, list_fn,
|
||||
(void *)smbc_file_table[slot])) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
if (resolve_name(server, &rem_ip, 0x20)) {
|
||||
|
||||
/* Now, list the shares ... */
|
||||
|
||||
smbc_file_table[slot]->dir_type = SMBC_FILE_SHARE;
|
||||
|
||||
srv = smbc_server(server, "IPC$");
|
||||
|
||||
if (!srv) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
smbc_file_table[slot]->srv = srv;
|
||||
|
||||
/* Now, list the servers ... */
|
||||
|
||||
if (!cli_RNetShareEnum(&srv->cli, list_fn,
|
||||
(void *)smbc_file_table[slot])) {
|
||||
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
errno = EINVAL;
|
||||
if (smbc_file_table[slot]) free(smbc_file_table[slot]);
|
||||
smbc_file_table[slot] = NULL;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else { /* The server and share are specified ... work from there ... */
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return smbc_file_table[slot]->smbc_fd;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Routine to close a directory
|
||||
*/
|
||||
@ -1101,10 +1464,81 @@ int smbc_closedir(int fd)
|
||||
* Routine to get a directory entry
|
||||
*/
|
||||
|
||||
int smbc_getdents(unsigned int fd, struct dirent *dirp, int count)
|
||||
int smbc_getdents(unsigned int fd, struct smbc_dirent *dirp, int count)
|
||||
{
|
||||
struct smbc_file *fe;
|
||||
struct smbc_dir_list *dir;
|
||||
int rem = count, reqd;
|
||||
|
||||
return 0;
|
||||
/* Check that all is ok first ... */
|
||||
|
||||
if (fd < smbc_start_fd || fd >= (smbc_start_fd + smbc_max_fd)) {
|
||||
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
fe = smbc_file_table[fd - smbc_start_fd];
|
||||
|
||||
if (fe->file != False) { /* FIXME, should be dir, perhaps */
|
||||
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, retrieve the number of entries that will fit in what was passed
|
||||
* We have to figure out if the info is in the list, or we need to
|
||||
* send a request to the server to get the info.
|
||||
*/
|
||||
|
||||
while ((dir = fe->dir_next)) {
|
||||
struct smbc_dirent *dirent;
|
||||
|
||||
if (!dir->dirent) {
|
||||
|
||||
errno = ENOENT; /* Bad error */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (rem < (reqd = (sizeof(struct smbc_dirent) + dir->dirent->namelen +
|
||||
dir->dirent->commentlen + 1))) {
|
||||
|
||||
if (rem < count) { /* We managed to copy something */
|
||||
|
||||
errno = 0;
|
||||
return count - rem;
|
||||
|
||||
}
|
||||
else { /* Nothing copied ... */
|
||||
|
||||
errno = EINVAL; /* Not enough space ... */
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dirent = dir->dirent;
|
||||
|
||||
bcopy(dirent, dirp, reqd); /* Copy the data in ... */
|
||||
|
||||
dirp->comment = (char *)(&dirp->name + dirent->namelen + 1);
|
||||
|
||||
(char *)dirp += reqd;
|
||||
|
||||
rem -= reqd;
|
||||
|
||||
fe->dir_next = dir = dir -> next;
|
||||
}
|
||||
|
||||
if (rem == count)
|
||||
return 0;
|
||||
else
|
||||
return count - rem;
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user