X-Git-Url: http://git.samba.org/?p=samba.git;a=blobdiff_plain;f=source%2Flib%2Fsystem.c;h=39f845b30ebaa28acc7f9003d2a0130df4cc205f;hp=521f5e304ce94155cb414c3d2dfcad25e31b3de3;hb=07f7e378c4839d0ca4bb79c8755481f4bf5637de;hpb=cf23a155a1315f50d488794a2caf88402bf3e3e6 diff --git a/source/lib/system.c b/source/lib/system.c index 521f5e304ce..39f845b30eb 100644 --- a/source/lib/system.c +++ b/source/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; } /******************************************************************* @@ -216,6 +331,22 @@ int sys_chmod(char *fname,int mode) return(chmod(dos_to_unix(fname,False),mode)); } +/******************************************************************* +for getwd +********************************************************************/ +char *sys_getwd(char *s) +{ + char *wd; +#ifdef USE_GETCWD + wd = (char *) getcwd (s, sizeof (pstring)); +#else + wd = (char *) getwd (s); +#endif + if (wd) + unix_to_dos (wd, True); + return wd; +} + /******************************************************************* chown isn't used much but OS/2 doesn't have it ********************************************************************/