]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
vol: Fix ntops to provide expected semantics
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 15 Jan 2011 16:07:19 +0000 (11:07 -0500)
committerJeffrey Altman <jaltman@openafs.org>
Sat, 15 Jan 2011 23:01:09 +0000 (15:01 -0800)
nt_open() can be asked to open a file with a path containing
directory components that do not yet exist.  Modify nt_open()
to automatically create directories if necessary.

nt_read() and nt_pread() should not treat partial reads due
to reaching EOF as an error.  Instead, return the bytes read.

Change-Id: If088393a842d6f6d7ad901345e94e92d23f2321c
Reviewed-on: http://gerrit.openafs.org/3666
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
src/vol/ntops.c

index cf546b4eb6f27cb0544e46ce745cb3fbcaf4d4f8..905c4e7c545f49be76230f26b84b4c055390de33 100644 (file)
@@ -116,11 +116,44 @@ nt_open(char *name, int flags, int mode)
        break;
     }
 
+  retry:
     fh = CreateFile(name, nt_access, nt_share, NULL, nt_create, FandA, NULL);
-
     if (fh == INVALID_HANDLE_VALUE) {
-       fh = INVALID_FD;
-       errno = nterr_nt2unix(GetLastError(), EBADF);
+        DWORD gle = GetLastError();
+
+        if (gle == ERROR_PATH_NOT_FOUND) {
+            /*
+             * one or more of the directories in the path
+             * does not exist.  We must create them and
+             * try again to create the file.
+             */
+            char * p;
+
+            for (p=name; *p && *p != OS_DIRSEPC; p++);
+            while (*p == OS_DIRSEPC) p++;    /* ignore the first dirsep */
+            for (; *p; p++) {
+                if (*p == OS_DIRSEPC) {
+                    *p = '\0';
+                    if (CreateDirectory(name, NULL))
+                        gle = 0;
+                    else
+                        gle = GetLastError();
+                    *p = OS_DIRSEPC;
+                    if (gle != ERROR_SUCCESS &&
+                         gle != ERROR_ALREADY_EXISTS) {
+                        /* The directory creation failed. */
+                        fh = INVALID_FD;
+                        break;
+                    } else {
+                        while (*(p+1) == OS_DIRSEPC) p++;
+                    }
+                }
+            }
+
+            if (!*p) /* successful creation of the path */
+                goto retry;
+        }
+        errno = nterr_nt2unix(gle, EBADF);
     }
     return fh;
 }
@@ -187,8 +220,11 @@ nt_read(FD_t fd, char *buf, size_t size)
     code = ReadFile((HANDLE) fd, (void *)buf, (DWORD) size, &nbytes, NULL);
 
     if (!code) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       return -1;
+        DWORD gle = GetLastError();
+        if (gle != ERROR_HANDLE_EOF) {
+               errno = nterr_nt2unix(GetLastError(), EBADF);
+               return -1;
+        }
     }
     return (int)nbytes;
 }
@@ -214,8 +250,11 @@ nt_pread(FD_t fd, void * buf, size_t count, afs_foff_t offset)
     code = ReadFile((HANDLE) fd, (void *)buf, (DWORD) count, &nbytes, &overlap);
 
     if (!code) {
-       errno = nterr_nt2unix(GetLastError(), EBADF);
-       return -1;
+        DWORD gle = GetLastError();
+        if (gle != ERROR_HANDLE_EOF) {
+               errno = nterr_nt2unix(GetLastError(), EBADF);
+               return -1;
+        }
     }
     return (ssize_t)nbytes;
 }