2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* I/O operations for the Windows NT platforms. */
12 #include <afsconfig.h>
13 #include <afs/param.h>
29 #include <afs/afsutil.h>
31 #include <afs/afsint.h>
35 #include "viceinode.h"
37 #include <afs/afs_assert.h>
38 #include <afs/errmap_nt.h>
40 #define BASEFILEATTRIBUTE FILE_ATTRIBUTE_NORMAL
42 /* nt_unlink - unlink a case sensitive name.
44 * nt_unlink supports the nt_dec call.
46 * This nt_unlink has the delete on last close semantics of the Unix unlink
47 * with a minor twist. Subsequent CreateFile calls on this file can succeed
48 * if they open for delete. If a CreateFile call tries to create a new file
49 * with the same name it will fail. Fortunately, neither case should occur
58 GENERIC_READ
| GENERIC_WRITE
| DELETE
,
59 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
61 BASEFILEATTRIBUTE
| FILE_FLAG_DELETE_ON_CLOSE
| FILE_FLAG_POSIX_SEMANTICS
,
63 if (fh
!= INVALID_HANDLE_VALUE
)
66 errno
= nterr_nt2unix(GetLastError(), ENOENT
);
72 /* nt_open - open an NT handle for a file.
75 * the handle or -1 on error.
78 nt_open(const char *name
, int flags
, int mode
)
82 DWORD nt_share
= FILE_SHARE_READ
;
84 /* Really use the sequential one for data files, random for meta data. */
85 DWORD FandA
= BASEFILEATTRIBUTE
| FILE_FLAG_SEQUENTIAL_SCAN
;
88 if ((flags
& O_RDWR
) || (flags
& O_WRONLY
)) {
89 nt_access
|= GENERIC_WRITE
;
90 nt_share
|= FILE_SHARE_WRITE
| FILE_SHARE_DELETE
;
92 if ((flags
& O_RDWR
) || (flags
== O_RDONLY
))
93 nt_access
|= GENERIC_READ
;
96 switch (flags
& (O_CREAT
| O_EXCL
| O_TRUNC
)) {
98 nt_create
= OPEN_EXISTING
;
101 nt_create
= OPEN_ALWAYS
;
103 case O_CREAT
| O_TRUNC
:
104 nt_create
= CREATE_ALWAYS
;
106 case O_CREAT
| O_EXCL
:
107 case O_CREAT
| O_EXCL
| O_TRUNC
:
108 nt_create
= CREATE_NEW
;
111 nt_create
= TRUNCATE_EXISTING
;
113 case O_TRUNC
| O_EXCL
:
121 fh
= CreateFile(name
, nt_access
, nt_share
, NULL
, nt_create
, FandA
, NULL
);
122 if (fh
== INVALID_HANDLE_VALUE
) {
123 DWORD gle
= GetLastError();
124 errno
= nterr_nt2unix(gle
, EBADF
);
134 code
= CloseHandle(fd
);
136 errno
= nterr_nt2unix(GetLastError(), EBADF
);
143 nt_write(FD_t fd
, void *buf
, afs_sfsize_t size
)
148 code
= WriteFile((HANDLE
) fd
, buf
, (DWORD
) size
, &nbytes
, NULL
);
151 errno
= nterr_nt2unix(GetLastError(), EBADF
);
158 nt_pwrite(FD_t fd
, const void * buf
, afs_sfsize_t count
, afs_foff_t offset
)
161 * same comment as read
166 OVERLAPPED overlap
= {0};
167 LARGE_INTEGER liOffset
;
169 liOffset
.QuadPart
= offset
;
170 overlap
.Offset
= liOffset
.LowPart
;
171 overlap
.OffsetHigh
= liOffset
.HighPart
;
173 code
= WriteFile((HANDLE
) fd
, (void *)buf
, (DWORD
) count
, &nbytes
, &overlap
);
176 errno
= nterr_nt2unix(GetLastError(), EBADF
);
179 return (ssize_t
)nbytes
;
183 nt_read(FD_t fd
, void *buf
, afs_sfsize_t size
)
188 code
= ReadFile((HANDLE
) fd
, buf
, (DWORD
) size
, &nbytes
, NULL
);
191 DWORD gle
= GetLastError();
192 if (gle
!= ERROR_HANDLE_EOF
) {
193 errno
= nterr_nt2unix(GetLastError(), EBADF
);
201 nt_pread(FD_t fd
, void * buf
, afs_sfsize_t count
, afs_foff_t offset
)
204 * This really ought to call NtReadFile
208 OVERLAPPED overlap
= {0};
209 LARGE_INTEGER liOffset
;
211 * Cast through a LARGE_INTEGER - make no assumption about
212 * byte ordering and leave that to the compiler..
214 liOffset
.QuadPart
= offset
;
215 overlap
.Offset
= liOffset
.LowPart
;
216 overlap
.OffsetHigh
= liOffset
.HighPart
;
218 code
= ReadFile((HANDLE
) fd
, (void *)buf
, (DWORD
) count
, &nbytes
, &overlap
);
221 DWORD gle
= GetLastError();
222 if (gle
!= ERROR_HANDLE_EOF
) {
223 errno
= nterr_nt2unix(GetLastError(), EBADF
);
227 return (ssize_t
)nbytes
;
233 BY_HANDLE_FILE_INFORMATION finfo
;
234 LARGE_INTEGER FileSize
;
236 if (!GetFileInformationByHandle(fd
, &finfo
))
239 FileSize
.HighPart
= finfo
.nFileSizeHigh
;
240 FileSize
.LowPart
= finfo
.nFileSizeLow
;
241 return FileSize
.QuadPart
;
246 nt_getFileCreationTime(FD_t fd
, FILETIME
* ftime
)
248 BY_HANDLE_FILE_INFORMATION finfo
;
250 if (!GetFileInformationByHandle(fd
, &finfo
))
253 *ftime
= finfo
.ftCreationTime
;
259 nt_setFileCreationTime(FD_t fd
, FILETIME
* ftime
)
261 return !SetFileTime(fd
, ftime
, NULL
, NULL
);
273 cdrive
= 'A' + (n
- 1);
276 cdrive
= _toupper(cdrive
);
278 (void)sprintf(sdrive
, "\\\\.\\%c:", cdrive
);
279 drive_fd
= nt_open(sdrive
, O_RDWR
, 0666);
280 if (drive_fd
== INVALID_FD
) {
284 if (!FlushFileBuffers((HANDLE
) drive_fd
)) {
285 errno
= nterr_nt2unix(GetLastError(), EBADF
);
294 /* Currently nt_ftruncate only tested to shrink a file. */
296 nt_ftruncate(FD_t fd
, afs_foff_t len
)
298 LARGE_INTEGER length
;
300 length
.QuadPart
= len
;
302 if (SetFilePointerEx(fd
, length
, NULL
, FILE_BEGIN
)
304 errno
= nterr_nt2unix(GetLastError(), EBADF
);
307 if (!SetEndOfFile(fd
)) {
308 errno
= nterr_nt2unix(GetLastError(), EBADF
);
318 int code
= FlushFileBuffers(fd
);
319 return code
== 0 ? -1 : 0;
324 nt_seek(FD_t fd
, afs_foff_t off
, int whence
)
327 LARGE_INTEGER offset
;
330 if (SEEK_SET
== whence
) {
332 } else if (SEEK_END
== whence
) {
334 } else if (SEEK_CUR
== whence
) {
335 where
= FILE_CURRENT
;
340 offset
.QuadPart
= off
;
342 code
= SetFilePointerEx(fd
, offset
, NULL
, where
);
344 errno
= nterr_nt2unix(GetLastError(), EBADF
);
351 * converts a device number (2-25) into a drive letter name.
354 * drive - assumes drive is a pointer to a string at least 3 bytes long.
355 * dev - drive number 2-25, since A-C already in use.
358 * Returns pointer to end of drive if successful, else NULL.
362 nt_DevToDrive(char *drive
, int dev
)
364 if (dev
< 2 || dev
> 25) {
366 return; /* Invalid drive */
368 drive
[0] = (char)('A' + dev
);
377 * converts a drive letter to a device number (2-25)
380 * drive - assumes drive is a pointer to a string at least 3 bytes long.
383 * dev - drive number 2-25 if successful (A-C already in use), else -1
387 nt_DriveToDev(char *drive
)
392 dev
= toupper(*drive
) - 'A';
393 if ((dev
< 2) || (dev
> 25))