Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / vol / ntops.c
blobb9c08e6fc5f86ada8ed4534534466b3579e2519c
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>
16 #ifdef AFS_NT40_ENV
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <direct.h>
22 #include <io.h>
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <windows.h>
26 #include <winnt.h>
27 #include <winbase.h>
28 #include <lock.h>
29 #include <afs/afsutil.h>
30 #include "nfs.h"
31 #include <afs/afsint.h>
32 #include "ihandle.h"
33 #include "vnode.h"
34 #include "volume.h"
35 #include "viceinode.h"
36 #include <dirent.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
50 * as part of nt_dec.
52 int
53 nt_unlink(char *name)
55 HANDLE fh;
57 fh = CreateFile(name,
58 GENERIC_READ | GENERIC_WRITE | DELETE,
59 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
60 NULL, OPEN_EXISTING,
61 BASEFILEATTRIBUTE | FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_POSIX_SEMANTICS,
62 NULL);
63 if (fh != INVALID_HANDLE_VALUE)
64 CloseHandle(fh);
65 else {
66 errno = nterr_nt2unix(GetLastError(), ENOENT);
67 return -1;
69 return 0;
72 /* nt_open - open an NT handle for a file.
74 * Return Value:
75 * the handle or -1 on error.
77 FD_t
78 nt_open(const char *name, int flags, int mode)
80 HANDLE fh;
81 DWORD nt_access = 0;
82 DWORD nt_share = FILE_SHARE_READ;
83 DWORD nt_create = 0;
84 /* Really use the sequential one for data files, random for meta data. */
85 DWORD FandA = BASEFILEATTRIBUTE | FILE_FLAG_SEQUENTIAL_SCAN;
87 /* set access */
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;
95 /* set creation */
96 switch (flags & (O_CREAT | O_EXCL | O_TRUNC)) {
97 case 0:
98 nt_create = OPEN_EXISTING;
99 break;
100 case O_CREAT:
101 nt_create = OPEN_ALWAYS;
102 break;
103 case O_CREAT | O_TRUNC:
104 nt_create = CREATE_ALWAYS;
105 break;
106 case O_CREAT | O_EXCL:
107 case O_CREAT | O_EXCL | O_TRUNC:
108 nt_create = CREATE_NEW;
109 break;
110 case O_TRUNC:
111 nt_create = TRUNCATE_EXISTING;
112 break;
113 case O_TRUNC | O_EXCL:
114 case O_EXCL:
115 default:
116 errno = EINVAL;
117 return INVALID_FD;
118 break;
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);
126 return fh;
130 nt_close(FD_t fd)
132 BOOL code;
134 code = CloseHandle(fd);
135 if (!code) {
136 errno = nterr_nt2unix(GetLastError(), EBADF);
137 return -1;
139 return 0;
143 nt_write(FD_t fd, void *buf, afs_sfsize_t size)
145 BOOL code;
146 DWORD nbytes;
148 code = WriteFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL);
150 if (!code) {
151 errno = nterr_nt2unix(GetLastError(), EBADF);
152 return -1;
154 return (int)nbytes;
158 nt_pwrite(FD_t fd, const void * buf, afs_sfsize_t count, afs_foff_t offset)
161 * same comment as read
164 DWORD nbytes;
165 BOOL code;
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);
175 if (!code) {
176 errno = nterr_nt2unix(GetLastError(), EBADF);
177 return -1;
179 return (ssize_t)nbytes;
183 nt_read(FD_t fd, void *buf, afs_sfsize_t size)
185 BOOL code;
186 DWORD nbytes;
188 code = ReadFile((HANDLE) fd, buf, (DWORD) size, &nbytes, NULL);
190 if (!code) {
191 DWORD gle = GetLastError();
192 if (gle != ERROR_HANDLE_EOF) {
193 errno = nterr_nt2unix(GetLastError(), EBADF);
194 return -1;
197 return (int)nbytes;
201 nt_pread(FD_t fd, void * buf, afs_sfsize_t count, afs_foff_t offset)
204 * This really ought to call NtReadFile
206 DWORD nbytes;
207 BOOL code;
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);
220 if (!code) {
221 DWORD gle = GetLastError();
222 if (gle != ERROR_HANDLE_EOF) {
223 errno = nterr_nt2unix(GetLastError(), EBADF);
224 return -1;
227 return (ssize_t)nbytes;
230 afs_sfsize_t
231 nt_size(FD_t fd)
233 BY_HANDLE_FILE_INFORMATION finfo;
234 LARGE_INTEGER FileSize;
236 if (!GetFileInformationByHandle(fd, &finfo))
237 return -1;
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))
251 return -1;
253 *ftime = finfo.ftCreationTime;
255 return 0;
259 nt_setFileCreationTime(FD_t fd, FILETIME * ftime)
261 return !SetFileTime(fd, ftime, NULL, NULL);
265 nt_sync(int cdrive)
267 FD_t drive_fd;
268 char sdrive[32];
269 int n;
271 n = cdrive;
272 if (n <= 26) {
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) {
281 return -1;
284 if (!FlushFileBuffers((HANDLE) drive_fd)) {
285 errno = nterr_nt2unix(GetLastError(), EBADF);
286 nt_close(drive_fd);
287 return -1;
289 nt_close(drive_fd);
290 return 0;
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)
303 == 0xffffffff) {
304 errno = nterr_nt2unix(GetLastError(), EBADF);
305 return -1;
307 if (!SetEndOfFile(fd)) {
308 errno = nterr_nt2unix(GetLastError(), EBADF);
309 return -1;
311 return 0;
316 nt_fsync(FD_t fd)
318 int code = FlushFileBuffers(fd);
319 return code == 0 ? -1 : 0;
324 nt_seek(FD_t fd, afs_foff_t off, int whence)
326 int code;
327 LARGE_INTEGER offset;
328 int where;
330 if (SEEK_SET == whence) {
331 where = FILE_BEGIN;
332 } else if (SEEK_END == whence) {
333 where = FILE_END;
334 } else if (SEEK_CUR == whence) {
335 where = FILE_CURRENT;
336 } else {
337 errno = EINVAL;
338 return -1;
340 offset.QuadPart = off;
342 code = SetFilePointerEx(fd, offset, NULL, where);
343 if (0 == code) {
344 errno = nterr_nt2unix(GetLastError(), EBADF);
345 return -1;
347 return 0;
350 /* nt_DevToDrive
351 * converts a device number (2-25) into a drive letter name.
353 * Arguments:
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.
357 * Return Value:
358 * Returns pointer to end of drive if successful, else NULL.
361 void
362 nt_DevToDrive(char *drive, int dev)
364 if (dev < 2 || dev > 25) {
365 errno = EINVAL;
366 return; /* Invalid drive */
368 drive[0] = (char)('A' + dev);
369 drive[1] = ':';
370 drive[2] = '\0';
372 return;
376 /* nt_DriveToDev
377 * converts a drive letter to a device number (2-25)
379 * Arguments:
380 * drive - assumes drive is a pointer to a string at least 3 bytes long.
382 * Return Value:
383 * dev - drive number 2-25 if successful (A-C already in use), else -1
387 nt_DriveToDev(char *drive)
389 int dev = -1;
391 if (drive)
392 dev = toupper(*drive) - 'A';
393 if ((dev < 2) || (dev > 25))
394 return -1;
396 #endif