#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)))
#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)))
-
-
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;
}
goto failed;
}
+ file->f->ref_count=1;
+
bitmap_set(smbw_file_bmap, file->fd);
DLIST_ADD(smbw_files, file);
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);
}
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);
return -1;
}
- file->offset += ret;
+ file->f->offset += ret;
smbw_busy--;
return ret;
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);
return -1;
}
- file->offset += ret;
+ file->f->offset += ret;
smbw_busy--;
return ret;
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;
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);
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;
}
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;