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 #include <afsconfig.h>
11 #include <afs/param.h>
16 #if defined(AFS_AIX_ENV)
18 #include <sys/statfs.h>
21 #include <sys/ioccom.h>
23 #ifndef AFS_DARWIN100_ENV
26 #endif /* AFS_AIX_ENV */
31 typedef off64_t osi_lloff_t
;
32 #define osi_llseek lseek64
33 #else /* O_LARGEFILE */
34 #ifdef AFS_HAVE_LLSEEK
35 typedef offset_t osi_lloff_t
;
36 #define osi_llseek llseek
37 #else /* AFS_HAVE_LLSEEK */
38 typedef off_t osi_lloff_t
;
39 #define osi_llseek lseek
40 #endif /* AFS_HAVE_LLSEEK */
41 #endif /* O_LARGEFILE */
44 * This macro should be used inside assertions wherever offset/hyper
45 * conversion occur. A good compiler in a 64 bit environment will
46 * elide the entire statement if the offset type is 64 bits wide.
48 #define osi_hFitsInOff(val) \
49 ((sizeof(osi_lloff_t) == 4) ? (((val) & 0xffffffff00000000LL) == 0) : 1)
51 /************ End of osi wrappers ***********************************/
53 /* Implementation of user space device I/O for regular POSIX files. */
56 usd_FileRead(usd_handle_t usd
, char *buf
, afs_uint32 nbytes
,
59 int fd
= (intptr_t)(usd
->handle
);
62 got
= read(fd
, buf
, nbytes
);
74 usd_FileWrite(usd_handle_t usd
, char *buf
, afs_uint32 nbytes
,
77 int fd
= (intptr_t)(usd
->handle
);
80 sent
= write(fd
, buf
, nbytes
);
91 extern osi_lloff_t
osi_llseek(int, osi_lloff_t
, int);
94 usd_FileSeek(usd_handle_t usd
, afs_int64 reqOff
, int whence
,
97 int fd
= (intptr_t)(usd
->handle
);
100 if (!osi_hFitsInOff(reqOff
))
103 lloff
= osi_llseek(fd
, reqOff
, whence
);
104 if (lloff
== (((osi_lloff_t
) 0) - 1))
113 usd_FileIoctl(usd_handle_t usd
, int req
, void *arg
)
115 int fd
= (intptr_t)(usd
->handle
);
118 #else /* O_LARGEFILE */
120 #endif /* O_LARGEFILE */
122 struct statfs fsinfo
; /* AIX stat structure doesn't have st_blksize */
123 #endif /* AFS_AIX_ENV */
128 case USD_IOCTL_GETBLKSIZE
:
130 code
= fstatfs(fd
, &fsinfo
);
132 *((long *)arg
) = (long)4096;
136 #endif /* AFS_AIX_ENV */
137 case USD_IOCTL_GETTYPE
:
138 case USD_IOCTL_GETDEV
:
139 case USD_IOCTL_GETSIZE
:
141 code
= fstat64(fd
, &info
);
142 #else /* O_LARGEFILE */
143 code
= fstat(fd
, &info
);
144 #endif /* O_LARGEFILE */
151 case USD_IOCTL_GETTYPE
:
152 *(int *)arg
= info
.st_mode
& S_IFMT
;
154 case USD_IOCTL_GETDEV
:
155 if (!(S_ISCHR(info
.st_mode
) || S_ISBLK(info
.st_mode
)))
156 return ENODEV
; /* not a device */
157 *(dev_t
*) arg
= info
.st_rdev
;
159 case USD_IOCTL_GETSIZE
:
160 if (S_ISCHR(info
.st_mode
) || S_ISBLK(info
.st_mode
))
161 return ENOTTY
; /* shouldn't be a device */
162 *(afs_int64
*)arg
= info
.st_size
;
164 case USD_IOCTL_GETFULLNAME
:
165 *(char **)arg
= usd
->fullPathName
;
168 case USD_IOCTL_SETSIZE
:
170 /* We could just use ftruncate in all cases. (This even works on AIX;
171 * I tried it). -blake 931118 */
173 /* However, I'm pretty sure this doesn't work on Ultrix so I am
174 * unsure about OSF/1 and HP/UX. 931118 */
176 size
= *(afs_int64
*) arg
;
177 if (!osi_hFitsInOff(size
))
180 code
= ftruncate64(fd
, size
);
181 #else /* O_LARGEFILE */
182 code
= ftruncate(fd
, size
);
183 #endif /* O_LARGEFILE */
188 case USD_IOCTL_TAPEOPERATION
:
190 #ifdef AFS_DARWIN100_ENV
193 usd_tapeop_t
*tapeOpp
= (usd_tapeop_t
*) arg
;
194 #if defined(AFS_AIX_ENV)
195 struct stop os_tapeop
;
197 if (tapeOpp
->tp_op
== USDTAPE_WEOF
) {
198 os_tapeop
.st_op
= STWEOF
;
199 } else if (tapeOpp
->tp_op
== USDTAPE_REW
) {
200 os_tapeop
.st_op
= STREW
;
201 } else if (tapeOpp
->tp_op
== USDTAPE_FSF
) {
202 os_tapeop
.st_op
= STFSF
;
203 } else if (tapeOpp
->tp_op
== USDTAPE_BSF
) {
204 os_tapeop
.st_op
= STRSF
;
205 } else if (tapeOpp
->tp_op
== USDTAPE_PREPARE
) {
207 } else if (tapeOpp
->tp_op
== USDTAPE_SHUTDOWN
) {
210 /* unsupported tape operation */
213 os_tapeop
.st_count
= tapeOpp
->tp_count
;
215 code
= ioctl(fd
, STIOCTOP
, &os_tapeop
);
217 struct mtop os_tapeop
;
219 if (tapeOpp
->tp_op
== USDTAPE_WEOF
) {
220 os_tapeop
.mt_op
= MTWEOF
;
221 } else if (tapeOpp
->tp_op
== USDTAPE_REW
) {
222 os_tapeop
.mt_op
= MTREW
;
223 } else if (tapeOpp
->tp_op
== USDTAPE_FSF
) {
224 os_tapeop
.mt_op
= MTFSF
;
225 } else if (tapeOpp
->tp_op
== USDTAPE_BSF
) {
226 os_tapeop
.mt_op
= MTBSF
;
227 } else if (tapeOpp
->tp_op
== USDTAPE_PREPARE
) {
229 } else if (tapeOpp
->tp_op
== USDTAPE_SHUTDOWN
) {
232 /* unsupported tape operation */
235 os_tapeop
.mt_count
= tapeOpp
->tp_count
;
237 code
= ioctl(fd
, MTIOCTOP
, &os_tapeop
);
238 #endif /* AFS_AIX_ENV */
248 case USD_IOCTL_GETBLKSIZE
:
249 if (S_ISCHR(info
.st_mode
) || S_ISBLK(info
.st_mode
)) {
250 *((long *)arg
) = (long)4096;
254 *((long *)arg
) = (long)fsinfo
.f_bsize
;
255 #else /* AFS_AIX_ENV */
256 *((long *)arg
) = (long)info
.st_blksize
;
257 #endif /* AFS_AIX_ENV */
267 usd_FileClose(usd_handle_t usd
)
269 int fd
= (intptr_t)(usd
->handle
);
273 /* I can't really believe this is necessary. On the one hand the user
274 * space code always uses character devices, which aren't supposed to do
275 * any buffering. On the other, I very much doubt fsyncing a regular file
276 * being salvaged is ever necessary. But the salvager used to do this
277 * before returning, so... */
279 if (usd
->openFlags
& (O_WRONLY
| O_RDWR
)) {
281 code
= usd_FileIoctl(usd
, USD_IOCTL_GETTYPE
, &mode
);
282 if (code
== 0 && S_ISBLK(mode
)) {
292 if (usd
->fullPathName
)
293 free(usd
->fullPathName
);
300 usd_FileOpen(const char *path
, int flags
, int mode
, usd_handle_t
* usdP
)
310 oflags
= (flags
& USD_OPEN_RDWR
) ? O_RDWR
: O_RDONLY
;
312 #ifdef O_SYNC /* AFS_DARWIN_ENV XXX */
313 if (flags
& USD_OPEN_SYNC
)
317 if (flags
& USD_OPEN_CREATE
)
321 fd
= open64(path
, oflags
| O_LARGEFILE
, mode
);
322 #else /* O_LARGEFILE */
323 fd
= open(path
, oflags
, mode
);
324 #endif /* O_LARGEFILE */
328 usd
= calloc(1, sizeof(*usd
));
329 usd
->handle
= (void *)(intptr_t)fd
;
330 usd
->read
= usd_FileRead
;
331 usd
->write
= usd_FileWrite
;
332 usd
->seek
= usd_FileSeek
;
333 usd
->ioctl
= usd_FileIoctl
;
334 usd
->close
= usd_FileClose
;
335 usd
->fullPathName
= strdup(path
);
336 usd
->openFlags
= flags
;
339 if (flags
& (USD_OPEN_RLOCK
| USD_OPEN_WLOCK
)) {
342 #else /* O_LARGEFILE */
344 #endif /* O_LARGEFILE */
346 /* make sure both lock bits aren't set */
347 opr_Assert(~flags
& (USD_OPEN_RLOCK
| USD_OPEN_WLOCK
));
349 fl
.l_type
= ((flags
& USD_OPEN_RLOCK
) ? F_RDLCK
: F_WRLCK
);
350 fl
.l_whence
= SEEK_SET
;
351 fl
.l_start
= (osi_lloff_t
) 0;
352 fl
.l_len
= (osi_lloff_t
) 0; /* whole file */
354 code
= fcntl(fd
, F_SETLK64
, &fl
);
355 #else /* O_LARGEFILE */
356 code
= fcntl(fd
, F_SETLK
, &fl
);
357 #endif /* O_LARGEFILE */
361 /* If we're trying to obtain a write lock on a real disk, then the
362 * aggregate must not be attached by the kernel. If so, unlock it
364 * WARNING: The code to check for the above has been removed when this
365 * file was ported from DFS src. It should be put back if
366 * this library is used to access hard disks
370 if (code
== 0 && usdP
)
378 usd_FileDummyClose(usd_handle_t usd
)
385 usd_Open(const char *path
, int oflag
, int mode
, usd_handle_t
* usdP
)
387 return usd_FileOpen(path
, oflag
, mode
, usdP
);
391 usd_FileStandardInput(usd_handle_t
* usdP
)
395 usd
= calloc(1, sizeof(*usd
));
396 usd
->handle
= (void *)((unsigned long)0);
397 usd
->read
= usd_FileRead
;
398 usd
->write
= usd_FileWrite
;
399 usd
->seek
= usd_FileSeek
;
400 usd
->ioctl
= usd_FileIoctl
;
401 usd
->close
= usd_FileDummyClose
;
402 usd
->fullPathName
= "STDIN";
410 usd_StandardInput(usd_handle_t
* usdP
)
412 return usd_FileStandardInput(usdP
);
416 usd_FileStandardOutput(usd_handle_t
* usdP
)
420 usd
= calloc(1, sizeof(*usd
));
421 usd
->handle
= (void *)((unsigned long)1);
422 usd
->read
= usd_FileRead
;
423 usd
->write
= usd_FileWrite
;
424 usd
->seek
= usd_FileSeek
;
425 usd
->ioctl
= usd_FileIoctl
;
426 usd
->close
= usd_FileDummyClose
;
427 usd
->fullPathName
= "STDOUT";
435 usd_StandardOutput(usd_handle_t
* usdP
)
437 return usd_FileStandardOutput(usdP
);