summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/smbwrapper/realcalls.h4
-rw-r--r--source3/smbwrapper/smbw.c162
-rw-r--r--source3/smbwrapper/smbw.h12
-rw-r--r--source3/smbwrapper/smbw_stat.c6
-rw-r--r--source3/smbwrapper/wrapped.c22
5 files changed, 181 insertions, 25 deletions
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);
+}