this fixes the failure of MS office on VFAT partitions on Linux
authorAndrew Tridgell <tridge@samba.org>
Thu, 5 Jul 2001 10:33:10 +0000 (10:33 +0000)
committerAndrew Tridgell <tridge@samba.org>
Thu, 5 Jul 2001 10:33:10 +0000 (10:33 +0000)
The problem is that ftruncate can't expand on VFAT, but it can on
ext2. That means our autoconf test is useless. I have recoded it to
use the alternative to ftruncate when then sys_ftruncate fails.

Jeremy, do you want this for 2.2.1?
(This used to be commit 970236ee9926b64c0b39bd8a36b2a9317206873c)

source3/smbd/vfs-wrap.c

index 241216e9d718271004e6809e6d86d4d362146f7c..2b465dbe15087cf5434734b533eb60466302b14d 100644 (file)
@@ -479,33 +479,34 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim
 int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
 {
        int result = -1;
-    START_PROFILE(syscall_ftruncate);
-
-#ifdef HAVE_FTRUNCATE_EXTEND
-       result = sys_ftruncate(fd, len);
-    END_PROFILE(syscall_ftruncate);
-    return result;
-#else
-
-       /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
-               extend a file with ftruncate. Provide alternate implementation
-               for this */
-
        struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops;
        SMB_STRUCT_STAT st;
        char c = 0;
        SMB_OFF_T currpos;
 
-       currpos = vfs_ops->lseek(fsp, (SMB_OFF_T)0, SEEK_CUR);
-       if(currpos == -1) {
+       START_PROFILE(syscall_ftruncate);
+
+       /* we used to just check HAVE_FTRUNCATE_EXTEND and only use
+          sys_ftruncate if the system supports it. Then I discovered that
+          you can have some filesystems that support ftruncate
+          expansion and some that don't! On Linux fat can't do
+          ftruncate extend but ext2 can. */
+       result = sys_ftruncate(fd, len);
+       if (result == 0) goto done;
+
+       /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
+          extend a file with ftruncate. Provide alternate implementation
+          for this */
+       currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR);
+       if (currpos == -1) {
                goto done;
        }
 
-       /* Do an fstat to see if the file is longer than
-               the requested size (call ftruncate),
-               or shorter, in which case seek to len - 1 and write 1
-               byte of zero */
-       if(vfs_ops->fstat(fsp, &st)<0) {
+       /* Do an fstat to see if the file is longer than the requested
+          size in which case the ftruncate above should have
+          succeeded or shorter, in which case seek to len - 1 and
+          write 1 byte of zero */
+       if (vfs_ops->fstat(fsp, fd, &st) < 0) {
                goto done;
        }
 
@@ -516,35 +517,33 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len)
        }
 #endif
 
-       if(st.st_size == len) {
+       if (st.st_size == len) {
                result = 0;
                goto done;
        }
 
-       if(st.st_size > len) {
-               /* Yes this is *deliberately* sys_ftruncate ! JRA */
-               result = sys_ftruncate(fd, len);
+       if (st.st_size > len) {
+               /* the sys_ftruncate should have worked */
                goto done;
        }
 
-       if(vfs_ops->lseek(fsp, len-1, SEEK_SET) != len -1) {
+       if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) {
                goto done;
        }
 
-       if(vfs_ops->write(fsp, &c, 1)!=1) {
+       if (vfs_ops->write(fsp, fd, &c, 1)!=1) {
                goto done;
        }
 
        /* Seek to where we were */
-       if(vfs_ops->lseek(fsp, currpos, SEEK_SET) != currpos) {
+       if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) {
                goto done;
        }
+       result = 0;
   done:
 
-    END_PROFILE(syscall_ftruncate);
-    return result;
-#endif
-
+       END_PROFILE(syscall_ftruncate);
+       return result;
 }
 
 BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)