/*
- Unix SMB/Netbios implementation.
- Version 2.0
+ Unix SMB/CIFS implementation.
SMB wrapper directory functions
Copyright (C) Andrew Tridgell 1998
*/
#include "includes.h"
-#include "wrapper.h"
+#include "realcalls.h"
-extern pstring smb_cwd;
+extern pstring smbw_cwd;
+extern fstring smbw_prefix;
static struct smbw_dir *smbw_dirs;
extern struct bitmap *smbw_file_bmap;
-extern int DEBUGLEVEL;
extern int smbw_busy;
*******************************************************/
static void free_dir(struct smbw_dir *dir)
{
- if (dir->list) {
- free(dir->list);
- }
- if (dir->path) free(dir->path);
+ if(!dir) return;
+
+ SAFE_FREE(dir->list);
+ SAFE_FREE(dir->path);
ZERO_STRUCTP(dir);
- free(dir);
+ SAFE_FREE(dir);
}
-
static struct smbw_dir *cur_dir;
/*****************************************************
add a entry to a directory listing
*******************************************************/
-static void smbw_dir_add(struct file_info *finfo)
+static void smbw_dir_add(struct file_info *finfo, const char *mask,
+ void *state)
{
+ struct file_info *cdl;
+
DEBUG(5,("%s\n", finfo->name));
if (cur_dir->malloced == cur_dir->count) {
- cur_dir->list = (struct file_info *)Realloc(cur_dir->list,
+ cdl = (struct file_info *)Realloc(cur_dir->list,
sizeof(cur_dir->list[0])*
(cur_dir->count+100));
- if (!cur_dir->list) {
+ if (!cdl) {
/* oops */
return;
}
+ cur_dir->list = cdl;
cur_dir->malloced += 100;
}
/*****************************************************
add a entry to a directory listing
*******************************************************/
-static void smbw_share_add(const char *share, uint32 type, const char *comment)
+static void smbw_share_add(const char *share, uint32 type,
+ const char *comment, void *state)
{
struct file_info finfo;
+ if (strcmp(share,"IPC$") == 0) return;
+
ZERO_STRUCT(finfo);
pstrcpy(finfo.name, share);
finfo.mode = aRONLY | aDIR;
- smbw_dir_add(&finfo);
+ smbw_dir_add(&finfo, NULL, NULL);
+}
+
+
+/*****************************************************
+add a server to a directory listing
+*******************************************************/
+static void smbw_server_add(const char *name, uint32 type,
+ const char *comment, void *state)
+{
+ struct file_info finfo;
+
+ ZERO_STRUCT(finfo);
+
+ pstrcpy(finfo.name, name);
+ finfo.mode = aRONLY | aDIR;
+
+ smbw_dir_add(&finfo, NULL, NULL);
}
finfo.mode = aRONLY;
finfo.size = job->size;
- smbw_dir_add(&finfo);
+ smbw_dir_add(&finfo, NULL, NULL);
}
struct smbw_dir *dir=NULL;
pstring mask;
int fd;
- char *s;
-
- DEBUG(4,("%s\n", __FUNCTION__));
+ char *s, *p;
if (!fname) {
errno = EINVAL;
cur_dir = dir;
slprintf(mask, sizeof(mask)-1, "%s\\*", path);
- string_sub(mask,"\\\\","\\");
-
- if (strcmp(srv->cli.dev,"IPC") == 0) {
+ all_string_sub(mask,"\\\\","\\",0);
+
+ if ((p=strstr(srv->server_name,"#01"))) {
+ *p = 0;
+ smbw_server_add(".",0,"", NULL);
+ smbw_server_add("..",0,"", NULL);
+ smbw_NetServerEnum(&srv->cli, srv->server_name,
+ SV_TYPE_DOMAIN_ENUM, smbw_server_add, NULL);
+ *p = '#';
+ } else if ((p=strstr(srv->server_name,"#1D"))) {
+ DEBUG(4,("doing NetServerEnum\n"));
+ *p = 0;
+ smbw_server_add(".",0,"", NULL);
+ smbw_server_add("..",0,"", NULL);
+ smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL,
+ smbw_server_add, NULL);
+ *p = '#';
+ } else if ((strcmp(srv->cli.dev,"IPC") == 0) || (strequal(share,"IPC$"))) {
DEBUG(4,("doing NetShareEnum\n"));
- if (cli_RNetShareEnum(&srv->cli, smbw_share_add) < 0) {
+ smbw_share_add(".",0,"", NULL);
+ smbw_share_add("..",0,"", NULL);
+ if (smbw_RNetShareEnum(&srv->cli, smbw_share_add, NULL) < 0) {
errno = smbw_errno(&srv->cli);
goto failed;
}
} else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
+ smbw_share_add(".",0,"", NULL);
+ smbw_share_add("..",0,"", NULL);
if (cli_print_queue(&srv->cli, smbw_printjob_add) < 0) {
errno = smbw_errno(&srv->cli);
goto failed;
}
} else {
+#if 0
+ if (strcmp(path,"\\") == 0) {
+ smbw_share_add(".",0,"");
+ smbw_share_add("..",0,"");
+ }
+#endif
if (cli_list(&srv->cli, mask, aHIDDEN|aSYSTEM|aDIR,
- smbw_dir_add) < 0) {
+ smbw_dir_add, NULL) < 0) {
errno = smbw_errno(&srv->cli);
goto failed;
}
return dir->fd;
failed:
- if (dir) {
- free_dir(dir);
- }
-
+ free_dir(dir);
+
return -1;
}
{
struct smbw_dir *dir;
- DEBUG(4,("%s\n", __FUNCTION__));
-
dir = smbw_dir(fd);
if (!dir) {
errno = EBADF;
ZERO_STRUCTP(st);
- smbw_setup_stat(st, "", dir->count*sizeof(struct dirent), aDIR);
+ smbw_setup_stat(st, "", dir->count*DIRP_SIZE, aDIR);
st->st_dev = dir->srv->dev;
{
struct smbw_dir *dir;
- DEBUG(4,("%s\n", __FUNCTION__));
-
dir = smbw_dir(fd);
if (!dir) {
- DEBUG(4,("%s(%d)\n", __FUNCTION__, __LINE__));
errno = EBADF;
return -1;
}
return 0;
}
-
/*****************************************************
a wrapper for getdents()
*******************************************************/
struct smbw_dir *dir;
int n=0;
- DEBUG(4,("%s\n", __FUNCTION__));
-
smbw_busy++;
dir = smbw_dir(fd);
smbw_busy--;
return -1;
}
-
- while (count>=sizeof(*dirp) && (dir->offset < dir->count)) {
- dirp->d_off = (dir->offset+1)*sizeof(*dirp);
- dirp->d_reclen = sizeof(*dirp);
- safe_strcpy(&dirp->d_name[0], dir->list[dir->offset].name,
- sizeof(dirp->d_name)-1);
+
+ while (count>=DIRP_SIZE && (dir->offset < dir->count)) {
+#if HAVE_DIRENT_D_OFF
+ dirp->d_off = (dir->offset+1)*DIRP_SIZE;
+#endif
+ dirp->d_reclen = DIRP_SIZE;
+ fstrcpy(&dirp->d_name[0], dir->list[dir->offset].name);
dirp->d_ino = smbw_inode(dir->list[dir->offset].name);
dir->offset++;
count -= dirp->d_reclen;
+#if HAVE_DIRENT_D_OFF
if (dir->offset == dir->count) {
dirp->d_off = -1;
}
- dirp++;
+#endif
+ dirp = (struct dirent *)(((char *)dirp) + DIRP_SIZE);
n++;
}
smbw_busy--;
- return n*sizeof(*dirp);
+ return n*DIRP_SIZE;
}
struct smbw_server *srv;
fstring server, share;
pstring path;
- uint32 mode = aDIR;
+ uint16 mode = aDIR;
char *cwd;
+ int len;
smbw_init();
- if (smbw_busy) return real_chdir(cwd);
+ len = strlen(smbw_prefix);
+
+ if (smbw_busy) return real_chdir(name);
smbw_busy++;
goto failed;
}
- DEBUG(4,("%s (%s)\n", __FUNCTION__, name));
+ DEBUG(4,("smbw_chdir(%s)\n", name));
/* work out what server they are after */
cwd = smbw_parse_path(name, server, share, path);
- if (strncmp(cwd,SMBW_PREFIX,strlen(SMBW_PREFIX))) {
+ /* a special case - accept cd to /smb */
+ if (strncmp(cwd, smbw_prefix, len-1) == 0 &&
+ cwd[len-1] == 0) {
+ goto success1;
+ }
+
+ if (strncmp(cwd,smbw_prefix,strlen(smbw_prefix))) {
if (real_chdir(cwd) == 0) {
- DEBUG(4,("set SMBW_CWD to %s\n", cwd));
- pstrcpy(smb_cwd, cwd);
- if (setenv(SMBW_PWD_ENV, smb_cwd, 1)) {
- DEBUG(4,("setenv failed\n"));
- }
- goto success;
+ goto success2;
}
- errno = ENOENT;
goto failed;
}
goto failed;
}
- if (strncmp(srv->cli.dev,"IPC",3) &&
+ if (strncmp(srv->cli.dev,"IPC",3) &&
+ !strequal(share, "IPC$") &&
strncmp(srv->cli.dev,"LPT",3) &&
!smbw_getatr(srv, path,
- &mode, NULL, NULL, NULL, NULL)) {
+ &mode, NULL, NULL, NULL, NULL, NULL)) {
errno = smbw_errno(&srv->cli);
goto failed;
}
goto failed;
}
- DEBUG(4,("set SMBW_CWD2 to %s\n", cwd));
- pstrcpy(smb_cwd, cwd);
- if (setenv(SMBW_PWD_ENV, smb_cwd, 1)) {
- DEBUG(4,("setenv failed\n"));
- }
-
+ success1:
/* we don't want the old directory to be busy */
real_chdir("/");
- success:
+ success2:
+
+ DEBUG(4,("set SMBW_CWD to %s\n", cwd));
+
+ pstrcpy(smbw_cwd, cwd);
+
smbw_busy--;
return 0;
struct smbw_dir *dir;
off_t ret;
- DEBUG(4,("%s offset=%d whence=%d\n", __FUNCTION__,
- (int)offset, whence));
-
dir = smbw_dir(fd);
if (!dir) {
errno = EBADF;
switch (whence) {
case SEEK_SET:
- dir->offset = offset/sizeof(struct dirent);
+ dir->offset = offset/DIRP_SIZE;
break;
case SEEK_CUR:
- dir->offset += offset/sizeof(struct dirent);
+ dir->offset += offset/DIRP_SIZE;
break;
case SEEK_END:
- dir->offset = (dir->count * sizeof(struct dirent)) + offset;
- dir->offset /= sizeof(struct dirent);
+ dir->offset = (dir->count * DIRP_SIZE) + offset;
+ dir->offset /= DIRP_SIZE;
break;
}
- ret = dir->offset * sizeof(struct dirent);
+ ret = dir->offset * DIRP_SIZE;
DEBUG(4,(" -> %d\n", (int)ret));
fstring server, share;
pstring path;
- DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
-
if (!fname) {
errno = EINVAL;
return -1;
fstring server, share;
pstring path;
- DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
-
if (!fname) {
errno = EINVAL;
return -1;
smbw_init();
if (smbw_busy) {
- return __getcwd(buf, size);
+ return (char *)real_getcwd(buf, size);
}
smbw_busy++;
if (!buf) {
- if (size <= 0) size = strlen(smb_cwd)+1;
+ if (size <= 0) size = strlen(smbw_cwd)+1;
buf = (char *)malloc(size);
if (!buf) {
errno = ENOMEM;
}
}
- if (strlen(smb_cwd) > size-1) {
+ if (strlen(smbw_cwd) > size-1) {
errno = ERANGE;
smbw_busy--;
return NULL;
}
- safe_strcpy(buf, smb_cwd, size);
+ safe_strcpy(buf, smbw_cwd, size);
smbw_busy--;
return buf;
int smbw_fchdir(unsigned int fd)
{
struct smbw_dir *dir;
-
- DEBUG(4,("%s\n", __FUNCTION__));
+ int ret;
smbw_busy++;
dir = smbw_dir(fd);
- if (!dir) {
- errno = EBADF;
+ if (dir) {
smbw_busy--;
- return -1;
+ return chdir(dir->path);
}
+ ret = real_fchdir(fd);
+ if (ret == 0) {
+ sys_getwd(smbw_cwd);
+ }
+
smbw_busy--;
-
- return chdir(dir->path);
+ return ret;
}
/*****************************************************
struct dirent *smbw_readdir(DIR *dirp)
{
struct smbw_dir *d = (struct smbw_dir *)dirp;
- static struct dirent de;
+ static union {
+ char buf[DIRP_SIZE];
+ struct dirent de;
+ } dbuf;
- if (smbw_getdents(d->fd, &de, sizeof(struct dirent)) > 0)
- return &de;
+ if (smbw_getdents(d->fd, &dbuf.de, DIRP_SIZE) > 0)
+ return &dbuf.de;
return NULL;
}