2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * User space client specific interface glue
14 #include <afsconfig.h>
15 #include "../afs/param.h"
22 #include "../afs/sysincludes.h" /* Standard vendor system headers */
24 #include "../afs/afsincludes.h" /* Afs-based standard headers */
25 #include "../afs/afs_usrops.h"
26 #include "../afs/afs_stats.h"
27 #include "../afs/auth.h"
28 #include "../afs/cellconfig.h"
29 #include "../afs/vice.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"
45 #define MIN(A,B) ((A)<(B)?(A):(B))
48 #define MAX(A,B) ((A)>(B)?(A):(B))
51 extern int cacheDiskType;
53 char afs_LclCellName[64];
55 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
56 int afs_FileFlags[MAX_OSI_FILES];
57 int afs_FileOffsets[MAX_OSI_FILES];
59 #define MAX_CACHE_LOOPS 4
61 struct usr_vfs afs_RootVfs;
62 struct usr_vnode *afs_RootVnode = NULL;
63 struct usr_vnode *afs_CurrentDir = NULL;
65 afs_int32 cacheBlocks; /* Num blocks in cache */
66 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
67 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
68 char cacheBaseDir[1024]; /* AFS cache directory */
69 char confDir[1024]; /* AFS configuration directory */
70 char afs_mountDir[1024]; /* AFS mount point */
71 int afs_mountDirLen; /* strlen of AFS mount point */
72 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
73 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
74 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
75 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
76 char fullpn_VFile[1024]; /* Full pathname of data cache files */
77 char *vFileNumber; /* Ptr to number in file pathname */
78 char rootVolume[64] = "root.afs"; /* AFS root volume name */
79 afs_int32 isHomeCell; /* Is current cell info for home cell */
80 afs_int32 lookingForHomeCell; /* Are we still looking for home cell */
81 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
82 int ownerRWmode = 0600; /* Read/write OK by owner */
83 static int nDaemons = 2; /* Number of background daemons */
84 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
85 static int dCacheSize = 300; /* # of dcache entries */
86 static int vCacheSize = 50; /* # of volume cache entries */
87 static int cacheFlags = 0; /* Flags to cache manager */
88 static int preallocs = 400; /* Def # of allocated memory blocks */
89 int afsd_verbose = 0; /* Are we being chatty? */
90 int afsd_debug = 0; /* Are we printing debugging info? */
91 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
93 #define AFSD_INO_T afs_uint32
94 char **pathname_for_V; /* Array of cache file pathnames */
95 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
96 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
97 struct afs_cacheParams cparams; /* params passed to cache manager */
98 struct afsconf_dir *afs_cdir; /* config dir */
100 static int HandleMTab();
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;
108 struct usr_ucred *afs_global_ucredp;
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;
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);
144 * Hash table mapping addresses onto wait structures for
145 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
147 typedef struct osi_wait {
151 struct osi_wait *next;
152 struct osi_wait *prev;
154 struct osi_wait *timedNext;
155 struct osi_wait *timedPrev;
159 * Head of the linked list of available waitq structures.
161 osi_wait_t *osi_waithash_avail;
164 * List of timed waits, NSAPI does not provide a cond_timed
165 * wait, so we need to keep track of the timed waits ourselves and
166 * periodically check for expirations
168 osi_wait_t *osi_timedwait_head;
169 osi_wait_t *osi_timedwait_tail;
174 } osi_waithash_table[OSI_WAITHASH_SIZE];
177 * Never call afs_brelse
179 int ufs_brelse(vp, bp)
180 struct usr_vnode *vp;
187 * I am not sure what to do with these, they assert for now
195 struct usr_file *getf(fd)
202 * Every user is a super user
204 int afs_osi_suser(credp)
205 struct usr_ucred *credp;
211 struct usr_ucred *credp;
217 * These are no-ops in user space
220 int afs_osi_SetTime(atv)
227 * xflock should never fall through, the only files we know
228 * about are AFS files
236 * ioctl should never fall through, the only files we know
237 * about are AFS files
245 * We do not support the inode related system calls
247 int afs_syscall_icreate()
252 int afs_syscall_iincdec()
257 int afs_syscall_iopen()
262 int afs_syscall_ireadwrite()
268 * these routines are referenced in the vfsops structure, but
269 * should never get called
292 * uiomove copies data between kernel buffers and uio buffers
294 int usr_uiomove(kbuf, n, rw, uio)
305 nio = uio->uio_iovcnt;
315 while(nio > 0 && n > 0) {
316 len = MIN(n, iovp->iov_len);
317 if (rw == UIO_READ) {
318 memcpy(iovp->iov_base, ptr, len);
320 memcpy(ptr, iovp->iov_base, len);
324 uio->uio_resid -= len;
325 uio->uio_offset += len;
326 iovp->iov_base = (char *)(iovp->iov_base) + len;
327 iovp->iov_len -= len;
338 * routines to manage user credentials
340 struct usr_ucred *usr_crcopy(credp)
341 struct usr_ucred *credp;
343 struct usr_ucred *newcredp;
345 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
347 newcredp->cr_ref = 1;
351 struct usr_ucred *usr_crget()
353 struct usr_ucred *newcredp;
355 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
356 newcredp->cr_ref = 1;
360 int usr_crfree(credp)
361 struct usr_ucred *credp;
364 if (credp->cr_ref == 0) {
365 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
369 int usr_crhold(credp)
370 struct usr_ucred *credp;
375 void usr_vattr_null(vap)
376 struct usr_vattr *vap;
381 n = sizeof(struct usr_vattr);
389 * Initialize the thread specific data used to simulate the
390 * kernel environment for each thread. The user structure
391 * is stored in the thread specific data.
393 void uafs_InitThread()
396 struct usr_user *uptr;
399 * initialize the thread specific user structure. Use malloc to
400 * allocate the data block, so pthread_finish can free the buffer
401 * when this thread terminates.
403 uptr = (struct usr_user *)malloc(sizeof(struct usr_user) +
404 sizeof(struct usr_ucred));
405 usr_assert(uptr != NULL);
408 uptr->u_procp = afs_global_procp;
409 uptr->u_cred = (struct usr_ucred *)(uptr+1);
410 *uptr->u_cred = *afs_global_ucredp;
411 st = usr_setspecific(afs_global_u_key, (void *)uptr);
416 * routine to get the user structure from the thread specific data.
417 * this routine is used to implement the global 'u' structure. Initializes
418 * the thread if needed.
420 struct usr_user *get_user_struct()
422 struct usr_user *uptr;
424 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
428 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
430 usr_assert(uptr != NULL);
436 * Hash an address for the waithash table
438 #define WAITHASH(X) \
439 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
449 int rxGlockOwner = ISAFS_RXGLOCK();
450 int glockOwner = ISAFS_GLOCK();
452 usr_mutex_lock(&osi_waitq_lock);
460 if (osi_waithash_avail == NULL) {
461 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
462 usr_cond_init(&waitp->cond);
464 waitp = osi_waithash_avail;
465 osi_waithash_avail = osi_waithash_avail->next;
469 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
470 osi_waithash_table[index].tail, next, prev);
471 waitp->expiration = 0;
472 waitp->timedNext = NULL;
473 waitp->timedPrev = NULL;
474 while (waitp->flag == 0) {
475 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
477 DLL_DELETE(waitp, osi_waithash_table[index].head,
478 osi_waithash_table[index].tail, next, prev);
479 waitp->next = osi_waithash_avail;
480 osi_waithash_avail = waitp;
481 usr_mutex_unlock(&osi_waitq_lock);
490 int afs_osi_Wakeup(x)
497 usr_mutex_lock(&osi_waitq_lock);
498 waitp = osi_waithash_table[index].head;
500 if (waitp->addr == x && waitp->flag == 0) {
502 usr_cond_signal(&waitp->cond);
506 usr_mutex_unlock(&osi_waitq_lock);
509 int afs_osi_Wait(msec, handle, intok)
511 struct afs_osi_WaitHandle *handle;
518 int rxGlockOwner = ISAFS_RXGLOCK();
519 int glockOwner = ISAFS_GLOCK();
521 tv.tv_sec = msec / 1000;
522 tv.tv_nsec = (msec % 1000) * 1000000;
523 if (handle == NULL) {
530 usr_thread_sleep(&tv);
539 usr_mutex_lock(&osi_waitq_lock);
546 index = WAITHASH((caddr_t)handle);
547 if (osi_waithash_avail == NULL) {
548 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
549 usr_cond_init(&waitp->cond);
551 waitp = osi_waithash_avail;
552 osi_waithash_avail = osi_waithash_avail->next;
554 waitp->addr = (caddr_t)handle;
556 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
557 osi_waithash_table[index].tail, next, prev);
558 tv.tv_sec += time(NULL);
559 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0)?0:1);
560 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
561 timedNext, timedPrev);
562 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
568 DLL_DELETE(waitp, osi_waithash_table[index].head,
569 osi_waithash_table[index].tail, next, prev);
570 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail,
571 timedNext, timedPrev);
572 waitp->next = osi_waithash_avail;
573 osi_waithash_avail = waitp;
574 usr_mutex_unlock(&osi_waitq_lock);
585 void afs_osi_CancelWait(handle)
586 struct afs_osi_WaitHandle *handle;
588 afs_osi_Wakeup((caddr_t)handle);
592 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
593 * to explicitly signal cond_timed_waits when their timers expire
595 int afs_osi_CheckTimedWaits()
600 curTime = time(NULL);
601 usr_mutex_lock(&osi_waitq_lock);
602 waitp = osi_timedwait_head;
603 while (waitp != NULL) {
604 usr_assert(waitp->expiration != 0);
605 if (waitp->expiration <= curTime) {
607 usr_cond_signal(&waitp->cond);
609 waitp = waitp->timedNext;
611 usr_mutex_unlock(&osi_waitq_lock);
615 * I-node numbers are indeces into a table containing a filename
616 * i-node structure and a vnode structure. When we create an i-node,
617 * we copy the name into the array and initialize enough of the fields
618 * in the inode and vnode structures to get the client to work.
621 struct usr_inode i_node;
624 osi_file_table_t *osi_file_table;
626 int max_osi_files = 0;
629 * Allocate a slot in the file table if there is not one there already,
630 * copy in the file name and kludge up the vnode and inode structures
632 int lookupname(fnamep, segflg, followlink, dirvpp, compvpp)
636 struct usr_vnode **dirvpp;
637 struct usr_vnode **compvpp;
641 struct usr_inode *ip;
642 struct usr_vnode *vp;
644 /*usr_assert(followlink == 0);*/
645 usr_assert(dirvpp == NULL);
648 * Assume relative pathnames refer to files in AFS
650 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
652 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
657 usr_mutex_lock(&osi_inode_lock);
659 for (i = 0 ; i < n_osi_files ; i++) {
660 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
661 *compvpp = &osi_file_table[i].i_node.i_vnode;
662 (*compvpp)->v_count++;
663 usr_mutex_unlock(&osi_inode_lock);
668 if (n_osi_files == max_osi_files) {
669 usr_mutex_unlock(&osi_inode_lock);
673 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep)+1);
674 usr_assert(osi_file_table[n_osi_files].name != NULL);
675 strcpy(osi_file_table[n_osi_files].name, fnamep);
676 ip = &osi_file_table[i].i_node;
678 vp->v_data = (caddr_t)ip;
681 ip->i_number = n_osi_files;
683 usr_mutex_unlock(&osi_inode_lock);
689 * open a file given its i-node number
691 void *osi_UFSOpen(ino)
700 if (ino > n_osi_files) {
706 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
707 usr_assert(fp != NULL);
708 fp->fd = open(osi_file_table[ino-1].name, O_RDWR|O_CREAT, 0);
711 afs_osi_Free((char *)fp, sizeof(struct osi_file));
715 rc = fstat(fp->fd, &st);
718 afs_osi_Free((void *)fp, sizeof(struct osi_file));
722 fp->size = st.st_size;
725 fp->vnode = (struct usr_vnode *)fp;
742 afs_osi_Free((void *)fp, sizeof(struct osi_file));
746 afs_osi_Free((void *)fp, sizeof(struct osi_file));
751 int osi_UFSTruncate(fp, len)
760 rc = ftruncate(fp->fd, len);
771 int afs_osi_Read(fp, offset, buf, len)
785 rc = lseek(fp->fd, offset, SEEK_SET);
787 rc = lseek(fp->fd, fp->offset, SEEK_SET);
795 ret = read(fp->fd, buf, len);
802 rc = fstat(fp->fd, &st);
808 fp->size = st.st_size;
813 int afs_osi_Write(fp, offset, buf, len)
827 rc = lseek(fp->fd, offset, SEEK_SET);
829 rc = lseek(fp->fd, fp->offset, SEEK_SET);
837 ret = write(fp->fd, buf, len);
844 rc = fstat(fp->fd, &st);
850 fp->size = st.st_size;
855 int afs_osi_Stat(fp, stp)
857 struct osi_stat *stp;
863 rc = fstat(fp->fd, &st);
869 stp->size = st.st_size;
870 stp->blksize = st.st_blksize;
871 stp->mtime = st.st_mtime;
872 stp->atime = st.st_atime;
880 int afs_osi_VOP_RDWR(
881 struct usr_vnode *vnodeP,
882 struct usr_uio *uioP,
885 struct usr_ucred* credP)
888 struct osi_file *fp = (struct osi_file *)vnodeP;
891 * We don't support readv/writev.
893 usr_assert(uioP->uio_iovcnt == 1);
894 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
896 if (rw == UIO_WRITE) {
897 usr_assert(uioP->uio_fmode == FWRITE);
898 rc = afs_osi_Write(fp, uioP->uio_offset,
899 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,
904 uioP->uio_iov[0].iov_base,
905 uioP->uio_iov[0].iov_len);
911 uioP->uio_resid -= rc;
912 uioP->uio_offset += rc;
913 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
914 uioP->uio_iov[0].iov_len -= rc;
919 * Use malloc/free routines with check patterns before and after each block
922 static char *afs_check_string1 = "UAFS";
923 static char *afs_check_string2 = "AFS_OSI_";
925 void *afs_osi_Alloc(size_t size)
930 void afs_osi_Free(void *ptr, size_t size)
935 void *osi_AllocLargeSpace(size_t size)
937 AFS_STATCNT(osi_AllocLargeSpace);
938 return afs_osi_Alloc(size);
941 void osi_FreeLargeSpace(void *ptr)
943 AFS_STATCNT(osi_FreeLargeSpace);
944 afs_osi_Free(ptr, 0);
947 void *osi_AllocSmallSpace(size_t size)
949 AFS_STATCNT(osi_AllocSmallSpace);
950 return afs_osi_Alloc(size);
953 void osi_FreeSmallSpace(void *ptr)
955 AFS_STATCNT(osi_FreeSmallSpace);
956 afs_osi_Free(ptr, 0);
961 AFS_STATCNT(shutdown_osi);
965 void shutdown_osinet()
967 AFS_STATCNT(shutdown_osinet);
971 void shutdown_osifile()
973 AFS_STATCNT(shutdown_osifile);
977 int afs_nfsclient_init()
982 void shutdown_nfsclnt()
987 int afs_osi_Invisible()
995 gettimeofday(tv, NULL);
1008 AFS_STATCNT(osi_Active);
1009 if (avc->opens > 0) return(1);
1013 int afs_osi_MapStrategy(aproc, bp)
1017 afs_int32 returnCode;
1018 returnCode = (*aproc)(bp);
1022 osi_FlushPages(avc, credp)
1023 register struct vcache *avc;
1024 struct AFS_UCRED *credp;
1026 ObtainSharedLock(&avc->lock,555);
1027 if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0) ||
1028 ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1029 ReleaseSharedLock(&avc->lock);
1032 UpgradeSToWLock(&avc->lock,565);
1033 hset(avc->mapDV, avc->m.DataVersion);
1034 ReleaseWriteLock(&avc->lock);
1038 osi_FlushText_really(vp)
1039 register struct vcache *vp;
1041 if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
1042 hset(vp->flushDV, vp->m.DataVersion);
1053 void osi_ReleaseVM(avc, len, credp)
1056 struct usr_ucred *credp;
1068 * Allocate the table used to implement psuedo-inodes.
1070 max_osi_files = cacheFiles + 100;
1071 osi_file_table = (osi_file_table_t *)
1072 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1073 usr_assert(osi_file_table != NULL);
1075 #ifndef NETSCAPE_NSAPI
1077 * Initialize the mutex and condition variable used to implement
1080 pthread_mutex_init(&usr_sleep_mutex, NULL);
1081 pthread_cond_init(&usr_sleep_cond, NULL);
1082 #endif /* !NETSCAPE_NSAPI */
1085 * Initialize the hash table used for sleep/wakeup
1087 for (i = 0 ; i < OSI_WAITHASH_SIZE ; i++) {
1088 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1090 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1091 osi_waithash_avail = NULL;
1094 * Initialize the AFS file table
1096 for (i = 0 ; i < MAX_OSI_FILES ; i++) {
1097 afs_FileTable[i] = NULL;
1101 * Initialize the global locks
1103 usr_mutex_init(&afs_global_lock);
1104 usr_mutex_init(&rx_global_lock);
1105 usr_mutex_init(&osi_inode_lock);
1106 usr_mutex_init(&osi_waitq_lock);
1107 usr_mutex_init(&osi_authenticate_lock);
1110 * Initialize the AFS OSI credentials
1112 afs_osi_cred = *afs_global_ucredp;
1115 /* ParseArgs is now obsolete, being handled by cmd */
1117 /*---------------------------------------------------------------------
1121 * Given the final component of a filename expected to be a data cache file,
1122 * return the integer corresponding to the file. Note: we reject names that
1123 * are not a ``V'' followed by an integer. We also reject those names having
1124 * the right format but lying outside the range [0..cacheFiles-1].
1127 * fname : Char ptr to the filename to parse.
1130 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1134 * Nothing interesting.
1138 *------------------------------------------------------------------------*/
1140 int GetVFileNumber(fname)
1143 int computedVNumber; /*The computed file number we return*/
1144 int filenameLen; /*Number of chars in filename*/
1145 int currDigit; /*Current digit being processed*/
1148 * The filename must have at least two characters, the first of which must be a ``V''
1149 * and the second of which cannot be a zero unless the file is exactly two chars long.
1151 filenameLen = strlen(fname);
1152 if (filenameLen < 2)
1154 if (fname[0] != 'V')
1156 if ((filenameLen > 2) && (fname[1] == '0'))
1160 * Scan through the characters in the given filename, failing immediately if a non-digit
1163 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1164 if (isdigit(fname[currDigit]) == 0)
1168 * All relevant characters are digits. Pull out the decimal number they represent.
1169 * Reject it if it's out of range, otherwise return it.
1171 computedVNumber = atoi(++fname);
1172 if (computedVNumber < cacheFiles)
1173 return(computedVNumber);
1178 /*---------------------------------------------------------------------
1182 * Given a full pathname for a file we need to create for the workstation AFS
1183 * cache, go ahead and create the file.
1186 * fname : Full pathname of file to create.
1189 * 0 iff the file was created,
1193 * The given cache file has been found to be missing.
1197 *------------------------------------------------------------------------*/
1199 int CreateCacheFile(fname)
1202 static char rn[] = "CreateCacheFile"; /*Routine name*/
1203 int cfd; /*File descriptor to AFS cache file*/
1204 int closeResult; /*Result of close()*/
1207 printf("%s: Creating cache file '%s'\n",
1209 cfd = open(fname, createAndTrunc, ownerRWmode);
1211 printf("%s: Can't create '%s', error return is %d (%d)\n",
1212 rn, fname, cfd, errno);
1215 closeResult = close(cfd);
1217 printf("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1225 /*---------------------------------------------------------------------
1229 * Sweep through the AFS cache directory, recording the inode number for
1230 * each valid data cache file there. Also, delete any file that doesn't beint32
1231 * in the cache directory during this sweep, and remember which of the other
1232 * residents of this directory were seen. After the sweep, we create any data
1233 * cache files that were missing.
1236 * vFilesFound : Set to the number of data cache files found.
1239 * 0 if everything went well,
1243 * This routine may be called several times. If the number of data cache files
1244 * found is less than the global cacheFiles, then the caller will need to call it
1245 * again to record the inodes of the missing zero-length data cache files created
1246 * in the previous call.
1249 * Fills up the global pathname_for_V array, may create and/or
1250 * delete files as explained above.
1251 *------------------------------------------------------------------------*/
1253 int SweepAFSCache(vFilesFound)
1256 static char rn[] = "SweepAFSCache"; /*Routine name*/
1257 char fullpn_FileToDelete[1024]; /*File to be deleted from cache*/
1258 char *fileToDelete; /*Ptr to last component of above*/
1259 DIR *cdirp; /*Ptr to cache directory structure*/
1261 struct dirent *currp; /*Current directory entry*/
1262 int vFileNum; /*Data cache file's associated number*/
1264 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1266 printf("%s: Memory Cache, no cache sweep done\n");
1272 printf("%s: Opening cache directory '%s'\n",
1275 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1276 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n",
1280 cdirp = opendir(cacheBaseDir);
1281 if (cdirp == (DIR *)0) {
1282 printf("%s: Can't open AFS cache directory, '%s'.\n",
1288 * Scan the directory entries, remembering data cache file inodes and the existance
1289 * of other important residents. Delete all files that don't belong here.
1292 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1293 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1295 for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
1298 printf("%s: Current directory entry:\n",
1300 printf("\tinode=%d, reclen=%d, name='%s'\n",
1301 currp->d_ino, currp->d_reclen, currp->d_name);
1305 * Guess current entry is for a data cache file.
1307 vFileNum = GetVFileNumber(currp->d_name);
1308 if (vFileNum >= 0) {
1310 * Found a valid data cache filename. Remember this file's name
1311 * and bump the number of files found.
1313 pathname_for_V[vFileNum] = afs_osi_Alloc(strlen(currp->d_name) +
1314 strlen(cacheBaseDir) + 2);
1315 usr_assert(pathname_for_V[vFileNum] != NULL);
1316 sprintf(pathname_for_V[vFileNum], "%s/%s",
1317 cacheBaseDir, currp->d_name);
1320 else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1322 * Found the file holding the dcache entries.
1324 missing_DCacheFile = 0;
1326 else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1328 * Found the file holding the volume info.
1330 missing_VolInfoFile = 0;
1332 else if ((strcmp(currp->d_name, ".") == 0) ||
1333 (strcmp(currp->d_name, "..") == 0) ||
1334 (strcmp(currp->d_name, "lost+found") == 0)) {
1336 * Don't do anything - this file is legit, and is to be left alone.
1341 * This file doesn't belong in the cache. Nuke it.
1343 sprintf(fileToDelete, "%s", currp->d_name);
1345 printf("%s: Deleting '%s'\n",
1346 rn, fullpn_FileToDelete);
1347 if (unlink(fullpn_FileToDelete)) {
1348 printf("%s: Can't unlink '%s', errno is %d\n",
1349 rn, fullpn_FileToDelete, errno);
1355 * Create all the cache files that are missing.
1357 if (missing_DCacheFile) {
1359 printf("%s: Creating '%s'\n",
1360 rn, fullpn_DCacheFile);
1361 if (CreateCacheFile(fullpn_DCacheFile))
1362 printf("%s: Can't create '%s'\n",
1363 rn, fullpn_DCacheFile);
1365 if (missing_VolInfoFile) {
1367 printf("%s: Creating '%s'\n",
1368 rn, fullpn_VolInfoFile);
1369 if (CreateCacheFile(fullpn_VolInfoFile))
1370 printf("%s: Can't create '%s'\n",
1371 rn, fullpn_VolInfoFile);
1374 if (*vFilesFound < cacheFiles) {
1376 * We came up short on the number of data cache files found. Scan through the inode
1377 * list and create all missing files.
1379 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1380 if (pathname_for_V[vFileNum] == (AFSD_INO_T)0) {
1381 sprintf(vFileNumber, "%d", vFileNum);
1383 printf("%s: Creating '%s'\n",
1385 if (CreateCacheFile(fullpn_VFile))
1386 printf("%s: Can't create '%s'\n",
1392 * Close the directory, return success.
1395 printf("%s: Closing cache directory.\n",
1401 static ConfigCell(aci, arock, adir)
1402 register struct afsconf_cell *aci;
1404 struct afsconf_dir *adir; {
1405 register int isHomeCell;
1407 afs_int32 cellFlags;
1408 afs_int32 hosts[MAXHOSTSPERCELL];
1410 /* figure out if this is the home cell */
1411 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1413 lookingForHomeCell = 0;
1414 cellFlags = 1; /* home cell, suid is ok */
1417 cellFlags = 2; /* not home, suid is forbidden */
1420 /* build address list */
1421 for(i=0;i<MAXHOSTSPERCELL;i++)
1422 bcopy(&aci->hostAddr[i].sin_addr, &hosts[i], sizeof(afs_int32));
1424 if (aci->linkedCell) cellFlags |= 4; /* Flag that linkedCell arg exists,
1425 for upwards compatibility */
1427 /* configure one cell */
1428 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2,
1429 (long)hosts, /* server addresses */
1430 (long)aci->name, /* cell name */
1431 (long)cellFlags, /* is this the home cell? */
1432 (long)aci->linkedCell); /* Linked cell, if any */
1437 * Set the UDP port number RX uses for UDP datagrams
1439 void uafs_SetRxPort(
1442 usr_assert(usr_rx_port == 0);
1448 * Initialize the user space client.
1452 char *mountDirParam,
1454 char *cacheBaseDirParam,
1455 int cacheBlocksParam,
1456 int cacheFilesParam,
1457 int cacheStatEntriesParam,
1458 int dCacheSizeParam,
1459 int vCacheSizeParam,
1461 int closeSynchParam,
1464 int cacheFlagsParam,
1468 struct usr_proc *procp;
1469 struct usr_ucred *ucredp;
1472 int currVFile; /* Current AFS cache file number */
1473 int lookupResult; /* Result of GetLocalCellName() */
1474 int cacheIteration; /* cache verification loop counter */
1475 int vFilesFound; /* Num data cache files found in sweep */
1477 afs_int32 vfs1_type = -1;
1478 struct afs_ioctl iob;
1482 afs_int32 buffer[MAXIPADDRS];
1483 afs_int32 maskbuffer[MAXIPADDRS];
1484 afs_int32 mtubuffer[MAXIPADDRS];
1487 * Use the thread specific data to implement the user structure
1489 usr_keycreate(&afs_global_u_key, free);
1492 * Initialize the global ucred structure
1494 afs_global_ucredp = (struct usr_ucred *)
1495 afs_osi_Alloc(sizeof(struct usr_ucred));
1496 usr_assert(afs_global_ucredp != NULL);
1497 afs_global_ucredp->cr_ref = 1;
1498 afs_global_ucredp->cr_uid = geteuid();
1499 afs_global_ucredp->cr_gid = getegid();
1500 afs_global_ucredp->cr_ruid = getuid();
1501 afs_global_ucredp->cr_rgid = getgid();
1502 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1503 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1504 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1505 usr_assert(st >= 0);
1506 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1507 for (i = st ; i < NGROUPS ; i++) {
1508 afs_global_ucredp->cr_groups[i] = NOGROUP;
1512 * Initialize the global process structure
1514 afs_global_procp = (struct usr_proc *)
1515 afs_osi_Alloc(sizeof(struct usr_proc));
1516 usr_assert(afs_global_procp != NULL);
1517 afs_global_procp->p_pid = getpid();
1518 afs_global_procp->p_ppid = (pid_t)1;
1519 afs_global_procp->p_ucred = afs_global_ucredp;
1522 * Initialize the AFS mount point, default is '/afs'.
1523 * Strip duplicate/trailing slashes from mount point string.
1524 * afs_mountDirLen is set to strlen(afs_mountDir).
1526 if (mountDirParam) {
1527 sprintf(tbuffer, "%s", mountDirParam);
1529 sprintf(tbuffer, "afs");
1531 afs_mountDir[0] = '/';
1532 afs_mountDirLen = 1;
1533 for (lastchar = '/', p = &tbuffer[0] ; *p != '\0' ; p++) {
1534 if (lastchar != '/' || *p != '/') {
1535 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1538 if (lastchar == '/' && afs_mountDirLen > 1)
1540 afs_mountDir[afs_mountDirLen] = '\0';
1541 usr_assert(afs_mountDirLen > 1);
1544 * Initialize cache parameters using the input arguments
1547 cacheBlocks = cacheBlocksParam;
1548 if (cacheFilesParam != 0) {
1549 cacheFiles = cacheFilesParam;
1551 cacheFiles = cacheBlocks/10;
1553 if (cacheStatEntriesParam != 0) {
1554 cacheStatEntries = cacheStatEntriesParam;
1556 strcpy(cacheBaseDir, cacheBaseDirParam);
1557 if (nDaemons != 0) {
1558 nDaemons = nDaemonsParam;
1562 afsd_verbose = debugParam;
1563 afsd_debug = debugParam;
1564 chunkSize = chunkSizeParam;
1565 if (dCacheSizeParam != 0) {
1566 dCacheSize = dCacheSizeParam;
1568 dCacheSize = cacheFiles/2;
1570 if (vCacheSizeParam != 0) {
1571 vCacheSize = vCacheSizeParam;
1573 strcpy(confDir, confDirParam);
1574 afsd_CloseSynch = closeSynchParam;
1575 if (cacheFlagsParam >= 0) {
1576 cacheFlags = cacheFlagsParam;
1578 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1579 cacheFiles = dCacheSize;
1582 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1583 if (logFile == NULL) {
1584 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1586 strcpy(fullpn_AFSLogFile, logFile);
1589 printf("\n%s: Initializing user space AFS client\n\n", rn);
1590 printf(" mountDir: %s\n", afs_mountDir);
1591 printf(" confDir: %s\n", confDir);
1592 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1593 printf(" cacheBlocks: %d\n", cacheBlocks);
1594 printf(" cacheFiles: %d\n", cacheFiles);
1595 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1596 printf(" dCacheSize: %d\n", dCacheSize);
1597 printf(" vCacheSize: %d\n", vCacheSize);
1598 printf(" chunkSize: %d\n", chunkSize);
1599 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1600 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1601 printf(" nDaemons: %d\n", nDaemons);
1602 printf(" cacheFlags: %d\n", cacheFlags);
1603 printf(" logFile: %s\n", fullpn_AFSLogFile);
1608 * Initialize the AFS client
1613 * Pull out all the configuration info for the workstation's AFS cache and
1614 * the cellular community we're willing to let our users see.
1616 afs_cdir = afsconf_Open(confDir);
1618 printf("afsd: some file missing or bad in %s\n", confDir);
1622 lookupResult = afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1623 sizeof(afs_LclCellName));
1625 printf("%s: Can't get my home cell name! [Error is %d]\n",
1630 printf("%s: My home cell is '%s'\n",
1631 rn, afs_LclCellName);
1634 if ((logfd = fopen(fullpn_AFSLogFile,"r+")) == 0) {
1635 if (afsd_verbose) printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1636 if (CreateCacheFile(fullpn_AFSLogFile)) {
1637 printf("%s: Can't create '%s' (You may want to use the -logfile option)\n", rn, fullpn_AFSLogFile);
1644 * Create and zero the pathname table for the desired cache files.
1646 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1647 if (pathname_for_V == NULL) {
1648 printf("%s: malloc() failed for cache file table with %d entries.\n",
1652 bzero(pathname_for_V, (cacheFiles * sizeof(char *)));
1654 printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n",
1655 rn, cacheFiles, (cacheFiles * sizeof(AFSD_INO_T)));
1658 * Set up all the pathnames we'll need for later.
1660 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1661 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1662 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1663 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1666 * Start the RX listener.
1669 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1670 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE);
1673 * Start the RX event handler.
1676 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1677 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1680 * Set up all the kernel processes needed for AFS.
1683 /* initialize AFS callback interface */
1685 /* parse multihomed address files */
1687 st=parseNetFiles(buffer,maskbuffer,mtubuffer,MAXIPADDRS,reason,
1688 AFSDIR_CLIENT_NETINFO_FILEPATH,
1689 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1691 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st, (long) (&buffer[0]),
1692 (long) (&maskbuffer[0]), (long) (&mtubuffer[0]));
1694 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",reason);
1700 printf("%s: Forking rx callback listener.\n", rn);
1702 if (preallocs < cacheStatEntries+50)
1703 preallocs = cacheStatEntries+50;
1704 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1707 printf("%s: Forking AFS daemon.\n", rn);
1708 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1711 printf("%s: Forking check server daemon.\n", rn);
1712 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1715 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1716 for (i=0;i<nDaemons;i++) {
1717 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1721 * Tell the kernel about each cell in the configuration.
1723 lookingForHomeCell = 1;
1725 afsconf_CellApply(afs_cdir, ConfigCell, (char *) 0);
1728 * If we're still looking for the home cell after the whole cell
1729 * configuration database has been parsed, there's something wrong.
1731 if (lookingForHomeCell) {
1732 printf("%s: Can't find home cell '%s' in cell database!\n",
1733 rn, afs_LclCellName);
1737 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n",
1739 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1742 * Tell the kernel some basic information about the workstation's cache.
1745 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1746 " %d optimum cache files, %d blocks in the cache,"
1747 " flags = 0x%x, dcache entries %d\n",
1748 rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
1750 bzero(&cparams, sizeof(cparams));
1751 cparams.cacheScaches = cacheStatEntries;
1752 cparams.cacheFiles = cacheFiles;
1753 cparams.cacheBlocks = cacheBlocks;
1754 cparams.cacheDcaches = dCacheSize;
1755 cparams.cacheVolumes = vCacheSize;
1756 cparams.chunkSize = chunkSize;
1757 cparams.setTimeFlag = FALSE;
1758 cparams.memCacheFlag = cacheFlags;
1759 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1760 if (afsd_CloseSynch)
1761 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1764 * Sweep the workstation AFS cache directory, remembering the inodes of
1765 * valid files and deleting extraneous files. Keep sweeping until we
1766 * have the right number of data cache files or we've swept too many
1770 printf("%s: Sweeping workstation's AFS cache directory.\n",
1773 /* Memory-cache based system doesn't need any of this */
1774 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1777 if (SweepAFSCache(&vFilesFound)) {
1778 printf("%s: Error on sweep %d of workstation AFS cache \
1779 directory.\n", rn, cacheIteration);
1783 printf("%s: %d out of %d data cache files found in sweep %d.\n",
1784 rn, vFilesFound, cacheFiles, cacheIteration);
1785 } while ((vFilesFound < cacheFiles) &&
1786 (cacheIteration < MAX_CACHE_LOOPS));
1787 } else if(afsd_verbose)
1788 printf("%s: Using memory cache, not swept\n", rn);
1791 * Pass the kernel the name of the workstation cache file holding the
1795 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
1796 rn, fullpn_DCacheFile);
1797 /* once again, meaningless for a memory-based cache. */
1798 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1799 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1804 * Pass the kernel the name of the workstation cache file holding the
1805 * volume information.
1808 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n",
1809 rn, fullpn_VolInfoFile);
1810 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO,(long)fullpn_VolInfoFile,
1814 * Pass the kernel the name of the afs logging file holding the volume
1818 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n",
1819 rn, fullpn_AFSLogFile);
1820 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1821 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG,(long)fullpn_AFSLogFile,
1825 * Give the kernel the names of the AFS files cached on the workstation's
1829 printf("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1830 rn, cacheFiles, cacheBaseDir);
1831 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1832 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1833 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1834 (long)pathname_for_V[currVFile], 0, 0, 0);
1837 #ifndef NETSCAPE_NSAPI
1839 * Copy our tokens from the kernel to the user space client
1841 for(i = 0 ; i < 200 ; i++) {
1843 * Get the i'th token from the kernel
1845 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1846 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1848 iob.in_size = sizeof(int);
1850 iob.out_size = sizeof(tbuffer);
1852 #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)
1853 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1854 #elif defined(AFS_USR_SGI_ENV)
1855 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1856 #else /* AFS_USR_AIX_ENV */
1857 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1860 usr_assert(errno == EDOM);
1865 * Now pass the token into the user space kernel
1867 rc = uafs_SetTokens(tbuffer, iob.out_size);
1868 usr_assert(rc == 0);
1870 #endif /* !NETSCAPE_NSAPI */
1873 * All the necessary info has been passed into the kernel to run an AFS
1874 * system. Give the kernel our go-ahead.
1877 printf("%s: Calling AFSOP_GO\n", rn);
1878 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1881 * At this point, we have finished passing the kernel all the info
1882 * it needs to set up the AFS. Mount the AFS root.
1884 printf("%s: All AFS daemons started.\n", rn);
1887 printf("%s: Forking trunc-cache daemon.\n", rn);
1888 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1891 * Mount the AFS filesystem
1894 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1895 usr_assert(rc == 0);
1896 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1897 usr_assert(rc == 0);
1901 * initialize the current directory to the AFS root
1903 afs_CurrentDir = afs_RootVnode;
1904 VN_HOLD(afs_CurrentDir);
1909 void uafs_Shutdown()
1916 VN_RELE(afs_CurrentDir);
1917 rc = afs_unmount(&afs_RootVfs);
1918 usr_assert(rc == 0);
1925 * Donate the current thread to the RX server pool.
1927 void uafs_RxServerProc()
1931 struct rx_call *newcall = NULL;
1933 rxi_MorePackets(2); /* alloc more packets */
1934 threadID = rxi_availProcs++;
1937 sock = OSI_NULLSOCKET;
1938 rxi_ServerProc(threadID, newcall, &sock);
1939 if (sock == OSI_NULLSOCKET) {
1944 rxi_ListenerProc(sock, &threadID, &newcall);
1945 /* assert(threadID != -1); */
1946 /* assert(newcall != NULL); */
1950 struct syscallThreadArgs {
1959 #ifdef NETSCAPE_NSAPI
1960 void syscallThread(argp)
1961 #else /* NETSCAPE_NSAPI */
1962 void *syscallThread(argp)
1963 #endif /* NETSCAPE_NSAPI */
1967 struct usr_ucred *crp;
1968 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1971 * AFS daemons run authenticated
1973 u.u_viceid = getuid();
1975 crp->cr_uid = getuid();
1976 crp->cr_ruid = getuid();
1977 crp->cr_suid = getuid();
1978 crp->cr_groups[0] = getgid();
1979 crp->cr_ngroups = 1;
1980 for (i = 1 ; i < NGROUPS ; i++) {
1981 crp->cr_groups[i] = NOGROUP;
1984 call_syscall(sysArgsP->syscall, sysArgsP->afscall,
1985 sysArgsP->param1, sysArgsP->param2,
1986 sysArgsP->param3, sysArgsP->param4);
1988 afs_osi_Free(argp, -1);
1991 fork_syscall(syscall, afscall, param1, param2, param3, param4)
1992 long syscall, afscall, param1, param2, param3, param4;
1995 struct syscallThreadArgs *sysArgsP;
1997 sysArgsP = (struct syscallThreadArgs *)
1998 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1999 usr_assert(sysArgsP != NULL);
2000 sysArgsP->syscall = syscall;
2001 sysArgsP->afscall = afscall;
2002 sysArgsP->param1 = param1;
2003 sysArgsP->param2 = param2;
2004 sysArgsP->param3 = param3;
2005 sysArgsP->param4 = param4;
2007 usr_thread_create(&tid, syscallThread, sysArgsP);
2008 usr_thread_detach(tid);
2011 call_syscall(syscall, afscall, param1, param2, param3, param4)
2012 long syscall, afscall, param1, param2, param3, param4;
2024 a.syscall = syscall;
2025 a.afscall = afscall;
2032 u.u_ap = (char *)&a;
2034 code = Afs_syscall();
2038 int uafs_SetTokens(char *tbuffer, int tlen)
2041 struct afs_ioctl iob;
2046 iob.out = &outbuf[0];
2047 iob.out_size = sizeof(outbuf);
2048 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2056 int uafs_RPCStatsEnableProc()
2059 struct afs_ioctl iob;
2062 flag = AFSCALL_RXSTATS_ENABLE;
2063 iob.in = (char *)&flag;
2064 iob.in_size = sizeof(afs_int32);
2067 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2075 int uafs_RPCStatsDisableProc()
2078 struct afs_ioctl iob;
2081 flag = AFSCALL_RXSTATS_DISABLE;
2082 iob.in = (char *)&flag;
2083 iob.in_size = sizeof(afs_int32);
2086 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2094 int uafs_RPCStatsClearProc()
2097 struct afs_ioctl iob;
2100 flag = AFSCALL_RXSTATS_CLEAR;
2101 iob.in = (char *)&flag;
2102 iob.in_size = sizeof(afs_int32);
2105 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2113 int uafs_RPCStatsEnablePeer()
2116 struct afs_ioctl iob;
2119 flag = AFSCALL_RXSTATS_ENABLE;
2120 iob.in = (char *)&flag;
2121 iob.in_size = sizeof(afs_int32);
2124 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2132 int uafs_RPCStatsDisablePeer()
2135 struct afs_ioctl iob;
2138 flag = AFSCALL_RXSTATS_DISABLE;
2139 iob.in = (char *)&flag;
2140 iob.in_size = sizeof(afs_int32);
2143 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2151 int uafs_RPCStatsClearPeer()
2154 struct afs_ioctl iob;
2157 flag = AFSCALL_RXSTATS_CLEAR;
2158 iob.in = (char *)&flag;
2159 iob.in_size = sizeof(afs_int32);
2162 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2171 * Lookup a file or directory given its path.
2172 * Call VN_HOLD on the output vnode if successful.
2173 * Returns zero on success, error code on failure.
2175 * Note: Caller must hold the AFS global lock.
2177 int uafs_LookupName(
2179 struct usr_vnode *parentVp,
2180 struct usr_vnode **vpp,
2186 struct usr_vnode *vp;
2187 struct usr_vnode *nextVp;
2188 struct usr_vnode *linkVp;
2196 * Absolute paths must start with the AFS mount point.
2198 if (path[0] != '/') {
2201 path = uafs_afsPathName(path);
2209 * Loop through the path looking for the new directory
2211 tmpPath = afs_osi_Alloc(strlen(path)+1);
2212 usr_assert(tmpPath != NULL);
2213 strcpy(tmpPath, path);
2216 while (pathP != NULL && *pathP != '\0') {
2217 usr_assert(*pathP != '/');
2220 * terminate the current component and skip over slashes
2222 nextPathP = strchr(pathP, '/');
2223 if (nextPathP != NULL) {
2224 while (*nextPathP == '/') {
2225 *(nextPathP++) = '\0';
2230 * Don't call afs_lookup on non-directories
2232 if (vp->v_type != VDIR) {
2234 afs_osi_Free(tmpPath, strlen(path)+1);
2238 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2240 * The AFS root is its own parent
2242 nextVp = afs_RootVnode;
2245 * We need execute permission to search a directory
2247 code = afs_access(vp, VEXEC, u.u_cred);
2250 afs_osi_Free(tmpPath, strlen(path)+1);
2255 * lookup the next component in the path, we can release the
2256 * subdirectory since we hold the global lock
2259 #ifdef AFS_WEB_ENHANCEMENTS
2260 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2261 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2263 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, AFS_LOOKUP_NOEVAL);
2265 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2266 #endif /* AFS_WEB_ENHANCEMENTS */
2269 afs_osi_Free(tmpPath, strlen(path)+1);
2275 * Follow symbolic links for parent directories and
2276 * for leaves when the follow flag is set.
2278 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2280 while(nextVp->v_type == VLNK) {
2281 if (++linkCount > MAX_OSI_LINKS) {
2284 afs_osi_Free(tmpPath, strlen(path)+1);
2287 code = uafs_LookupLink(nextVp, vp, &linkVp);
2291 afs_osi_Free(tmpPath, strlen(path)+1);
2305 * Special case, nextPathP is non-null if pathname ends in slash
2307 if (nextPathP != NULL && vp->v_type != VDIR) {
2309 afs_osi_Free(tmpPath, strlen(path)+1);
2313 afs_osi_Free(tmpPath, strlen(path)+1);
2319 * Lookup the target of a symbolic link
2320 * Call VN_HOLD on the output vnode if successful.
2321 * Returns zero on success, error code on failure.
2323 * Note: Caller must hold the AFS global lock.
2325 int uafs_LookupLink(
2326 struct usr_vnode *vp,
2327 struct usr_vnode *parentVp,
2328 struct usr_vnode **vpp)
2333 struct usr_vnode *linkVp;
2335 struct iovec iov[1];
2339 pathP = afs_osi_Alloc(MAX_OSI_PATH+1);
2340 usr_assert(pathP != NULL);
2343 * set up the uio buffer
2345 iov[0].iov_base = pathP;
2346 iov[0].iov_len = MAX_OSI_PATH+1;
2347 uio.uio_iov = &iov[0];
2351 uio.uio_fmode = FREAD;
2352 uio.uio_resid = MAX_OSI_PATH+1;
2355 * Read the link data
2357 code = afs_readlink(vp, &uio, u.u_cred);
2359 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2362 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2366 * Find the target of the symbolic link
2368 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2370 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2374 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2380 * Lookup the parent of a file or directory given its path
2381 * Call VN_HOLD on the output vnode if successful.
2382 * Returns zero on success, error code on failure.
2384 * Note: Caller must hold the AFS global lock.
2386 int uafs_LookupParent(
2388 struct usr_vnode **vpp)
2393 struct usr_vnode *parentP;
2398 * Absolute path names must start with the AFS mount point.
2401 pathP = uafs_afsPathName(path);
2402 if (pathP == NULL) {
2408 * Find the length of the parent path
2411 while(len > 0 && path[len-1] == '/') {
2417 while(len > 0 && path[len-1] != '/') {
2424 pathP = afs_osi_Alloc(len);
2425 usr_assert(pathP != NULL);
2426 memcpy(pathP, path, len-1);
2427 pathP[len-1] = '\0';
2430 * look up the parent
2432 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2433 afs_osi_Free(pathP, len);
2437 if (parentP->v_type != VDIR) {
2447 * Return a pointer to the first character in the last component
2450 char *uafs_LastPath(char *path)
2455 while (len > 0 && path[len-1] == '/') {
2458 while (len > 0 && path[len-1] != '/') {
2468 * Set the working directory.
2475 retval = uafs_chdir_r(path);
2486 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2491 if (dirP->v_type != VDIR) {
2496 VN_RELE(afs_CurrentDir);
2497 afs_CurrentDir = dirP;
2502 * Create a directory.
2510 retval = uafs_mkdir_r(path, mode);
2521 struct vnode *parentP;
2523 struct usr_vattr attrs;
2525 if (uafs_IsRoot(path)) {
2530 * Look up the parent directory.
2532 nameP = uafs_LastPath(path);
2533 if (nameP != NULL) {
2534 code = uafs_LookupParent(path, &parentP);
2540 parentP = afs_CurrentDir;
2546 * Make sure the directory has at least one character
2548 if (*nameP == '\0') {
2555 * Create the directory
2557 usr_vattr_null(&attrs);
2558 attrs.va_type = VREG;
2559 attrs.va_mode = mode;
2560 attrs.va_uid = u.u_cred->cr_uid;
2561 attrs.va_gid = u.u_cred->cr_gid;
2563 code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
2574 * Return 1 if path is the AFS root, otherwise return 0
2576 int uafs_IsRoot(char *path)
2578 while(*path == '/' && *(path+1) == '/') {
2581 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2584 path += afs_mountDirLen;
2585 while (*path == '/') {
2588 if (*path != '\0') {
2596 * Note: file name may not end in a slash.
2605 retval = uafs_open_r(path, flags, mode);
2619 struct usr_vnode *fileP;
2620 struct usr_vnode *dirP;
2621 struct usr_vattr attrs;
2624 if (uafs_IsRoot(path)) {
2625 fileP = afs_RootVnode;
2629 * Look up the parent directory.
2631 nameP = uafs_LastPath(path);
2632 if (nameP != NULL) {
2633 code = uafs_LookupParent(path, &dirP);
2639 dirP = afs_CurrentDir;
2645 * Make sure the filename has at least one character
2647 if (*nameP == '\0') {
2654 * Get the VNODE for this file
2656 if (flags & O_CREAT) {
2657 usr_vattr_null(&attrs);
2658 attrs.va_type = VREG;
2659 attrs.va_mode = mode;
2660 attrs.va_uid = u.u_cred->cr_uid;
2661 attrs.va_gid = u.u_cred->cr_gid;
2662 if (flags & O_TRUNC) {
2666 code = afs_create(dirP, nameP, &attrs,
2667 (flags & O_EXCL)?usr_EXCL:usr_NONEXCL,
2668 mode, &fileP, u.u_cred);
2676 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2684 * Check whether we have access to this file
2687 if (flags & (O_RDONLY|O_RDWR)) {
2690 if (flags & (O_WRONLY|O_RDWR)) {
2693 if (!fileMode) fileMode = VREAD; /* since O_RDONLY is 0 */
2694 code = afs_access(fileP, fileMode, u.u_cred);
2702 * Get the file attributes, all we need is the size
2704 code = afs_getattr(fileP, &attrs, u.u_cred);
2714 * Setup the open flags
2717 if (flags & O_TRUNC) {
2718 openFlags |= FTRUNC;
2720 if (flags & O_APPEND) {
2721 openFlags |= FAPPEND;
2723 if (flags & O_SYNC) {
2726 if (flags & O_SYNC) {
2729 if (flags & (O_RDONLY|O_RDWR)) {
2732 if (flags & (O_WRONLY|O_RDWR)) {
2733 openFlags |= FWRITE;
2737 * Truncate if necessary
2739 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2740 usr_vattr_null(&attrs);
2742 code = afs_setattr(fileP, &attrs, u.u_cred);
2753 code = afs_open(&fileP, openFlags, u.u_cred);
2761 * Put the vnode pointer into the file table
2763 for (fd = 0 ; fd < MAX_OSI_FILES ; fd++) {
2764 if (afs_FileTable[fd] == NULL) {
2765 afs_FileTable[fd] = fileP;
2766 afs_FileFlags[fd] = openFlags;
2767 if (flags & O_APPEND) {
2768 afs_FileOffsets[fd] = attrs.va_size;
2770 afs_FileOffsets[fd] = 0;
2775 if (fd == MAX_OSI_FILES) {
2792 rc = uafs_open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2801 rc = uafs_open_r(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2815 retval = uafs_write_r(fd, buf, len);
2827 struct iovec iov[1];
2828 struct usr_vnode *fileP;
2831 * Make sure this is an open file
2833 fileP = afs_FileTable[fd];
2834 if (fileP == NULL) {
2840 * set up the uio buffer
2842 iov[0].iov_base = buf;
2843 iov[0].iov_len = len;
2844 uio.uio_iov = &iov[0];
2846 uio.uio_offset = afs_FileOffsets[fd];
2848 uio.uio_fmode = FWRITE;
2849 uio.uio_resid = len;
2855 code = afs_write(fileP, &uio, afs_FileFlags[fd], u.u_cred, 0);
2861 afs_FileOffsets[fd] = uio.uio_offset;
2862 return(len - uio.uio_resid);
2875 retval = uafs_read_r(fd, buf, len);
2887 struct iovec iov[1];
2888 struct usr_vnode *fileP;
2889 struct usr_buf *bufP;
2892 * Make sure this is an open file
2894 fileP = afs_FileTable[fd];
2895 if (fileP == NULL) {
2901 * set up the uio buffer
2903 iov[0].iov_base = buf;
2904 iov[0].iov_len = len;
2905 uio.uio_iov = &iov[0];
2907 uio.uio_offset = afs_FileOffsets[fd];
2909 uio.uio_fmode = FREAD;
2910 uio.uio_resid = len;
2915 code = afs_read(fileP, &uio, u.u_cred, 0, &bufP, 0);
2921 afs_FileOffsets[fd] = uio.uio_offset;
2922 return(len - uio.uio_resid);
2926 * Copy the attributes of a file into a stat structure.
2928 * NOTE: Caller must hold the global AFS lock.
2931 struct usr_vnode *vp,
2935 struct usr_vattr attrs;
2940 * Get the attributes
2942 code = afs_getattr(vp, &attrs, u.u_cred);
2948 * Copy the attributes, zero fields that aren't set
2950 memset((void *)stats, 0, sizeof(struct stat));
2952 stats->st_ino = attrs.va_nodeid;
2953 stats->st_mode = attrs.va_mode;
2954 stats->st_nlink = attrs.va_nlink;
2955 stats->st_uid = attrs.va_uid;
2956 stats->st_gid = attrs.va_gid;
2957 stats->st_rdev = attrs.va_rdev;
2958 stats->st_size = attrs.va_size;
2959 stats->st_atime = attrs.va_atime.tv_sec;
2960 stats->st_mtime = attrs.va_mtime.tv_sec;
2961 stats->st_ctime = attrs.va_ctime.tv_sec;
2962 stats->st_blksize = attrs.va_blocksize;
2963 stats->st_blocks = attrs.va_blocks;
2969 * Get the attributes of a file, do follow links
2977 retval = uafs_stat_r(path, buf);
2989 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2994 code = uafs_GetAttr(vp, buf);
3004 * Get the attributes of a file, don't follow links
3012 retval = uafs_lstat_r(path, buf);
3024 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3029 code = uafs_GetAttr(vp, buf);
3039 * Get the attributes of an open file
3047 retval = uafs_fstat_r(fd, buf);
3059 vp = afs_FileTable[fd];
3064 code = uafs_GetAttr(vp, buf);
3074 * change the permissions on a file
3082 retval = uafs_chmod_r(path, mode);
3093 struct usr_vattr attrs;
3095 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3100 usr_vattr_null(&attrs);
3101 attrs.va_mode = mode;
3102 code = afs_setattr(vp, &attrs, u.u_cred);
3112 * change the permissions on an open file
3120 retval = uafs_fchmod_r(fd, mode);
3131 struct usr_vattr attrs;
3133 vp = afs_FileTable[fd];
3138 usr_vattr_null(&attrs);
3139 attrs.va_mode = mode;
3140 code = afs_setattr(vp, &attrs, u.u_cred);
3157 retval = uafs_truncate_r(path, length);
3162 int uafs_truncate_r(
3168 struct usr_vattr attrs;
3170 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3175 usr_vattr_null(&attrs);
3176 attrs.va_size = length;
3177 code = afs_setattr(vp, &attrs, u.u_cred);
3187 * truncate an open file
3195 retval = uafs_ftruncate_r(fd, length);
3200 int uafs_ftruncate_r(
3206 struct usr_vattr attrs;
3208 vp = afs_FileTable[fd];
3213 usr_vattr_null(&attrs);
3214 attrs.va_size = length;
3215 code = afs_setattr(vp, &attrs, u.u_cred);
3224 * set the read/write file pointer of an open file
3233 retval = uafs_lseek_r(fd, offset, whence);
3245 struct usr_vattr attrs;
3246 struct usr_vnode *vp;
3248 vp = afs_FileTable[fd];
3255 newpos = afs_FileOffsets[fd] + offset;
3261 code = afs_getattr(vp, &attrs, u.u_cred);
3266 newpos = attrs.va_size + offset;
3276 afs_FileOffsets[fd] = newpos;
3288 retval = uafs_fsync_r(fd);
3297 struct usr_vnode *fileP;
3300 fileP = afs_FileTable[fd];
3301 if (fileP == NULL) {
3306 code = afs_fsync(fileP, u.u_cred);
3323 retval = uafs_close_r(fd);
3332 struct usr_vnode *fileP;
3334 fileP = afs_FileTable[fd];
3335 if (fileP == NULL) {
3339 afs_FileTable[fd] = NULL;
3341 code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
3352 * Create a hard link from the source to the target
3353 * Note: file names may not end in a slash.
3361 retval = uafs_link_r(existing, new);
3371 struct usr_vnode *existP;
3372 struct usr_vnode *dirP;
3375 if (uafs_IsRoot(new)) {
3380 * Look up the existing node.
3382 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3389 * Look up the parent directory.
3391 nameP = uafs_LastPath(new);
3392 if (nameP != NULL) {
3393 code = uafs_LookupParent(new, &dirP);
3400 dirP = afs_CurrentDir;
3406 * Make sure the filename has at least one character
3408 if (*nameP == '\0') {
3418 code = afs_link(existP, dirP, nameP, u.u_cred);
3429 * Create a symbolic link from the source to the target
3430 * Note: file names may not end in a slash.
3438 retval = uafs_symlink_r(target, source);
3448 struct usr_vnode *dirP;
3449 struct usr_vattr attrs;
3452 if (uafs_IsRoot(source)) {
3457 * Look up the parent directory.
3459 nameP = uafs_LastPath(source);
3460 if (nameP != NULL) {
3461 code = uafs_LookupParent(source, &dirP);
3467 dirP = afs_CurrentDir;
3473 * Make sure the filename has at least one character
3475 if (*nameP == '\0') {
3484 usr_vattr_null(&attrs);
3485 attrs.va_type = VLNK;
3486 attrs.va_mode = 0777;
3487 attrs.va_uid = u.u_cred->cr_uid;
3488 attrs.va_gid = u.u_cred->cr_gid;
3489 code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
3499 * Read a symbolic link into the buffer
3508 retval = uafs_readlink_r(path, buf, len);
3513 int uafs_readlink_r(
3519 struct usr_vnode *vp;
3521 struct iovec iov[1];
3523 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3529 if (vp->v_type != VLNK) {
3536 * set up the uio buffer
3538 iov[0].iov_base = buf;
3539 iov[0].iov_len = len;
3540 uio.uio_iov = &iov[0];
3544 uio.uio_fmode = FREAD;
3545 uio.uio_resid = len;
3550 code = afs_readlink(vp, &uio, u.u_cred);
3558 * return the number of bytes read
3560 return (len - uio.uio_resid);
3564 * Remove a file (or directory)
3565 * Note: file name may not end in a slash.
3572 retval = uafs_unlink_r(path);
3582 struct usr_vnode *fileP;
3583 struct usr_vnode *dirP;
3586 if (uafs_IsRoot(path)) {
3591 * Look up the parent directory.
3593 nameP = uafs_LastPath(path);
3594 if (nameP != NULL) {
3595 code = uafs_LookupParent(path, &dirP);
3601 dirP = afs_CurrentDir;
3607 * Make sure the filename has at least one character
3609 if (*nameP == '\0') {
3618 code = afs_remove(dirP, nameP, u.u_cred);
3629 * Rename a file (or directory)
3637 retval = uafs_rename_r(old, new);
3649 struct usr_vnode *odirP;
3650 struct usr_vnode *ndirP;
3652 if (uafs_IsRoot(new)) {
3657 * Look up the parent directories.
3659 onameP = uafs_LastPath(old);
3660 if (onameP != NULL) {
3661 code = uafs_LookupParent(old, &odirP);
3667 odirP = afs_CurrentDir;
3671 nnameP = uafs_LastPath(new);
3672 if (nnameP != NULL) {
3673 code = uafs_LookupParent(new, &ndirP);
3679 ndirP = afs_CurrentDir;
3685 * Make sure the filename has at least one character
3687 if (*onameP == '\0' || *nnameP == '\0') {
3697 code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
3709 * Remove a or directory
3710 * Note: file name may not end in a slash.
3717 retval = uafs_rmdir_r(path);
3727 struct usr_vnode *fileP;
3728 struct usr_vnode *dirP;
3731 if (uafs_IsRoot(path)) {
3736 * Look up the parent directory.
3738 nameP = uafs_LastPath(path);
3739 if (nameP != NULL) {
3740 code = uafs_LookupParent(path, &dirP);
3746 dirP = afs_CurrentDir;
3752 * Make sure the directory name has at least one character
3754 if (*nameP == '\0') {
3761 * Remove the directory
3763 code = afs_rmdir(dirP, nameP, u.u_cred);
3774 * Flush a file from the AFS cache
3780 struct afs_ioctl iob;
3787 code = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6),
3796 int uafs_FlushFile_r(
3801 retval = uafs_FlushFile(path);
3809 usr_DIR *uafs_opendir(
3814 retval = uafs_opendir_r(path);
3819 usr_DIR *uafs_opendir_r(
3823 struct usr_vnode *fileP;
3827 * Open the directory for reading
3829 fd = uafs_open_r(path, O_RDONLY, 0);
3834 fileP = afs_FileTable[fd];
3835 if (fileP == NULL) {
3839 if (fileP->v_type != VDIR) {
3846 * Set up the directory structures
3848 dirp = (usr_DIR *)afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3849 sizeof(struct usr_dirent));
3850 usr_assert(dirp != NULL);
3851 dirp->dd_buf = (char *)(dirp+1);
3861 * Read directory entries into a file system independent format.
3862 * This routine was developed to support AFS cache consistency testing.
3863 * You should use uafs_readdir instead.
3867 struct min_direct *buf,
3872 retval = uafs_getdents_r(fd, buf, len);
3877 int uafs_getdents_r(
3879 struct min_direct *buf,
3884 struct usr_vnode *vp;
3885 struct iovec iov[1];
3888 * Make sure this is an open file
3890 vp = afs_FileTable[fd];
3898 * set up the uio buffer
3900 iov[0].iov_base = (char *)buf;
3901 iov[0].iov_len = len;
3902 uio.uio_iov = &iov[0];
3904 uio.uio_offset = afs_FileOffsets[fd];
3906 uio.uio_fmode = FREAD;
3907 uio.uio_resid = len;
3910 * read the next chunk from the directory
3912 code = afs_readdir(vp, &uio, u.u_cred);
3918 afs_FileOffsets[fd] = uio.uio_offset;
3919 return(len - uio.uio_resid);
3923 * read from a directory (names only)
3925 struct usr_dirent *uafs_readdir(
3928 struct usr_dirent *retval;
3930 retval = uafs_readdir_r(dirp);
3935 struct usr_dirent *uafs_readdir_r(
3942 struct usr_vnode *vp;
3943 struct iovec iov[1];
3944 struct usr_dirent *direntP;
3945 struct min_direct *directP;
3948 * Make sure this is an open file
3950 vp = afs_FileTable[dirp->dd_fd];
3957 * If there are no entries in the stream buffer
3958 * then read another chunk
3960 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3961 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3963 * set up the uio buffer
3965 iov[0].iov_base = dirp->dd_buf;
3966 iov[0].iov_len = USR_DIRSIZE;
3967 uio.uio_iov = &iov[0];
3969 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3971 uio.uio_fmode = FREAD;
3972 uio.uio_resid = USR_DIRSIZE;
3975 * read the next chunk from the directory
3977 code = afs_readdir(vp, &uio, u.u_cred);
3982 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3984 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3986 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3990 * Check for end of file
3992 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3996 len = ((sizeof(struct min_direct)+directP->d_namlen+4) & (~3));
3997 usr_assert(len <= dirp->dd_size);
4000 * Copy the next entry into the usr_dirent structure and advance
4002 direntP = (struct usr_dirent *)(dirp->dd_buf+USR_DIRSIZE);
4003 direntP->d_ino = directP->d_fileno;
4004 direntP->d_off = direntP->d_reclen;
4005 direntP->d_reclen = sizeof(struct usr_dirent) - MAXNAMLEN +
4006 directP->d_namlen + 1;
4007 memcpy(&direntP->d_name[0], (void *)(directP+1), directP->d_namlen);
4008 direntP->d_name[directP->d_namlen] = '\0';
4009 dirp->dd_loc += len;
4010 dirp->dd_size -= len;
4023 retval = uafs_closedir_r(dirp);
4028 int uafs_closedir_r(
4035 afs_osi_Free((char *)dirp,
4036 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4037 rc = uafs_close_r(fd);
4042 * Do AFS authentication
4051 afs_int32 password_expires = -1;
4053 usr_mutex_lock(&osi_authenticate_lock);
4054 code = ka_UserAuthenticateGeneral(
4055 KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG2, user,
4056 NULL, cell, passwd, 0, &password_expires,
4058 usr_mutex_unlock(&osi_authenticate_lock);
4070 retval = uafs_klog(user, cell, passwd, reason);
4076 * Destroy AFS credentials from the kernel cache
4082 usr_mutex_lock(&osi_authenticate_lock);
4083 code = ktc_ForgetAllTokens();
4084 usr_mutex_unlock(&osi_authenticate_lock);
4092 retval = uafs_unlog();
4098 * Strip the AFS mount point from a pathname string. Return
4099 * NULL if the path is a relative pathname or if the path
4100 * doesn't start with the AFS mount point string.
4102 char *uafs_afsPathName(char *path)
4111 for (i = 1, p = path+1; *p != '\0' ; p++) {
4112 /* Ignore duplicate slashes */
4113 if (*p == '/' && lastchar == '/')
4115 /* Is this a subdirectory of the AFS mount point? */
4116 if (afs_mountDir[i] == '\0' && *p == '/') {
4117 /* strip leading slashes */
4118 while (*(++p) == '/');
4121 /* Reject paths that are not within AFS */
4122 if (*p != afs_mountDir[i])
4127 /* Is this the AFS mount point? */
4128 if (afs_mountDir[i] == '\0') {
4129 usr_assert(*p == '\0');
4135 #ifdef AFS_WEB_ENHANCEMENTS
4138 * klog but don't allocate a new pag
4140 int uafs_klog_nopag(
4147 afs_int32 password_expires = -1;
4149 usr_mutex_lock(&osi_authenticate_lock);
4150 code = ka_UserAuthenticateGeneral(
4151 KA_USERAUTH_VERSION /*+KA_USERAUTH_DOSETPAG2*/, user,
4152 NULL, cell, passwd, 0, &password_expires,
4154 usr_mutex_unlock(&osi_authenticate_lock);
4159 * uafs_getcellstatus
4160 * get the cell status
4162 int uafs_getcellstatus(char *cell, afs_int32 *status)
4165 struct afs_ioctl iob;
4168 iob.in_size = strlen(cell)+1;
4172 rc = call_syscall(AFSCALL_PIOCTL, /*path*/0, _VICEIOCTL(35),
4186 * Get quota of volume associated with path
4188 int uafs_getvolquota(char *path, afs_int32 *BlocksInUse, afs_int32 *MaxQuota)
4191 struct afs_ioctl iob;
4192 VolumeStatus *status;
4198 iob.out_size = 1024;
4200 rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(4),
4208 status = (VolumeStatus *) buf;
4209 *BlocksInUse = status->BlocksInUse;
4210 *MaxQuota = status->MaxQuota;
4216 * Set quota of volume associated with path
4218 int uafs_setvolquota(char *path, afs_int32 MaxQuota)
4221 struct afs_ioctl iob;
4222 VolumeStatus *status;
4230 memset(buf, 0, sizeof(VolumeStatus));
4231 status = (VolumeStatus *) buf;
4232 status->MaxQuota = MaxQuota;
4233 status->MinQuota = -1;
4235 rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(5),
4247 * uafs_statmountpoint
4248 * Determine whether a dir. is a mount point or not
4249 * return 1 if mount point, 0 if not
4251 int uafs_statmountpoint(char *path)
4258 retval = uafs_statmountpoint_r(path);
4263 int uafs_statmountpoint_r(char *path)
4268 struct vrequest treq;
4271 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4277 avc = (struct vcache *) vp;
4286 * Get a list of rights for the current user on path.
4288 int uafs_getRights(char *path)
4295 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4302 afs_rights = PRSFS_READ |
4310 afs_rights = afs_getRights (vp, afs_rights, u.u_cred);
4315 #endif /* AFS_WEB_ENHANCEMENTS */
4317 #endif /* UKERNEL */