Merge 1.8.0~pre4 packaging into master
[pkg-k5-afs_openafs.git] / src / vol / ntops.c
blob3cb0c5e723297a9aa5a09849b3b9988620a6d72f
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
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
8 */
10 /* I/O operations for the Windows NT platforms. */
12 #include <afsconfig.h>
13 #include <afs/param.h>
15 #include <roken.h>
17 #ifdef AFS_NT40_ENV
18 #include <direct.h>
19 #include <windows.h>
20 #include <winnt.h>
21 #include <winbase.h>
22 #include <lock.h>
23 #include <afs/afsutil.h>
24 #include <rx/rx_queue.h>
25 #include "nfs.h"
26 #include <afs/afsint.h>
27 #include "ihandle.h"
28 #include "vnode.h"
29 #include "volume.h"
30 #include "viceinode.h"
31 #include <afs/errmap_nt.h>
33 #define BASEFILEATTRIBUTE FILE_ATTRIBUTE_NORMAL
35 /* nt_unlink - unlink a case sensitive name.
37 * nt_unlink supports the nt_dec call.
39 * This nt_unlink has the delete on last close semantics of the Unix unlink
40 * with a minor twist. Subsequent CreateFile calls on this file can succeed
41 * if they open for delete. If a CreateFile call tries to create a new file
42 * with the same name it will fail. Fortunately, neither case should occur
43 * as part of nt_dec.
45 int
46 nt_unlink(char *name)
48 HANDLE fh;
50 fh = CreateFile(name,
51 GENERIC_READ | GENERIC_WRITE | DELETE,
52 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
53 NULL, OPEN_EXISTING,
54 BASEFILEATTRIBUTE | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_POSIX_SEMANTICS,
55 NULL);
56 if (fh != INVALID_HANDLE_VALUE)
57 CloseHandle(fh);
58 else {
59 errno = nterr_nt2unix(GetLastError(), ENOENT);
60 return -1;
62 return 0;
65 /* nt_open - open an NT handle for a file.
67 * Return Value:
68 * the handle or -1 on error.
70 FD_t
71 nt_open(const char *name, int flags, int mode)
73 HANDLE fh;
74 DWORD nt_access = 0;
75 DWORD nt_share = FILE_SHARE_READ;
76 DWORD nt_create = 0;
77 /* Really use the sequential one for data files, random for meta data. */
78 DWORD FandA = BASEFILEATTRIBUTE | FILE_FLAG_SEQUENTIAL_SCAN;
80 /* set access */
81 if ((flags & O_RDWR) || (flags & O_WRONLY)) {
82 nt_access |= GENERIC_WRITE;
83 nt_share |= FILE_SHARE_WRITE | FILE_SHARE_DELETE;
85 if ((flags & O_RDWR) || (flags == O_RDONLY))
86 nt_access |= GENERIC_READ;
88 /* set creation */
89 switch (flags & (O_CREAT | O_EXCL | O_TRUNC)) {
90 case 0:
91 nt_create = OPEN_EXISTING;
92 break;
93 case O_CREAT:
94 nt_create = OPEN_ALWAYS;
95 break;
96 case O_CREAT | O_TRUNC:
97 nt_create = CREATE_ALWAYS;
98 break;
99 case O_CREAT | O_EXCL:
100 case O_CREAT | O_EXCL | O_TRUNC:
101 nt_create = CREATE_NEW;
102 break;
103 case O_TRUNC:
104 nt_create = TRUNCATE_EXISTING;
105 break;
106 case O_TRUNC | O_EXCL:
107 case O_EXCL:
108 default:
109 errno = EINVAL;
110 return INVALID_FD;
111 break;
114 fh = CreateFile(name, nt_access, nt_share, NULL, nt_create, FandA, NULL);
115 if (fh == INVALID_HANDLE_VALUE) {
116 DWORD gle = GetLastError();
117 errno = nterr_nt2unix(gle, EBADF);
119 return fh;
123 nt_close(FD_t fd)
125 BOOL code;
127 code = CloseHandle(fd);
128 if (!code) {
129 errno = nterr_nt2unix(GetLastError(), EBADF);
130 return -1;
132 return 0;
136 nt_write(FD_t fd, void *buf, afs_sfsize_t size)
138 BOOL code;
139 DWORD nbytes;
141 code = WriteFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL);
143 if (!code) {
144 errno = nterr_nt2unix(GetLastError(), EBADF);
145 return -1;
147 return (int)nbytes;
151 nt_pwrite(FD_t fd, const void * buf, afs_sfsize_t count, afs_foff_t offset)
154 * same comment as read
157 DWORD nbytes;
158 BOOL code;
159 OVERLAPPED overlap = {0};
160 LARGE_INTEGER liOffset;
162 liOffset.QuadPart = offset;
163 overlap.Offset = liOffset.LowPart;
164 overlap.OffsetHigh = liOffset.HighPart;
166 code = WriteFile((HANDLE) fd, (void *)buf, (DWORD) count, &nbytes, &overlap);
168 if (!code) {
169 errno = nterr_nt2unix(GetLastError(), EBADF);
170 return -1;
172 return (ssize_t)nbytes;
176 nt_read(FD_t fd, void *buf, afs_sfsize_t size)
178 BOOL code;
179 DWORD nbytes;
181 code = ReadFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL);
183 if (!code) {
184 DWORD gle = GetLastError();
185 if (gle != ERROR_HANDLE_EOF) {
186 errno = nterr_nt2unix(GetLastError(), EBADF);
187 return -1;
190 return (int)nbytes;
194 nt_pread(FD_t fd, void * buf, afs_sfsize_t count, afs_foff_t offset)
197 * This really ought to call NtReadFile
199 DWORD nbytes;
200 BOOL code;
201 OVERLAPPED overlap = {0};
202 LARGE_INTEGER liOffset;
204 * Cast through a LARGE_INTEGER - make no assumption about
205 * byte ordering and leave that to the compiler..
207 liOffset.QuadPart = offset;
208 overlap.Offset = liOffset.LowPart;
209 overlap.OffsetHigh = liOffset.HighPart;
211 code = ReadFile((HANDLE) fd, (void *)buf, (DWORD) count, &nbytes, &overlap);
213 if (!code) {
214 DWORD gle = GetLastError();
215 if (gle != ERROR_HANDLE_EOF) {
216 errno = nterr_nt2unix(GetLastError(), EBADF);
217 return -1;
220 return (ssize_t)nbytes;
223 afs_sfsize_t
224 nt_size(FD_t fd)
226 BY_HANDLE_FILE_INFORMATION finfo;
227 LARGE_INTEGER FileSize;
229 if (!GetFileInformationByHandle(fd, &finfo))
230 return -1;
232 FileSize.HighPart = finfo.nFileSizeHigh;
233 FileSize.LowPart = finfo.nFileSizeLow;
234 return FileSize.QuadPart;
239 nt_getFileCreationTime(FD_t fd, FILETIME * ftime)
241 BY_HANDLE_FILE_INFORMATION finfo;
243 if (!GetFileInformationByHandle(fd, &finfo))
244 return -1;
246 *ftime = finfo.ftCreationTime;
248 return 0;
252 nt_setFileCreationTime(FD_t fd, FILETIME * ftime)
254 return !SetFileTime(fd, ftime, NULL, NULL);
258 nt_sync(int cdrive)
260 FD_t drive_fd;
261 char sdrive[32];
262 int n;
264 n = cdrive;
265 if (n <= 26) {
266 cdrive = 'A' + (n - 1);
269 cdrive = _toupper(cdrive);
271 (void)sprintf(sdrive, "\\\\.\\%c:", cdrive);
272 drive_fd = nt_open(sdrive, O_RDWR, 0666);
273 if (drive_fd == INVALID_FD) {
274 return -1;
277 if (!FlushFileBuffers((HANDLE) drive_fd)) {
278 errno = nterr_nt2unix(GetLastError(), EBADF);
279 nt_close(drive_fd);
280 return -1;
282 nt_close(drive_fd);
283 return 0;
287 /* Currently nt_ftruncate only tested to shrink a file. */
289 nt_ftruncate(FD_t fd, afs_foff_t len)
291 LARGE_INTEGER length;
293 length.QuadPart = len;
295 if (SetFilePointerEx(fd, length, NULL, FILE_BEGIN)
296 == 0xffffffff) {
297 errno = nterr_nt2unix(GetLastError(), EBADF);
298 return -1;
300 if (!SetEndOfFile(fd)) {
301 errno = nterr_nt2unix(GetLastError(), EBADF);
302 return -1;
304 return 0;
309 nt_fsync(FD_t fd)
311 int code = FlushFileBuffers(fd);
312 return code == 0 ? -1 : 0;
317 nt_seek(FD_t fd, afs_foff_t off, int whence)
319 int code;
320 LARGE_INTEGER offset;
321 int where;
323 if (SEEK_SET == whence) {
324 where = FILE_BEGIN;
325 } else if (SEEK_END == whence) {
326 where = FILE_END;
327 } else if (SEEK_CUR == whence) {
328 where = FILE_CURRENT;
329 } else {
330 errno = EINVAL;
331 return -1;
333 offset.QuadPart = off;
335 code = SetFilePointerEx(fd, offset, NULL, where);
336 if (0 == code) {
337 errno = nterr_nt2unix(GetLastError(), EBADF);
338 return -1;
340 return 0;
343 /* nt_DevToDrive
344 * converts a device number (2-25) into a drive letter name.
346 * Arguments:
347 * drive - assumes drive is a pointer to a string at least 3 bytes long.
348 * dev - drive number 2-25, since A-C already in use.
350 * Return Value:
351 * Returns pointer to end of drive if successful, else NULL.
354 void
355 nt_DevToDrive(char *drive, int dev)
357 if (dev < 2 || dev > 25) {
358 errno = EINVAL;
359 return; /* Invalid drive */
361 drive[0] = (char)('A' + dev);
362 drive[1] = ':';
363 drive[2] = '\0';
365 return;
369 /* nt_DriveToDev
370 * converts a drive letter to a device number (2-25)
372 * Arguments:
373 * drive - assumes drive is a pointer to a string at least 3 bytes long.
375 * Return Value:
376 * dev - drive number 2-25 if successful (A-C already in use), else -1
380 nt_DriveToDev(char *drive)
382 int dev = -1;
384 if (drive)
385 dev = toupper(*drive) - 'A';
386 if ((dev < 2) || (dev > 25))
387 return -1;
389 return dev;
391 #endif