add support for dup() and dup2()
authorAndrew Tridgell <tridge@samba.org>
Sun, 4 Oct 1998 07:52:00 +0000 (07:52 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 4 Oct 1998 07:52:00 +0000 (07:52 +0000)
source/smbwrapper/realcalls.h
source/smbwrapper/smbw.c
source/smbwrapper/smbw.h
source/smbwrapper/smbw_stat.c
source/smbwrapper/wrapped.c

index 786e8966416686b18500c754d1855aeda56c80e5..46784268691a7eefb3533f89c9e90335c431ac4e 100644 (file)
@@ -58,6 +58,8 @@
 #define real_lseek(fd, offset, whence) (syscall(SYS_lseek, (fd), (offset), (whence)))
 #define real_write(fd, buf, count )    (syscall(SYS_write, (fd), (buf), (count)))
 #define real_close(fd)                 (syscall(SYS_close, (fd)))
+#define real_dup(fd)                   (syscall(SYS_dup, (fd)))
+#define real_dup2(fd1, fd2)             (syscall(SYS_dup2, (fd1), (fd2)))
 #define real_fchdir(fd)                        (syscall(SYS_fchdir, (fd)))
 #define real_fcntl(fd,cmd,arg)         (syscall(SYS_fcntl, (fd), (cmd), (arg)))
 #define real_symlink(fn1, fn2)         (syscall(SYS_symlink, (fn1), (fn2)))
@@ -66,5 +68,3 @@
 #define real_mkdir(fn, mode)           (syscall(SYS_mkdir, (fn), (mode)))
 #define real_utime(fn, buf)            (syscall(SYS_utime, (fn), (buf)))
 #define real_utimes(fn, buf)           (syscall(SYS_utimes, (fn), (buf)))
-
-
index 39c3eec90c185514b7b73b26025afbdeadef4bc1..74a40a2451b19dfb1545ec459031ff34e4e70755 100644 (file)
@@ -516,9 +516,17 @@ int smbw_open(const char *fname, int flags, mode_t mode)
 
        ZERO_STRUCTP(file);
 
-       file->cli_fd = fd;
-       file->fname = strdup(path);
-       if (!file->fname) {
+       file->f = (struct smbw_filedes *)malloc(sizeof(*(file->f)));
+       if (!file->f) {
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       ZERO_STRUCTP(file->f);
+
+       file->f->cli_fd = fd;
+       file->f->fname = strdup(path);
+       if (!file->f->fname) {
                errno = ENOMEM;
                goto failed;
        }
@@ -535,6 +543,8 @@ int smbw_open(const char *fname, int flags, mode_t mode)
                goto failed;
        }
 
+       file->f->ref_count=1;
+
        bitmap_set(smbw_file_bmap, file->fd);
 
        DLIST_ADD(smbw_files, file);
@@ -549,8 +559,11 @@ int smbw_open(const char *fname, int flags, mode_t mode)
                cli_close(&srv->cli, fd);
        }
        if (file) {
-               if (file->fname) {
-                       free(file->fname);
+               if (file->f) {
+                       if (file->f->fname) {
+                               free(file->f->fname);
+                       }
+                       free(file->f);
                }
                free(file);
        }
@@ -579,7 +592,7 @@ ssize_t smbw_read(int fd, void *buf, size_t count)
                return -1;
        }
        
-       ret = cli_read(&file->srv->cli, file->cli_fd, buf, file->offset, count);
+       ret = cli_read(&file->srv->cli, file->f->cli_fd, buf, file->f->offset, count);
 
        if (ret == -1) {
                errno = smbw_errno(&file->srv->cli);
@@ -587,7 +600,7 @@ ssize_t smbw_read(int fd, void *buf, size_t count)
                return -1;
        }
 
-       file->offset += ret;
+       file->f->offset += ret;
 
        smbw_busy--;
        return ret;
@@ -613,7 +626,7 @@ ssize_t smbw_write(int fd, void *buf, size_t count)
                return -1;
        }
        
-       ret = cli_write(&file->srv->cli, file->cli_fd, buf, file->offset, count);
+       ret = cli_write(&file->srv->cli, file->f->cli_fd, buf, file->f->offset, count);
 
        if (ret == -1) {
                errno = smbw_errno(&file->srv->cli);
@@ -621,7 +634,7 @@ ssize_t smbw_write(int fd, void *buf, size_t count)
                return -1;
        }
 
-       file->offset += ret;
+       file->f->offset += ret;
 
        smbw_busy--;
        return ret;
@@ -645,7 +658,8 @@ int smbw_close(int fd)
                return ret;
        }
        
