From ce843e9735742626bb03cbea61041fff5d215930 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 4 Oct 1998 07:52:00 +0000 Subject: add support for dup() and dup2() (This used to be commit c5210cb0fffd406ef1809db8644b299bb661df4d) --- source3/smbwrapper/realcalls.h | 4 +- source3/smbwrapper/smbw.c | 162 ++++++++++++++++++++++++++++++++++++----- source3/smbwrapper/smbw.h | 12 ++- source3/smbwrapper/smbw_stat.c | 6 +- source3/smbwrapper/wrapped.c | 22 ++++++ 5 files changed, 181 insertions(+), 25 deletions(-) (limited to 'source3') diff --git a/source3/smbwrapper/realcalls.h b/source3/smbwrapper/realcalls.h index 786e896641..4678426869 100644 --- a/source3/smbwrapper/realcalls.h +++ b/source3/smbwrapper/realcalls.h @@ -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))) - - diff --git a/source3/smbwrapper/smbw.c b/source3/smbwrapper/smbw.c index 39c3eec90c..74a40a2451 100644 --- a/source3/smbwrapper/smbw.c +++ b/source3/smbwrapper/smbw.c @@ -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; } diff --git a/source3/smbwrapper/smbw.h b/source3/smbwrapper/smbw.h index af48061ff0..2f16efd216 100644 --- a/source3/smbwrapper/smbw.h +++ b/source3/smbwrapper/smbw.h @@ -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; }; diff --git a/source3/smbwrapper/smbw_stat.c b/source3/smbwrapper/smbw_stat.c index 5ca71ee2ef..ae8671c591 100644 --- a/source3/smbwrapper/smbw_stat.c +++ b/source3/smbwrapper/smbw_stat.c @@ -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; diff --git a/source3/smbwrapper/wrapped.c b/source3/smbwrapper/wrapped.c index 13bd449db3..0ee7341e3b 100644 --- a/source3/smbwrapper/wrapped.c +++ b/source3/smbwrapper/wrapped.c @@ -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); +} -- cgit