diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-11-13 06:46:51 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:05:46 -0500 |
commit | 1b2b72ff61c6e81189fd0552bfce5d2c7d365554 (patch) | |
tree | d5e820087ea577b3b8dd9f03569bc9fe322dd108 /source4/ntvfs/posix/pvfs_util.c | |
parent | 1c59d825afc3cdfe2ea42821123ece934ad7b5e0 (diff) | |
download | samba-1b2b72ff61c6e81189fd0552bfce5d2c7d365554.tar.gz samba-1b2b72ff61c6e81189fd0552bfce5d2c7d365554.tar.bz2 samba-1b2b72ff61c6e81189fd0552bfce5d2c7d365554.zip |
r3718: added support for the ntrename level in pvfs_rename().
(This used to be commit 3d50982f5419b9a5c53f2b82a2313669cdeaaa21)
Diffstat (limited to 'source4/ntvfs/posix/pvfs_util.c')
-rw-r--r-- | source4/ntvfs/posix/pvfs_util.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/source4/ntvfs/posix/pvfs_util.c b/source4/ntvfs/posix/pvfs_util.c index 92d696970a..6503769013 100644 --- a/source4/ntvfs/posix/pvfs_util.c +++ b/source4/ntvfs/posix/pvfs_util.c @@ -79,3 +79,84 @@ uint32_t pvfs_attrib_normalise(uint32_t attrib) return attrib; } + +/* + copy a file. Caller is supposed to have already ensured that the + operation is allowed. The destination file must not exist. +*/ +NTSTATUS pvfs_copy_file(struct pvfs_state *pvfs, + struct pvfs_filename *name1, + struct pvfs_filename *name2) +{ + int fd1, fd2; + mode_t mode; + NTSTATUS status; + size_t buf_size = 0x10000; + char *buf = talloc(name2, buf_size); + + if (buf == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fd1 = open(name1->full_name, O_RDONLY); + if (fd1 == -1) { + talloc_free(buf); + return pvfs_map_errno(pvfs, errno); + } + + fd2 = open(name2->full_name, O_CREAT|O_EXCL|O_WRONLY, 0); + if (fd2 == -1) { + close(fd1); + talloc_free(buf); + return pvfs_map_errno(pvfs, errno); + } + + while (1) { + ssize_t ret2, ret = read(fd1, buf, buf_size); + if (ret == -1 && + (errno == EINTR || errno == EAGAIN)) { + continue; + } + if (ret <= 0) break; + + ret2 = write(fd2, buf, ret); + if (ret2 == -1 && + (errno == EINTR || errno == EAGAIN)) { + continue; + } + + if (ret2 != ret) { + close(fd1); + close(fd2); + talloc_free(buf); + unlink(name2->full_name); + if (ret2 == -1) { + return pvfs_map_errno(pvfs, errno); + } + return NT_STATUS_DISK_FULL; + } + } + + close(fd1); + + mode = pvfs_fileperms(pvfs, name1->dos.attrib); + if (fchmod(fd2, mode) == -1) { + status = pvfs_map_errno(pvfs, errno); + close(fd2); + unlink(name2->full_name); + return status; + } + + name2->dos = name1->dos; + + status = pvfs_dosattrib_save(pvfs, name2, fd2); + if (!NT_STATUS_IS_OK(status)) { + close(fd2); + unlink(name2->full_name); + return status; + } + + close(fd2); + + return NT_STATUS_OK; +} |