vol: Fix ntops to provide expected semantics

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>
This commit is contained in:
Jeffrey Altman 2011-01-15 11:07:19 -05:00 committed by Jeffrey Altman
parent 98f633c60d
commit 714b3ffb22

View 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;
}