3 * Copyright 2000, International Business Machines Corporation and others.
6 * This software has been released under the terms of the IBM Public
7 * License. For details, see the LICENSE file in the top-level source
8 * directory or online at http://www.openafs.org/dl/license10.html
12 * User space client specific interface glue
15 #include <afsconfig.h>
16 #include "afs/param.h"
20 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs_usrops.h"
25 #include "afs/afs_stats.h"
27 #include "afs/cellconfig.h"
29 #include "afs/afsutil.h"
30 #include "afs/afs_bypasscache.h"
31 #include "rx/rx_globals.h"
32 #include "afsd/afsd.h"
38 #ifndef AFS_CACHE_VNODE_PATH
39 #error You must compile UKERNEL code with -DAFS_CACHE_VNODE_PATH
42 #define CACHEINFOFILE "cacheinfo"
43 #define AFSLOGFILE "AFSLog"
44 #define DCACHEFILE "CacheItems"
45 #define VOLINFOFILE "VolumeItems"
46 #define CELLINFOFILE "CellItems"
50 #define MIN(A,B) ((A)<(B)?(A):(B))
53 #define MAX(A,B) ((A)>(B)?(A):(B))
56 extern int cacheDiskType
;
58 char afs_LclCellName
[64];
60 static struct usr_vnode
*afs_FileTable
[MAX_OSI_FILES
];
61 static int afs_FileFlags
[MAX_OSI_FILES
];
62 static off_t afs_FileOffsets
[MAX_OSI_FILES
];
64 #define MAX_CACHE_LOOPS 4
66 static struct usr_vfs afs_RootVfs
;
67 static struct usr_vnode
*afs_RootVnode
= NULL
;
68 static struct usr_vnode
*afs_CurrentDir
= NULL
;
70 static char afs_mountDir
[1024]; /* AFS mount point */
71 static int afs_mountDirLen
; /* strlen of AFS mount point */
73 struct afsconf_dir
*afs_cdir
; /* config dir */
75 int afs_bufferpages
= 100;
77 static usr_key_t afs_global_u_key
;
79 static struct usr_proc
*afs_global_procp
= NULL
;
80 static struct usr_ucred
*afs_global_ucredp
= NULL
;
82 struct usr_ucred afs_osi_cred
, *afs_osi_credp
;
83 usr_mutex_t afs_global_lock
;
84 usr_thread_t afs_global_owner
;
85 usr_mutex_t rx_global_lock
;
86 usr_thread_t rx_global_owner
;
88 static usr_mutex_t osi_dummy_lock
;
89 static usr_mutex_t osi_waitq_lock
;
90 static usr_mutex_t osi_authenticate_lock
;
92 afs_lock_t osi_flplock
;
93 afs_lock_t osi_fsplock
;
96 * Mutex and condition variable used to implement sleep
98 pthread_mutex_t usr_sleep_mutex
;
99 pthread_cond_t usr_sleep_cond
;
101 int call_syscall(long, long, long, long, long, long);
102 int fork_syscall(long, long, long, long, long, long);
106 * Hash table mapping addresses onto wait structures for
107 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
109 typedef struct osi_wait
{
113 struct osi_wait
*next
;
114 struct osi_wait
*prev
;
116 struct osi_wait
*timedNext
;
117 struct osi_wait
*timedPrev
;
121 * Head of the linked list of available waitq structures.
123 static osi_wait_t
*osi_waithash_avail
;
126 * List of timed waits, NSAPI does not provide a cond_timed
127 * wait, so we need to keep track of the timed waits ourselves and
128 * periodically check for expirations
130 static osi_wait_t
*osi_timedwait_head
;
131 static osi_wait_t
*osi_timedwait_tail
;
136 } osi_waithash_table
[OSI_WAITHASH_SIZE
];
139 * Never call afs_brelse
142 ufs_brelse(struct usr_vnode
*vp
, struct usr_buf
*bp
)
149 * I am not sure what to do with these, they assert for now
152 iodone(struct usr_buf
*bp
)
166 * Every user is a super user
169 afs_osi_suser(void *credp
)
175 afs_suser(void *credp
)
181 * These are no-ops in user space
185 * xflock should never fall through, the only files we know
186 * about are AFS files
196 * ioctl should never fall through, the only files we know
197 * about are AFS files
207 * We do not support the inode related system calls
210 afs_syscall_icreate(long a
, long b
, long c
, long d
, long e
, long f
)
217 afs_syscall_iincdec(int dev
, int inode
, int inode_p1
, int amount
)
224 afs_syscall_iopen(int dev
, int inode
, int usrmod
)
231 afs_syscall_ireadwrite(void)
238 * these routines are referenced in the vfsops structure, but
239 * should never get called
270 * uiomove copies data between kernel buffers and uio buffers
273 usr_uiomove(char *kbuf
, int n
, int rw
, struct usr_uio
*uio
)
280 nio
= uio
->uio_iovcnt
;
290 while (nio
> 0 && n
> 0) {
291 len
= MIN(n
, iovp
->iov_len
);
292 if (rw
== UIO_READ
) {
293 memcpy(iovp
->iov_base
, ptr
, len
);
295 memcpy(ptr
, iovp
->iov_base
, len
);
299 uio
->uio_resid
-= len
;
300 uio
->uio_offset
+= len
;
301 iovp
->iov_base
= (char *)(iovp
->iov_base
) + len
;
302 iovp
->iov_len
-= len
;
313 * routines to manage user credentials
316 usr_crcopy(struct usr_ucred
*credp
)
318 struct usr_ucred
*newcredp
;
320 newcredp
= afs_osi_Alloc(sizeof(struct usr_ucred
));
322 newcredp
->cr_ref
= 1;
329 struct usr_ucred
*newcredp
;
331 newcredp
= afs_osi_Alloc(sizeof(struct usr_ucred
));
332 newcredp
->cr_ref
= 1;
337 usr_crfree(struct usr_ucred
*credp
)
340 if (credp
->cr_ref
== 0) {
341 afs_osi_Free((char *)credp
, sizeof(struct usr_ucred
));
347 usr_crhold(struct usr_ucred
*credp
)
354 usr_vattr_null(struct usr_vattr
*vap
)
359 n
= sizeof(struct usr_vattr
);
367 * Initialize the thread specific data used to simulate the
368 * kernel environment for each thread. The user structure
369 * is stored in the thread specific data.
372 uafs_InitThread(void)
375 struct usr_user
*uptr
;
378 * initialize the thread specific user structure. Use malloc to
379 * allocate the data block, so pthread_finish can free the buffer
380 * when this thread terminates.
382 uptr
= malloc(sizeof(struct usr_user
) + sizeof(struct usr_ucred
));
383 usr_assert(uptr
!= NULL
);
386 uptr
->u_procp
= afs_global_procp
;
387 uptr
->u_cred
= (struct usr_ucred
*)(uptr
+ 1);
388 *uptr
->u_cred
= *afs_global_ucredp
;
389 st
= usr_setspecific(afs_global_u_key
, (void *)uptr
);
394 * routine to get the user structure from the thread specific data.
395 * this routine is used to implement the global 'u' structure. Initializes
396 * the thread if needed.
399 get_user_struct(void)
401 struct usr_user
*uptr
;
404 st
= usr_getspecific(afs_global_u_key
, &uptr
);
408 st
= usr_getspecific(afs_global_u_key
, &uptr
);
410 usr_assert(uptr
!= NULL
);
416 * Hash an address for the waithash table
418 #define WAITHASH(X) \
419 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
425 afs_osi_Sleep(void *x
)
429 int glockOwner
= ISAFS_GLOCK();
431 usr_mutex_lock(&osi_waitq_lock
);
436 if (osi_waithash_avail
== NULL
) {
437 waitp
= afs_osi_Alloc(sizeof(osi_wait_t
));
438 usr_cond_init(&waitp
->cond
);
440 waitp
= osi_waithash_avail
;
441 osi_waithash_avail
= osi_waithash_avail
->next
;
445 DLL_INSERT_TAIL(waitp
, osi_waithash_table
[index
].head
,
446 osi_waithash_table
[index
].tail
, next
, prev
);
447 waitp
->expiration
= 0;
448 waitp
->timedNext
= NULL
;
449 waitp
->timedPrev
= NULL
;
450 while (waitp
->flag
== 0) {
451 usr_cond_wait(&waitp
->cond
, &osi_waitq_lock
);
453 DLL_DELETE(waitp
, osi_waithash_table
[index
].head
,
454 osi_waithash_table
[index
].tail
, next
, prev
);
455 waitp
->next
= osi_waithash_avail
;
456 osi_waithash_avail
= waitp
;
457 usr_mutex_unlock(&osi_waitq_lock
);
464 afs_osi_SleepSig(void *x
)
471 afs_osi_Wakeup(void *x
)
477 usr_mutex_lock(&osi_waitq_lock
);
478 waitp
= osi_waithash_table
[index
].head
;
480 if (waitp
->addr
== x
&& waitp
->flag
== 0) {
482 usr_cond_signal(&waitp
->cond
);
486 usr_mutex_unlock(&osi_waitq_lock
);
491 afs_osi_TimedSleep(void *event
, afs_int32 ams
, int aintok
)
493 return afs_osi_Wait(ams
, event
, aintok
);
497 afs_osi_Wait(afs_int32 msec
, struct afs_osi_WaitHandle
*handle
, int intok
)
503 int glockOwner
= ISAFS_GLOCK();
505 tv
.tv_sec
= msec
/ 1000;
506 tv
.tv_nsec
= (msec
% 1000) * 1000000;
507 if (handle
== NULL
) {
511 usr_thread_sleep(&tv
);
517 usr_mutex_lock(&osi_waitq_lock
);
521 index
= WAITHASH((caddr_t
) handle
);
522 if (osi_waithash_avail
== NULL
) {
523 waitp
= afs_osi_Alloc(sizeof(osi_wait_t
));
524 usr_cond_init(&waitp
->cond
);
526 waitp
= osi_waithash_avail
;
527 osi_waithash_avail
= osi_waithash_avail
->next
;
529 waitp
->addr
= (caddr_t
) handle
;
531 DLL_INSERT_TAIL(waitp
, osi_waithash_table
[index
].head
,
532 osi_waithash_table
[index
].tail
, next
, prev
);
533 tv
.tv_sec
+= time(NULL
);
534 waitp
->expiration
= tv
.tv_sec
+ ((tv
.tv_nsec
== 0) ? 0 : 1);
535 DLL_INSERT_TAIL(waitp
, osi_timedwait_head
, osi_timedwait_tail
,
536 timedNext
, timedPrev
);
537 usr_cond_wait(&waitp
->cond
, &osi_waitq_lock
);
543 DLL_DELETE(waitp
, osi_waithash_table
[index
].head
,
544 osi_waithash_table
[index
].tail
, next
, prev
);
545 DLL_DELETE(waitp
, osi_timedwait_head
, osi_timedwait_tail
, timedNext
,
547 waitp
->next
= osi_waithash_avail
;
548 osi_waithash_avail
= waitp
;
549 usr_mutex_unlock(&osi_waitq_lock
);
558 afs_osi_CancelWait(struct afs_osi_WaitHandle
*handle
)
560 afs_osi_Wakeup(handle
);
564 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
565 * to explicitly signal cond_timed_waits when their timers expire
568 afs_osi_CheckTimedWaits(void)
573 curTime
= time(NULL
);
574 usr_mutex_lock(&osi_waitq_lock
);
575 waitp
= osi_timedwait_head
;
576 while (waitp
!= NULL
) {
577 usr_assert(waitp
->expiration
!= 0);
578 if (waitp
->expiration
<= curTime
) {
580 usr_cond_signal(&waitp
->cond
);
582 waitp
= waitp
->timedNext
;
584 usr_mutex_unlock(&osi_waitq_lock
);
589 * 'dummy' vnode, for non-AFS files. We don't actually need most vnode
590 * information for non-AFS files, so point all of them towards this vnode
593 static struct usr_vnode dummy_vnode
= {
604 * Allocate a slot in the file table if there is not one there already,
605 * copy in the file name and kludge up the vnode and inode structures
608 lookupname(char *fnamep
, int segflg
, int followlink
,
609 struct usr_vnode
**compvpp
)
614 * Assume relative pathnames refer to files in AFS
616 if (*fnamep
!= '/' || uafs_afsPathName(fnamep
) != NULL
) {
618 code
= uafs_LookupName(fnamep
, afs_CurrentDir
, compvpp
, 0, 0);
623 /* For non-afs files, nobody really looks at the meaningful values in the
624 * returned vnode, so we can return a 'fake' one. The vnode can be held,
625 * released, etc. and some callers check for a NULL vnode anyway, so we
626 * to return something. */
628 usr_mutex_lock(&osi_dummy_lock
);
629 VN_HOLD(&dummy_vnode
);
630 usr_mutex_unlock(&osi_dummy_lock
);
632 *compvpp
= &dummy_vnode
;
638 * open a file given its i-node number
641 osi_UFSOpen(afs_dcache_id_t
*ino
)
650 fp
= afs_osi_Alloc(sizeof(struct osi_file
));
651 usr_assert(fp
!= NULL
);
653 usr_assert(ino
->ufs
);
655 fp
->fd
= open(ino
->ufs
, O_RDWR
| O_CREAT
, 0);
657 get_user_struct()->u_error
= errno
;
658 afs_osi_Free((char *)fp
, sizeof(struct osi_file
));
662 rc
= fstat(fp
->fd
, &st
);
664 get_user_struct()->u_error
= errno
;
665 afs_osi_Free((void *)fp
, sizeof(struct osi_file
));
669 fp
->size
= st
.st_size
;
671 fp
->vnode
= (struct usr_vnode
*)fp
;
678 osi_UFSClose(struct osi_file
*fp
)
687 get_user_struct()->u_error
= errno
;
688 afs_osi_Free((void *)fp
, sizeof(struct osi_file
));
692 afs_osi_Free((void *)fp
, sizeof(struct osi_file
));
698 osi_UFSTruncate(struct osi_file
*fp
, afs_int32 len
)
705 rc
= ftruncate(fp
->fd
, len
);
707 get_user_struct()->u_error
= errno
;
717 afs_osi_Read(struct osi_file
*fp
, int offset
, void *buf
, afs_int32 len
)
726 rc
= lseek(fp
->fd
, offset
, SEEK_SET
);
728 rc
= lseek(fp
->fd
, fp
->offset
, SEEK_SET
);
731 get_user_struct()->u_error
= errno
;
736 ret
= read(fp
->fd
, buf
, len
);
738 get_user_struct()->u_error
= errno
;
743 rc
= fstat(fp
->fd
, &st
);
745 get_user_struct()->u_error
= errno
;
749 fp
->size
= st
.st_size
;
755 afs_osi_Write(struct osi_file
*fp
, afs_int32 offset
, void *buf
, afs_int32 len
)
764 rc
= lseek(fp
->fd
, offset
, SEEK_SET
);
766 rc
= lseek(fp
->fd
, fp
->offset
, SEEK_SET
);
769 get_user_struct()->u_error
= errno
;
774 ret
= write(fp
->fd
, buf
, len
);
776 get_user_struct()->u_error
= errno
;
781 rc
= fstat(fp
->fd
, &st
);
783 get_user_struct()->u_error
= errno
;
787 fp
->size
= st
.st_size
;
793 afs_osi_Stat(struct osi_file
*fp
, struct osi_stat
*stp
)
799 rc
= fstat(fp
->fd
, &st
);
801 get_user_struct()->u_error
= errno
;
805 stp
->size
= st
.st_size
;
806 stp
->mtime
= st
.st_mtime
;
807 stp
->atime
= st
.st_atime
;
816 afs_osi_VOP_RDWR(struct usr_vnode
*vnodeP
, struct usr_uio
*uioP
, int rw
,
817 int flags
, struct usr_ucred
*credP
)
820 struct osi_file
*fp
= (struct osi_file
*)vnodeP
;
823 * We don't support readv/writev.
825 usr_assert(uioP
->uio_iovcnt
== 1);
826 usr_assert(uioP
->uio_resid
== uioP
->uio_iov
[0].iov_len
);
828 if (rw
== UIO_WRITE
) {
829 usr_assert(uioP
->uio_fmode
== FWRITE
);
830 rc
= afs_osi_Write(fp
, uioP
->uio_offset
, uioP
->uio_iov
[0].iov_base
,
831 uioP
->uio_iov
[0].iov_len
);
833 usr_assert(uioP
->uio_fmode
== FREAD
);
834 rc
= afs_osi_Read(fp
, uioP
->uio_offset
, uioP
->uio_iov
[0].iov_base
,
835 uioP
->uio_iov
[0].iov_len
);
838 return get_user_struct()->u_error
;
841 uioP
->uio_resid
-= rc
;
842 uioP
->uio_offset
+= rc
;
843 uioP
->uio_iov
[0].iov_base
= (char *)(uioP
->uio_iov
[0].iov_base
) + rc
;
844 uioP
->uio_iov
[0].iov_len
-= rc
;
849 afs_osi_Alloc(size_t size
)
855 afs_osi_Free(void *ptr
, size_t size
)
861 afs_osi_FreeStr(char *ptr
)
867 osi_AllocLargeSpace(size_t size
)
869 AFS_STATCNT(osi_AllocLargeSpace
);
870 return afs_osi_Alloc(size
);
874 osi_FreeLargeSpace(void *ptr
)
876 AFS_STATCNT(osi_FreeLargeSpace
);
877 afs_osi_Free(ptr
, 0);
881 osi_AllocSmallSpace(size_t size
)
883 AFS_STATCNT(osi_AllocSmallSpace
);
884 return afs_osi_Alloc(size
);
888 osi_FreeSmallSpace(void *ptr
)
890 AFS_STATCNT(osi_FreeSmallSpace
);
891 afs_osi_Free(ptr
, 0);
897 AFS_STATCNT(shutdown_osi
);
902 shutdown_osinet(void)
904 AFS_STATCNT(shutdown_osinet
);
909 shutdown_osifile(void)
911 AFS_STATCNT(shutdown_osifile
);
916 afs_nfsclient_init(void)
921 shutdown_nfsclnt(void)
927 afs_osi_Invisible(void)
933 afs_osi_Visible(void)
939 osi_GetTime(struct timeval
*tv
)
941 gettimeofday(tv
, NULL
);
946 osi_SetTime(struct timeval
*tv
)
952 osi_Active(struct vcache
*avc
)
954 AFS_STATCNT(osi_Active
);
961 afs_osi_MapStrategy(int (*aproc
) (struct usr_buf
*), struct usr_buf
*bp
)
963 afs_int32 returnCode
;
964 returnCode
= (*aproc
) (bp
);
969 osi_FlushPages(struct vcache
*avc
, afs_ucred_t
*credp
)
971 ObtainSharedLock(&avc
->lock
, 555);
972 if ((hcmp((avc
->f
.m
.DataVersion
), (avc
->mapDV
)) <= 0)
973 || ((avc
->execsOrWriters
> 0) && afs_DirtyPages(avc
))) {
974 ReleaseSharedLock(&avc
->lock
);
977 UpgradeSToWLock(&avc
->lock
, 565);
978 hset(avc
->mapDV
, avc
->f
.m
.DataVersion
);
979 ReleaseWriteLock(&avc
->lock
);
984 osi_FlushText_really(struct vcache
*vp
)
986 if (hcmp(vp
->f
.m
.DataVersion
, vp
->flushDV
) > 0) {
987 hset(vp
->flushDV
, vp
->f
.m
.DataVersion
);
993 osi_SyncVM(struct vcache
*avc
)
999 osi_ReleaseVM(struct vcache
*avc
, int len
, struct usr_ucred
*credp
)
1011 * Use the thread specific data to implement the user structure
1013 usr_keycreate(&afs_global_u_key
, free
);
1016 * Initialize the global ucred structure
1018 afs_global_ucredp
= (struct usr_ucred
*)
1019 afs_osi_Alloc(sizeof(struct usr_ucred
));
1020 usr_assert(afs_global_ucredp
!= NULL
);
1021 afs_global_ucredp
->cr_ref
= 1;
1022 afs_set_cr_uid(afs_global_ucredp
, geteuid());
1023 afs_set_cr_gid(afs_global_ucredp
, getegid());
1024 afs_set_cr_ruid(afs_global_ucredp
, getuid());
1025 afs_set_cr_rgid(afs_global_ucredp
, getgid());
1026 afs_global_ucredp
->cr_suid
= afs_cr_ruid(afs_global_ucredp
);
1027 afs_global_ucredp
->cr_sgid
= afs_cr_rgid(afs_global_ucredp
);
1028 st
= getgroups(NGROUPS
, &afs_global_ucredp
->cr_groups
[0]);
1029 usr_assert(st
>= 0);
1030 afs_global_ucredp
->cr_ngroups
= (unsigned long)st
;
1031 for (i
= st
; i
< NGROUPS
; i
++) {
1032 afs_global_ucredp
->cr_groups
[i
] = NOGROUP
;
1036 * Initialize the global process structure
1038 afs_global_procp
= (struct usr_proc
*)
1039 afs_osi_Alloc(sizeof(struct usr_proc
));
1040 usr_assert(afs_global_procp
!= NULL
);
1041 afs_global_procp
->p_pid
= osi_getpid();
1042 afs_global_procp
->p_ppid
= (pid_t
) 1;
1043 afs_global_procp
->p_ucred
= afs_global_ucredp
;
1046 * Initialize the mutex and condition variable used to implement
1049 pthread_mutex_init(&usr_sleep_mutex
, NULL
);
1050 pthread_cond_init(&usr_sleep_cond
, NULL
);
1053 * Initialize the hash table used for sleep/wakeup
1055 for (i
= 0; i
< OSI_WAITHASH_SIZE
; i
++) {
1056 DLL_INIT_LIST(osi_waithash_table
[i
].head
, osi_waithash_table
[i
].tail
);
1058 DLL_INIT_LIST(osi_timedwait_head
, osi_timedwait_tail
);
1059 osi_waithash_avail
= NULL
;
1062 * Initialize the AFS file table
1064 for (i
= 0; i
< MAX_OSI_FILES
; i
++) {
1065 afs_FileTable
[i
] = NULL
;
1069 * Initialize the global locks
1071 usr_mutex_init(&afs_global_lock
);
1072 usr_mutex_init(&rx_global_lock
);
1073 usr_mutex_init(&osi_dummy_lock
);
1074 usr_mutex_init(&osi_waitq_lock
);
1075 usr_mutex_init(&osi_authenticate_lock
);
1078 * Initialize the AFS OSI credentials
1080 afs_osi_cred
= *afs_global_ucredp
;
1081 afs_osi_credp
= &afs_osi_cred
;
1083 init_et_to_sys_error();
1087 * Set the UDP port number RX uses for UDP datagrams
1090 uafs_SetRxPort(int port
)
1092 usr_assert(usr_rx_port
== 0);
1097 * uafs_Init is for backwards compatibility only! Do not use it; use
1098 * uafs_Setup, uafs_ParseArgs, and uafs_Run instead.
1101 uafs_Init(char *rn
, char *mountDirParam
, char *confDirParam
,
1102 char *cacheBaseDirParam
, int cacheBlocksParam
, int cacheFilesParam
,
1103 int cacheStatEntriesParam
, int dCacheSizeParam
, int vCacheSizeParam
,
1104 int chunkSizeParam
, int closeSynchParam
, int debugParam
,
1105 int nDaemonsParam
, int cacheFlagsParam
, char *logFile
)
1115 code
= uafs_Setup(mountDirParam
);
1116 usr_assert(code
== 0);
1119 if (mountDirParam
) {
1120 argv
[argc
++] = "-mountdir";
1121 argv
[argc
++] = mountDirParam
;
1124 argv
[argc
++] = "-confdir";
1125 argv
[argc
++] = confDirParam
;
1127 if (cacheBaseDirParam
) {
1128 argv
[argc
++] = "-cachedir";
1129 argv
[argc
++] = cacheBaseDirParam
;
1131 if (cacheBlocksParam
) {
1132 snprintf(buf
, sizeof(buf
), "%d", cacheBlocksParam
);
1134 argv
[argc
++] = "-blocks";
1135 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1137 if (cacheFilesParam
) {
1138 snprintf(buf
, sizeof(buf
), "%d", cacheFilesParam
);
1140 argv
[argc
++] = "-files";
1141 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1143 if (cacheStatEntriesParam
) {
1144 snprintf(buf
, sizeof(buf
), "%d", cacheStatEntriesParam
);
1146 argv
[argc
++] = "-stat";
1147 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1149 if (dCacheSizeParam
) {
1150 snprintf(buf
, sizeof(buf
), "%d", dCacheSizeParam
);
1152 argv
[argc
++] = "-dcache";
1153 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1155 if (vCacheSizeParam
) {
1156 snprintf(buf
, sizeof(buf
), "%d", vCacheSizeParam
);
1158 argv
[argc
++] = "-volumes";
1159 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1161 if (chunkSizeParam
) {
1162 snprintf(buf
, sizeof(buf
), "%d", chunkSizeParam
);
1164 argv
[argc
++] = "-chunksize";
1165 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1167 if (closeSynchParam
) {
1168 argv
[argc
++] = "-waitclose";
1171 argv
[argc
++] = "-debug";
1173 if (nDaemonsParam
) {
1174 snprintf(buf
, sizeof(buf
), "%d", nDaemonsParam
);
1176 argv
[argc
++] = "-daemons";
1177 argv
[argc
++] = freeargv
[freeargc
++] = strdup(buf
);
1179 if (cacheFlagsParam
) {
1180 if (cacheFlagsParam
& AFSCALL_INIT_MEMCACHE
) {
1181 argv
[argc
++] = "-memcache";
1185 argv
[argc
++] = "-logfile";
1186 argv
[argc
++] = logFile
;
1191 code
= uafs_ParseArgs(argc
, argv
);
1192 usr_assert(code
== 0);
1194 for (i
= 0; i
< freeargc
; i
++) {
1199 usr_assert(code
== 0);
1203 * Calculate the cacheMountDir used for a specified dir.
1205 * @param[in] dir Desired mount dir
1206 * @param[out] mountdir On success, contains the literal string that should
1207 * be used as the cache mount dir.
1208 * @param[in] size The number of bytes allocated in mountdir
1210 * @post On success, mountdir begins with a slash, and does not contain two
1211 * slashes adjacent to each other
1213 * @return operation status
1215 * @retval ENAMETOOLONG the specified dir is too long to fix in the given
1217 * @retval EINVAL the specified dir does not actually specify any meaningful
1221 calcMountDir(const char *dir
, char *mountdir
, size_t size
)
1228 if (dir
&& strlen(dir
) > size
-1) {
1229 return ENAMETOOLONG
;
1233 * Initialize the AFS mount point, default is '/afs'.
1234 * Strip duplicate/trailing slashes from mount point string.
1235 * afs_mountDirLen is set to strlen(afs_mountDir).
1240 sprintf(buf
, "%s", dir
);
1244 for (lastchar
= '/', p
= &buf
[0]; *p
!= '\0'; p
++) {
1245 if (lastchar
!= '/' || *p
!= '/') {
1246 mountdir
[len
++] = lastchar
= *p
;
1249 if (lastchar
== '/' && len
> 1)
1251 mountdir
[len
] = '\0';
1264 * Mount the AFS filesystem
1267 rc
= afs_mount(&afs_RootVfs
, NULL
, NULL
);
1268 usr_assert(rc
== 0);
1269 rc
= afs_root(&afs_RootVfs
, &afs_RootVnode
);
1270 usr_assert(rc
== 0);
1274 * initialize the current directory to the AFS root
1276 afs_CurrentDir
= afs_RootVnode
;
1277 VN_HOLD(afs_CurrentDir
);
1283 uafs_setMountDir(const char *dir
)
1287 char tmp_mountDir
[1024];
1289 rc
= calcMountDir(dir
, tmp_mountDir
, sizeof(tmp_mountDir
));
1291 afs_warn("Invalid mount dir specification (error %d): %s\n", rc
, dir
);
1293 if (strcmp(tmp_mountDir
, afs_mountDir
) != 0) {
1294 /* mount dir changed */
1295 strcpy(afs_mountDir
, tmp_mountDir
);
1296 afs_mountDirLen
= strlen(afs_mountDir
);
1303 uafs_statvfs(struct statvfs
*buf
)
1309 rc
= afs_statvfs(&afs_RootVfs
, buf
);
1329 if (afs_CurrentDir
) {
1330 VN_RELE(afs_CurrentDir
);
1332 rc
= afs_unmount(&afs_RootVfs
);
1333 usr_assert(rc
== 0);
1340 * Donate the current thread to the RX server pool.
1343 uafs_RxServerProc(void)
1347 struct rx_call
*newcall
= NULL
;
1349 rxi_MorePackets(2); /* alloc more packets */
1350 threadID
= rxi_availProcs
++;
1353 sock
= OSI_NULLSOCKET
;
1354 rxi_ServerProc(threadID
, newcall
, &sock
);
1355 if (sock
== OSI_NULLSOCKET
) {
1360 rxi_ListenerProc(sock
, &threadID
, &newcall
);
1361 /* assert(threadID != -1); */
1362 /* assert(newcall != NULL); */
1366 struct syscallThreadArgs
{
1376 syscallThread(void *argp
)
1379 struct usr_ucred
*crp
;
1380 struct syscallThreadArgs
*sysArgsP
= (struct syscallThreadArgs
*)argp
;
1383 * AFS daemons run authenticated
1385 get_user_struct()->u_viceid
= getuid();
1386 crp
= get_user_struct()->u_cred
;
1387 afs_set_cr_uid(crp
, getuid());
1388 afs_set_cr_ruid(crp
, getuid());
1389 crp
->cr_suid
= getuid();
1390 crp
->cr_groups
[0] = getgid();
1391 crp
->cr_ngroups
= 1;
1392 for (i
= 1; i
< NGROUPS
; i
++) {
1393 crp
->cr_groups
[i
] = NOGROUP
;
1396 call_syscall(sysArgsP
->syscall
, sysArgsP
->afscall
, sysArgsP
->param1
,
1397 sysArgsP
->param2
, sysArgsP
->param3
, sysArgsP
->param4
);
1399 afs_osi_Free(argp
, -1);
1404 fork_syscall(long syscall
, long afscall
, long param1
, long param2
,
1405 long param3
, long param4
)
1408 struct syscallThreadArgs
*sysArgsP
;
1410 sysArgsP
= (struct syscallThreadArgs
*)
1411 afs_osi_Alloc(sizeof(struct syscallThreadArgs
));
1412 usr_assert(sysArgsP
!= NULL
);
1413 sysArgsP
->syscall
= syscall
;
1414 sysArgsP
->afscall
= afscall
;
1415 sysArgsP
->param1
= param1
;
1416 sysArgsP
->param2
= param2
;
1417 sysArgsP
->param3
= param3
;
1418 sysArgsP
->param4
= param4
;
1420 usr_thread_create(&tid
, syscallThread
, sysArgsP
);
1421 usr_thread_detach(tid
);
1426 call_syscall(long syscall
, long afscall
, long param1
, long param2
,
1427 long param3
, long param4
)
1439 a
.syscall
= syscall
;
1440 a
.afscall
= afscall
;
1446 get_user_struct()->u_error
= 0;
1447 get_user_struct()->u_ap
= (char *)&a
;
1449 code
= Afs_syscall();
1454 uafs_Setup(const char *mount
)
1457 static int inited
= 0;
1464 rc
= calcMountDir(mount
, afs_mountDir
, sizeof(afs_mountDir
));
1468 afs_mountDirLen
= strlen(afs_mountDir
);
1470 /* initialize global vars and such */
1473 /* initialize cache manager foo */
1480 uafs_ParseArgs(int argc
, char **argv
)
1482 return afsd_parse(argc
, argv
);
1494 return afsd_cacheMountDir
;
1498 uafs_SetTokens(char *tbuffer
, int tlen
)
1501 struct afs_ioctl iob
;
1506 iob
.out
= &outbuf
[0];
1507 iob
.out_size
= sizeof(outbuf
);
1509 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(3), (long)&iob
, 0, 0);
1518 uafs_RPCStatsEnableProc(void)
1521 struct afs_ioctl iob
;
1524 flag
= AFSCALL_RXSTATS_ENABLE
;
1525 iob
.in
= (char *)&flag
;
1526 iob
.in_size
= sizeof(afs_int32
);
1529 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(53), (long)&iob
, 0, 0);
1538 uafs_RPCStatsDisableProc(void)
1541 struct afs_ioctl iob
;
1544 flag
= AFSCALL_RXSTATS_DISABLE
;
1545 iob
.in
= (char *)&flag
;
1546 iob
.in_size
= sizeof(afs_int32
);
1549 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(53), (long)&iob
, 0, 0);
1558 uafs_RPCStatsClearProc(void)
1561 struct afs_ioctl iob
;
1564 flag
= AFSCALL_RXSTATS_CLEAR
;
1565 iob
.in
= (char *)&flag
;
1566 iob
.in_size
= sizeof(afs_int32
);
1569 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(53), (long)&iob
, 0, 0);
1578 uafs_RPCStatsEnablePeer(void)
1581 struct afs_ioctl iob
;
1584 flag
= AFSCALL_RXSTATS_ENABLE
;
1585 iob
.in
= (char *)&flag
;
1586 iob
.in_size
= sizeof(afs_int32
);
1589 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(54), (long)&iob
, 0, 0);
1598 uafs_RPCStatsDisablePeer(void)
1601 struct afs_ioctl iob
;
1604 flag
= AFSCALL_RXSTATS_DISABLE
;
1605 iob
.in
= (char *)&flag
;
1606 iob
.in_size
= sizeof(afs_int32
);
1609 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(54), (long)&iob
, 0, 0);
1618 uafs_RPCStatsClearPeer(void)
1621 struct afs_ioctl iob
;
1624 flag
= AFSCALL_RXSTATS_CLEAR
;
1625 iob
.in
= (char *)&flag
;
1626 iob
.in_size
= sizeof(afs_int32
);
1629 rc
= call_syscall(AFSCALL_PIOCTL
, 0, _VICEIOCTL(54), (long)&iob
, 0, 0);
1638 * Lookup the target of a symbolic link
1639 * Call VN_HOLD on the output vnode if successful.
1640 * Returns zero on success, error code on failure.
1641 * If provided, use a path for confirming we are not linked to ourself.
1643 * Note: Caller must hold the AFS global lock.
1646 uafs_LookupLinkPath(struct usr_vnode
*vp
, struct usr_vnode
*parentVp
,
1647 char *ppathP
, struct usr_vnode
**vpp
)
1652 struct usr_vnode
*linkVp
;
1654 struct iovec iov
[1];
1658 pathP
= afs_osi_Alloc(MAX_OSI_PATH
+ 1);
1659 usr_assert(pathP
!= NULL
);
1662 * set up the uio buffer
1664 iov
[0].iov_base
= pathP
;
1665 iov
[0].iov_len
= MAX_OSI_PATH
+ 1;
1666 uio
.uio_iov
= &iov
[0];
1670 uio
.uio_fmode
= FREAD
;
1671 uio
.uio_resid
= MAX_OSI_PATH
+ 1;
1674 * Read the link data
1676 code
= afs_readlink(VTOAFS(vp
), &uio
, get_user_struct()->u_cred
);
1678 afs_osi_Free(pathP
, MAX_OSI_PATH
+ 1);
1681 len
= MAX_OSI_PATH
+ 1 - uio
.uio_resid
;
1684 /* are we linked to ourname or ./ourname? ELOOP */
1686 if ((strcmp(pathP
, ppathP
) == 0) ||
1687 ((pathP
[0] == '.') &&
1688 (pathP
[1] == '/') &&
1689 (strcmp(&(pathP
[2]), ppathP
) == 0))) {
1695 * Find the target of the symbolic link
1697 code
= uafs_LookupName(pathP
, parentVp
, &linkVp
, 1, 0);
1699 afs_osi_Free(pathP
, MAX_OSI_PATH
+ 1);
1703 afs_osi_Free(pathP
, MAX_OSI_PATH
+ 1);
1709 * Lookup a file or directory given its path.
1710 * Call VN_HOLD on the output vnode if successful.
1711 * Returns zero on success, error code on failure.
1713 * Note: Caller must hold the AFS global lock.
1716 uafs_LookupName(char *path
, struct usr_vnode
*parentVp
,
1717 struct usr_vnode
**vpp
, int follow
, int no_eval_mtpt
)
1721 struct usr_vnode
*vp
;
1722 struct usr_vnode
*nextVp
;
1723 struct usr_vnode
*linkVp
;
1724 struct vcache
*nextVc
;
1727 char *nextPathP
= NULL
;
1732 * Absolute paths must start with the AFS mount point.
1734 if (path
[0] != '/') {
1737 path
= uafs_afsPathName(path
);
1745 * Loop through the path looking for the new directory
1747 tmpPath
= afs_osi_Alloc(strlen(path
) + 1);
1748 usr_assert(tmpPath
!= NULL
);
1749 strcpy(tmpPath
, path
);
1752 while (pathP
!= NULL
&& *pathP
!= '\0') {
1753 usr_assert(*pathP
!= '/');
1756 * terminate the current component and skip over slashes
1758 nextPathP
= afs_strchr(pathP
, '/');
1759 if (nextPathP
!= NULL
) {
1760 while (*nextPathP
== '/') {
1761 *(nextPathP
++) = '\0';
1766 * Don't call afs_lookup on non-directories
1768 if (vp
->v_type
!= VDIR
) {
1770 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1774 if (vp
== afs_RootVnode
&& strcmp(pathP
, "..") == 0) {
1776 * The AFS root is its own parent
1778 nextVp
= afs_RootVnode
;
1781 * We need execute permission to search a directory
1783 code
= afs_access(VTOAFS(vp
), VEXEC
, get_user_struct()->u_cred
);
1786 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1791 * lookup the next component in the path, we can release the
1792 * subdirectory since we hold the global lock
1796 if ((nextPathP
!= NULL
&& *nextPathP
!= '\0') || !no_eval_mtpt
)
1797 code
= afs_lookup(VTOAFS(vp
), pathP
, &nextVc
, get_user_struct()->u_cred
, 0);
1800 afs_lookup(VTOAFS(vp
), pathP
, &nextVc
, get_user_struct()->u_cred
,
1803 nextVp
=AFSTOV(nextVc
);
1806 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1812 * Follow symbolic links for parent directories and
1813 * for leaves when the follow flag is set.
1815 if ((nextPathP
!= NULL
&& *nextPathP
!= '\0') || follow
) {
1817 while (nextVp
->v_type
== VLNK
) {
1818 if (++linkCount
> MAX_OSI_LINKS
) {
1821 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1824 code
= uafs_LookupLinkPath(nextVp
, vp
, NULL
, &linkVp
);
1828 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1842 * Special case, nextPathP is non-null if pathname ends in slash
1844 if (nextPathP
!= NULL
&& vp
->v_type
!= VDIR
) {
1846 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1850 afs_osi_Free(tmpPath
, strlen(path
) + 1);
1856 uafs_LookupLink(struct usr_vnode
*vp
, struct usr_vnode
*parentVp
,
1857 struct usr_vnode
**vpp
)
1859 return uafs_LookupLinkPath(vp
, parentVp
, NULL
, vpp
);
1863 * Lookup the parent of a file or directory given its path
1864 * Call VN_HOLD on the output vnode if successful.
1865 * Returns zero on success, error code on failure.
1867 * Note: Caller must hold the AFS global lock.
1870 uafs_LookupParent(char *path
, struct usr_vnode
**vpp
)
1875 struct usr_vnode
*parentP
;
1880 * Absolute path names must start with the AFS mount point.
1883 pathP
= uafs_afsPathName(path
);
1884 if (pathP
== NULL
) {
1890 * Find the length of the parent path
1893 while (len
> 0 && path
[len
- 1] == '/') {
1899 while (len
> 0 && path
[len
- 1] != '/') {
1906 pathP
= afs_osi_Alloc(len
);
1907 usr_assert(pathP
!= NULL
);
1908 memcpy(pathP
, path
, len
- 1);
1909 pathP
[len
- 1] = '\0';
1912 * look up the parent
1914 code
= uafs_LookupName(pathP
, afs_CurrentDir
, &parentP
, 1, 0);
1915 afs_osi_Free(pathP
, len
);
1919 if (parentP
->v_type
!= VDIR
) {
1929 * Return a pointer to the first character in the last component
1933 uafs_LastPath(char *path
)
1938 while (len
> 0 && path
[len
- 1] == '/') {
1941 while (len
> 0 && path
[len
- 1] != '/') {
1951 * Set the working directory.
1954 uafs_chdir(char *path
)
1958 retval
= uafs_chdir_r(path
);
1964 uafs_chdir_r(char *path
)
1969 code
= uafs_LookupName(path
, afs_CurrentDir
, &dirP
, 1, 0);
1974 if (dirP
->v_type
!= VDIR
) {
1979 VN_RELE(afs_CurrentDir
);
1980 afs_CurrentDir
= dirP
;
1985 * Create a directory.
1988 uafs_mkdir(char *path
, int mode
)
1992 retval
= uafs_mkdir_r(path
, mode
);
1998 uafs_mkdir_r(char *path
, int mode
)
2002 struct vnode
*parentP
;
2003 struct vcache
*dirP
;
2004 struct usr_vattr attrs
;
2006 if (uafs_IsRoot(path
)) {
2011 * Look up the parent directory.
2013 nameP
= uafs_LastPath(path
);
2014 if (nameP
!= NULL
) {
2015 code
= uafs_LookupParent(path
, &parentP
);
2021 parentP
= afs_CurrentDir
;
2027 * Make sure the directory has at least one character
2029 if (*nameP
== '\0') {
2036 * Create the directory
2038 usr_vattr_null(&attrs
);
2039 attrs
.va_type
= VREG
;
2040 attrs
.va_mode
= mode
;
2041 attrs
.va_uid
= afs_cr_uid(get_user_struct()->u_cred
);
2042 attrs
.va_gid
= afs_cr_gid(get_user_struct()->u_cred
);
2044 code
= afs_mkdir(VTOAFS(parentP
), nameP
, &attrs
, &dirP
, get_user_struct()->u_cred
);
2050 VN_RELE(AFSTOV(dirP
));
2055 * Return 1 if path is the AFS root, otherwise return 0
2058 uafs_IsRoot(char *path
)
2060 while (*path
== '/' && *(path
+ 1) == '/') {
2063 if (strncmp(path
, afs_mountDir
, afs_mountDirLen
) != 0) {
2066 path
+= afs_mountDirLen
;
2067 while (*path
== '/') {
2070 if (*path
!= '\0') {
2078 * Note: file name may not end in a slash.
2081 uafs_open(char *path
, int flags
, int mode
)
2085 retval
= uafs_open_r(path
, flags
, mode
);
2091 uafs_open_r(char *path
, int flags
, int mode
)
2097 struct usr_vnode
*fileP
;
2098 struct usr_vnode
*dirP
;
2099 struct usr_vattr attrs
;
2104 if (uafs_IsRoot(path
)) {
2105 fileP
= afs_RootVnode
;
2109 * Look up the parent directory.
2111 nameP
= uafs_LastPath(path
);
2112 if (nameP
!= NULL
) {
2113 code
= uafs_LookupParent(path
, &dirP
);
2119 dirP
= afs_CurrentDir
;
2125 * Make sure the filename has at least one character
2127 if (*nameP
== '\0') {
2134 * Get the VNODE for this file
2136 if (flags
& O_CREAT
) {
2137 usr_vattr_null(&attrs
);
2138 attrs
.va_type
= VREG
;
2139 attrs
.va_mode
= mode
;
2140 attrs
.va_uid
= afs_cr_uid(get_user_struct()->u_cred
);
2141 attrs
.va_gid
= afs_cr_gid(get_user_struct()->u_cred
);
2142 if (flags
& O_TRUNC
) {
2148 afs_create(VTOAFS(dirP
), nameP
, &attrs
,
2149 (flags
& O_EXCL
) ? usr_EXCL
: usr_NONEXCL
, mode
,
2150 &vc
, get_user_struct()->u_cred
);
2159 code
= uafs_LookupName(nameP
, dirP
, &fileP
, 1, 0);
2167 * Check whether we have access to this file
2170 if (flags
& (O_RDONLY
| O_RDWR
)) {
2173 if (flags
& (O_WRONLY
| O_RDWR
)) {
2177 fileMode
= VREAD
; /* since O_RDONLY is 0 */
2178 code
= afs_access(VTOAFS(fileP
), fileMode
, get_user_struct()->u_cred
);
2186 * Get the file attributes, all we need is the size
2188 code
= afs_getattr(VTOAFS(fileP
), &attrs
, get_user_struct()->u_cred
);
2198 * Setup the open flags
2201 if (flags
& O_TRUNC
) {
2202 openFlags
|= FTRUNC
;
2204 if (flags
& O_APPEND
) {
2205 openFlags
|= FAPPEND
;
2207 if (flags
& O_SYNC
) {
2210 if (flags
& O_SYNC
) {
2213 if (flags
& (O_RDONLY
| O_RDWR
)) {
2216 if (flags
& (O_WRONLY
| O_RDWR
)) {
2217 openFlags
|= FWRITE
;
2219 if ((openFlags
& (FREAD
| FWRITE
)) == 0) {
2220 /* O_RDONLY is 0, so ... */
2225 * Truncate if necessary
2227 if ((flags
& O_TRUNC
) && (attrs
.va_size
!= 0)) {
2228 usr_vattr_null(&attrs
);
2229 attrs
.va_mask
= ATTR_SIZE
;
2231 code
= afs_setattr(VTOAFS(fileP
), &attrs
, get_user_struct()->u_cred
);
2243 code
= afs_open(&vc
, openFlags
, get_user_struct()->u_cred
);
2251 * Put the vnode pointer into the file table
2253 for (fd
= 0; fd
< MAX_OSI_FILES
; fd
++) {
2254 if (afs_FileTable
[fd
] == NULL
) {
2255 afs_FileTable
[fd
] = fileP
;
2256 afs_FileFlags
[fd
] = openFlags
;
2257 if (flags
& O_APPEND
) {
2258 afs_FileOffsets
[fd
] = attrs
.va_size
;
2260 afs_FileOffsets
[fd
] = 0;
2265 if (fd
== MAX_OSI_FILES
) {
2278 uafs_creat(char *path
, int mode
)
2281 rc
= uafs_open(path
, O_CREAT
| O_WRONLY
| O_TRUNC
, mode
);
2286 uafs_creat_r(char *path
, int mode
)
2289 rc
= uafs_open_r(path
, O_CREAT
| O_WRONLY
| O_TRUNC
, mode
);
2297 uafs_write(int fd
, char *buf
, int len
)
2301 retval
= uafs_pwrite_r(fd
, buf
, len
, afs_FileOffsets
[fd
]);
2307 uafs_pwrite(int fd
, char *buf
, int len
, off_t offset
)
2311 retval
= uafs_pwrite_r(fd
, buf
, len
, offset
);
2317 uafs_pwrite_r(int fd
, char *buf
, int len
, off_t offset
)
2321 struct iovec iov
[1];
2322 struct usr_vnode
*fileP
;
2325 * Make sure this is an open file
2327 fileP
= afs_FileTable
[fd
];
2328 if (fileP
== NULL
) {
2334 * set up the uio buffer
2336 iov
[0].iov_base
= buf
;
2337 iov
[0].iov_len
= len
;
2338 uio
.uio_iov
= &iov
[0];
2340 uio
.uio_offset
= offset
;
2342 uio
.uio_fmode
= FWRITE
;
2343 uio
.uio_resid
= len
;
2349 code
= afs_write(VTOAFS(fileP
), &uio
, afs_FileFlags
[fd
], get_user_struct()->u_cred
, 0);
2355 afs_FileOffsets
[fd
] = uio
.uio_offset
;
2356 return (len
- uio
.uio_resid
);
2363 uafs_read(int fd
, char *buf
, int len
)
2367 retval
= uafs_pread_r(fd
, buf
, len
, afs_FileOffsets
[fd
]);
2373 uafs_pread_nocache(int fd
, char *buf
, int len
, off_t offset
)
2377 retval
= uafs_pread_nocache_r(fd
, buf
, len
, offset
);
2383 uafs_pread_nocache_r(int fd
, char *buf
, int len
, off_t offset
)
2386 struct iovec iov
[1];
2387 struct usr_vnode
*fileP
;
2388 struct nocache_read_request
*bparms
;
2392 * Make sure this is an open file
2394 fileP
= afs_FileTable
[fd
];
2395 if (fileP
== NULL
) {
2400 /* these get freed in PrefetchNoCache, so... */
2401 bparms
= afs_osi_Alloc(sizeof(struct nocache_read_request
));
2403 code
= afs_CreateReq(&bparms
->areq
, get_user_struct()->u_cred
);
2405 afs_DestroyReq(bparms
->areq
);
2406 afs_osi_Free(bparms
, sizeof(struct nocache_read_request
));
2411 bparms
->auio
= &uio
;
2412 bparms
->offset
= offset
;
2413 bparms
->length
= len
;
2416 * set up the uio buffer
2418 iov
[0].iov_base
= buf
;
2419 iov
[0].iov_len
= len
;
2420 uio
.uio_iov
= &iov
[0];
2422 uio
.uio_offset
= offset
;
2424 uio
.uio_fmode
= FREAD
;
2425 uio
.uio_resid
= len
;
2430 code
= afs_PrefetchNoCache(VTOAFS(fileP
), get_user_struct()->u_cred
,
2438 afs_FileOffsets
[fd
] = uio
.uio_offset
;
2439 return (len
- uio
.uio_resid
);
2443 uafs_pread(int fd
, char *buf
, int len
, off_t offset
)
2447 retval
= uafs_pread_r(fd
, buf
, len
, offset
);
2453 uafs_pread_r(int fd
, char *buf
, int len
, off_t offset
)
2457 struct iovec iov
[1];
2458 struct usr_vnode
*fileP
;
2461 * Make sure this is an open file
2463 fileP
= afs_FileTable
[fd
];
2464 if (fileP
== NULL
) {
2470 * set up the uio buffer
2472 iov
[0].iov_base
= buf
;
2473 iov
[0].iov_len
= len
;
2474 uio
.uio_iov
= &iov
[0];
2476 uio
.uio_offset
= offset
;
2478 uio
.uio_fmode
= FREAD
;
2479 uio
.uio_resid
= len
;
2484 code
= afs_read(VTOAFS(fileP
), &uio
, get_user_struct()->u_cred
, 0);
2490 afs_FileOffsets
[fd
] = uio
.uio_offset
;
2491 return (len
- uio
.uio_resid
);
2495 * Copy the attributes of a file into a stat structure.
2497 * NOTE: Caller must hold the global AFS lock.
2500 uafs_GetAttr(struct usr_vnode
*vp
, struct stat
*stats
)
2503 struct usr_vattr attrs
;
2508 * Get the attributes
2510 code
= afs_getattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2516 * Copy the attributes, zero fields that aren't set
2518 memset((void *)stats
, 0, sizeof(struct stat
));
2520 stats
->st_ino
= attrs
.va_nodeid
;
2521 stats
->st_mode
= attrs
.va_mode
;
2522 stats
->st_nlink
= attrs
.va_nlink
;
2523 stats
->st_uid
= attrs
.va_uid
;
2524 stats
->st_gid
= attrs
.va_gid
;
2525 stats
->st_rdev
= attrs
.va_rdev
;
2526 stats
->st_size
= attrs
.va_size
;
2527 stats
->st_atime
= attrs
.va_atime
.tv_sec
;
2528 stats
->st_mtime
= attrs
.va_mtime
.tv_sec
;
2529 stats
->st_ctime
= attrs
.va_ctime
.tv_sec
;
2530 /* preserve dv if possible */
2531 #if defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
2532 stats
->st_atimespec
.tv_nsec
= attrs
.va_atime
.tv_usec
* 1000;
2533 stats
->st_mtimespec
.tv_nsec
= attrs
.va_mtime
.tv_usec
* 1000;
2534 stats
->st_ctimespec
.tv_nsec
= attrs
.va_ctime
.tv_usec
* 1000;
2535 #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
2536 stats
->st_atimensec
= attrs
.va_atime
.tv_usec
* 1000;
2537 stats
->st_mtimensec
= attrs
.va_mtime
.tv_usec
* 1000;
2538 stats
->st_ctimensec
= attrs
.va_ctime
.tv_usec
* 1000;
2540 stats
->st_blksize
= attrs
.va_blocksize
;
2541 stats
->st_blocks
= attrs
.va_blocks
;
2547 * Get the attributes of a file, do follow links
2550 uafs_stat(char *path
, struct stat
*buf
)
2554 retval
= uafs_stat_r(path
, buf
);
2560 uafs_stat_r(char *path
, struct stat
*buf
)
2565 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 1, 0);
2570 code
= uafs_GetAttr(vp
, buf
);
2580 * Get the attributes of a file, don't follow links
2583 uafs_lstat(char *path
, struct stat
*buf
)
2587 retval
= uafs_lstat_r(path
, buf
);
2593 uafs_lstat_r(char *path
, struct stat
*buf
)
2598 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 0, 0);
2603 code
= uafs_GetAttr(vp
, buf
);
2613 * Get the attributes of an open file
2616 uafs_fstat(int fd
, struct stat
*buf
)
2620 retval
= uafs_fstat_r(fd
, buf
);
2626 uafs_fstat_r(int fd
, struct stat
*buf
)
2631 vp
= afs_FileTable
[fd
];
2636 code
= uafs_GetAttr(vp
, buf
);
2645 * change the permissions on a file
2648 uafs_chmod(char *path
, int mode
)
2652 retval
= uafs_chmod_r(path
, mode
);
2658 uafs_chmod_r(char *path
, int mode
)
2662 struct usr_vattr attrs
;
2664 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 1, 0);
2669 usr_vattr_null(&attrs
);
2670 attrs
.va_mask
= ATTR_MODE
;
2671 attrs
.va_mode
= mode
;
2672 code
= afs_setattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2682 * change the permissions on an open file
2685 uafs_fchmod(int fd
, int mode
)
2689 retval
= uafs_fchmod_r(fd
, mode
);
2695 uafs_fchmod_r(int fd
, int mode
)
2699 struct usr_vattr attrs
;
2701 vp
= afs_FileTable
[fd
];
2706 usr_vattr_null(&attrs
);
2707 attrs
.va_mask
= ATTR_MODE
;
2708 attrs
.va_mode
= mode
;
2709 code
= afs_setattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2721 uafs_truncate(char *path
, int length
)
2725 retval
= uafs_truncate_r(path
, length
);
2731 uafs_truncate_r(char *path
, int length
)
2735 struct usr_vattr attrs
;
2737 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 1, 0);
2742 usr_vattr_null(&attrs
);
2743 attrs
.va_mask
= ATTR_SIZE
;
2744 attrs
.va_size
= length
;
2745 code
= afs_setattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2755 * truncate an open file
2758 uafs_ftruncate(int fd
, int length
)
2762 retval
= uafs_ftruncate_r(fd
, length
);
2768 uafs_ftruncate_r(int fd
, int length
)
2772 struct usr_vattr attrs
;
2774 vp
= afs_FileTable
[fd
];
2779 usr_vattr_null(&attrs
);
2780 attrs
.va_mask
= ATTR_SIZE
;
2781 attrs
.va_size
= length
;
2782 code
= afs_setattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2791 * set the read/write file pointer of an open file
2794 uafs_lseek(int fd
, int offset
, int whence
)
2798 retval
= uafs_lseek_r(fd
, offset
, whence
);
2804 uafs_lseek_r(int fd
, int offset
, int whence
)
2808 struct usr_vattr attrs
;
2809 struct usr_vnode
*vp
;
2811 vp
= afs_FileTable
[fd
];
2818 newpos
= afs_FileOffsets
[fd
] + offset
;
2824 code
= afs_getattr(VTOAFS(vp
), &attrs
, get_user_struct()->u_cred
);
2829 newpos
= attrs
.va_size
+ offset
;
2839 afs_FileOffsets
[fd
] = newpos
;
2851 retval
= uafs_fsync_r(fd
);
2857 uafs_fsync_r(int fd
)
2860 struct usr_vnode
*fileP
;
2863 fileP
= afs_FileTable
[fd
];
2864 if (fileP
== NULL
) {
2869 code
= afs_fsync(VTOAFS(fileP
), get_user_struct()->u_cred
);
2886 retval
= uafs_close_r(fd
);
2892 uafs_close_r(int fd
)
2895 struct usr_vnode
*fileP
;
2897 fileP
= afs_FileTable
[fd
];
2898 if (fileP
== NULL
) {
2902 afs_FileTable
[fd
] = NULL
;
2904 code
= afs_close(VTOAFS(fileP
), afs_FileFlags
[fd
], get_user_struct()->u_cred
);
2915 * Create a hard link from the source to the target
2916 * Note: file names may not end in a slash.
2919 uafs_link(char *existing
, char *new)
2923 retval
= uafs_link_r(existing
, new);
2929 uafs_link_r(char *existing
, char *new)
2932 struct usr_vnode
*existP
;
2933 struct usr_vnode
*dirP
;
2936 if (uafs_IsRoot(new)) {
2941 * Look up the existing node.
2943 code
= uafs_LookupName(existing
, afs_CurrentDir
, &existP
, 1, 0);
2950 * Look up the parent directory.
2952 nameP
= uafs_LastPath(new);
2953 if (nameP
!= NULL
) {
2954 code
= uafs_LookupParent(new, &dirP
);
2961 dirP
= afs_CurrentDir
;
2967 * Make sure the filename has at least one character
2969 if (*nameP
== '\0') {
2979 code
= afs_link(VTOAFS(existP
), VTOAFS(dirP
), nameP
, get_user_struct()->u_cred
);
2990 * Create a symbolic link from the source to the target
2991 * Note: file names may not end in a slash.
2994 uafs_symlink(char *target
, char *source
)
2998 retval
= uafs_symlink_r(target
, source
);
3004 uafs_symlink_r(char *target
, char *source
)
3007 struct usr_vnode
*dirP
;
3008 struct usr_vattr attrs
;
3011 if (uafs_IsRoot(source
)) {
3016 * Look up the parent directory.
3018 nameP
= uafs_LastPath(source
);
3019 if (nameP
!= NULL
) {
3020 code
= uafs_LookupParent(source
, &dirP
);
3026 dirP
= afs_CurrentDir
;
3032 * Make sure the filename has at least one character
3034 if (*nameP
== '\0') {
3043 usr_vattr_null(&attrs
);
3044 attrs
.va_type
= VLNK
;
3045 attrs
.va_mode
= 0777;
3046 attrs
.va_uid
= afs_cr_uid(get_user_struct()->u_cred
);
3047 attrs
.va_gid
= afs_cr_gid(get_user_struct()->u_cred
);
3048 code
= afs_symlink(VTOAFS(dirP
), nameP
, &attrs
, target
, NULL
,
3049 get_user_struct()->u_cred
);
3059 * Read a symbolic link into the buffer
3062 uafs_readlink(char *path
, char *buf
, int len
)
3066 retval
= uafs_readlink_r(path
, buf
, len
);
3072 uafs_readlink_r(char *path
, char *buf
, int len
)
3075 struct usr_vnode
*vp
;
3077 struct iovec iov
[1];
3079 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 0, 0);
3085 if (vp
->v_type
!= VLNK
) {
3092 * set up the uio buffer
3094 iov
[0].iov_base
= buf
;
3095 iov
[0].iov_len
= len
;
3096 uio
.uio_iov
= &iov
[0];
3100 uio
.uio_fmode
= FREAD
;
3101 uio
.uio_resid
= len
;
3106 code
= afs_readlink(VTOAFS(vp
), &uio
, get_user_struct()->u_cred
);
3114 * return the number of bytes read
3116 return (len
- uio
.uio_resid
);
3120 * Remove a file (or directory)
3121 * Note: file name may not end in a slash.
3124 uafs_unlink(char *path
)
3128 retval
= uafs_unlink_r(path
);
3134 uafs_unlink_r(char *path
)
3137 struct usr_vnode
*dirP
;
3140 if (uafs_IsRoot(path
)) {
3145 * Look up the parent directory.
3147 nameP
= uafs_LastPath(path
);
3148 if (nameP
!= NULL
) {
3149 code
= uafs_LookupParent(path
, &dirP
);
3155 dirP
= afs_CurrentDir
;
3161 * Make sure the filename has at least one character
3163 if (*nameP
== '\0') {
3172 code
= afs_remove(VTOAFS(dirP
), nameP
, get_user_struct()->u_cred
);
3183 * Rename a file (or directory)
3186 uafs_rename(char *old
, char *new)
3190 retval
= uafs_rename_r(old
, new);
3196 uafs_rename_r(char *old
, char *new)
3201 struct usr_vnode
*odirP
;
3202 struct usr_vnode
*ndirP
;
3204 if (uafs_IsRoot(new)) {
3209 * Look up the parent directories.
3211 onameP
= uafs_LastPath(old
);
3212 if (onameP
!= NULL
) {
3213 code
= uafs_LookupParent(old
, &odirP
);
3219 odirP
= afs_CurrentDir
;
3223 nnameP
= uafs_LastPath(new);
3224 if (nnameP
!= NULL
) {
3225 code
= uafs_LookupParent(new, &ndirP
);
3231 ndirP
= afs_CurrentDir
;
3237 * Make sure the filename has at least one character
3239 if (*onameP
== '\0' || *nnameP
== '\0') {
3249 code
= afs_rename(VTOAFS(odirP
), onameP
, VTOAFS(ndirP
), nnameP
, get_user_struct()->u_cred
);
3261 * Remove a or directory
3262 * Note: file name may not end in a slash.
3265 uafs_rmdir(char *path
)
3269 retval
= uafs_rmdir_r(path
);
3275 uafs_rmdir_r(char *path
)
3278 struct usr_vnode
*dirP
;
3281 if (uafs_IsRoot(path
)) {
3286 * Look up the parent directory.
3288 nameP
= uafs_LastPath(path
);
3289 if (nameP
!= NULL
) {
3290 code
= uafs_LookupParent(path
, &dirP
);
3296 dirP
= afs_CurrentDir
;
3302 * Make sure the directory name has at least one character
3304 if (*nameP
== '\0') {
3311 * Remove the directory
3313 code
= afs_rmdir(VTOAFS(dirP
), nameP
, get_user_struct()->u_cred
);
3324 * Flush a file from the AFS cache
3327 uafs_FlushFile(char *path
)
3330 struct afs_ioctl iob
;
3338 call_syscall(AFSCALL_PIOCTL
, (long)path
, _VICEIOCTL(6), (long)&iob
, 0,
3349 uafs_FlushFile_r(char *path
)
3353 retval
= uafs_FlushFile(path
);
3362 uafs_opendir(char *path
)
3366 retval
= uafs_opendir_r(path
);
3372 uafs_opendir_r(char *path
)
3375 struct usr_vnode
*fileP
;
3379 * Open the directory for reading
3381 fd
= uafs_open_r(path
, O_RDONLY
, 0);
3386 fileP
= afs_FileTable
[fd
];
3387 if (fileP
== NULL
) {
3391 if (fileP
->v_type
!= VDIR
) {
3398 * Set up the directory structures
3400 dirp
= afs_osi_Alloc(sizeof(usr_DIR
) + USR_DIRSIZE
+
3401 sizeof(struct usr_dirent
));
3402 usr_assert(dirp
!= NULL
);
3403 dirp
->dd_buf
= (char *)(dirp
+ 1);
3413 * Read directory entries into a file system independent format.
3414 * This routine was developed to support AFS cache consistency testing.
3415 * You should use uafs_readdir instead.
3418 uafs_getdents(int fd
, struct min_direct
*buf
, int len
)
3422 retval
= uafs_getdents_r(fd
, buf
, len
);
3428 uafs_getdents_r(int fd
, struct min_direct
*buf
, int len
)
3432 struct usr_vnode
*vp
;
3433 struct iovec iov
[1];
3436 * Make sure this is an open file
3438 vp
= afs_FileTable
[fd
];
3446 * set up the uio buffer
3448 iov
[0].iov_base
= (char *)buf
;
3449 iov
[0].iov_len
= len
;
3450 uio
.uio_iov
= &iov
[0];
3452 uio
.uio_offset
= afs_FileOffsets
[fd
];
3454 uio
.uio_fmode
= FREAD
;
3455 uio
.uio_resid
= len
;
3458 * read the next chunk from the directory
3460 code
= afs_readdir(VTOAFS(vp
), &uio
, get_user_struct()->u_cred
);
3466 afs_FileOffsets
[fd
] = uio
.uio_offset
;
3467 return (len
- uio
.uio_resid
);
3471 * read from a directory (names only)
3474 uafs_readdir(usr_DIR
* dirp
)
3476 struct usr_dirent
*retval
;
3478 retval
= uafs_readdir_r(dirp
);
3484 uafs_readdir_r(usr_DIR
* dirp
)
3489 struct usr_vnode
*vp
;
3490 struct iovec iov
[1];
3491 struct usr_dirent
*direntP
;
3492 struct min_direct
*directP
;
3500 * Make sure this is an open file
3502 vp
= afs_FileTable
[dirp
->dd_fd
];
3509 * If there are no entries in the stream buffer
3510 * then read another chunk
3512 directP
= (struct min_direct
*)(dirp
->dd_buf
+ dirp
->dd_loc
);
3513 if (dirp
->dd_size
== 0 || directP
->d_fileno
== 0) {
3515 * set up the uio buffer
3517 iov
[0].iov_base
= dirp
->dd_buf
;
3518 iov
[0].iov_len
= USR_DIRSIZE
;
3519 uio
.uio_iov
= &iov
[0];
3521 uio
.uio_offset
= afs_FileOffsets
[dirp
->dd_fd
];
3523 uio
.uio_fmode
= FREAD
;
3524 uio
.uio_resid
= USR_DIRSIZE
;
3527 * read the next chunk from the directory
3529 code
= afs_readdir(VTOAFS(vp
), &uio
, get_user_struct()->u_cred
);
3534 afs_FileOffsets
[dirp
->dd_fd
] = uio
.uio_offset
;
3536 dirp
->dd_size
= USR_DIRSIZE
- iov
[0].iov_len
;
3538 directP
= (struct min_direct
*)(dirp
->dd_buf
+ dirp
->dd_loc
);
3542 * Check for end of file
3544 if (dirp
->dd_size
== 0 || directP
->d_fileno
== 0) {
3548 len
= ((sizeof(struct min_direct
) + directP
->d_namlen
+ 4) & (~3));
3549 usr_assert(len
<= dirp
->dd_size
);
3552 * Copy the next entry into the usr_dirent structure and advance
3554 direntP
= (struct usr_dirent
*)(dirp
->dd_buf
+ USR_DIRSIZE
);
3555 direntP
->d_ino
= directP
->d_fileno
;
3556 direntP
->d_off
= direntP
->d_reclen
;
3558 sizeof(struct usr_dirent
) - MAXNAMLEN
+ directP
->d_namlen
+ 1;
3559 memcpy(&direntP
->d_name
[0], (void *)(directP
+ 1), directP
->d_namlen
);
3560 direntP
->d_name
[directP
->d_namlen
] = '\0';
3561 dirp
->dd_loc
+= len
;
3562 dirp
->dd_size
-= len
;
3571 uafs_closedir(usr_DIR
* dirp
)
3575 retval
= uafs_closedir_r(dirp
);
3581 uafs_closedir_r(usr_DIR
* dirp
)
3592 afs_osi_Free((char *)dirp
,
3593 sizeof(usr_DIR
) + USR_DIRSIZE
+ sizeof(struct usr_dirent
));
3594 rc
= uafs_close_r(fd
);
3599 * Destroy AFS credentials from the kernel cache
3606 usr_mutex_lock(&osi_authenticate_lock
);
3607 code
= ktc_ForgetAllTokens();
3608 usr_mutex_unlock(&osi_authenticate_lock
);
3617 retval
= uafs_unlog();
3623 * Strip the AFS mount point from a pathname string. Return
3624 * NULL if the path is a relative pathname or if the path
3625 * doesn't start with the AFS mount point string.
3628 uafs_afsPathName(char *path
)
3637 for (i
= 1, p
= path
+ 1; *p
!= '\0'; p
++) {
3638 /* Ignore duplicate slashes */
3639 if (*p
== '/' && lastchar
== '/')
3641 /* Is this a subdirectory of the AFS mount point? */
3642 if (afs_mountDir
[i
] == '\0' && *p
== '/') {
3643 /* strip leading slashes */
3644 while (*(++p
) == '/');
3647 /* Reject paths that are not within AFS */
3648 if (*p
!= afs_mountDir
[i
])
3653 /* Is this the AFS mount point? */
3654 if (afs_mountDir
[i
] == '\0') {
3655 usr_assert(*p
== '\0');
3662 * uafs_getcellstatus
3663 * get the cell status
3666 uafs_getcellstatus(char *cell
, afs_int32
* status
)
3669 struct afs_ioctl iob
;
3672 iob
.in_size
= strlen(cell
) + 1;
3676 rc
= call_syscall(AFSCALL_PIOCTL
, /*path */ 0, _VICEIOCTL(35),
3684 *status
= (intptr_t)iob
.out
;
3690 * Get quota of volume associated with path
3693 uafs_getvolquota(char *path
, afs_int32
* BlocksInUse
, afs_int32
* MaxQuota
)
3696 struct afs_ioctl iob
;
3697 VolumeStatus status
;
3701 iob
.out
= (char *)&status
;
3702 iob
.out_size
= sizeof status
;
3704 rc
= call_syscall(AFSCALL_PIOCTL
, (long)path
, _VICEIOCTL(4), (long)&iob
,
3712 *BlocksInUse
= status
.BlocksInUse
;
3713 *MaxQuota
= status
.MaxQuota
;
3719 * Set quota of volume associated with path
3722 uafs_setvolquota(char *path
, afs_int32 MaxQuota
)
3725 struct afs_ioctl iob
;
3726 VolumeStatus status
= { 0 };
3728 iob
.in
= (char *)&status
;
3729 iob
.in_size
= sizeof status
;
3733 status
.MaxQuota
= MaxQuota
;
3734 status
.MinQuota
= -1;
3736 rc
= call_syscall(AFSCALL_PIOCTL
, (long)path
, _VICEIOCTL(5), (long)&iob
,
3748 * uafs_statmountpoint
3749 * Determine whether a dir. is a mount point or not
3750 * return 1 if mount point, 0 if not
3753 uafs_statmountpoint(char *path
)
3758 retval
= uafs_statmountpoint_r(path
);
3764 uafs_statmountpoint_r(char *path
)
3771 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 0, 1);
3786 * Get a list of rights for the current user on path.
3789 uafs_access(char *path
, int flags
)
3806 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 1, 0);
3813 code
= afs_access(VTOAFS(vp
), fileMode
, get_user_struct()->u_cred
);
3820 return code
? -1 : 0;
3825 * Get a list of rights for the current user on path.
3828 uafs_getRights(char *path
)
3835 code
= uafs_LookupName(path
, afs_CurrentDir
, &vp
, 1, 0);
3843 PRSFS_READ
| PRSFS_WRITE
| PRSFS_INSERT
| PRSFS_LOOKUP
| PRSFS_DELETE
3844 | PRSFS_LOCK
| PRSFS_ADMINISTER
;
3846 afs_rights
= afs_getRights(VTOAFS(vp
), afs_rights
, get_user_struct()->u_cred
);
3851 #endif /* UKERNEL */