From fb1429c1970bc123e191f0cb7cc764faf4b86998 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Tue, 1 Jul 1997 01:19:13 +0000 Subject: client.c: New print queue query code from Jeff C. Foster " ipc.c: Added code for returning restricted lists of servers. loadparm.c: Changed default for force create mode to 000. Changed default maxmux to 50 to comply with NT. locking.c: Fixed silly crash bug with slow share mode code. nameannounce.c: Added code for returning restricted lists of servers. namedbserver.c: Added code for returning restricted lists of servers. nameelect.c: Added code for returning restricted lists of servers. namework.c: Added code for returning restricted lists of servers. nmbsync.c: Added code for returning restricted lists of servers. server.c: Added quota fix Albrecht Gebhardt smb.h: Added define for COPYBUF_SIZE. system.c: Rename across filesystems Patch from Warren Birnbaum util.c: Minor fix for warning. (This used to be commit 1c6e433caa22813a699c9766847886eb59755f8b) --- source3/lib/system.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) (limited to 'source3/lib/system.c') diff --git a/source3/lib/system.c b/source3/lib/system.c index 521f5e304c..ea86e9ccaa 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -197,15 +197,130 @@ int sys_utime(char *fname,struct utimbuf *times) return(utime(dos_to_unix(fname,False),times)); } +/********************************************************* +for rename across filesystems Patch from Warren Birnbaum + +**********************************************************/ + +static int +copy_reg (const char *source, const char *dest) +{ + struct stat source_stats; + int ifd; + int full_write(); + int safe_read(); + int ofd; + char *buf; + int len; /* Number of bytes read into `buf'. */ + + lstat (source, &source_stats); + if (!S_ISREG (source_stats.st_mode)) + { + return 1; + } + + if (unlink (dest) && errno != ENOENT) + { + return 1; + } + + if((ifd = open (source, O_RDONLY, 0)) < 0) + { + return 1; + } + if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 ) + { + close (ifd); + return 1; + } + + if((buf = malloc( COPYBUF_SIZE )) == NULL) + { + close (ifd); + close (ofd); + unlink (dest); + return 1; + } + + while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0) + { + if (write_data(ofd, buf, len) < 0) + { + close (ifd); + close (ofd); + unlink (dest); + free(buf); + return 1; + } + } + free(buf); + if (len < 0) + { + close (ifd); + close (ofd); + unlink (dest); + return 1; + } + + if (close (ifd) < 0) + { + close (ofd); + return 1; + } + if (close (ofd) < 0) + { + return 1; + } + + /* chown turns off set[ug]id bits for non-root, + so do the chmod last. */ + + /* Try to copy the old file's modtime and access time. */ + { + struct utimbuf tv; + + tv.actime = source_stats.st_atime; + tv.modtime = source_stats.st_mtime; + if (utime (dest, &tv)) + { + return 1; + } + } + + /* Try to preserve ownership. For non-root it might fail, but that's ok. + But root probably wants to know, e.g. if NFS disallows it. */ + if (chown (dest, source_stats.st_uid, source_stats.st_gid) + && (errno != EPERM)) + { + return 1; + } + + if (chmod (dest, source_stats.st_mode & 07777)) + { + return 1; + } + unlink (source); + return 0; +} + /******************************************************************* for rename() ********************************************************************/ int sys_rename(char *from, char *to) { + int rcode; pstring zfrom, zto; + strcpy (zfrom, dos_to_unix (from, False)); strcpy (zto, dos_to_unix (to, False)); - return rename (zfrom, zto); + rcode = rename (zfrom, zto); + + if (errno == EXDEV) + { + /* Rename across filesystems needed. */ + rcode = copy_reg (zfrom, zto); + } + return rcode; } /******************************************************************* -- cgit