This little piece of insanity is inspired by the
authorJeremy Allison <jra@samba.org>
Sat, 14 Apr 2001 20:47:30 +0000 (20:47 +0000)
committerJeremy Allison <jra@samba.org>
Sat, 14 Apr 2001 20:47:30 +0000 (20:47 +0000)
fact that an NT client can open a file for O_RDONLY,
but set the create disposition to FILE_EXISTS_TRUNCATE.
If the client *can* write to the file, then it expects to
truncate the file, even though it is opening for readonly.
Quicken uses this stupid trick in backup file creation...
Thanks *greatly* to "David W. Chapman Jr." <dwcjr@inethouston.net>
for helping track this one down. It didn't bite us in 2.0.x
as we always opened files read-write in that release.
Jeremy.
(This used to be commit 5baef56831f9bc4fa10a851abd5f9305b974fb3b)

source3/smbd/open.c
source3/utils/torture.c

index f450e74e58c630cd59997e02af6ab4c10b162770..cebb37ab291be43613c185cf4dcda8d72355c41e 100644 (file)
@@ -48,8 +48,8 @@ static int fd_open(struct connection_struct *conn, char *fname,
                fd = conn->vfs_ops.open(conn,dos_to_unix(fname,False),flags,mode);
        }
 
-       DEBUG(10,("fd_open: name %s, mode = %d, fd = %d. %s\n", fname, (int)mode, fd,
-               (fd == -1) ? strerror(errno) : "" ));
+       DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname,
+               flags, (int)mode, fd, (fd == -1) ? strerror(errno) : "" ));
 
        return fd;
 }
@@ -647,7 +647,22 @@ files_struct *open_file_shared(connection_struct *conn,char *fname, SMB_STRUCT_S
                        flags = O_RDWR; 
                        break;
                default:
-                       flags = O_RDONLY;
+                       /*
+                        * This little piece of insanity is inspired by the
+                        * fact that an NT client can open a file for O_RDONLY,
+                        * but set the create disposition to FILE_EXISTS_TRUNCATE.
+                        * If the client *can* write to the file, then it expects to
+                        * truncate the file, even though it is opening for readonly.
+                        * Quicken uses this stupid trick in backup file creation...
+                        * Thanks *greatly* to "David W. Chapman Jr." <dwcjr@inethouston.net>
+                        * for helping track this one down. It didn't bite us in 2.0.x
+                        * as we always opened files read-write in that release. JRA.
+                        */
+
+                       if (flags2 & O_TRUNC)
+                               flags = O_RDWR; 
+                       else
+                               flags = O_RDONLY;
                        break;
        }
 
index 446bf7eaf22afa71bf5f379b6a69001fa2028434..871e2adfc342ecc02ef1a9f3a3541c2d1f49647a 100644 (file)
@@ -2397,6 +2397,8 @@ static void run_opentest(int dummy)
     int fnum1, fnum2;
        uint8 eclass;
        uint32 errnum;
+       char buf[20];
+       size_t fsize;
 
     printf("starting open test\n");
 
@@ -2470,11 +2472,76 @@ static void run_opentest(int dummy)
                printf("correct error code ERRDOS/ERRbadshare returned\n");
        }
 
+    if (!cli_close(&cli1, fnum1)) {
+        printf("close2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       cli_unlink(&cli1, fname);
+
+    printf("finished open test 2\n");
+
+       /* Test truncate open disposition on file opened for read. */
+
+    fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
+    if (fnum1 == -1) {
+        printf("(3) open (1) of %s failed (%s)\n", fname, cli_errstr(&cli1));
+        return;
+    }
+
+       /* write 20 bytes. */
+
+       memset(buf, '\0', 20);
+
+       if (cli_write(&cli1, fnum1, 0, buf, 0, 20) != 20) {
+               printf("write failed (%s)\n", cli_errstr(&cli1));
+       }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("(3) close1 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* Ensure size == 20. */
+       if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
+               printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
+               return;
+       }
+
+       if (fsize != 20) {
+               printf("(3) file size != 20\n");
+               return;
+       }
+
+       /* Now test if we can truncate a file opened for readonly. */
+
+       fnum1 = cli_open(&cli1, fname, O_RDONLY|O_TRUNC, DENY_NONE);
+    if (fnum1 == -1) {
+        printf("(3) open (2) of %s failed (%s)\n", fname, cli_errstr(&cli1));
+        return;
+    }
+
+    if (!cli_close(&cli1, fnum1)) {
+        printf("close2 failed (%s)\n", cli_errstr(&cli1));
+        return;
+    }
+
+       /* Ensure size == 0. */
+       if (!cli_getatr(&cli1, fname, NULL, &fsize, NULL)) {
+               printf("(3) getatr failed (%s)\n", cli_errstr(&cli1));
+               return;
+       }
+
+       if (fsize != 0) {
+               printf("(3) file size != 0\n");
+               return;
+       }
+    printf("finished open test 3\n");
+
        cli_unlink(&cli1, fname);
 
     close_connection(&cli1);
 
-    printf("finished open test 2\n");
 }
 
 static void list_fn(file_info *finfo, const char *name, void *state)