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 "rx/rx_globals.h"
38 #define CACHEINFOFILE "cacheinfo"
39 #define AFSLOGFILE "AFSLog"
40 #define DCACHEFILE "CacheItems"
41 #define VOLINFOFILE "VolumeItems"
42 #define CELLINFOFILE "CellItems"
46 #define MIN(A,B) ((A)<(B)?(A):(B))
49 #define MAX(A,B) ((A)>(B)?(A):(B))
52 extern int cacheDiskType;
54 char afs_LclCellName[64];
56 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
57 int afs_FileFlags[MAX_OSI_FILES];
58 off_t afs_FileOffsets[MAX_OSI_FILES];
60 #define MAX_CACHE_LOOPS 4
62 struct usr_vfs afs_RootVfs;
63 struct usr_vnode *afs_RootVnode = NULL;
64 struct usr_vnode *afs_CurrentDir = NULL;
66 afs_int32 cacheBlocks; /* Num blocks in cache */
67 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
68 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
69 char cacheBaseDir[1024]; /* AFS cache directory */
70 char confDir[1024]; /* AFS configuration directory */
71 char afs_mountDir[1024]; /* AFS mount point */
72 int afs_mountDirLen; /* strlen of AFS mount point */
73 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
74 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
75 char fullpn_CellInfoFile[1024]; /* Full pathname of CELLINFOFILE */
76 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
77 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
78 char fullpn_VFile[1024]; /* Full pathname of data cache files */
79 char *vFileNumber; /* Ptr to number in file pathname */
80 char rootVolume[64] = "root.afs"; /* AFS root volume name */
81 afs_int32 isHomeCell; /* Is current cell info for home cell */
82 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
83 int ownerRWmode = 0600; /* Read/write OK by owner */
84 static int nDaemons = 2; /* Number of background daemons */
85 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
86 static int dCacheSize = 300; /* # of dcache entries */
87 static int vCacheSize = 50; /* # of volume cache entries */
88 static int cacheFlags = 0; /* Flags to cache manager */
89 static int preallocs = 400; /* Def # of allocated memory blocks */
90 int afsd_verbose = 0; /* Are we being chatty? */
91 int afsd_debug = 0; /* Are we printing debugging info? */
92 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
94 #define AFSD_INO_T afs_uint32
95 char **pathname_for_V; /* Array of cache file pathnames */
96 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
97 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
98 int missing_CellInfoFile = 1;
99 struct afs_cacheParams cparams; /* params passed to cache manager */
100 struct afsconf_dir *afs_cdir; /* config dir */
102 int afs_bufferpages = 100;
103 int usr_udpcksum = 0;
105 usr_key_t afs_global_u_key;
107 struct usr_proc *afs_global_procp = NULL;
108 struct usr_ucred *afs_global_ucredp = NULL;
109 struct usr_sysent usr_sysent[200];
111 #ifdef AFS_USR_OSF_ENV
113 #else /* AFS_USR_OSF_ENV */
115 #endif /* AFS_USR_OSF_ENV */
117 struct usr_ucred afs_osi_cred, *afs_osi_credp;
118 usr_mutex_t afs_global_lock;
119 usr_thread_t afs_global_owner;
120 usr_mutex_t rx_global_lock;
121 usr_thread_t rx_global_owner;
122 usr_mutex_t osi_inode_lock;
123 usr_mutex_t osi_waitq_lock;
124 usr_mutex_t osi_authenticate_lock;
126 afs_lock_t osi_flplock;
127 afs_lock_t osi_fsplock;
130 #ifndef NETSCAPE_NSAPI
133 * Mutex and condition variable used to implement sleep
135 pthread_mutex_t usr_sleep_mutex;
136 pthread_cond_t usr_sleep_cond;
138 #endif /* !NETSCAPE_NSAPI */
140 int call_syscall(long, long, long, long, long, long);
141 int fork_syscall(long, long, long, long, long, long);
145 * Hash table mapping addresses onto wait structures for
146 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
148 typedef struct osi_wait {
152 struct osi_wait *next;
153 struct osi_wait *prev;
155 struct osi_wait *timedNext;
156 struct osi_wait *timedPrev;
160 * Head of the linked list of available waitq structures.
162 osi_wait_t *osi_waithash_avail;
165 * List of timed waits, NSAPI does not provide a cond_timed
166 * wait, so we need to keep track of the timed waits ourselves and
167 * periodically check for expirations
169 osi_wait_t *osi_timedwait_head;
170 osi_wait_t *osi_timedwait_tail;
175 } osi_waithash_table[OSI_WAITHASH_SIZE];
178 * Never call afs_brelse
181 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
188 * I am not sure what to do with these, they assert for now
191 iodone(struct usr_buf *bp)
205 * Every user is a super user
208 afs_osi_suser(void *credp)
214 afs_suser(void *credp)
220 * These are no-ops in user space
224 afs_osi_SetTime(osi_timeval_t * atv)
230 * xflock should never fall through, the only files we know
231 * about are AFS files
241 * ioctl should never fall through, the only files we know
242 * about are AFS files
252 * We do not support the inode related system calls
255 afs_syscall_icreate(long a, long b, long c, long d, long e, long f)
262 afs_syscall_iincdec(int dev, int inode, int inode_p1, int amount)
269 afs_syscall_iopen(int dev, int inode, int usrmod)
276 afs_syscall_ireadwrite(void)
283 * these routines are referenced in the vfsops structure, but
284 * should never get called
315 * uiomove copies data between kernel buffers and uio buffers
318 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
325 nio = uio->uio_iovcnt;
335 while (nio > 0 && n > 0) {
336 len = MIN(n, iovp->iov_len);
337 if (rw == UIO_READ) {
338 memcpy(iovp->iov_base, ptr, len);
340 memcpy(ptr, iovp->iov_base, len);
344 uio->uio_resid -= len;
345 uio->uio_offset += len;
346 iovp->iov_base = (char *)(iovp->iov_base) + len;
347 iovp->iov_len -= len;
358 * routines to manage user credentials
361 usr_crcopy(struct usr_ucred *credp)
363 struct usr_ucred *newcredp;
365 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
367 newcredp->cr_ref = 1;
374 struct usr_ucred *newcredp;
376 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
377 newcredp->cr_ref = 1;
382 usr_crfree(struct usr_ucred *credp)
385 if (credp->cr_ref == 0) {
386 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
392 usr_crhold(struct usr_ucred *credp)
399 usr_vattr_null(struct usr_vattr *vap)
404 n = sizeof(struct usr_vattr);
412 * Initialize the thread specific data used to simulate the
413 * kernel environment for each thread. The user structure
414 * is stored in the thread specific data.
417 uafs_InitThread(void)
420 struct usr_user *uptr;
423 * initialize the thread specific user structure. Use malloc to
424 * allocate the data block, so pthread_finish can free the buffer
425 * when this thread terminates.
428 (struct usr_user *)malloc(sizeof(struct usr_user) +
429 sizeof(struct usr_ucred));
430 usr_assert(uptr != NULL);
433 uptr->u_procp = afs_global_procp;
434 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
435 *uptr->u_cred = *afs_global_ucredp;
436 st = usr_setspecific(afs_global_u_key, (void *)uptr);
441 * routine to get the user structure from the thread specific data.
442 * this routine is used to implement the global 'u' structure. Initializes
443 * the thread if needed.
446 get_user_struct(void)
448 struct usr_user *uptr;
450 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
454 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
456 usr_assert(uptr != NULL);
462 * Hash an address for the waithash table
464 #define WAITHASH(X) \
465 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
471 afs_osi_Sleep(void *x)
475 int glockOwner = ISAFS_GLOCK();
477 usr_mutex_lock(&osi_waitq_lock);
482 if (osi_waithash_avail == NULL) {
483 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
484 usr_cond_init(&waitp->cond);
486 waitp = osi_waithash_avail;
487 osi_waithash_avail = osi_waithash_avail->next;
491 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
492 osi_waithash_table[index].tail, next, prev);
493 waitp->expiration = 0;
494 waitp->timedNext = NULL;
495 waitp->timedPrev = NULL;
496 while (waitp->flag == 0) {
497 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
499 DLL_DELETE(waitp, osi_waithash_table[index].head,
500 osi_waithash_table[index].tail, next, prev);
501 waitp->next = osi_waithash_avail;
502 osi_waithash_avail = waitp;
503 usr_mutex_unlock(&osi_waitq_lock);
510 afs_osi_SleepSig(void *x)
517 afs_osi_Wakeup(void *x)
523 usr_mutex_lock(&osi_waitq_lock);
524 waitp = osi_waithash_table[index].head;
526 if (waitp->addr == x && waitp->flag == 0) {
528 usr_cond_signal(&waitp->cond);
532 usr_mutex_unlock(&osi_waitq_lock);
537 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
539 return afs_osi_Wait(ams, event, aintok);
543 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
549 int glockOwner = ISAFS_GLOCK();
551 tv.tv_sec = msec / 1000;
552 tv.tv_nsec = (msec % 1000) * 1000000;
553 if (handle == NULL) {
557 usr_thread_sleep(&tv);
563 usr_mutex_lock(&osi_waitq_lock);
567 index = WAITHASH((caddr_t) handle);
568 if (osi_waithash_avail == NULL) {
569 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
570 usr_cond_init(&waitp->cond);
572 waitp = osi_waithash_avail;
573 osi_waithash_avail = osi_waithash_avail->next;
575 waitp->addr = (caddr_t) handle;
577 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
578 osi_waithash_table[index].tail, next, prev);
579 tv.tv_sec += time(NULL);
580 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
581 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
582 timedNext, timedPrev);
583 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
589 DLL_DELETE(waitp, osi_waithash_table[index].head,
590 osi_waithash_table[index].tail, next, prev);
591 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
593 waitp->next = osi_waithash_avail;
594 osi_waithash_avail = waitp;
595 usr_mutex_unlock(&osi_waitq_lock);
604 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
606 afs_osi_Wakeup(handle);
610 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
611 * to explicitly signal cond_timed_waits when their timers expire
614 afs_osi_CheckTimedWaits(void)
619 curTime = time(NULL);
620 usr_mutex_lock(&osi_waitq_lock);
621 waitp = osi_timedwait_head;
622 while (waitp != NULL) {
623 usr_assert(waitp->expiration != 0);
624 if (waitp->expiration <= curTime) {
626 usr_cond_signal(&waitp->cond);
628 waitp = waitp->timedNext;
630 usr_mutex_unlock(&osi_waitq_lock);
635 * I-node numbers are indeces into a table containing a filename
636 * i-node structure and a vnode structure. When we create an i-node,
637 * we copy the name into the array and initialize enough of the fields
638 * in the inode and vnode structures to get the client to work.
641 struct usr_inode i_node;
644 osi_file_table_t *osi_file_table;
646 int max_osi_files = 0;
649 * Allocate a slot in the file table if there is not one there already,
650 * copy in the file name and kludge up the vnode and inode structures
653 lookupname(char *fnamep, int segflg, int followlink,
654 struct usr_vnode **compvpp)
658 struct usr_inode *ip;
659 struct usr_vnode *vp;
661 /*usr_assert(followlink == 0); */
664 * Assume relative pathnames refer to files in AFS
666 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
668 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
673 usr_mutex_lock(&osi_inode_lock);
675 for (i = 0; i < n_osi_files; i++) {
676 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
677 *compvpp = &osi_file_table[i].i_node.i_vnode;
678 (*compvpp)->v_count++;
679 usr_mutex_unlock(&osi_inode_lock);
684 if (n_osi_files == max_osi_files) {
685 usr_mutex_unlock(&osi_inode_lock);
689 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep) + 1);
690 usr_assert(osi_file_table[n_osi_files].name != NULL);
691 strcpy(osi_file_table[n_osi_files].name, fnamep);
692 ip = &osi_file_table[i].i_node;
694 vp->v_data = (caddr_t) ip;
697 ip->i_number = n_osi_files;
699 usr_mutex_unlock(&osi_inode_lock);
705 * open a file given its i-node number
708 osi_UFSOpen(afs_dcache_id_t *ino)
716 if (ino->ufs > n_osi_files) {
717 get_user_struct()->u_error = ENOENT;
722 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
723 usr_assert(fp != NULL);
724 fp->fd = open(osi_file_table[ino->ufs - 1].name, O_RDWR | O_CREAT, 0);
726 get_user_struct()->u_error = errno;
727 afs_osi_Free((char *)fp, sizeof(struct osi_file));
731 rc = fstat(fp->fd, &st);
733 get_user_struct()->u_error = errno;
734 afs_osi_Free((void *)fp, sizeof(struct osi_file));
738 fp->size = st.st_size;
740 fp->vnode = (struct usr_vnode *)fp;
747 osi_UFSClose(struct osi_file *fp)
756 get_user_struct()->u_error = errno;
757 afs_osi_Free((void *)fp, sizeof(struct osi_file));
761 afs_osi_Free((void *)fp, sizeof(struct osi_file));
767 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
774 rc = ftruncate(fp->fd, len);
776 get_user_struct()->u_error = errno;
786 afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
795 rc = lseek(fp->fd, offset, SEEK_SET);
797 rc = lseek(fp->fd, fp->offset, SEEK_SET);
800 get_user_struct()->u_error = errno;
805 ret = read(fp->fd, buf, len);
807 get_user_struct()->u_error = errno;
812 rc = fstat(fp->fd, &st);
814 get_user_struct()->u_error = errno;
818 fp->size = st.st_size;
824 afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
833 rc = lseek(fp->fd, offset, SEEK_SET);
835 rc = lseek(fp->fd, fp->offset, SEEK_SET);
838 get_user_struct()->u_error = errno;
843 ret = write(fp->fd, buf, len);
845 get_user_struct()->u_error = errno;
850 rc = fstat(fp->fd, &st);
852 get_user_struct()->u_error = errno;
856 fp->size = st.st_size;
862 afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
868 rc = fstat(fp->fd, &st);
870 get_user_struct()->u_error = errno;
874 stp->size = st.st_size;
875 stp->mtime = st.st_mtime;
876 stp->atime = st.st_atime;
885 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
886 int flags, struct usr_ucred *credP)
889 struct osi_file *fp = (struct osi_file *)vnodeP;
892 * We don't support readv/writev.
894 usr_assert(uioP->uio_iovcnt == 1);
895 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
897 if (rw == UIO_WRITE) {
898 usr_assert(uioP->uio_fmode == FWRITE);
899 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
900 uioP->uio_iov[0].iov_len);
902 usr_assert(uioP->uio_fmode == FREAD);
903 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
904 uioP->uio_iov[0].iov_len);
907 return get_user_struct()->u_error;
910 uioP->uio_resid -= rc;
911 uioP->uio_offset += rc;
912 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
913 uioP->uio_iov[0].iov_len -= rc;
918 afs_osi_Alloc(size_t size)
924 afs_osi_Free(void *ptr, size_t size)
930 afs_osi_FreeStr(char *ptr)
936 osi_AllocLargeSpace(size_t size)
938 AFS_STATCNT(osi_AllocLargeSpace);
939 return afs_osi_Alloc(size);
943 osi_FreeLargeSpace(void *ptr)
945 AFS_STATCNT(osi_FreeLargeSpace);
946 afs_osi_Free(ptr, 0);
950 osi_AllocSmallSpace(size_t size)
952 AFS_STATCNT(osi_AllocSmallSpace);
953 return afs_osi_Alloc(size);
957 osi_FreeSmallSpace(void *ptr)
959 AFS_STATCNT(osi_FreeSmallSpace);
960 afs_osi_Free(ptr, 0);
966 AFS_STATCNT(shutdown_osi);
971 shutdown_osinet(void)
973 AFS_STATCNT(shutdown_osinet);
978 shutdown_osifile(void)
980 AFS_STATCNT(shutdown_osifile);
985 afs_nfsclient_init(void)
990 shutdown_nfsclnt(void)
996 afs_osi_Invisible(void)
1002 afs_osi_Visible(void)
1008 osi_GetTime(struct timeval *tv)
1010 gettimeofday(tv, NULL);
1015 osi_SetTime(struct timeval *tv)
1021 osi_Active(struct vcache *avc)
1023 AFS_STATCNT(osi_Active);
1030 afs_osi_MapStrategy(int (*aproc) (struct usr_buf *), struct usr_buf *bp)
1032 afs_int32 returnCode;
1033 returnCode = (*aproc) (bp);
1038 osi_FlushPages(register struct vcache *avc, afs_ucred_t *credp)
1040 ObtainSharedLock(&avc->lock, 555);
1041 if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
1042 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1043 ReleaseSharedLock(&avc->lock);
1046 UpgradeSToWLock(&avc->lock, 565);
1047 hset(avc->mapDV, avc->f.m.DataVersion);
1048 ReleaseWriteLock(&avc->lock);
1053 osi_FlushText_really(register struct vcache *vp)
1055 if (hcmp(vp->f.m.DataVersion, vp->flushDV) > 0) {
1056 hset(vp->flushDV, vp->f.m.DataVersion);
1062 osi_SyncVM(struct vcache *avc)
1068 osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1079 * Allocate the table used to implement psuedo-inodes.
1081 max_osi_files = cacheFiles + 100;
1082 osi_file_table = (osi_file_table_t *)
1083 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1084 usr_assert(osi_file_table != NULL);
1086 #ifndef NETSCAPE_NSAPI
1088 * Initialize the mutex and condition variable used to implement
1091 pthread_mutex_init(&usr_sleep_mutex, NULL);
1092 pthread_cond_init(&usr_sleep_cond, NULL);
1093 #endif /* !NETSCAPE_NSAPI */
1096 * Initialize the hash table used for sleep/wakeup
1098 for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
1099 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1101 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1102 osi_waithash_avail = NULL;
1105 * Initialize the AFS file table
1107 for (i = 0; i < MAX_OSI_FILES; i++) {
1108 afs_FileTable[i] = NULL;
1112 * Initialize the global locks
1114 usr_mutex_init(&afs_global_lock);
1115 usr_mutex_init(&rx_global_lock);
1116 usr_mutex_init(&osi_inode_lock);
1117 usr_mutex_init(&osi_waitq_lock);
1118 usr_mutex_init(&osi_authenticate_lock);
1121 * Initialize the AFS OSI credentials
1123 afs_osi_cred = *afs_global_ucredp;
1124 afs_osi_credp = &afs_osi_cred;
1127 /* ParseArgs is now obsolete, being handled by cmd */
1129 /*---------------------------------------------------------------------
1133 * Given the final component of a filename expected to be a data cache file,
1134 * return the integer corresponding to the file. Note: we reject names that
1135 * are not a ``V'' followed by an integer. We also reject those names having
1136 * the right format but lying outside the range [0..cacheFiles-1].
1139 * fname : Char ptr to the filename to parse.
1142 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1146 * Nothing interesting.
1150 *------------------------------------------------------------------------*/
1153 GetVFileNumber(char *fname)
1155 int computedVNumber; /*The computed file number we return */
1156 int filenameLen; /*Number of chars in filename */
1157 int currDigit; /*Current digit being processed */
1160 * The filename must have at least two characters, the first of which must be a ``V''
1161 * and the second of which cannot be a zero unless the file is exactly two chars long.
1163 filenameLen = strlen(fname);
1164 if (filenameLen < 2)
1166 if (fname[0] != 'V')
1168 if ((filenameLen > 2) && (fname[1] == '0'))
1172 * Scan through the characters in the given filename, failing immediately if a non-digit
1175 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1176 if (isdigit(fname[currDigit]) == 0)
1180 * All relevant characters are digits. Pull out the decimal number they represent.
1181 * Reject it if it's out of range, otherwise return it.
1183 computedVNumber = atoi(++fname);
1184 if (computedVNumber < cacheFiles)
1185 return (computedVNumber);
1190 /*---------------------------------------------------------------------
1194 * Given a full pathname for a file we need to create for the workstation AFS
1195 * cache, go ahead and create the file.
1198 * fname : Full pathname of file to create.
1201 * 0 iff the file was created,
1205 * The given cache file has been found to be missing.
1209 *------------------------------------------------------------------------*/
1212 CreateCacheFile(char *fname)
1214 static char rn[] = "CreateCacheFile"; /*Routine name */
1215 int cfd; /*File descriptor to AFS cache file */
1216 int closeResult; /*Result of close() */
1219 printf("%s: Creating cache file '%s'\n", rn, fname);
1220 cfd = open(fname, createAndTrunc, ownerRWmode);
1222 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
1226 closeResult = close(cfd);
1229 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1237 /*---------------------------------------------------------------------
1241 * Sweep through the AFS cache directory, recording the inode number for
1242 * each valid data cache file there. Also, delete any file that doesn't beint32
1243 * in the cache directory during this sweep, and remember which of the other
1244 * residents of this directory were seen. After the sweep, we create any data
1245 * cache files that were missing.
1248 * vFilesFound : Set to the number of data cache files found.
1251 * 0 if everything went well,
1255 * This routine may be called several times. If the number of data cache files
1256 * found is less than the global cacheFiles, then the caller will need to call it
1257 * again to record the inodes of the missing zero-length data cache files created
1258 * in the previous call.
1261 * Fills up the global pathname_for_V array, may create and/or
1262 * delete files as explained above.
1263 *------------------------------------------------------------------------*/
1266 SweepAFSCache(int *vFilesFound)
1268 static char rn[] = "SweepAFSCache"; /*Routine name */
1269 char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
1270 char *fileToDelete; /*Ptr to last component of above */
1271 DIR *cdirp; /*Ptr to cache directory structure */
1273 struct dirent *currp; /*Current directory entry */
1274 int vFileNum; /*Data cache file's associated number */
1276 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1278 printf("%s: Memory Cache, no cache sweep done\n", rn);
1284 printf("%s: Opening cache directory '%s'\n", rn, cacheBaseDir);
1286 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1287 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
1291 cdirp = opendir(cacheBaseDir);
1292 if (cdirp == (DIR *) 0) {
1293 printf("%s: Can't open AFS cache directory, '%s'.\n", rn,
1299 * Scan the directory entries, remembering data cache file inodes and the existance
1300 * of other important residents. Delete all files that don't belong here.
1303 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1304 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1306 for (currp = readdir(cdirp); currp; currp = readdir(cdirp)) {
1308 printf("%s: Current directory entry:\n", rn);
1309 #if defined(AFS_SGI62_ENV) || defined(AFS_USR_DARWIN100_ENV)
1310 printf("\tinode=%" AFS_INT64_FMT ", reclen=%d, name='%s'\n",
1311 currp->d_ino, currp->d_reclen, currp->d_name);
1312 #elif defined(AFS_USR_DFBSD_ENV)
1313 printf("\tinode=%d, name='%s'\n", currp->d_ino,
1316 printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
1317 currp->d_reclen, currp->d_name);
1322 * Guess current entry is for a data cache file.
1324 vFileNum = GetVFileNumber(currp->d_name);
1325 if (vFileNum >= 0) {
1327 * Found a valid data cache filename. Remember this file's name
1328 * and bump the number of files found.
1330 pathname_for_V[vFileNum] =
1331 afs_osi_Alloc(strlen(currp->d_name) + strlen(cacheBaseDir) +
1333 usr_assert(pathname_for_V[vFileNum] != NULL);
1334 sprintf(pathname_for_V[vFileNum], "%s/%s", cacheBaseDir,
1337 } else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1339 * Found the file holding the dcache entries.
1341 missing_DCacheFile = 0;
1342 } else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1344 * Found the file holding the volume info.
1346 missing_VolInfoFile = 0;
1347 } else if (strcmp(currp->d_name, CELLINFOFILE) == 0) {
1348 missing_CellInfoFile = 0;
1349 } else if ((strcmp(currp->d_name, ".") == 0)
1350 || (strcmp(currp->d_name, "..") == 0)
1351 || (strcmp(currp->d_name, "lost+found") == 0)) {
1353 * Don't do anything - this file is legit, and is to be left alone.
1357 * This file doesn't belong in the cache. Nuke it.
1359 sprintf(fileToDelete, "%s", currp->d_name);
1361 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
1362 if (unlink(fullpn_FileToDelete)) {
1363 printf("%s: Can't unlink '%s', errno is %d\n", rn,
1364 fullpn_FileToDelete, errno);
1370 * Create all the cache files that are missing.
1372 if (missing_DCacheFile) {
1374 printf("%s: Creating '%s'\n", rn, fullpn_DCacheFile);
1375 if (CreateCacheFile(fullpn_DCacheFile))
1376 printf("%s: Can't create '%s'\n", rn, fullpn_DCacheFile);
1378 if (missing_VolInfoFile) {
1380 printf("%s: Creating '%s'\n", rn, fullpn_VolInfoFile);
1381 if (CreateCacheFile(fullpn_VolInfoFile))
1382 printf("%s: Can't create '%s'\n", rn, fullpn_VolInfoFile);
1384 if (missing_CellInfoFile) {
1386 printf("%s: Creating '%s'\n", rn, fullpn_CellInfoFile);
1387 if (CreateCacheFile(fullpn_CellInfoFile))
1388 printf("%s: Can't create '%s'\n", rn, fullpn_CellInfoFile);
1391 if (*vFilesFound < cacheFiles) {
1393 * We came up short on the number of data cache files found. Scan through the inode
1394 * list and create all missing files.
1396 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1397 if (pathname_for_V[vFileNum] == (AFSD_INO_T) 0) {
1398 sprintf(vFileNumber, "%d", vFileNum);
1400 printf("%s: Creating '%s'\n", rn, fullpn_VFile);
1401 if (CreateCacheFile(fullpn_VFile))
1402 printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
1407 * Close the directory, return success.
1410 printf("%s: Closing cache directory.\n", rn);
1416 ConfigCell(register struct afsconf_cell *aci, void *arock,
1417 struct afsconf_dir *adir)
1419 register int isHomeCell;
1421 afs_int32 cellFlags = 0;
1422 afs_int32 hosts[MAXHOSTSPERCELL];
1424 /* figure out if this is the home cell */
1425 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1427 cellFlags = 2; /* not home, suid is forbidden */
1429 /* build address list */
1430 for (i = 0; i < MAXHOSTSPERCELL; i++)
1431 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1433 if (aci->linkedCell)
1434 cellFlags |= 4; /* Flag that linkedCell arg exists,
1435 * for upwards compatibility */
1437 /* configure one cell */
1438 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2, (long)hosts, /* server addresses */
1439 (long)aci->name, /* cell name */
1440 (long)cellFlags, /* is this the home cell? */
1441 (long)aci->linkedCell); /* Linked cell, if any */
1446 ConfigCellAlias(struct afsconf_cellalias *aca, void *arock, struct afsconf_dir *adir)
1448 call_syscall(AFSOP_ADDCELLALIAS, (long)aca->aliasName,
1449 (long)aca->realName, 0, 0, 0);
1454 * Set the UDP port number RX uses for UDP datagrams
1457 uafs_SetRxPort(int port)
1459 usr_assert(usr_rx_port == 0);
1465 * Initialize the user space client.
1468 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1469 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1470 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1471 int chunkSizeParam, int closeSynchParam, int debugParam,
1472 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1477 int currVFile; /* Current AFS cache file number */
1478 int lookupResult; /* Result of GetLocalCellName() */
1479 int cacheIteration; /* cache verification loop counter */
1480 int vFilesFound; /* Num data cache files found in sweep */
1485 afs_int32 buffer[MAXIPADDRS];
1486 afs_int32 maskbuffer[MAXIPADDRS];
1487 afs_int32 mtubuffer[MAXIPADDRS];
1490 * Use the thread specific data to implement the user structure
1492 usr_keycreate(&afs_global_u_key, free);
1495 * Initialize the global ucred structure
1497 afs_global_ucredp = (struct usr_ucred *)
1498 afs_osi_Alloc(sizeof(struct usr_ucred));
1499 usr_assert(afs_global_ucredp != NULL);
1500 afs_global_ucredp->cr_ref = 1;
1501 afs_set_cr_uid(afs_global_ucredp, geteuid());
1502 afs_set_cr_gid(afs_global_ucredp, getegid());
1503 afs_set_cr_ruid(afs_global_ucredp, getuid());
1504 afs_set_cr_rgid(afs_global_ucredp, getgid());
1505 afs_global_ucredp->cr_suid = afs_cr_ruid(afs_global_ucredp);
1506 afs_global_ucredp->cr_sgid = afs_cr_rgid(afs_global_ucredp);
1507 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1508 usr_assert(st >= 0);
1509 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1510 for (i = st; i < NGROUPS; i++) {
1511 afs_global_ucredp->cr_groups[i] = NOGROUP;
1515 * Initialize the global process structure
1517 afs_global_procp = (struct usr_proc *)
1518 afs_osi_Alloc(sizeof(struct usr_proc));
1519 usr_assert(afs_global_procp != NULL);
1520 afs_global_procp->p_pid = osi_getpid();
1521 afs_global_procp->p_ppid = (pid_t) 1;
1522 afs_global_procp->p_ucred = afs_global_ucredp;
1525 * Initialize the AFS mount point, default is '/afs'.
1526 * Strip duplicate/trailing slashes from mount point string.
1527 * afs_mountDirLen is set to strlen(afs_mountDir).
1529 if (mountDirParam) {
1530 sprintf(tbuffer, "%s", mountDirParam);
1532 sprintf(tbuffer, "afs");
1534 afs_mountDir[0] = '/';
1535 afs_mountDirLen = 1;
1536 for (lastchar = '/', p = &tbuffer[0]; *p != '\0'; p++) {
1537 if (lastchar != '/' || *p != '/') {
1538 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1541 if (lastchar == '/' && afs_mountDirLen > 1)
1543 afs_mountDir[afs_mountDirLen] = '\0';
1544 usr_assert(afs_mountDirLen > 1);
1547 * Initialize cache parameters using the input arguments
1550 cacheBlocks = cacheBlocksParam;
1551 if (cacheFilesParam != 0) {
1552 cacheFiles = cacheFilesParam;
1554 cacheFiles = cacheBlocks / 10;
1556 if (cacheStatEntriesParam != 0) {
1557 cacheStatEntries = cacheStatEntriesParam;
1559 strcpy(cacheBaseDir, cacheBaseDirParam);
1560 if (nDaemonsParam != 0) {
1561 nDaemons = nDaemonsParam;
1565 afsd_verbose = debugParam;
1566 afsd_debug = debugParam;
1567 chunkSize = chunkSizeParam;
1568 if (dCacheSizeParam != 0) {
1569 dCacheSize = dCacheSizeParam;
1571 dCacheSize = cacheFiles / 2;
1573 if (vCacheSizeParam != 0) {
1574 vCacheSize = vCacheSizeParam;
1576 strcpy(confDir, confDirParam);
1577 afsd_CloseSynch = closeSynchParam;
1578 if (cacheFlagsParam >= 0) {
1579 cacheFlags = cacheFlagsParam;
1581 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1582 cacheFiles = dCacheSize;
1585 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1586 if (logFile == NULL) {
1587 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1589 strcpy(fullpn_AFSLogFile, logFile);
1592 printf("\n%s: Initializing user space AFS client\n\n", rn);
1593 printf(" mountDir: %s\n", afs_mountDir);
1594 printf(" confDir: %s\n", confDir);
1595 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1596 printf(" cacheBlocks: %d\n", cacheBlocks);
1597 printf(" cacheFiles: %d\n", cacheFiles);
1598 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1599 printf(" dCacheSize: %d\n", dCacheSize);
1600 printf(" vCacheSize: %d\n", vCacheSize);
1601 printf(" chunkSize: %d\n", chunkSize);
1602 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1603 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1604 printf(" nDaemons: %d\n", nDaemons);
1605 printf(" cacheFlags: %d\n", cacheFlags);
1606 printf(" logFile: %s\n", fullpn_AFSLogFile);
1611 * Initialize the AFS client
1616 * Pull out all the configuration info for the workstation's AFS cache and
1617 * the cellular community we're willing to let our users see.
1619 afs_cdir = afsconf_Open(confDir);
1621 printf("afsd: some file missing or bad in %s\n", confDir);
1626 afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1627 sizeof(afs_LclCellName));
1629 printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
1633 printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
1636 if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
1638 printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1639 if (CreateCacheFile(fullpn_AFSLogFile)) {
1641 ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
1642 rn, fullpn_AFSLogFile);
1649 * Create and zero the pathname table for the desired cache files.
1651 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1652 if (pathname_for_V == NULL) {
1653 printf("%s: malloc() failed for cache file table with %d entries.\n",
1657 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1659 printf("%s: %d pathname_for_V entries at %" AFS_PTR_FMT
1660 ", %lud bytes\n", rn, cacheFiles, pathname_for_V,
1661 afs_printable_uint32_lu(cacheFiles * sizeof(AFSD_INO_T)));
1664 * Set up all the pathnames we'll need for later.
1666 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1667 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1668 sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
1669 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1670 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1672 /* initialize AFS callback interface */
1674 /* parse multihomed address files */
1676 st = parseNetFiles((afs_uint32*)buffer,(afs_uint32*) maskbuffer, (afs_uint32*)mtubuffer, MAXIPADDRS, reason,
1677 AFSDIR_CLIENT_NETINFO_FILEPATH,
1678 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1680 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st,
1681 (long)(&buffer[0]), (long)(&maskbuffer[0]),
1682 (long)(&mtubuffer[0]));
1684 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
1691 * Start the RX listener.
1694 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1695 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE, FALSE, FALSE, 0);
1698 printf("%s: Forking rx callback listener.\n", rn);
1700 if (preallocs < cacheStatEntries + 50)
1701 preallocs = cacheStatEntries + 50;
1702 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs, 0, 0, 0);
1705 * Start the RX event handler.
1708 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1709 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE, 0, 0, 0);
1712 * Set up all the kernel processes needed for AFS.
1716 printf("%s: Initializing AFS daemon.\n", rn);
1717 call_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT, 1, 0, 0, 0);
1720 * Tell the kernel some basic information about the workstation's cache.
1723 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1724 " %d optimum cache files, %d blocks in the cache,"
1725 " flags = 0x%x, dcache entries %d\n", rn, cacheStatEntries,
1726 cacheFiles, cacheBlocks, cacheFlags, dCacheSize);
1727 memset(&cparams, 0, sizeof(cparams));
1728 cparams.cacheScaches = cacheStatEntries;
1729 cparams.cacheFiles = cacheFiles;
1730 cparams.cacheBlocks = cacheBlocks;
1731 cparams.cacheDcaches = dCacheSize;
1732 cparams.cacheVolumes = vCacheSize;
1733 cparams.chunkSize = chunkSize;
1734 cparams.setTimeFlag = FALSE;
1735 cparams.memCacheFlag = cacheFlags;
1736 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1737 if (afsd_CloseSynch)
1738 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1741 * Sweep the workstation AFS cache directory, remembering the inodes of
1742 * valid files and deleting extraneous files. Keep sweeping until we
1743 * have the right number of data cache files or we've swept too many
1747 printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
1749 /* Memory-cache based system doesn't need any of this */
1750 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1753 if (SweepAFSCache(&vFilesFound)) {
1754 printf("%s: Error on sweep %d of workstation AFS cache \
1755 directory.\n", rn, cacheIteration);
1760 ("%s: %d out of %d data cache files found in sweep %d.\n",
1761 rn, vFilesFound, cacheFiles, cacheIteration);
1762 } while ((vFilesFound < cacheFiles)
1763 && (cacheIteration < MAX_CACHE_LOOPS));
1764 } else if (afsd_verbose)
1765 printf("%s: Using memory cache, not swept\n", rn);
1768 * Pass the kernel the name of the workstation cache file holding the
1772 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
1774 /* once again, meaningless for a memory-based cache. */
1775 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1776 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1779 call_syscall(AFSCALL_CALL, AFSOP_CELLINFO, (long)fullpn_CellInfoFile, 0,
1783 * Pass the kernel the name of the workstation cache file holding the
1784 * volume information.
1787 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
1788 fullpn_VolInfoFile);
1789 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO, (long)fullpn_VolInfoFile, 0,
1793 * Pass the kernel the name of the afs logging file holding the volume
1797 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
1799 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1800 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG, (long)fullpn_AFSLogFile, 0,
1804 * Tell the kernel about each cell in the configuration.
1806 afsconf_CellApply(afs_cdir, ConfigCell, NULL);
1807 afsconf_CellAliasApply(afs_cdir, ConfigCellAlias, NULL);
1810 * Set the primary cell name.
1812 call_syscall(AFSCALL_CALL, AFSOP_SET_THISCELL, (long)afs_LclCellName, 0, 0, 0);
1815 printf("%s: Forking AFS daemon.\n", rn);
1816 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS, 0, 0, 0, 0);
1819 printf("%s: Forking check server daemon.\n", rn);
1820 fork_syscall(AFSCALL_CALL, AFSOP_START_CS, 0, 0, 0, 0);
1823 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1824 for (i = 0; i < nDaemons; i++) {
1825 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG, 0, 0, 0, 0);
1829 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn, rootVolume);
1830 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1833 * Give the kernel the names of the AFS files cached on the workstation's
1838 ("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1839 rn, cacheFiles, cacheBaseDir);
1840 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1841 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1842 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1843 (long)pathname_for_V[currVFile], 0, 0, 0);
1846 /*#ifndef NETSCAPE_NSAPI*/
1848 /* this breaks solaris if the kernel-mode client has never been installed,
1849 * and it doesn't seem to work now anyway, so just disable it */
1852 * Copy our tokens from the kernel to the user space client
1854 for (i = 0; i < 200; i++) {
1856 * Get the i'th token from the kernel
1858 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1859 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1861 iob.in_size = sizeof(int);
1863 iob.out_size = sizeof(tbuffer);
1865 #if defined(AFS_USR_SUN5_ENV) || defined(AFS_USR_OSF_ENV) || defined(AFS_USR_HPUX_ENV) || defined(AFS_USR_LINUX22_ENV) || defined(AFS_USR_DARWIN_ENV) || defined(AFS_USR_FBSD_ENV)
1866 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1867 #elif defined(AFS_USR_SGI_ENV)
1868 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1869 #else /* AFS_USR_AIX_ENV */
1870 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1873 usr_assert(errno == EDOM || errno == ENOSYS || errno == ERANGE);
1878 * Now pass the token into the user space kernel
1880 rc = uafs_SetTokens(tbuffer, iob.out_size);
1881 usr_assert(rc == 0);
1883 #endif /* !NETSCAPE_NSAPI */
1886 * All the necessary info has been passed into the kernel to run an AFS
1887 * system. Give the kernel our go-ahead.
1890 printf("%s: Calling AFSOP_GO\n", rn);
1891 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1894 * At this point, we have finished passing the kernel all the info
1895 * it needs to set up the AFS. Mount the AFS root.
1897 printf("%s: All AFS daemons started.\n", rn);
1900 printf("%s: Forking trunc-cache daemon.\n", rn);
1901 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON, 0, 0, 0, 0);
1904 * Mount the AFS filesystem
1907 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1908 usr_assert(rc == 0);
1909 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1910 usr_assert(rc == 0);
1914 * initialize the current directory to the AFS root
1916 afs_CurrentDir = afs_RootVnode;
1917 VN_HOLD(afs_CurrentDir);
1923 uafs_statvfs(struct statvfs *buf)
1929 rc = afs_statvfs(&afs_RootVfs, buf);
1949 VN_RELE(afs_CurrentDir);
1950 rc = afs_unmount(&afs_RootVfs);
1951 usr_assert(rc == 0);
1958 * Donate the current thread to the RX server pool.
1961 uafs_RxServerProc(void)
1965 struct rx_call *newcall = NULL;
1967 rxi_MorePackets(2); /* alloc more packets */
1968 threadID = rxi_availProcs++;
1971 sock = OSI_NULLSOCKET;
1972 rxi_ServerProc(threadID, newcall, &sock);
1973 if (sock == OSI_NULLSOCKET) {
1978 rxi_ListenerProc(sock, &threadID, &newcall);
1979 /* assert(threadID != -1); */
1980 /* assert(newcall != NULL); */
1984 struct syscallThreadArgs {
1993 #ifdef NETSCAPE_NSAPI
1995 syscallThread(void *argp)
1996 #else /* NETSCAPE_NSAPI */
1998 syscallThread(void *argp)
1999 #endif /* NETSCAPE_NSAPI */
2002 struct usr_ucred *crp;
2003 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
2006 * AFS daemons run authenticated
2008 get_user_struct()->u_viceid = getuid();
2009 crp = get_user_struct()->u_cred;
2010 afs_set_cr_uid(crp, getuid());
2011 afs_set_cr_ruid(crp, getuid());
2012 crp->cr_suid = getuid();
2013 crp->cr_groups[0] = getgid();
2014 crp->cr_ngroups = 1;
2015 for (i = 1; i < NGROUPS; i++) {
2016 crp->cr_groups[i] = NOGROUP;
2019 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
2020 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
2022 afs_osi_Free(argp, -1);
2027 fork_syscall(long syscall, long afscall, long param1, long param2,
2028 long param3, long param4)
2031 struct syscallThreadArgs *sysArgsP;
2033 sysArgsP = (struct syscallThreadArgs *)
2034 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
2035 usr_assert(sysArgsP != NULL);
2036 sysArgsP->syscall = syscall;
2037 sysArgsP->afscall = afscall;
2038 sysArgsP->param1 = param1;
2039 sysArgsP->param2 = param2;
2040 sysArgsP->param3 = param3;
2041 sysArgsP->param4 = param4;
2043 usr_thread_create(&tid, syscallThread, sysArgsP);
2044 usr_thread_detach(tid);
2049 call_syscall(long syscall, long afscall, long param1, long param2,
2050 long param3, long param4)
2062 a.syscall = syscall;
2063 a.afscall = afscall;
2069 get_user_struct()->u_error = 0;
2070 get_user_struct()->u_ap = (char *)&a;
2072 code = Afs_syscall();
2077 uafs_SetTokens(char *tbuffer, int tlen)
2080 struct afs_ioctl iob;
2085 iob.out = &outbuf[0];
2086 iob.out_size = sizeof(outbuf);
2088 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2097 uafs_RPCStatsEnableProc(void)
2100 struct afs_ioctl iob;
2103 flag = AFSCALL_RXSTATS_ENABLE;
2104 iob.in = (char *)&flag;
2105 iob.in_size = sizeof(afs_int32);
2108 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2117 uafs_RPCStatsDisableProc(void)
2120 struct afs_ioctl iob;
2123 flag = AFSCALL_RXSTATS_DISABLE;
2124 iob.in = (char *)&flag;
2125 iob.in_size = sizeof(afs_int32);
2128 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2137 uafs_RPCStatsClearProc(void)
2140 struct afs_ioctl iob;
2143 flag = AFSCALL_RXSTATS_CLEAR;
2144 iob.in = (char *)&flag;
2145 iob.in_size = sizeof(afs_int32);
2148 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2157 uafs_RPCStatsEnablePeer(void)
2160 struct afs_ioctl iob;
2163 flag = AFSCALL_RXSTATS_ENABLE;
2164 iob.in = (char *)&flag;
2165 iob.in_size = sizeof(afs_int32);
2168 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2177 uafs_RPCStatsDisablePeer(void)
2180 struct afs_ioctl iob;
2183 flag = AFSCALL_RXSTATS_DISABLE;
2184 iob.in = (char *)&flag;
2185 iob.in_size = sizeof(afs_int32);
2188 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2197 uafs_RPCStatsClearPeer(void)
2200 struct afs_ioctl iob;
2203 flag = AFSCALL_RXSTATS_CLEAR;
2204 iob.in = (char *)&flag;
2205 iob.in_size = sizeof(afs_int32);
2208 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2217 * Lookup a file or directory given its path.
2218 * Call VN_HOLD on the output vnode if successful.
2219 * Returns zero on success, error code on failure.
2221 * Note: Caller must hold the AFS global lock.
2224 uafs_LookupName(char *path, struct usr_vnode *parentVp,
2225 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
2229 struct usr_vnode *vp;
2230 struct usr_vnode *nextVp;
2231 struct usr_vnode *linkVp;
2232 struct vcache *nextVc;
2235 char *nextPathP = NULL;
2240 * Absolute paths must start with the AFS mount point.
2242 if (path[0] != '/') {
2245 path = uafs_afsPathName(path);
2253 * Loop through the path looking for the new directory
2255 tmpPath = afs_osi_Alloc(strlen(path) + 1);
2256 usr_assert(tmpPath != NULL);
2257 strcpy(tmpPath, path);
2260 while (pathP != NULL && *pathP != '\0') {
2261 usr_assert(*pathP != '/');
2264 * terminate the current component and skip over slashes
2266 nextPathP = afs_strchr(pathP, '/');
2267 if (nextPathP != NULL) {
2268 while (*nextPathP == '/') {
2269 *(nextPathP++) = '\0';
2274 * Don't call afs_lookup on non-directories
2276 if (vp->v_type != VDIR) {
2278 afs_osi_Free(tmpPath, strlen(path) + 1);
2282 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2284 * The AFS root is its own parent
2286 nextVp = afs_RootVnode;
2289 * We need execute permission to search a directory
2291 code = afs_access(VTOAFS(vp), VEXEC, get_user_struct()->u_cred);
2294 afs_osi_Free(tmpPath, strlen(path) + 1);
2299 * lookup the next component in the path, we can release the
2300 * subdirectory since we hold the global lock
2304 #ifdef AFS_WEB_ENHANCEMENTS
2305 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2306 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
2309 afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred,
2312 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
2313 #endif /* AFS_WEB_ENHANCEMENTS */
2315 nextVp=AFSTOV(nextVc);
2318 afs_osi_Free(tmpPath, strlen(path) + 1);
2324 * Follow symbolic links for parent directories and
2325 * for leaves when the follow flag is set.
2327 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2329 while (nextVp->v_type == VLNK) {
2330 if (++linkCount > MAX_OSI_LINKS) {
2333 afs_osi_Free(tmpPath, strlen(path) + 1);
2336 code = uafs_LookupLink(nextVp, vp, &linkVp);
2340 afs_osi_Free(tmpPath, strlen(path) + 1);
2354 * Special case, nextPathP is non-null if pathname ends in slash
2356 if (nextPathP != NULL && vp->v_type != VDIR) {
2358 afs_osi_Free(tmpPath, strlen(path) + 1);
2362 afs_osi_Free(tmpPath, strlen(path) + 1);
2368 * Lookup the target of a symbolic link
2369 * Call VN_HOLD on the output vnode if successful.
2370 * Returns zero on success, error code on failure.
2372 * Note: Caller must hold the AFS global lock.
2375 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
2376 struct usr_vnode **vpp)
2381 struct usr_vnode *linkVp;
2383 struct iovec iov[1];
2387 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
2388 usr_assert(pathP != NULL);
2391 * set up the uio buffer
2393 iov[0].iov_base = pathP;
2394 iov[0].iov_len = MAX_OSI_PATH + 1;
2395 uio.uio_iov = &iov[0];
2399 uio.uio_fmode = FREAD;
2400 uio.uio_resid = MAX_OSI_PATH + 1;
2403 * Read the link data
2405 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
2407 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2410 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2414 * Find the target of the symbolic link
2416 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2418 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2422 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2428 * Lookup the parent of a file or directory given its path
2429 * Call VN_HOLD on the output vnode if successful.
2430 * Returns zero on success, error code on failure.
2432 * Note: Caller must hold the AFS global lock.
2435 uafs_LookupParent(char *path, struct usr_vnode **vpp)
2440 struct usr_vnode *parentP;
2445 * Absolute path names must start with the AFS mount point.
2448 pathP = uafs_afsPathName(path);
2449 if (pathP == NULL) {
2455 * Find the length of the parent path
2458 while (len > 0 && path[len - 1] == '/') {
2464 while (len > 0 && path[len - 1] != '/') {
2471 pathP = afs_osi_Alloc(len);
2472 usr_assert(pathP != NULL);
2473 memcpy(pathP, path, len - 1);
2474 pathP[len - 1] = '\0';
2477 * look up the parent
2479 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2480 afs_osi_Free(pathP, len);
2484 if (parentP->v_type != VDIR) {
2494 * Return a pointer to the first character in the last component
2498 uafs_LastPath(char *path)
2503 while (len > 0 && path[len - 1] == '/') {
2506 while (len > 0 && path[len - 1] != '/') {
2516 * Set the working directory.
2519 uafs_chdir(char *path)
2523 retval = uafs_chdir_r(path);
2529 uafs_chdir_r(char *path)
2534 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2539 if (dirP->v_type != VDIR) {
2544 VN_RELE(afs_CurrentDir);
2545 afs_CurrentDir = dirP;
2550 * Create a directory.
2553 uafs_mkdir(char *path, int mode)
2557 retval = uafs_mkdir_r(path, mode);
2563 uafs_mkdir_r(char *path, int mode)
2567 struct vnode *parentP;
2568 struct vcache *dirP;
2569 struct usr_vattr attrs;
2571 if (uafs_IsRoot(path)) {
2576 * Look up the parent directory.
2578 nameP = uafs_LastPath(path);
2579 if (nameP != NULL) {
2580 code = uafs_LookupParent(path, &parentP);
2586 parentP = afs_CurrentDir;
2592 * Make sure the directory has at least one character
2594 if (*nameP == '\0') {
2601 * Create the directory
2603 usr_vattr_null(&attrs);
2604 attrs.va_type = VREG;
2605 attrs.va_mode = mode;
2606 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2607 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2609 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, get_user_struct()->u_cred);
2615 VN_RELE(AFSTOV(dirP));
2620 * Return 1 if path is the AFS root, otherwise return 0
2623 uafs_IsRoot(char *path)
2625 while (*path == '/' && *(path + 1) == '/') {
2628 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2631 path += afs_mountDirLen;
2632 while (*path == '/') {
2635 if (*path != '\0') {
2643 * Note: file name may not end in a slash.
2646 uafs_open(char *path, int flags, int mode)
2650 retval = uafs_open_r(path, flags, mode);
2656 uafs_open_r(char *path, int flags, int mode)
2662 struct usr_vnode *fileP;
2663 struct usr_vnode *dirP;
2664 struct usr_vattr attrs;
2669 if (uafs_IsRoot(path)) {
2670 fileP = afs_RootVnode;
2674 * Look up the parent directory.
2676 nameP = uafs_LastPath(path);
2677 if (nameP != NULL) {
2678 code = uafs_LookupParent(path, &dirP);
2684 dirP = afs_CurrentDir;
2690 * Make sure the filename has at least one character
2692 if (*nameP == '\0') {
2699 * Get the VNODE for this file
2701 if (flags & O_CREAT) {
2702 usr_vattr_null(&attrs);
2703 attrs.va_type = VREG;
2704 attrs.va_mode = mode;
2705 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2706 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2707 if (flags & O_TRUNC) {
2713 afs_create(VTOAFS(dirP), nameP, &attrs,
2714 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2715 &vc, get_user_struct()->u_cred);
2724 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2732 * Check whether we have access to this file
2735 if (flags & (O_RDONLY | O_RDWR)) {
2738 if (flags & (O_WRONLY | O_RDWR)) {
2742 fileMode = VREAD; /* since O_RDONLY is 0 */
2743 code = afs_access(VTOAFS(fileP), fileMode, get_user_struct()->u_cred);
2751 * Get the file attributes, all we need is the size
2753 code = afs_getattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2763 * Setup the open flags
2766 if (flags & O_TRUNC) {
2767 openFlags |= FTRUNC;
2769 if (flags & O_APPEND) {
2770 openFlags |= FAPPEND;
2772 if (flags & O_SYNC) {
2775 if (flags & O_SYNC) {
2778 if (flags & (O_RDONLY | O_RDWR)) {
2781 if (flags & (O_WRONLY | O_RDWR)) {
2782 openFlags |= FWRITE;
2784 if ((openFlags & (FREAD | FWRITE)) == 0) {
2785 /* O_RDONLY is 0, so ... */
2790 * Truncate if necessary
2792 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2793 usr_vattr_null(&attrs);
2794 attrs.va_mask = ATTR_SIZE;
2796 code = afs_setattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2808 code = afs_open(&vc, openFlags, get_user_struct()->u_cred);
2816 * Put the vnode pointer into the file table
2818 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2819 if (afs_FileTable[fd] == NULL) {
2820 afs_FileTable[fd] = fileP;
2821 afs_FileFlags[fd] = openFlags;
2822 if (flags & O_APPEND) {
2823 afs_FileOffsets[fd] = attrs.va_size;
2825 afs_FileOffsets[fd] = 0;
2830 if (fd == MAX_OSI_FILES) {
2843 uafs_creat(char *path, int mode)
2846 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2851 uafs_creat_r(char *path, int mode)
2854 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2862 uafs_write(int fd, char *buf, int len)
2866 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2872 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2876 retval = uafs_pwrite_r(fd, buf, len, offset);
2882 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2886 struct iovec iov[1];
2887 struct usr_vnode *fileP;
2890 * Make sure this is an open file
2892 fileP = afs_FileTable[fd];
2893 if (fileP == NULL) {
2899 * set up the uio buffer
2901 iov[0].iov_base = buf;
2902 iov[0].iov_len = len;
2903 uio.uio_iov = &iov[0];
2905 uio.uio_offset = offset;
2907 uio.uio_fmode = FWRITE;
2908 uio.uio_resid = len;
2914 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], get_user_struct()->u_cred, 0);
2920 afs_FileOffsets[fd] = uio.uio_offset;
2921 return (len - uio.uio_resid);
2928 uafs_read(int fd, char *buf, int len)
2932 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2938 uafs_pread(int fd, char *buf, int len, off_t offset)
2942 retval = uafs_pread_r(fd, buf, len, offset);
2948 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2952 struct iovec iov[1];
2953 struct usr_vnode *fileP;
2954 struct usr_buf *bufP;
2957 * Make sure this is an open file
2959 fileP = afs_FileTable[fd];
2960 if (fileP == NULL) {
2966 * set up the uio buffer
2968 iov[0].iov_base = buf;
2969 iov[0].iov_len = len;
2970 uio.uio_iov = &iov[0];
2972 uio.uio_offset = offset;
2974 uio.uio_fmode = FREAD;
2975 uio.uio_resid = len;
2980 code = afs_read(VTOAFS(fileP), &uio, get_user_struct()->u_cred, 0, &bufP, 0);
2986 afs_FileOffsets[fd] = uio.uio_offset;
2987 return (len - uio.uio_resid);
2991 * Copy the attributes of a file into a stat structure.
2993 * NOTE: Caller must hold the global AFS lock.
2996 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2999 struct usr_vattr attrs;
3004 * Get the attributes
3006 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3012 * Copy the attributes, zero fields that aren't set
3014 memset((void *)stats, 0, sizeof(struct stat));
3016 stats->st_ino = attrs.va_nodeid;
3017 stats->st_mode = attrs.va_mode;
3018 stats->st_nlink = attrs.va_nlink;
3019 stats->st_uid = attrs.va_uid;
3020 stats->st_gid = attrs.va_gid;
3021 stats->st_rdev = attrs.va_rdev;
3022 stats->st_size = attrs.va_size;
3023 stats->st_atime = attrs.va_atime.tv_sec;
3024 stats->st_mtime = attrs.va_mtime.tv_sec;
3025 stats->st_ctime = attrs.va_ctime.tv_sec;
3026 stats->st_blksize = attrs.va_blocksize;
3027 stats->st_blocks = attrs.va_blocks;
3033 * Get the attributes of a file, do follow links
3036 uafs_stat(char *path, struct stat *buf)
3040 retval = uafs_stat_r(path, buf);
3046 uafs_stat_r(char *path, struct stat *buf)
3051 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3056 code = uafs_GetAttr(vp, buf);
3066 * Get the attributes of a file, don't follow links
3069 uafs_lstat(char *path, struct stat *buf)
3073 retval = uafs_lstat_r(path, buf);
3079 uafs_lstat_r(char *path, struct stat *buf)
3084 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3089 code = uafs_GetAttr(vp, buf);
3099 * Get the attributes of an open file
3102 uafs_fstat(int fd, struct stat *buf)
3106 retval = uafs_fstat_r(fd, buf);
3112 uafs_fstat_r(int fd, struct stat *buf)
3117 vp = afs_FileTable[fd];
3122 code = uafs_GetAttr(vp, buf);
3131 * change the permissions on a file
3134 uafs_chmod(char *path, int mode)
3138 retval = uafs_chmod_r(path, mode);
3144 uafs_chmod_r(char *path, int mode)
3148 struct usr_vattr attrs;
3150 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3155 usr_vattr_null(&attrs);
3156 attrs.va_mask = ATTR_MODE;
3157 attrs.va_mode = mode;
3158 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3168 * change the permissions on an open file
3171 uafs_fchmod(int fd, int mode)
3175 retval = uafs_fchmod_r(fd, mode);
3181 uafs_fchmod_r(int fd, int mode)
3185 struct usr_vattr attrs;
3187 vp = afs_FileTable[fd];
3192 usr_vattr_null(&attrs);
3193 attrs.va_mask = ATTR_MODE;
3194 attrs.va_mode = mode;
3195 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3207 uafs_truncate(char *path, int length)
3211 retval = uafs_truncate_r(path, length);
3217 uafs_truncate_r(char *path, int length)
3221 struct usr_vattr attrs;
3223 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3228 usr_vattr_null(&attrs);
3229 attrs.va_mask = ATTR_SIZE;
3230 attrs.va_size = length;
3231 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3241 * truncate an open file
3244 uafs_ftruncate(int fd, int length)
3248 retval = uafs_ftruncate_r(fd, length);
3254 uafs_ftruncate_r(int fd, int length)
3258 struct usr_vattr attrs;
3260 vp = afs_FileTable[fd];
3265 usr_vattr_null(&attrs);
3266 attrs.va_mask = ATTR_SIZE;
3267 attrs.va_size = length;
3268 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3277 * set the read/write file pointer of an open file
3280 uafs_lseek(int fd, int offset, int whence)
3284 retval = uafs_lseek_r(fd, offset, whence);
3290 uafs_lseek_r(int fd, int offset, int whence)
3294 struct usr_vattr attrs;
3295 struct usr_vnode *vp;
3297 vp = afs_FileTable[fd];
3304 newpos = afs_FileOffsets[fd] + offset;
3310 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3315 newpos = attrs.va_size + offset;
3325 afs_FileOffsets[fd] = newpos;
3337 retval = uafs_fsync_r(fd);
3343 uafs_fsync_r(int fd)
3346 struct usr_vnode *fileP;
3349 fileP = afs_FileTable[fd];
3350 if (fileP == NULL) {
3355 code = afs_fsync(VTOAFS(fileP), get_user_struct()->u_cred);
3372 retval = uafs_close_r(fd);
3378 uafs_close_r(int fd)
3381 struct usr_vnode *fileP;
3383 fileP = afs_FileTable[fd];
3384 if (fileP == NULL) {
3388 afs_FileTable[fd] = NULL;
3390 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], get_user_struct()->u_cred);
3401 * Create a hard link from the source to the target
3402 * Note: file names may not end in a slash.
3405 uafs_link(char *existing, char *new)
3409 retval = uafs_link_r(existing, new);
3415 uafs_link_r(char *existing, char *new)
3418 struct usr_vnode *existP;
3419 struct usr_vnode *dirP;
3422 if (uafs_IsRoot(new)) {
3427 * Look up the existing node.
3429 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3436 * Look up the parent directory.
3438 nameP = uafs_LastPath(new);
3439 if (nameP != NULL) {
3440 code = uafs_LookupParent(new, &dirP);
3447 dirP = afs_CurrentDir;
3453 * Make sure the filename has at least one character
3455 if (*nameP == '\0') {
3465 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3476 * Create a symbolic link from the source to the target
3477 * Note: file names may not end in a slash.
3480 uafs_symlink(char *target, char *source)
3484 retval = uafs_symlink_r(target, source);
3490 uafs_symlink_r(char *target, char *source)
3493 struct usr_vnode *dirP;
3494 struct usr_vattr attrs;
3497 if (uafs_IsRoot(source)) {
3502 * Look up the parent directory.
3504 nameP = uafs_LastPath(source);
3505 if (nameP != NULL) {
3506 code = uafs_LookupParent(source, &dirP);
3512 dirP = afs_CurrentDir;
3518 * Make sure the filename has at least one character
3520 if (*nameP == '\0') {
3529 usr_vattr_null(&attrs);
3530 attrs.va_type = VLNK;
3531 attrs.va_mode = 0777;
3532 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
3533 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
3534 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
3544 * Read a symbolic link into the buffer
3547 uafs_readlink(char *path, char *buf, int len)
3551 retval = uafs_readlink_r(path, buf, len);
3557 uafs_readlink_r(char *path, char *buf, int len)
3560 struct usr_vnode *vp;
3562 struct iovec iov[1];
3564 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3570 if (vp->v_type != VLNK) {
3577 * set up the uio buffer
3579 iov[0].iov_base = buf;
3580 iov[0].iov_len = len;
3581 uio.uio_iov = &iov[0];
3585 uio.uio_fmode = FREAD;
3586 uio.uio_resid = len;
3591 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3599 * return the number of bytes read
3601 return (len - uio.uio_resid);
3605 * Remove a file (or directory)
3606 * Note: file name may not end in a slash.
3609 uafs_unlink(char *path)
3613 retval = uafs_unlink_r(path);
3619 uafs_unlink_r(char *path)
3622 struct usr_vnode *dirP;
3625 if (uafs_IsRoot(path)) {
3630 * Look up the parent directory.
3632 nameP = uafs_LastPath(path);
3633 if (nameP != NULL) {
3634 code = uafs_LookupParent(path, &dirP);
3640 dirP = afs_CurrentDir;
3646 * Make sure the filename has at least one character
3648 if (*nameP == '\0') {
3657 code = afs_remove(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3668 * Rename a file (or directory)
3671 uafs_rename(char *old, char *new)
3675 retval = uafs_rename_r(old, new);
3681 uafs_rename_r(char *old, char *new)
3686 struct usr_vnode *odirP;
3687 struct usr_vnode *ndirP;
3689 if (uafs_IsRoot(new)) {
3694 * Look up the parent directories.
3696 onameP = uafs_LastPath(old);
3697 if (onameP != NULL) {
3698 code = uafs_LookupParent(old, &odirP);
3704 odirP = afs_CurrentDir;
3708 nnameP = uafs_LastPath(new);
3709 if (nnameP != NULL) {
3710 code = uafs_LookupParent(new, &ndirP);
3716 ndirP = afs_CurrentDir;
3722 * Make sure the filename has at least one character
3724 if (*onameP == '\0' || *nnameP == '\0') {
3734 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, get_user_struct()->u_cred);
3746 * Remove a or directory
3747 * Note: file name may not end in a slash.
3750 uafs_rmdir(char *path)
3754 retval = uafs_rmdir_r(path);
3760 uafs_rmdir_r(char *path)
3763 struct usr_vnode *dirP;
3766 if (uafs_IsRoot(path)) {
3771 * Look up the parent directory.
3773 nameP = uafs_LastPath(path);
3774 if (nameP != NULL) {
3775 code = uafs_LookupParent(path, &dirP);
3781 dirP = afs_CurrentDir;
3787 * Make sure the directory name has at least one character
3789 if (*nameP == '\0') {
3796 * Remove the directory
3798 code = afs_rmdir(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3809 * Flush a file from the AFS cache
3812 uafs_FlushFile(char *path)
3815 struct afs_ioctl iob;
3823 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3834 uafs_FlushFile_r(char *path)
3838 retval = uafs_FlushFile(path);
3847 uafs_opendir(char *path)
3851 retval = uafs_opendir_r(path);
3857 uafs_opendir_r(char *path)
3860 struct usr_vnode *fileP;
3864 * Open the directory for reading
3866 fd = uafs_open_r(path, O_RDONLY, 0);
3871 fileP = afs_FileTable[fd];
3872 if (fileP == NULL) {
3876 if (fileP->v_type != VDIR) {
3883 * Set up the directory structures
3886 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3887 sizeof(struct usr_dirent));
3888 usr_assert(dirp != NULL);
3889 dirp->dd_buf = (char *)(dirp + 1);
3899 * Read directory entries into a file system independent format.
3900 * This routine was developed to support AFS cache consistency testing.
3901 * You should use uafs_readdir instead.
3904 uafs_getdents(int fd, struct min_direct *buf, int len)
3908 retval = uafs_getdents_r(fd, buf, len);
3914 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3918 struct usr_vnode *vp;
3919 struct iovec iov[1];
3922 * Make sure this is an open file
3924 vp = afs_FileTable[fd];
3932 * set up the uio buffer
3934 iov[0].iov_base = (char *)buf;
3935 iov[0].iov_len = len;
3936 uio.uio_iov = &iov[0];
3938 uio.uio_offset = afs_FileOffsets[fd];
3940 uio.uio_fmode = FREAD;
3941 uio.uio_resid = len;
3944 * read the next chunk from the directory
3946 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3952 afs_FileOffsets[fd] = uio.uio_offset;
3953 return (len - uio.uio_resid);
3957 * read from a directory (names only)
3960 uafs_readdir(usr_DIR * dirp)
3962 struct usr_dirent *retval;
3964 retval = uafs_readdir_r(dirp);
3970 uafs_readdir_r(usr_DIR * dirp)
3975 struct usr_vnode *vp;
3976 struct iovec iov[1];
3977 struct usr_dirent *direntP;
3978 struct min_direct *directP;
3986 * Make sure this is an open file
3988 vp = afs_FileTable[dirp->dd_fd];
3995 * If there are no entries in the stream buffer
3996 * then read another chunk
3998 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3999 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
4001 * set up the uio buffer
4003 iov[0].iov_base = dirp->dd_buf;
4004 iov[0].iov_len = USR_DIRSIZE;
4005 uio.uio_iov = &iov[0];
4007 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
4009 uio.uio_fmode = FREAD;
4010 uio.uio_resid = USR_DIRSIZE;
4013 * read the next chunk from the directory
4015 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
4020 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
4022 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
4024 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
4028 * Check for end of file
4030 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
4034 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
4035 usr_assert(len <= dirp->dd_size);
4038 * Copy the next entry into the usr_dirent structure and advance
4040 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
4041 direntP->d_ino = directP->d_fileno;
4042 direntP->d_off = direntP->d_reclen;
4044 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
4045 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
4046 direntP->d_name[directP->d_namlen] = '\0';
4047 dirp->dd_loc += len;
4048 dirp->dd_size -= len;
4057 uafs_closedir(usr_DIR * dirp)
4061 retval = uafs_closedir_r(dirp);
4067 uafs_closedir_r(usr_DIR * dirp)
4078 afs_osi_Free((char *)dirp,
4079 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4080 rc = uafs_close_r(fd);
4085 * Do AFS authentication
4088 uafs_klog(char *user, char *cell, char *passwd, char **reason)
4091 afs_int32 password_expires = -1;
4093 usr_mutex_lock(&osi_authenticate_lock);
4095 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
4096 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
4097 passwd, 0, &password_expires, 0, reason);
4098 usr_mutex_unlock(&osi_authenticate_lock);
4103 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
4107 retval = uafs_klog(user, cell, passwd, reason);
4113 * Destroy AFS credentials from the kernel cache
4120 usr_mutex_lock(&osi_authenticate_lock);
4121 code = ktc_ForgetAllTokens();
4122 usr_mutex_unlock(&osi_authenticate_lock);
4131 retval = uafs_unlog();
4137 * Strip the AFS mount point from a pathname string. Return
4138 * NULL if the path is a relative pathname or if the path
4139 * doesn't start with the AFS mount point string.
4142 uafs_afsPathName(char *path)
4151 for (i = 1, p = path + 1; *p != '\0'; p++) {
4152 /* Ignore duplicate slashes */
4153 if (*p == '/' && lastchar == '/')
4155 /* Is this a subdirectory of the AFS mount point? */
4156 if (afs_mountDir[i] == '\0' && *p == '/') {
4157 /* strip leading slashes */
4158 while (*(++p) == '/');
4161 /* Reject paths that are not within AFS */
4162 if (*p != afs_mountDir[i])
4167 /* Is this the AFS mount point? */
4168 if (afs_mountDir[i] == '\0') {
4169 usr_assert(*p == '\0');
4175 #ifdef AFS_WEB_ENHANCEMENTS
4178 * klog but don't allocate a new pag
4181 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
4184 afs_int32 password_expires = -1;
4186 usr_mutex_lock(&osi_authenticate_lock);
4187 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
4188 /*+KA_USERAUTH_DOSETPAG2 */ , user,
4189 NULL, cell, passwd, 0,
4190 &password_expires, 0, reason);
4191 usr_mutex_unlock(&osi_authenticate_lock);
4196 * uafs_getcellstatus
4197 * get the cell status
4200 uafs_getcellstatus(char *cell, afs_int32 * status)
4203 struct afs_ioctl iob;
4206 iob.in_size = strlen(cell) + 1;
4210 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
4218 *status = (intptr_t)iob.out;
4224 * Get quota of volume associated with path
4227 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
4230 struct afs_ioctl iob;
4231 VolumeStatus *status;
4237 iob.out_size = 1024;
4239 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
4247 status = (VolumeStatus *) buf;
4248 *BlocksInUse = status->BlocksInUse;
4249 *MaxQuota = status->MaxQuota;
4255 * Set quota of volume associated with path
4258 uafs_setvolquota(char *path, afs_int32 MaxQuota)
4261 struct afs_ioctl iob;
4262 VolumeStatus *status;
4270 memset(buf, 0, sizeof(VolumeStatus));
4271 status = (VolumeStatus *) buf;
4272 status->MaxQuota = MaxQuota;
4273 status->MinQuota = -1;
4275 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
4287 * uafs_statmountpoint
4288 * Determine whether a dir. is a mount point or not
4289 * return 1 if mount point, 0 if not
4292 uafs_statmountpoint(char *path)
4297 retval = uafs_statmountpoint_r(path);
4303 uafs_statmountpoint_r(char *path)
4310 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4325 * Get a list of rights for the current user on path.
4328 uafs_getRights(char *path)
4335 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4343 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
4344 | PRSFS_LOCK | PRSFS_ADMINISTER;
4346 afs_rights = afs_getRights(VTOAFS(vp), afs_rights, get_user_struct()->u_cred);
4351 #endif /* AFS_WEB_ENHANCEMENTS */
4353 #endif /* UKERNEL */