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/kauth.h"
30 #include "afs/kautils.h"
31 #include "afs/afsutil.h"
32 #include "afs/afs_bypasscache.h"
33 #include "rx/rx_globals.h"
34 #include "afsd/afsd.h"
40 #ifndef AFS_CACHE_VNODE_PATH
41 #error You must compile UKERNEL code with -DAFS_CACHE_VNODE_PATH
44 #define CACHEINFOFILE "cacheinfo"
45 #define AFSLOGFILE "AFSLog"
46 #define DCACHEFILE "CacheItems"
47 #define VOLINFOFILE "VolumeItems"
48 #define CELLINFOFILE "CellItems"
52 #define MIN(A,B) ((A)<(B)?(A):(B))
55 #define MAX(A,B) ((A)>(B)?(A):(B))
58 extern int cacheDiskType;
60 char afs_LclCellName[64];
62 static struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
63 static int afs_FileFlags[MAX_OSI_FILES];
64 static off_t afs_FileOffsets[MAX_OSI_FILES];
66 #define MAX_CACHE_LOOPS 4
68 static struct usr_vfs afs_RootVfs;
69 static struct usr_vnode *afs_RootVnode = NULL;
70 static struct usr_vnode *afs_CurrentDir = NULL;
72 static char afs_mountDir[1024]; /* AFS mount point */
73 static int afs_mountDirLen; /* strlen of AFS mount point */
75 struct afsconf_dir *afs_cdir; /* config dir */
77 int afs_bufferpages = 100;
79 static usr_key_t afs_global_u_key;
81 static struct usr_proc *afs_global_procp = NULL;
82 static struct usr_ucred *afs_global_ucredp = NULL;
84 struct usr_ucred afs_osi_cred, *afs_osi_credp;
85 usr_mutex_t afs_global_lock;
86 usr_thread_t afs_global_owner;
87 usr_mutex_t rx_global_lock;
88 usr_thread_t rx_global_owner;
90 static usr_mutex_t osi_dummy_lock;
91 static usr_mutex_t osi_waitq_lock;
92 static usr_mutex_t osi_authenticate_lock;
94 afs_lock_t osi_flplock;
95 afs_lock_t osi_fsplock;
97 #ifndef NETSCAPE_NSAPI
100 * Mutex and condition variable used to implement sleep
102 pthread_mutex_t usr_sleep_mutex;
103 pthread_cond_t usr_sleep_cond;
105 #endif /* !NETSCAPE_NSAPI */
107 int call_syscall(long, long, long, long, long, long);
108 int fork_syscall(long, long, long, long, long, long);
112 * Hash table mapping addresses onto wait structures for
113 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
115 typedef struct osi_wait {
119 struct osi_wait *next;
120 struct osi_wait *prev;
122 struct osi_wait *timedNext;
123 struct osi_wait *timedPrev;
127 * Head of the linked list of available waitq structures.
129 static osi_wait_t *osi_waithash_avail;
132 * List of timed waits, NSAPI does not provide a cond_timed
133 * wait, so we need to keep track of the timed waits ourselves and
134 * periodically check for expirations
136 static osi_wait_t *osi_timedwait_head;
137 static osi_wait_t *osi_timedwait_tail;
142 } osi_waithash_table[OSI_WAITHASH_SIZE];
145 * Never call afs_brelse
148 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
155 * I am not sure what to do with these, they assert for now
158 iodone(struct usr_buf *bp)
172 * Every user is a super user
175 afs_osi_suser(void *credp)
181 afs_suser(void *credp)
187 * These are no-ops in user space
191 afs_osi_SetTime(osi_timeval_t * atv)
197 * xflock should never fall through, the only files we know
198 * about are AFS files
208 * ioctl should never fall through, the only files we know
209 * about are AFS files
219 * We do not support the inode related system calls
222 afs_syscall_icreate(long a, long b, long c, long d, long e, long f)
229 afs_syscall_iincdec(int dev, int inode, int inode_p1, int amount)
236 afs_syscall_iopen(int dev, int inode, int usrmod)
243 afs_syscall_ireadwrite(void)
250 * these routines are referenced in the vfsops structure, but
251 * should never get called
282 * uiomove copies data between kernel buffers and uio buffers
285 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
292 nio = uio->uio_iovcnt;
302 while (nio > 0 && n > 0) {
303 len = MIN(n, iovp->iov_len);
304 if (rw == UIO_READ) {
305 memcpy(iovp->iov_base, ptr, len);
307 memcpy(ptr, iovp->iov_base, len);
311 uio->uio_resid -= len;
312 uio->uio_offset += len;
313 iovp->iov_base = (char *)(iovp->iov_base) + len;
314 iovp->iov_len -= len;
325 * routines to manage user credentials
328 usr_crcopy(struct usr_ucred *credp)
330 struct usr_ucred *newcredp;
332 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
334 newcredp->cr_ref = 1;
341 struct usr_ucred *newcredp;
343 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
344 newcredp->cr_ref = 1;
349 usr_crfree(struct usr_ucred *credp)
352 if (credp->cr_ref == 0) {
353 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
359 usr_crhold(struct usr_ucred *credp)
366 usr_vattr_null(struct usr_vattr *vap)
371 n = sizeof(struct usr_vattr);
379 * Initialize the thread specific data used to simulate the
380 * kernel environment for each thread. The user structure
381 * is stored in the thread specific data.
384 uafs_InitThread(void)
387 struct usr_user *uptr;
390 * initialize the thread specific user structure. Use malloc to
391 * allocate the data block, so pthread_finish can free the buffer
392 * when this thread terminates.
395 (struct usr_user *)malloc(sizeof(struct usr_user) +
396 sizeof(struct usr_ucred));
397 usr_assert(uptr != NULL);
400 uptr->u_procp = afs_global_procp;
401 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
402 *uptr->u_cred = *afs_global_ucredp;
403 st = usr_setspecific(afs_global_u_key, (void *)uptr);
408 * routine to get the user structure from the thread specific data.
409 * this routine is used to implement the global 'u' structure. Initializes
410 * the thread if needed.
413 get_user_struct(void)
415 struct usr_user *uptr;
417 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
421 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
423 usr_assert(uptr != NULL);
429 * Hash an address for the waithash table
431 #define WAITHASH(X) \
432 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
438 afs_osi_Sleep(void *x)
442 int glockOwner = ISAFS_GLOCK();
444 usr_mutex_lock(&osi_waitq_lock);
449 if (osi_waithash_avail == NULL) {
450 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
451 usr_cond_init(&waitp->cond);
453 waitp = osi_waithash_avail;
454 osi_waithash_avail = osi_waithash_avail->next;
458 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
459 osi_waithash_table[index].tail, next, prev);
460 waitp->expiration = 0;
461 waitp->timedNext = NULL;
462 waitp->timedPrev = NULL;
463 while (waitp->flag == 0) {
464 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
466 DLL_DELETE(waitp, osi_waithash_table[index].head,
467 osi_waithash_table[index].tail, next, prev);
468 waitp->next = osi_waithash_avail;
469 osi_waithash_avail = waitp;
470 usr_mutex_unlock(&osi_waitq_lock);
477 afs_osi_SleepSig(void *x)
484 afs_osi_Wakeup(void *x)
490 usr_mutex_lock(&osi_waitq_lock);
491 waitp = osi_waithash_table[index].head;
493 if (waitp->addr == x && waitp->flag == 0) {
495 usr_cond_signal(&waitp->cond);
499 usr_mutex_unlock(&osi_waitq_lock);
504 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
506 return afs_osi_Wait(ams, event, aintok);
510 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
516 int glockOwner = ISAFS_GLOCK();
518 tv.tv_sec = msec / 1000;
519 tv.tv_nsec = (msec % 1000) * 1000000;
520 if (handle == NULL) {
524 usr_thread_sleep(&tv);
530 usr_mutex_lock(&osi_waitq_lock);
534 index = WAITHASH((caddr_t) handle);
535 if (osi_waithash_avail == NULL) {
536 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
537 usr_cond_init(&waitp->cond);
539 waitp = osi_waithash_avail;
540 osi_waithash_avail = osi_waithash_avail->next;
542 waitp->addr = (caddr_t) handle;
544 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
545 osi_waithash_table[index].tail, next, prev);
546 tv.tv_sec += time(NULL);
547 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
548 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
549 timedNext, timedPrev);
550 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
556 DLL_DELETE(waitp, osi_waithash_table[index].head,
557 osi_waithash_table[index].tail, next, prev);
558 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
560 waitp->next = osi_waithash_avail;
561 osi_waithash_avail = waitp;
562 usr_mutex_unlock(&osi_waitq_lock);
571 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
573 afs_osi_Wakeup(handle);
577 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
578 * to explicitly signal cond_timed_waits when their timers expire
581 afs_osi_CheckTimedWaits(void)
586 curTime = time(NULL);
587 usr_mutex_lock(&osi_waitq_lock);
588 waitp = osi_timedwait_head;
589 while (waitp != NULL) {
590 usr_assert(waitp->expiration != 0);
591 if (waitp->expiration <= curTime) {
593 usr_cond_signal(&waitp->cond);
595 waitp = waitp->timedNext;
597 usr_mutex_unlock(&osi_waitq_lock);
602 * 'dummy' vnode, for non-AFS files. We don't actually need most vnode
603 * information for non-AFS files, so point all of them towards this vnode
606 static struct usr_vnode dummy_vnode = {
617 * Allocate a slot in the file table if there is not one there already,
618 * copy in the file name and kludge up the vnode and inode structures
621 lookupname(char *fnamep, int segflg, int followlink,
622 struct usr_vnode **compvpp)
627 * Assume relative pathnames refer to files in AFS
629 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
631 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
636 /* For non-afs files, nobody really looks at the meaningful values in the
637 * returned vnode, so we can return a 'fake' one. The vnode can be held,
638 * released, etc. and some callers check for a NULL vnode anyway, so we
639 * to return something. */
641 usr_mutex_lock(&osi_dummy_lock);
642 VN_HOLD(&dummy_vnode);
643 usr_mutex_unlock(&osi_dummy_lock);
645 *compvpp = &dummy_vnode;
651 * open a file given its i-node number
654 osi_UFSOpen(afs_dcache_id_t *ino)
663 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
664 usr_assert(fp != NULL);
666 usr_assert(ino->ufs);
668 fp->fd = open(ino->ufs, O_RDWR | O_CREAT, 0);
670 get_user_struct()->u_error = errno;
671 afs_osi_Free((char *)fp, sizeof(struct osi_file));
675 rc = fstat(fp->fd, &st);
677 get_user_struct()->u_error = errno;
678 afs_osi_Free((void *)fp, sizeof(struct osi_file));
682 fp->size = st.st_size;
684 fp->vnode = (struct usr_vnode *)fp;
691 osi_UFSClose(struct osi_file *fp)
700 get_user_struct()->u_error = errno;
701 afs_osi_Free((void *)fp, sizeof(struct osi_file));
705 afs_osi_Free((void *)fp, sizeof(struct osi_file));
711 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
718 rc = ftruncate(fp->fd, len);
720 get_user_struct()->u_error = errno;
730 afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
739 rc = lseek(fp->fd, offset, SEEK_SET);
741 rc = lseek(fp->fd, fp->offset, SEEK_SET);
744 get_user_struct()->u_error = errno;
749 ret = read(fp->fd, buf, len);
751 get_user_struct()->u_error = errno;
756 rc = fstat(fp->fd, &st);
758 get_user_struct()->u_error = errno;
762 fp->size = st.st_size;
768 afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
777 rc = lseek(fp->fd, offset, SEEK_SET);
779 rc = lseek(fp->fd, fp->offset, SEEK_SET);
782 get_user_struct()->u_error = errno;
787 ret = write(fp->fd, buf, len);
789 get_user_struct()->u_error = errno;
794 rc = fstat(fp->fd, &st);
796 get_user_struct()->u_error = errno;
800 fp->size = st.st_size;
806 afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
812 rc = fstat(fp->fd, &st);
814 get_user_struct()->u_error = errno;
818 stp->size = st.st_size;
819 stp->mtime = st.st_mtime;
820 stp->atime = st.st_atime;
829 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
830 int flags, struct usr_ucred *credP)
833 struct osi_file *fp = (struct osi_file *)vnodeP;
836 * We don't support readv/writev.
838 usr_assert(uioP->uio_iovcnt == 1);
839 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
841 if (rw == UIO_WRITE) {
842 usr_assert(uioP->uio_fmode == FWRITE);
843 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
844 uioP->uio_iov[0].iov_len);
846 usr_assert(uioP->uio_fmode == FREAD);
847 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
848 uioP->uio_iov[0].iov_len);
851 return get_user_struct()->u_error;
854 uioP->uio_resid -= rc;
855 uioP->uio_offset += rc;
856 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
857 uioP->uio_iov[0].iov_len -= rc;
862 afs_osi_Alloc(size_t size)
868 afs_osi_Free(void *ptr, size_t size)
874 afs_osi_FreeStr(char *ptr)
880 osi_AllocLargeSpace(size_t size)
882 AFS_STATCNT(osi_AllocLargeSpace);
883 return afs_osi_Alloc(size);
887 osi_FreeLargeSpace(void *ptr)
889 AFS_STATCNT(osi_FreeLargeSpace);
890 afs_osi_Free(ptr, 0);
894 osi_AllocSmallSpace(size_t size)
896 AFS_STATCNT(osi_AllocSmallSpace);
897 return afs_osi_Alloc(size);
901 osi_FreeSmallSpace(void *ptr)
903 AFS_STATCNT(osi_FreeSmallSpace);
904 afs_osi_Free(ptr, 0);
910 AFS_STATCNT(shutdown_osi);
915 shutdown_osinet(void)
917 AFS_STATCNT(shutdown_osinet);
922 shutdown_osifile(void)
924 AFS_STATCNT(shutdown_osifile);
929 afs_nfsclient_init(void)
934 shutdown_nfsclnt(void)
940 afs_osi_Invisible(void)
946 afs_osi_Visible(void)
952 osi_GetTime(struct timeval *tv)
954 gettimeofday(tv, NULL);
959 osi_SetTime(struct timeval *tv)
965 osi_Active(struct vcache *avc)
967 AFS_STATCNT(osi_Active);
974 afs_osi_MapStrategy(int (*aproc) (struct usr_buf *), struct usr_buf *bp)
976 afs_int32 returnCode;
977 returnCode = (*aproc) (bp);
982 osi_FlushPages(struct vcache *avc, afs_ucred_t *credp)
984 ObtainSharedLock(&avc->lock, 555);
985 if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
986 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
987 ReleaseSharedLock(&avc->lock);
990 UpgradeSToWLock(&avc->lock, 565);
991 hset(avc->mapDV, avc->f.m.DataVersion);
992 ReleaseWriteLock(&avc->lock);
997 osi_FlushText_really(struct vcache *vp)
999 if (hcmp(vp->f.m.DataVersion, vp->flushDV) > 0) {
1000 hset(vp->flushDV, vp->f.m.DataVersion);
1006 osi_SyncVM(struct vcache *avc)
1012 osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1024 * Use the thread specific data to implement the user structure
1026 usr_keycreate(&afs_global_u_key, free);
1029 * Initialize the global ucred structure
1031 afs_global_ucredp = (struct usr_ucred *)
1032 afs_osi_Alloc(sizeof(struct usr_ucred));
1033 usr_assert(afs_global_ucredp != NULL);
1034 afs_global_ucredp->cr_ref = 1;
1035 afs_set_cr_uid(afs_global_ucredp, geteuid());
1036 afs_set_cr_gid(afs_global_ucredp, getegid());
1037 afs_set_cr_ruid(afs_global_ucredp, getuid());
1038 afs_set_cr_rgid(afs_global_ucredp, getgid());
1039 afs_global_ucredp->cr_suid = afs_cr_ruid(afs_global_ucredp);
1040 afs_global_ucredp->cr_sgid = afs_cr_rgid(afs_global_ucredp);
1041 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1042 usr_assert(st >= 0);
1043 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1044 for (i = st; i < NGROUPS; i++) {
1045 afs_global_ucredp->cr_groups[i] = NOGROUP;
1049 * Initialize the global process structure
1051 afs_global_procp = (struct usr_proc *)
1052 afs_osi_Alloc(sizeof(struct usr_proc));
1053 usr_assert(afs_global_procp != NULL);
1054 afs_global_procp->p_pid = osi_getpid();
1055 afs_global_procp->p_ppid = (pid_t) 1;
1056 afs_global_procp->p_ucred = afs_global_ucredp;
1058 #ifndef NETSCAPE_NSAPI
1060 * Initialize the mutex and condition variable used to implement
1063 pthread_mutex_init(&usr_sleep_mutex, NULL);
1064 pthread_cond_init(&usr_sleep_cond, NULL);
1065 #endif /* !NETSCAPE_NSAPI */
1068 * Initialize the hash table used for sleep/wakeup
1070 for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
1071 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1073 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1074 osi_waithash_avail = NULL;
1077 * Initialize the AFS file table
1079 for (i = 0; i < MAX_OSI_FILES; i++) {
1080 afs_FileTable[i] = NULL;
1084 * Initialize the global locks
1086 usr_mutex_init(&afs_global_lock);
1087 usr_mutex_init(&rx_global_lock);
1088 usr_mutex_init(&osi_dummy_lock);
1089 usr_mutex_init(&osi_waitq_lock);
1090 usr_mutex_init(&osi_authenticate_lock);
1093 * Initialize the AFS OSI credentials
1095 afs_osi_cred = *afs_global_ucredp;
1096 afs_osi_credp = &afs_osi_cred;
1098 init_et_to_sys_error();
1102 * Set the UDP port number RX uses for UDP datagrams
1105 uafs_SetRxPort(int port)
1107 usr_assert(usr_rx_port == 0);
1112 * uafs_Init is for backwards compatibility only! Do not use it; use
1113 * uafs_Setup, uafs_ParseArgs, and uafs_Run instead.
1116 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1117 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1118 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1119 int chunkSizeParam, int closeSynchParam, int debugParam,
1120 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1130 code = uafs_Setup(mountDirParam);
1131 usr_assert(code == 0);
1134 if (mountDirParam) {
1135 argv[argc++] = "-mountdir";
1136 argv[argc++] = mountDirParam;
1139 argv[argc++] = "-confdir";
1140 argv[argc++] = confDirParam;
1142 if (cacheBaseDirParam) {
1143 argv[argc++] = "-cachedir";
1144 argv[argc++] = cacheBaseDirParam;
1146 if (cacheBlocksParam) {
1147 snprintf(buf, sizeof(buf), "%d", cacheBlocksParam);
1149 argv[argc++] = "-blocks";
1150 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1152 if (cacheFilesParam) {
1153 snprintf(buf, sizeof(buf), "%d", cacheFilesParam);
1155 argv[argc++] = "-files";
1156 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1158 if (cacheStatEntriesParam) {
1159 snprintf(buf, sizeof(buf), "%d", cacheStatEntriesParam);
1161 argv[argc++] = "-stat";
1162 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1164 if (dCacheSizeParam) {
1165 snprintf(buf, sizeof(buf), "%d", dCacheSizeParam);
1167 argv[argc++] = "-dcache";
1168 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1170 if (vCacheSizeParam) {
1171 snprintf(buf, sizeof(buf), "%d", vCacheSizeParam);
1173 argv[argc++] = "-volumes";
1174 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1176 if (chunkSizeParam) {
1177 snprintf(buf, sizeof(buf), "%d", chunkSizeParam);
1179 argv[argc++] = "-chunksize";
1180 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1182 if (closeSynchParam) {
1183 argv[argc++] = "-waitclose";
1186 argv[argc++] = "-debug";
1188 if (nDaemonsParam) {
1189 snprintf(buf, sizeof(buf), "%d", nDaemonsParam);
1191 argv[argc++] = "-daemons";
1192 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1194 if (cacheFlagsParam) {
1195 if (cacheFlagsParam & AFSCALL_INIT_MEMCACHE) {
1196 argv[argc++] = "-memcache";
1200 argv[argc++] = "-logfile";
1201 argv[argc++] = logFile;
1206 code = uafs_ParseArgs(argc, argv);
1207 usr_assert(code == 0);
1209 for (i = 0; i < freeargc; i++) {
1214 usr_assert(code == 0);
1218 * Calculate the cacheMountDir used for a specified dir.
1220 * @param[in] dir Desired mount dir
1221 * @param[out] mountdir On success, contains the literal string that should
1222 * be used as the cache mount dir.
1223 * @param[in] size The number of bytes allocated in mountdir
1225 * @post On success, mountdir begins with a slash, and does not contain two
1226 * slashes adjacent to each other
1228 * @return operation status
1230 * @retval ENAMETOOLONG the specified dir is too long to fix in the given
1232 * @retval EINVAL the specified dir does not actually specify any meaningful
1236 calcMountDir(const char *dir, char *mountdir, size_t size)
1243 if (dir && strlen(dir) > size-1) {
1244 return ENAMETOOLONG;
1248 * Initialize the AFS mount point, default is '/afs'.
1249 * Strip duplicate/trailing slashes from mount point string.
1250 * afs_mountDirLen is set to strlen(afs_mountDir).
1255 sprintf(buf, "%s", dir);
1259 for (lastchar = '/', p = &buf[0]; *p != '\0'; p++) {
1260 if (lastchar != '/' || *p != '/') {
1261 mountdir[len++] = lastchar = *p;
1264 if (lastchar == '/' && len > 1)
1266 mountdir[len] = '\0';
1279 * Mount the AFS filesystem
1282 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1283 usr_assert(rc == 0);
1284 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1285 usr_assert(rc == 0);
1289 * initialize the current directory to the AFS root
1291 afs_CurrentDir = afs_RootVnode;
1292 VN_HOLD(afs_CurrentDir);
1298 uafs_setMountDir(const char *dir)
1302 char tmp_mountDir[1024];
1304 rc = calcMountDir(dir, tmp_mountDir, sizeof(tmp_mountDir));
1306 afs_warn("Invalid mount dir specification (error %d): %s\n", rc, dir);
1308 if (strcmp(tmp_mountDir, afs_mountDir) != 0) {
1309 /* mount dir changed */
1310 strcpy(afs_mountDir, tmp_mountDir);
1311 afs_mountDirLen = strlen(afs_mountDir);
1318 uafs_statvfs(struct statvfs *buf)
1324 rc = afs_statvfs(&afs_RootVfs, buf);
1344 if (afs_CurrentDir) {
1345 VN_RELE(afs_CurrentDir);
1347 rc = afs_unmount(&afs_RootVfs);
1348 usr_assert(rc == 0);
1355 * Donate the current thread to the RX server pool.
1358 uafs_RxServerProc(void)
1362 struct rx_call *newcall = NULL;
1364 rxi_MorePackets(2); /* alloc more packets */
1365 threadID = rxi_availProcs++;
1368 sock = OSI_NULLSOCKET;
1369 rxi_ServerProc(threadID, newcall, &sock);
1370 if (sock == OSI_NULLSOCKET) {
1375 rxi_ListenerProc(sock, &threadID, &newcall);
1376 /* assert(threadID != -1); */
1377 /* assert(newcall != NULL); */
1381 struct syscallThreadArgs {
1390 #ifdef NETSCAPE_NSAPI
1392 syscallThread(void *argp)
1393 #else /* NETSCAPE_NSAPI */
1395 syscallThread(void *argp)
1396 #endif /* NETSCAPE_NSAPI */
1399 struct usr_ucred *crp;
1400 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1403 * AFS daemons run authenticated
1405 get_user_struct()->u_viceid = getuid();
1406 crp = get_user_struct()->u_cred;
1407 afs_set_cr_uid(crp, getuid());
1408 afs_set_cr_ruid(crp, getuid());
1409 crp->cr_suid = getuid();
1410 crp->cr_groups[0] = getgid();
1411 crp->cr_ngroups = 1;
1412 for (i = 1; i < NGROUPS; i++) {
1413 crp->cr_groups[i] = NOGROUP;
1416 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1417 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1419 afs_osi_Free(argp, -1);
1424 fork_syscall(long syscall, long afscall, long param1, long param2,
1425 long param3, long param4)
1428 struct syscallThreadArgs *sysArgsP;
1430 sysArgsP = (struct syscallThreadArgs *)
1431 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1432 usr_assert(sysArgsP != NULL);
1433 sysArgsP->syscall = syscall;
1434 sysArgsP->afscall = afscall;
1435 sysArgsP->param1 = param1;
1436 sysArgsP->param2 = param2;
1437 sysArgsP->param3 = param3;
1438 sysArgsP->param4 = param4;
1440 usr_thread_create(&tid, syscallThread, sysArgsP);
1441 usr_thread_detach(tid);
1446 call_syscall(long syscall, long afscall, long param1, long param2,
1447 long param3, long param4)
1459 a.syscall = syscall;
1460 a.afscall = afscall;
1466 get_user_struct()->u_error = 0;
1467 get_user_struct()->u_ap = (char *)&a;
1469 code = Afs_syscall();
1474 uafs_Setup(const char *mount)
1477 static int inited = 0;
1484 rc = calcMountDir(mount, afs_mountDir, sizeof(afs_mountDir));
1488 afs_mountDirLen = strlen(afs_mountDir);
1490 /* initialize global vars and such */
1493 /* initialize cache manager foo */
1500 uafs_ParseArgs(int argc, char **argv)
1502 return afsd_parse(argc, argv);
1514 return afsd_cacheMountDir;
1518 uafs_SetTokens(char *tbuffer, int tlen)
1521 struct afs_ioctl iob;
1526 iob.out = &outbuf[0];
1527 iob.out_size = sizeof(outbuf);
1529 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
1538 uafs_RPCStatsEnableProc(void)
1541 struct afs_ioctl iob;
1544 flag = AFSCALL_RXSTATS_ENABLE;
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_RPCStatsDisableProc(void)
1561 struct afs_ioctl iob;
1564 flag = AFSCALL_RXSTATS_DISABLE;
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_RPCStatsClearProc(void)
1581 struct afs_ioctl iob;
1584 flag = AFSCALL_RXSTATS_CLEAR;
1585 iob.in = (char *)&flag;
1586 iob.in_size = sizeof(afs_int32);
1589 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1598 uafs_RPCStatsEnablePeer(void)
1601 struct afs_ioctl iob;
1604 flag = AFSCALL_RXSTATS_ENABLE;
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_RPCStatsDisablePeer(void)
1621 struct afs_ioctl iob;
1624 flag = AFSCALL_RXSTATS_DISABLE;
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 uafs_RPCStatsClearPeer(void)
1641 struct afs_ioctl iob;
1644 flag = AFSCALL_RXSTATS_CLEAR;
1645 iob.in = (char *)&flag;
1646 iob.in_size = sizeof(afs_int32);
1649 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1658 * Lookup a file or directory given its path.
1659 * Call VN_HOLD on the output vnode if successful.
1660 * Returns zero on success, error code on failure.
1662 * Note: Caller must hold the AFS global lock.
1665 uafs_LookupName(char *path, struct usr_vnode *parentVp,
1666 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
1670 struct usr_vnode *vp;
1671 struct usr_vnode *nextVp;
1672 struct usr_vnode *linkVp;
1673 struct vcache *nextVc;
1676 char *nextPathP = NULL;
1681 * Absolute paths must start with the AFS mount point.
1683 if (path[0] != '/') {
1686 path = uafs_afsPathName(path);
1694 * Loop through the path looking for the new directory
1696 tmpPath = afs_osi_Alloc(strlen(path) + 1);
1697 usr_assert(tmpPath != NULL);
1698 strcpy(tmpPath, path);
1701 while (pathP != NULL && *pathP != '\0') {
1702 usr_assert(*pathP != '/');
1705 * terminate the current component and skip over slashes
1707 nextPathP = afs_strchr(pathP, '/');
1708 if (nextPathP != NULL) {
1709 while (*nextPathP == '/') {
1710 *(nextPathP++) = '\0';
1715 * Don't call afs_lookup on non-directories
1717 if (vp->v_type != VDIR) {
1719 afs_osi_Free(tmpPath, strlen(path) + 1);
1723 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
1725 * The AFS root is its own parent
1727 nextVp = afs_RootVnode;
1730 * We need execute permission to search a directory
1732 code = afs_access(VTOAFS(vp), VEXEC, get_user_struct()->u_cred);
1735 afs_osi_Free(tmpPath, strlen(path) + 1);
1740 * lookup the next component in the path, we can release the
1741 * subdirectory since we hold the global lock
1745 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
1746 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
1749 afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred,
1752 nextVp=AFSTOV(nextVc);
1755 afs_osi_Free(tmpPath, strlen(path) + 1);
1761 * Follow symbolic links for parent directories and
1762 * for leaves when the follow flag is set.
1764 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
1766 while (nextVp->v_type == VLNK) {
1767 if (++linkCount > MAX_OSI_LINKS) {
1770 afs_osi_Free(tmpPath, strlen(path) + 1);
1773 code = uafs_LookupLink(nextVp, vp, &linkVp);
1777 afs_osi_Free(tmpPath, strlen(path) + 1);
1791 * Special case, nextPathP is non-null if pathname ends in slash
1793 if (nextPathP != NULL && vp->v_type != VDIR) {
1795 afs_osi_Free(tmpPath, strlen(path) + 1);
1799 afs_osi_Free(tmpPath, strlen(path) + 1);
1805 * Lookup the target of a symbolic link
1806 * Call VN_HOLD on the output vnode if successful.
1807 * Returns zero on success, error code on failure.
1809 * Note: Caller must hold the AFS global lock.
1812 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
1813 struct usr_vnode **vpp)
1818 struct usr_vnode *linkVp;
1820 struct iovec iov[1];
1824 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
1825 usr_assert(pathP != NULL);
1828 * set up the uio buffer
1830 iov[0].iov_base = pathP;
1831 iov[0].iov_len = MAX_OSI_PATH + 1;
1832 uio.uio_iov = &iov[0];
1836 uio.uio_fmode = FREAD;
1837 uio.uio_resid = MAX_OSI_PATH + 1;
1840 * Read the link data
1842 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
1844 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1847 len = MAX_OSI_PATH + 1 - uio.uio_resid;
1851 * Find the target of the symbolic link
1853 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
1855 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1859 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1865 * Lookup the parent of a file or directory given its path
1866 * Call VN_HOLD on the output vnode if successful.
1867 * Returns zero on success, error code on failure.
1869 * Note: Caller must hold the AFS global lock.
1872 uafs_LookupParent(char *path, struct usr_vnode **vpp)
1877 struct usr_vnode *parentP;
1882 * Absolute path names must start with the AFS mount point.
1885 pathP = uafs_afsPathName(path);
1886 if (pathP == NULL) {
1892 * Find the length of the parent path
1895 while (len > 0 && path[len - 1] == '/') {
1901 while (len > 0 && path[len - 1] != '/') {
1908 pathP = afs_osi_Alloc(len);
1909 usr_assert(pathP != NULL);
1910 memcpy(pathP, path, len - 1);
1911 pathP[len - 1] = '\0';
1914 * look up the parent
1916 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
1917 afs_osi_Free(pathP, len);
1921 if (parentP->v_type != VDIR) {
1931 * Return a pointer to the first character in the last component
1935 uafs_LastPath(char *path)
1940 while (len > 0 && path[len - 1] == '/') {
1943 while (len > 0 && path[len - 1] != '/') {
1953 * Set the working directory.
1956 uafs_chdir(char *path)
1960 retval = uafs_chdir_r(path);
1966 uafs_chdir_r(char *path)
1971 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
1976 if (dirP->v_type != VDIR) {
1981 VN_RELE(afs_CurrentDir);
1982 afs_CurrentDir = dirP;
1987 * Create a directory.
1990 uafs_mkdir(char *path, int mode)
1994 retval = uafs_mkdir_r(path, mode);
2000 uafs_mkdir_r(char *path, int mode)
2004 struct vnode *parentP;
2005 struct vcache *dirP;
2006 struct usr_vattr attrs;
2008 if (uafs_IsRoot(path)) {
2013 * Look up the parent directory.
2015 nameP = uafs_LastPath(path);
2016 if (nameP != NULL) {
2017 code = uafs_LookupParent(path, &parentP);
2023 parentP = afs_CurrentDir;
2029 * Make sure the directory has at least one character
2031 if (*nameP == '\0') {
2038 * Create the directory
2040 usr_vattr_null(&attrs);
2041 attrs.va_type = VREG;
2042 attrs.va_mode = mode;
2043 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2044 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2046 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, get_user_struct()->u_cred);
2052 VN_RELE(AFSTOV(dirP));
2057 * Return 1 if path is the AFS root, otherwise return 0
2060 uafs_IsRoot(char *path)
2062 while (*path == '/' && *(path + 1) == '/') {
2065 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2068 path += afs_mountDirLen;
2069 while (*path == '/') {
2072 if (*path != '\0') {
2080 * Note: file name may not end in a slash.
2083 uafs_open(char *path, int flags, int mode)
2087 retval = uafs_open_r(path, flags, mode);
2093 uafs_open_r(char *path, int flags, int mode)
2099 struct usr_vnode *fileP;
2100 struct usr_vnode *dirP;
2101 struct usr_vattr attrs;
2106 if (uafs_IsRoot(path)) {
2107 fileP = afs_RootVnode;
2111 * Look up the parent directory.
2113 nameP = uafs_LastPath(path);
2114 if (nameP != NULL) {
2115 code = uafs_LookupParent(path, &dirP);
2121 dirP = afs_CurrentDir;
2127 * Make sure the filename has at least one character
2129 if (*nameP == '\0') {
2136 * Get the VNODE for this file
2138 if (flags & O_CREAT) {
2139 usr_vattr_null(&attrs);
2140 attrs.va_type = VREG;
2141 attrs.va_mode = mode;
2142 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2143 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2144 if (flags & O_TRUNC) {
2150 afs_create(VTOAFS(dirP), nameP, &attrs,
2151 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2152 &vc, get_user_struct()->u_cred);
2161 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2169 * Check whether we have access to this file
2172 if (flags & (O_RDONLY | O_RDWR)) {
2175 if (flags & (O_WRONLY | O_RDWR)) {
2179 fileMode = VREAD; /* since O_RDONLY is 0 */
2180 code = afs_access(VTOAFS(fileP), fileMode, get_user_struct()->u_cred);
2188 * Get the file attributes, all we need is the size
2190 code = afs_getattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2200 * Setup the open flags
2203 if (flags & O_TRUNC) {
2204 openFlags |= FTRUNC;
2206 if (flags & O_APPEND) {
2207 openFlags |= FAPPEND;
2209 if (flags & O_SYNC) {
2212 if (flags & O_SYNC) {
2215 if (flags & (O_RDONLY | O_RDWR)) {
2218 if (flags & (O_WRONLY | O_RDWR)) {
2219 openFlags |= FWRITE;
2221 if ((openFlags & (FREAD | FWRITE)) == 0) {
2222 /* O_RDONLY is 0, so ... */
2227 * Truncate if necessary
2229 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2230 usr_vattr_null(&attrs);
2231 attrs.va_mask = ATTR_SIZE;
2233 code = afs_setattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2245 code = afs_open(&vc, openFlags, get_user_struct()->u_cred);
2253 * Put the vnode pointer into the file table
2255 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2256 if (afs_FileTable[fd] == NULL) {
2257 afs_FileTable[fd] = fileP;
2258 afs_FileFlags[fd] = openFlags;
2259 if (flags & O_APPEND) {
2260 afs_FileOffsets[fd] = attrs.va_size;
2262 afs_FileOffsets[fd] = 0;
2267 if (fd == MAX_OSI_FILES) {
2280 uafs_creat(char *path, int mode)
2283 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2288 uafs_creat_r(char *path, int mode)
2291 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2299 uafs_write(int fd, char *buf, int len)
2303 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2309 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2313 retval = uafs_pwrite_r(fd, buf, len, offset);
2319 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2323 struct iovec iov[1];
2324 struct usr_vnode *fileP;
2327 * Make sure this is an open file
2329 fileP = afs_FileTable[fd];
2330 if (fileP == NULL) {
2336 * set up the uio buffer
2338 iov[0].iov_base = buf;
2339 iov[0].iov_len = len;
2340 uio.uio_iov = &iov[0];
2342 uio.uio_offset = offset;
2344 uio.uio_fmode = FWRITE;
2345 uio.uio_resid = len;
2351 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], get_user_struct()->u_cred, 0);
2357 afs_FileOffsets[fd] = uio.uio_offset;
2358 return (len - uio.uio_resid);
2365 uafs_read(int fd, char *buf, int len)
2369 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2375 uafs_pread_nocache(int fd, char *buf, int len, off_t offset)
2379 retval = uafs_pread_nocache_r(fd, buf, len, offset);
2385 uafs_pread_nocache_r(int fd, char *buf, int len, off_t offset)
2388 struct iovec iov[1];
2389 struct usr_vnode *fileP;
2390 struct nocache_read_request *bparms;
2394 * Make sure this is an open file
2396 fileP = afs_FileTable[fd];
2397 if (fileP == NULL) {
2402 /* these get freed in PrefetchNoCache, so... */
2403 bparms = afs_osi_Alloc(sizeof(struct nocache_read_request));
2404 bparms->areq = afs_osi_Alloc(sizeof(struct vrequest));
2406 afs_InitReq(bparms->areq, get_user_struct()->u_cred);
2408 bparms->auio = &uio;
2409 bparms->offset = offset;
2410 bparms->length = len;
2413 * set up the uio buffer
2415 iov[0].iov_base = buf;
2416 iov[0].iov_len = len;
2417 uio.uio_iov = &iov[0];
2419 uio.uio_offset = offset;
2421 uio.uio_fmode = FREAD;
2422 uio.uio_resid = len;
2427 code = afs_PrefetchNoCache(VTOAFS(fileP), get_user_struct()->u_cred,
2435 afs_FileOffsets[fd] = uio.uio_offset;
2436 return (len - uio.uio_resid);
2440 uafs_pread(int fd, char *buf, int len, off_t offset)
2444 retval = uafs_pread_r(fd, buf, len, offset);
2450 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2454 struct iovec iov[1];
2455 struct usr_vnode *fileP;
2458 * Make sure this is an open file
2460 fileP = afs_FileTable[fd];
2461 if (fileP == NULL) {
2467 * set up the uio buffer
2469 iov[0].iov_base = buf;
2470 iov[0].iov_len = len;
2471 uio.uio_iov = &iov[0];
2473 uio.uio_offset = offset;
2475 uio.uio_fmode = FREAD;
2476 uio.uio_resid = len;
2481 code = afs_read(VTOAFS(fileP), &uio, get_user_struct()->u_cred, 0);
2487 afs_FileOffsets[fd] = uio.uio_offset;
2488 return (len - uio.uio_resid);
2492 * Copy the attributes of a file into a stat structure.
2494 * NOTE: Caller must hold the global AFS lock.
2497 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2500 struct usr_vattr attrs;
2505 * Get the attributes
2507 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2513 * Copy the attributes, zero fields that aren't set
2515 memset((void *)stats, 0, sizeof(struct stat));
2517 stats->st_ino = attrs.va_nodeid;
2518 stats->st_mode = attrs.va_mode;
2519 stats->st_nlink = attrs.va_nlink;
2520 stats->st_uid = attrs.va_uid;
2521 stats->st_gid = attrs.va_gid;
2522 stats->st_rdev = attrs.va_rdev;
2523 stats->st_size = attrs.va_size;
2524 stats->st_atime = attrs.va_atime.tv_sec;
2525 stats->st_mtime = attrs.va_mtime.tv_sec;
2526 stats->st_ctime = attrs.va_ctime.tv_sec;
2527 /* preserve dv if possible */
2528 #if defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
2529 stats->st_atimespec.tv_nsec = attrs.va_atime.tv_usec * 1000;
2530 stats->st_mtimespec.tv_nsec = attrs.va_mtime.tv_usec * 1000;
2531 stats->st_ctimespec.tv_nsec = attrs.va_ctime.tv_usec * 1000;
2532 #elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
2533 stats->st_atimensec = attrs.va_atime.tv_usec * 1000;
2534 stats->st_mtimensec = attrs.va_mtime.tv_usec * 1000;
2535 stats->st_ctimensec = attrs.va_ctime.tv_usec * 1000;
2537 stats->st_blksize = attrs.va_blocksize;
2538 stats->st_blocks = attrs.va_blocks;
2544 * Get the attributes of a file, do follow links
2547 uafs_stat(char *path, struct stat *buf)
2551 retval = uafs_stat_r(path, buf);
2557 uafs_stat_r(char *path, struct stat *buf)
2562 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2567 code = uafs_GetAttr(vp, buf);
2577 * Get the attributes of a file, don't follow links
2580 uafs_lstat(char *path, struct stat *buf)
2584 retval = uafs_lstat_r(path, buf);
2590 uafs_lstat_r(char *path, struct stat *buf)
2595 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2600 code = uafs_GetAttr(vp, buf);
2610 * Get the attributes of an open file
2613 uafs_fstat(int fd, struct stat *buf)
2617 retval = uafs_fstat_r(fd, buf);
2623 uafs_fstat_r(int fd, struct stat *buf)
2628 vp = afs_FileTable[fd];
2633 code = uafs_GetAttr(vp, buf);
2642 * change the permissions on a file
2645 uafs_chmod(char *path, int mode)
2649 retval = uafs_chmod_r(path, mode);
2655 uafs_chmod_r(char *path, int mode)
2659 struct usr_vattr attrs;
2661 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2666 usr_vattr_null(&attrs);
2667 attrs.va_mask = ATTR_MODE;
2668 attrs.va_mode = mode;
2669 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2679 * change the permissions on an open file
2682 uafs_fchmod(int fd, int mode)
2686 retval = uafs_fchmod_r(fd, mode);
2692 uafs_fchmod_r(int fd, int mode)
2696 struct usr_vattr attrs;
2698 vp = afs_FileTable[fd];
2703 usr_vattr_null(&attrs);
2704 attrs.va_mask = ATTR_MODE;
2705 attrs.va_mode = mode;
2706 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2718 uafs_truncate(char *path, int length)
2722 retval = uafs_truncate_r(path, length);
2728 uafs_truncate_r(char *path, int length)
2732 struct usr_vattr attrs;
2734 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2739 usr_vattr_null(&attrs);
2740 attrs.va_mask = ATTR_SIZE;
2741 attrs.va_size = length;
2742 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2752 * truncate an open file
2755 uafs_ftruncate(int fd, int length)
2759 retval = uafs_ftruncate_r(fd, length);
2765 uafs_ftruncate_r(int fd, int length)
2769 struct usr_vattr attrs;
2771 vp = afs_FileTable[fd];
2776 usr_vattr_null(&attrs);
2777 attrs.va_mask = ATTR_SIZE;
2778 attrs.va_size = length;
2779 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2788 * set the read/write file pointer of an open file
2791 uafs_lseek(int fd, int offset, int whence)
2795 retval = uafs_lseek_r(fd, offset, whence);
2801 uafs_lseek_r(int fd, int offset, int whence)
2805 struct usr_vattr attrs;
2806 struct usr_vnode *vp;
2808 vp = afs_FileTable[fd];
2815 newpos = afs_FileOffsets[fd] + offset;
2821 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2826 newpos = attrs.va_size + offset;
2836 afs_FileOffsets[fd] = newpos;
2848 retval = uafs_fsync_r(fd);
2854 uafs_fsync_r(int fd)
2857 struct usr_vnode *fileP;
2860 fileP = afs_FileTable[fd];
2861 if (fileP == NULL) {
2866 code = afs_fsync(VTOAFS(fileP), get_user_struct()->u_cred);
2883 retval = uafs_close_r(fd);
2889 uafs_close_r(int fd)
2892 struct usr_vnode *fileP;
2894 fileP = afs_FileTable[fd];
2895 if (fileP == NULL) {
2899 afs_FileTable[fd] = NULL;
2901 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], get_user_struct()->u_cred);
2912 * Create a hard link from the source to the target
2913 * Note: file names may not end in a slash.
2916 uafs_link(char *existing, char *new)
2920 retval = uafs_link_r(existing, new);
2926 uafs_link_r(char *existing, char *new)
2929 struct usr_vnode *existP;
2930 struct usr_vnode *dirP;
2933 if (uafs_IsRoot(new)) {
2938 * Look up the existing node.
2940 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
2947 * Look up the parent directory.
2949 nameP = uafs_LastPath(new);
2950 if (nameP != NULL) {
2951 code = uafs_LookupParent(new, &dirP);
2958 dirP = afs_CurrentDir;
2964 * Make sure the filename has at least one character
2966 if (*nameP == '\0') {
2976 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, get_user_struct()->u_cred);
2987 * Create a symbolic link from the source to the target
2988 * Note: file names may not end in a slash.
2991 uafs_symlink(char *target, char *source)
2995 retval = uafs_symlink_r(target, source);
3001 uafs_symlink_r(char *target, char *source)
3004 struct usr_vnode *dirP;
3005 struct usr_vattr attrs;
3008 if (uafs_IsRoot(source)) {
3013 * Look up the parent directory.
3015 nameP = uafs_LastPath(source);
3016 if (nameP != NULL) {
3017 code = uafs_LookupParent(source, &dirP);
3023 dirP = afs_CurrentDir;
3029 * Make sure the filename has at least one character
3031 if (*nameP == '\0') {
3040 usr_vattr_null(&attrs);
3041 attrs.va_type = VLNK;
3042 attrs.va_mode = 0777;
3043 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
3044 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
3045 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
3055 * Read a symbolic link into the buffer
3058 uafs_readlink(char *path, char *buf, int len)
3062 retval = uafs_readlink_r(path, buf, len);
3068 uafs_readlink_r(char *path, char *buf, int len)
3071 struct usr_vnode *vp;
3073 struct iovec iov[1];
3075 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3081 if (vp->v_type != VLNK) {
3088 * set up the uio buffer
3090 iov[0].iov_base = buf;
3091 iov[0].iov_len = len;
3092 uio.uio_iov = &iov[0];
3096 uio.uio_fmode = FREAD;
3097 uio.uio_resid = len;
3102 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3110 * return the number of bytes read
3112 return (len - uio.uio_resid);
3116 * Remove a file (or directory)
3117 * Note: file name may not end in a slash.
3120 uafs_unlink(char *path)
3124 retval = uafs_unlink_r(path);
3130 uafs_unlink_r(char *path)
3133 struct usr_vnode *dirP;
3136 if (uafs_IsRoot(path)) {
3141 * Look up the parent directory.
3143 nameP = uafs_LastPath(path);
3144 if (nameP != NULL) {
3145 code = uafs_LookupParent(path, &dirP);
3151 dirP = afs_CurrentDir;
3157 * Make sure the filename has at least one character
3159 if (*nameP == '\0') {
3168 code = afs_remove(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3179 * Rename a file (or directory)
3182 uafs_rename(char *old, char *new)
3186 retval = uafs_rename_r(old, new);
3192 uafs_rename_r(char *old, char *new)
3197 struct usr_vnode *odirP;
3198 struct usr_vnode *ndirP;
3200 if (uafs_IsRoot(new)) {
3205 * Look up the parent directories.
3207 onameP = uafs_LastPath(old);
3208 if (onameP != NULL) {
3209 code = uafs_LookupParent(old, &odirP);
3215 odirP = afs_CurrentDir;
3219 nnameP = uafs_LastPath(new);
3220 if (nnameP != NULL) {
3221 code = uafs_LookupParent(new, &ndirP);
3227 ndirP = afs_CurrentDir;
3233 * Make sure the filename has at least one character
3235 if (*onameP == '\0' || *nnameP == '\0') {
3245 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, get_user_struct()->u_cred);
3257 * Remove a or directory
3258 * Note: file name may not end in a slash.
3261 uafs_rmdir(char *path)
3265 retval = uafs_rmdir_r(path);
3271 uafs_rmdir_r(char *path)
3274 struct usr_vnode *dirP;
3277 if (uafs_IsRoot(path)) {
3282 * Look up the parent directory.
3284 nameP = uafs_LastPath(path);
3285 if (nameP != NULL) {
3286 code = uafs_LookupParent(path, &dirP);
3292 dirP = afs_CurrentDir;
3298 * Make sure the directory name has at least one character
3300 if (*nameP == '\0') {
3307 * Remove the directory
3309 code = afs_rmdir(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3320 * Flush a file from the AFS cache
3323 uafs_FlushFile(char *path)
3326 struct afs_ioctl iob;
3334 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3345 uafs_FlushFile_r(char *path)
3349 retval = uafs_FlushFile(path);
3358 uafs_opendir(char *path)
3362 retval = uafs_opendir_r(path);
3368 uafs_opendir_r(char *path)
3371 struct usr_vnode *fileP;
3375 * Open the directory for reading
3377 fd = uafs_open_r(path, O_RDONLY, 0);
3382 fileP = afs_FileTable[fd];
3383 if (fileP == NULL) {
3387 if (fileP->v_type != VDIR) {
3394 * Set up the directory structures
3397 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3398 sizeof(struct usr_dirent));
3399 usr_assert(dirp != NULL);
3400 dirp->dd_buf = (char *)(dirp + 1);
3410 * Read directory entries into a file system independent format.
3411 * This routine was developed to support AFS cache consistency testing.
3412 * You should use uafs_readdir instead.
3415 uafs_getdents(int fd, struct min_direct *buf, int len)
3419 retval = uafs_getdents_r(fd, buf, len);
3425 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3429 struct usr_vnode *vp;
3430 struct iovec iov[1];
3433 * Make sure this is an open file
3435 vp = afs_FileTable[fd];
3443 * set up the uio buffer
3445 iov[0].iov_base = (char *)buf;
3446 iov[0].iov_len = len;
3447 uio.uio_iov = &iov[0];
3449 uio.uio_offset = afs_FileOffsets[fd];
3451 uio.uio_fmode = FREAD;
3452 uio.uio_resid = len;
3455 * read the next chunk from the directory
3457 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3463 afs_FileOffsets[fd] = uio.uio_offset;
3464 return (len - uio.uio_resid);
3468 * read from a directory (names only)
3471 uafs_readdir(usr_DIR * dirp)
3473 struct usr_dirent *retval;
3475 retval = uafs_readdir_r(dirp);
3481 uafs_readdir_r(usr_DIR * dirp)
3486 struct usr_vnode *vp;
3487 struct iovec iov[1];
3488 struct usr_dirent *direntP;
3489 struct min_direct *directP;
3497 * Make sure this is an open file
3499 vp = afs_FileTable[dirp->dd_fd];
3506 * If there are no entries in the stream buffer
3507 * then read another chunk
3509 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3510 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3512 * set up the uio buffer
3514 iov[0].iov_base = dirp->dd_buf;
3515 iov[0].iov_len = USR_DIRSIZE;
3516 uio.uio_iov = &iov[0];
3518 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3520 uio.uio_fmode = FREAD;
3521 uio.uio_resid = USR_DIRSIZE;
3524 * read the next chunk from the directory
3526 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3531 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3533 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3535 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3539 * Check for end of file
3541 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3545 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
3546 usr_assert(len <= dirp->dd_size);
3549 * Copy the next entry into the usr_dirent structure and advance
3551 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
3552 direntP->d_ino = directP->d_fileno;
3553 direntP->d_off = direntP->d_reclen;
3555 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
3556 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
3557 direntP->d_name[directP->d_namlen] = '\0';
3558 dirp->dd_loc += len;
3559 dirp->dd_size -= len;
3568 uafs_closedir(usr_DIR * dirp)
3572 retval = uafs_closedir_r(dirp);
3578 uafs_closedir_r(usr_DIR * dirp)
3589 afs_osi_Free((char *)dirp,
3590 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
3591 rc = uafs_close_r(fd);
3596 * Do AFS authentication
3599 uafs_klog(char *user, char *cell, char *passwd, char **reason)
3602 afs_int32 password_expires = -1;
3604 usr_mutex_lock(&osi_authenticate_lock);
3606 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
3607 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
3608 passwd, 0, &password_expires, 0, reason);
3609 usr_mutex_unlock(&osi_authenticate_lock);
3614 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
3618 retval = uafs_klog(user, cell, passwd, reason);
3624 * Destroy AFS credentials from the kernel cache
3631 usr_mutex_lock(&osi_authenticate_lock);
3632 code = ktc_ForgetAllTokens();
3633 usr_mutex_unlock(&osi_authenticate_lock);
3642 retval = uafs_unlog();
3648 * Strip the AFS mount point from a pathname string. Return
3649 * NULL if the path is a relative pathname or if the path
3650 * doesn't start with the AFS mount point string.
3653 uafs_afsPathName(char *path)
3662 for (i = 1, p = path + 1; *p != '\0'; p++) {
3663 /* Ignore duplicate slashes */
3664 if (*p == '/' && lastchar == '/')
3666 /* Is this a subdirectory of the AFS mount point? */
3667 if (afs_mountDir[i] == '\0' && *p == '/') {
3668 /* strip leading slashes */
3669 while (*(++p) == '/');
3672 /* Reject paths that are not within AFS */
3673 if (*p != afs_mountDir[i])
3678 /* Is this the AFS mount point? */
3679 if (afs_mountDir[i] == '\0') {
3680 usr_assert(*p == '\0');
3688 * klog but don't allocate a new pag
3691 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
3694 afs_int32 password_expires = -1;
3696 usr_mutex_lock(&osi_authenticate_lock);
3697 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
3698 /*+KA_USERAUTH_DOSETPAG2 */ , user,
3699 NULL, cell, passwd, 0,
3700 &password_expires, 0, reason);
3701 usr_mutex_unlock(&osi_authenticate_lock);
3706 * uafs_getcellstatus
3707 * get the cell status
3710 uafs_getcellstatus(char *cell, afs_int32 * status)
3713 struct afs_ioctl iob;
3716 iob.in_size = strlen(cell) + 1;
3720 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
3728 *status = (intptr_t)iob.out;
3734 * Get quota of volume associated with path
3737 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
3740 struct afs_ioctl iob;
3741 VolumeStatus *status;
3747 iob.out_size = 1024;
3749 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
3757 status = (VolumeStatus *) buf;
3758 *BlocksInUse = status->BlocksInUse;
3759 *MaxQuota = status->MaxQuota;
3765 * Set quota of volume associated with path
3768 uafs_setvolquota(char *path, afs_int32 MaxQuota)
3771 struct afs_ioctl iob;
3772 VolumeStatus *status;
3780 memset(buf, 0, sizeof(VolumeStatus));
3781 status = (VolumeStatus *) buf;
3782 status->MaxQuota = MaxQuota;
3783 status->MinQuota = -1;
3785 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
3797 * uafs_statmountpoint
3798 * Determine whether a dir. is a mount point or not
3799 * return 1 if mount point, 0 if not
3802 uafs_statmountpoint(char *path)
3807 retval = uafs_statmountpoint_r(path);
3813 uafs_statmountpoint_r(char *path)
3820 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
3835 * Get a list of rights for the current user on path.
3838 uafs_access(char *path, int flags)
3855 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3862 code = afs_access(VTOAFS(vp), fileMode, get_user_struct()->u_cred);
3869 return code ? -1 : 0;
3874 * Get a list of rights for the current user on path.
3877 uafs_getRights(char *path)
3884 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3892 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
3893 | PRSFS_LOCK | PRSFS_ADMINISTER;
3895 afs_rights = afs_getRights(VTOAFS(vp), afs_rights, get_user_struct()->u_cred);
3900 #endif /* UKERNEL */