trying to get HEAD building again. If you want the code
[samba.git] / source3 / smbwrapper / smbw_dir.c
index c437a53e1f54a905bf43229b868c8d047865c2c6..6d55c1d9da2bf30fe9e37d36a608d31442ae6c56 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   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;
 
@@ -63,32 +62,35 @@ free a smbw_dir structure and all entries
 *******************************************************/
 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;
        }
 
@@ -99,16 +101,58 @@ static void smbw_dir_add(struct file_info *finfo)
 /***************************************************** 
 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);
+}
+
+
+/***************************************************** 
+add a entry to a directory listing
+*******************************************************/
+static void smbw_printjob_add(struct print_job_info *job)
+{
+       struct file_info finfo;
+
+       ZERO_STRUCT(finfo);
+
+       pstrcpy(finfo.name, job->name);
+       finfo.mode = aRONLY | aDIR;     
+       finfo.mtime = job->t;
+       finfo.atime = job->t;
+       finfo.ctime = job->t;
+       finfo.uid = nametouid(job->user);
+       finfo.mode = aRONLY;
+       finfo.size = job->size;
+
+       smbw_dir_add(&finfo, NULL, NULL);
 }
 
 
@@ -123,9 +167,7 @@ int smbw_dir_open(const char *fname)
        struct smbw_dir *dir=NULL;
        pstring mask;
        int fd;
-       char *s;
-
-       DEBUG(4,("%s\n", __FUNCTION__));
+       char *s, *p;
 
        if (!fname) {
                errno = EINVAL;
@@ -157,17 +199,47 @@ int smbw_dir_open(const char *fname)
        cur_dir = dir;
 
        slprintf(mask, sizeof(mask)-1, "%s\\*", path);
-       string_sub(mask,"\\\\","\\");
-
-       if (strcmp(share,"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) || (strcasecmp(share,"IPC$") == 0)) {
                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;
                }
@@ -175,7 +247,7 @@ int smbw_dir_open(const char *fname)
 
        cur_dir = NULL;
        
-       fd = open("/dev/null", O_WRONLY);
+       fd = open(SMBW_DUMMY, O_WRONLY);
        if (fd == -1) {
                errno = EMFILE;
                goto failed;
@@ -200,10 +272,8 @@ int smbw_dir_open(const char *fname)
        return dir->fd;
 
  failed:
-       if (dir) {
-               free_dir(dir);
-       }
-
+       free_dir(dir);
+       
        return -1;
 }
 
@@ -214,8 +284,6 @@ int smbw_dir_fstat(int fd, struct stat *st)
 {
        struct smbw_dir *dir;
 
-       DEBUG(4,("%s\n", __FUNCTION__));
-
        dir = smbw_dir(fd);
        if (!dir) {
                errno = EBADF;
@@ -224,7 +292,7 @@ int smbw_dir_fstat(int fd, struct stat *st)
 
        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;
 
@@ -238,11 +306,8 @@ int smbw_dir_close(int fd)
 {
        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;
        }
@@ -257,7 +322,6 @@ int smbw_dir_close(int fd)
        return 0;
 }
 
-
 /***************************************************** 
 a wrapper for getdents()
 *******************************************************/
@@ -266,8 +330,6 @@ int smbw_getdents(unsigned int fd, struct dirent *dirp, int count)
        struct smbw_dir *dir;
        int n=0;
 
-       DEBUG(4,("%s\n", __FUNCTION__));
-
        smbw_busy++;
 
        dir = smbw_dir(fd);
@@ -276,24 +338,27 @@ int smbw_getdents(unsigned int fd, struct dirent *dirp, int count)
                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;
 }
 
 
@@ -305,12 +370,15 @@ int smbw_chdir(const char *name)
        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++;
 
@@ -319,21 +387,21 @@ int smbw_chdir(const char *name)
                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;
        }
 
@@ -344,9 +412,11 @@ int smbw_chdir(const char *name)
                goto failed;
        }
 
-       if (strcmp(share,"IPC$") &&
+       if (strncmp(srv->cli.dev,"IPC",3) && 
+           strcasecmp(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;
        }
@@ -356,16 +426,16 @@ int smbw_chdir(const char *name)
                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;
 
@@ -383,9 +453,6 @@ off_t smbw_dir_lseek(int fd, off_t offset, int whence)
        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;
@@ -394,18 +461,18 @@ off_t smbw_dir_lseek(int fd, off_t offset, int whence)
 
        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));
 
@@ -422,8 +489,6 @@ int smbw_mkdir(const char *fname, mode_t mode)
        fstring server, share;
        pstring path;
 
-       DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
-
        if (!fname) {
                errno = EINVAL;
                return -1;
@@ -465,8 +530,6 @@ int smbw_rmdir(const char *fname)
        fstring server, share;
        pstring path;
 
-       DEBUG(4,("%s (%s)\n", __FUNCTION__, fname));
-
        if (!fname) {
                errno = EINVAL;
                return -1;
@@ -508,13 +571,13 @@ char *smbw_getcwd(char *buf, size_t size)
        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;
@@ -523,13 +586,13 @@ char *smbw_getcwd(char *buf, size_t size)
                }
        }
 
-       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;
@@ -541,21 +604,23 @@ a wrapper for fchdir()
 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;
 }
 
 /***************************************************** 
@@ -585,10 +650,13 @@ read one entry from a directory
 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;
 }