summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix/pvfs_util.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-11-13 06:46:51 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:05:46 -0500
commit1b2b72ff61c6e81189fd0552bfce5d2c7d365554 (patch)
treed5e820087ea577b3b8dd9f03569bc9fe322dd108 /source4/ntvfs/posix/pvfs_util.c
parent1c59d825afc3cdfe2ea42821123ece934ad7b5e0 (diff)
downloadsamba-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.c81
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;
+}