-       if (!cli_close(&file->srv->cli, file->cli_fd)) {
+       if (file->f->ref_count == 1 &&
+           !cli_close(&file->srv->cli, file->f->cli_fd)) {
                errno = smbw_errno(&file->srv->cli);
                smbw_busy--;
                return -1;
@@ -657,7 +671,11 @@ int smbw_close(int fd)
        
        DLIST_REMOVE(smbw_files, file);
 
-       free(file->fname);
+       file->f->ref_count--;
+       if (file->f->ref_count == 0) {
+               free(file->f->fname);
+               free(file->f);
+       }
        ZERO_STRUCTP(file);
        free(file);
        
@@ -969,25 +987,135 @@ off_t smbw_lseek(int fd, off_t offset, int whence)
 
        switch (whence) {
        case SEEK_SET:
-               file->offset = offset;
+               file->f->offset = offset;
                break;
        case SEEK_CUR:
-               file->offset += offset;
+               file->f->offset += offset;
                break;
        case SEEK_END:
-               if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, 
+               if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, 
                                   NULL, &size, NULL, NULL, NULL) &&
-                   !cli_getattrE(&file->srv->cli, file->cli_fd, 
+                   !cli_getattrE(&file->srv->cli, file->f->cli_fd, 
                                  NULL, &size, NULL, NULL, NULL)) {
                        errno = EINVAL;
                        smbw_busy--;
                        return -1;
                }
-               file->offset = size + offset;
+               file->f->offset = size + offset;
                break;
        }
 
        smbw_busy--;
-       return file->offset;
+       return file->f->offset;
+}
+
+
+/***************************************************** 
+a wrapper for dup()
+*******************************************************/
+int smbw_dup(int fd)
+{
+       int fd2;
+       struct smbw_file *file, *file2;
+
+       DEBUG(4,("%s\n", __FUNCTION__));
+
+       smbw_busy++;
+
+       file = smbw_file(fd);
+       if (!file) {
+               errno = EBADF;
+               goto failed;
+       }
+
+       fd2 = dup(file->fd);
+       if (fd2 == -1) {
+               goto failed;
+       }
+
+       if (bitmap_query(smbw_file_bmap, fd2)) {
+               DEBUG(0,("ERROR: fd already open in dup!\n"));
+               errno = EIO;
+               goto failed;
+       }
+
+       file2 = (struct smbw_file *)malloc(sizeof(*file2));
+       if (!file2) {
+               close(fd2);
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       ZERO_STRUCTP(file2);
+
+       *file2 = *file;
+       file2->fd = fd2;
+
+       file->f->ref_count++;
+
+       bitmap_set(smbw_file_bmap, fd2);
+       
+       DLIST_ADD(smbw_files, file2);
+       
+       smbw_busy--;
+       return fd2;
+
+ failed:
+       smbw_busy--;
+       return -1;
+}
+
+
+/***************************************************** 
+a wrapper for dup2()
+*******************************************************/
+int smbw_dup2(int fd, int fd2)
+{
+       struct smbw_file *file, *file2;
+
+       DEBUG(4,("%s\n", __FUNCTION__));
+
+       smbw_busy++;
+
+       file = smbw_file(fd);
+       if (!file) {
+               errno = EBADF;
+               goto failed;
+       }
+
+       if (bitmap_query(smbw_file_bmap, fd2)) {
+               DEBUG(0,("ERROR: fd already open in dup2!\n"));
+               errno = EIO;
+               goto failed;
+       }
+
+       if (dup2(file->fd, fd2) != fd2) {
+               goto failed;
+       }
+
+       file2 = (struct smbw_file *)malloc(sizeof(*file2));
+       if (!file2) {
+               close(fd2);
+               errno = ENOMEM;
+               goto failed;
+       }
+
+       ZERO_STRUCTP(file2);
+
+       *file2 = *file;
+       file2->fd = fd2;
+
+       file->f->ref_count++;
+
+       bitmap_set(smbw_file_bmap, fd2);
+       
+       DLIST_ADD(smbw_files, file2);
+       
+       smbw_busy--;
+       return fd2;
+
+ failed:
+       smbw_busy--;
+       return -1;
 }
 
index af48061ff0627e91236e95a01ddbf4d0fb6c0cc7..2f16efd216b8f68ba1ac587a7ec8bb2ae3bac323 100644 (file)
@@ -39,11 +39,17 @@ struct smbw_server {
        dev_t dev;
 };
 
-struct smbw_file {
-       struct smbw_file *next, *prev;
-       int cli_fd, fd;
+struct smbw_filedes {
+       int cli_fd;
+       int ref_count;
        char *fname;
        off_t offset;
+};
+
+struct smbw_file {
+       struct smbw_file *next, *prev;
+       struct smbw_filedes *f;
+       int fd;
        struct smbw_server *srv;
 };
 
index 5ca71ee2ef1e17e018b421650b6c6b96c9dac5a9..ae8671c591fb87ac88ee27ad55922c01c53b1e3b 100644 (file)
@@ -95,16 +95,16 @@ int smbw_fstat(int fd, struct stat *st)
                return ret;
        }
 
-       if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, 
+       if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, 
                          &mode, &size, &c_time, &a_time, &m_time) &&
-           !cli_getattrE(&file->srv->cli, file->cli_fd, 
+           !cli_getattrE(&file->srv->cli, file->f->cli_fd, 
                          &mode, &size, &c_time, &a_time, &m_time)) {
                errno = EINVAL;
                smbw_busy--;
                return -1;
        }
 
-       smbw_setup_stat(st, file->fname, size, mode);
+       smbw_setup_stat(st, file->f->fname, size, mode);
 
        st->st_atime = a_time;
        st->st_ctime = c_time;
index 13bd449db3a9110e275f6ba60976ec29cf5e52b8..0ee7341e3b256c2a7012537806afda075ff6f9ec 100644 (file)
@@ -509,3 +509,25 @@ __asm__(".globl __write; __write = write");
 
        return real_symlink(topath, frompath);
 }
+
+ int dup(int fd)
+{
+       if (smbw_fd(fd)) {
+               return smbw_dup(fd);
+       }
+
+       return real_dup(fd);
+}
+
+ int dup2(int oldfd, int newfd)
+{
+       if (smbw_fd(newfd)) {
+               close(newfd);
+       }
+
+       if (smbw_fd(oldfd)) {
+               return smbw_dup2(oldfd, newfd);
+       }
+
+       return real_dup2(oldfd, newfd);
+}