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_SleepSig(x)
497 int afs_osi_Wakeup(x)
504 usr_mutex_lock(&osi_waitq_lock);
505 waitp = osi_waithash_table[index].head;
507 if (waitp->addr == x && waitp->flag == 0) {
509 usr_cond_signal(&waitp->cond);
513 usr_mutex_unlock(&osi_waitq_lock);
516 int afs_osi_Wait(msec, handle, intok)
518 struct afs_osi_WaitHandle *handle;
525 int rxGlockOwner = ISAFS_RXGLOCK();
526 int glockOwner = ISAFS_GLOCK();
528 tv.tv_sec = msec / 1000;
529 tv.tv_nsec = (msec % 1000) * 1000000;
530 if (handle == NULL) {
537 usr_thread_sleep(&tv);
546 usr_mutex_lock(&osi_waitq_lock);
553 index = WAITHASH((caddr_t)handle);
554 if (osi_waithash_avail == NULL) {
555 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
556 usr_cond_init(&waitp->cond);
558 waitp = osi_waithash_avail;
559 osi_waithash_avail = osi_waithash_avail->next;
561 waitp->addr = (caddr_t)handle;
563 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
564 osi_waithash_table[index].tail, next, prev);
565 tv.tv_sec += time(NULL);
566 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0)?0:1);
567 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
568 timedNext, timedPrev);
569 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
575 DLL_DELETE(waitp, osi_waithash_table[index].head,
576 osi_waithash_table[index].tail, next, prev);
577 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail,
578 timedNext, timedPrev);
579 waitp->next = osi_waithash_avail;
580 osi_waithash_avail = waitp;
581 usr_mutex_unlock(&osi_waitq_lock);
592 void afs_osi_CancelWait(handle)
593 struct afs_osi_WaitHandle *handle;
595 afs_osi_Wakeup((caddr_t)handle);
599 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
600 * to explicitly signal cond_timed_waits when their timers expire
602 int afs_osi_CheckTimedWaits()
607 curTime = time(NULL);
608 usr_mutex_lock(&osi_waitq_lock);
609 waitp = osi_timedwait_head;
610 while (waitp != NULL) {
611 usr_assert(waitp->expiration != 0);
612 if (waitp->expiration <= curTime) {
614 usr_cond_signal(&waitp->cond);
616 waitp = waitp->timedNext;
618 usr_mutex_unlock(&osi_waitq_lock);
622 * I-node numbers are indeces into a table containing a filename
623 * i-node structure and a vnode structure. When we create an i-node,
624 * we copy the name into the array and initialize enough of the fields
625 * in the inode and vnode structures to get the client to work.
628 struct usr_inode i_node;
631 osi_file_table_t *osi_file_table;
633 int max_osi_files = 0;
636 * Allocate a slot in the file table if there is not one there already,
637 * copy in the file name and kludge up the vnode and inode structures
639 int lookupname(fnamep, segflg, followlink, dirvpp, compvpp)
643 struct usr_vnode **dirvpp;
644 struct usr_vnode **compvpp;
648 struct usr_inode *ip;
649 struct usr_vnode *vp;
651 /*usr_assert(followlink == 0);*/
652 usr_assert(dirvpp == NULL);
655 * Assume relative pathnames refer to files in AFS
657 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
659 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
664 usr_mutex_lock(&osi_inode_lock);
666 for (i = 0 ; i < n_osi_files ; i++) {
667 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
668 *compvpp = &osi_file_table[i].i_node.i_vnode;
669 (*compvpp)->v_count++;
670 usr_mutex_unlock(&osi_inode_lock);
675 if (n_osi_files == max_osi_files) {
676 usr_mutex_unlock(&osi_inode_lock);
680 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep)+1);
681 usr_assert(osi_file_table[n_osi_files].name != NULL);
682 strcpy(osi_file_table[n_osi_files].name, fnamep);
683 ip = &osi_file_table[i].i_node;
685 vp->v_data = (caddr_t)ip;
688 ip->i_number = n_osi_files;
690 usr_mutex_unlock(&osi_inode_lock);
696 * open a file given its i-node number
698 void *osi_UFSOpen(ino)
707 if (ino > n_osi_files) {
713 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
714 usr_assert(fp != NULL);
715 fp->fd = open(osi_file_table[ino-1].name, O_RDWR|O_CREAT, 0);
718 afs_osi_Free((char *)fp, sizeof(struct osi_file));
722 rc = fstat(fp->fd, &st);
725 afs_osi_Free((void *)fp, sizeof(struct osi_file));
729 fp->size = st.st_size;
732 fp->vnode = (struct usr_vnode *)fp;
749 afs_osi_Free((void *)fp, sizeof(struct osi_file));
753 afs_osi_Free((void *)fp, sizeof(struct osi_file));
758 int osi_UFSTruncate(fp, len)
767 rc = ftruncate(fp->fd, len);
778 int afs_osi_Read(fp, offset, buf, len)
792 rc = lseek(fp->fd, offset, SEEK_SET);
794 rc = lseek(fp->fd, fp->offset, SEEK_SET);
802 ret = read(fp->fd, buf, len);
809 rc = fstat(fp->fd, &st);
815 fp->size = st.st_size;
820 int afs_osi_Write(fp, offset, buf, len)
834 rc = lseek(fp->fd, offset, SEEK_SET);
836 rc = lseek(fp->fd, fp->offset, SEEK_SET);
844 ret = write(fp->fd, buf, len);
851 rc = fstat(fp->fd, &st);
857 fp->size = st.st_size;
862 int afs_osi_Stat(fp, stp)
864 struct osi_stat *stp;
870 rc = fstat(fp->fd, &st);
876 stp->size = st.st_size;
877 stp->blksize = st.st_blksize;
878 stp->mtime = st.st_mtime;
879 stp->atime = st.st_atime;
887 int afs_osi_VOP_RDWR(
888 struct usr_vnode *vnodeP,
889 struct usr_uio *uioP,
892 struct usr_ucred* credP)
895 struct osi_file *fp = (struct osi_file *)vnodeP;
898 * We don't support readv/writev.
900 usr_assert(uioP->uio_iovcnt == 1);
901 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
903 if (rw == UIO_WRITE) {
904 usr_assert(uioP->uio_fmode == FWRITE);
905 rc = afs_osi_Write(fp, uioP->uio_offset,
906 uioP->uio_iov[0].iov_base,
907 uioP->uio_iov[0].iov_len);
909 usr_assert(uioP->uio_fmode == FREAD);
910 rc = afs_osi_Read(fp, uioP->uio_offset,
911 uioP->uio_iov[0].iov_base,
912 uioP->uio_iov[0].iov_len);
918 uioP->uio_resid -= rc;
919 uioP->uio_offset += rc;
920 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
921 uioP->uio_iov[0].iov_len -= rc;
926 * Use malloc/free routines with check patterns before and after each block
929 static char *afs_check_string1 = "UAFS";
930 static char *afs_check_string2 = "AFS_OSI_";
932 void *afs_osi_Alloc(size_t size)
937 void afs_osi_Free(void *ptr, size_t size)
942 void *osi_AllocLargeSpace(size_t size)
944 AFS_STATCNT(osi_AllocLargeSpace);
945 return afs_osi_Alloc(size);
948 void osi_FreeLargeSpace(void *ptr)
950 AFS_STATCNT(osi_FreeLargeSpace);
951 afs_osi_Free(ptr, 0);
954 void *osi_AllocSmallSpace(size_t size)
956 AFS_STATCNT(osi_AllocSmallSpace);
957 return afs_osi_Alloc(size);
960 void osi_FreeSmallSpace(void *ptr)
962 AFS_STATCNT(osi_FreeSmallSpace);
963 afs_osi_Free(ptr, 0);
968 AFS_STATCNT(shutdown_osi);
972 void shutdown_osinet()
974 AFS_STATCNT(shutdown_osinet);
978 void shutdown_osifile()
980 AFS_STATCNT(shutdown_osifile);
984 int afs_nfsclient_init()
989 void shutdown_nfsclnt()
994 int afs_osi_Invisible()
1002 gettimeofday(tv, NULL);
1015 AFS_STATCNT(osi_Active);
1016 if (avc->opens > 0) return(1);
1020 int afs_osi_MapStrategy(aproc, bp)
1024 afs_int32 returnCode;
1025 returnCode = (*aproc)(bp);
1029 osi_FlushPages(avc, credp)
1030 register struct vcache *avc;
1031 struct AFS_UCRED *credp;
1033 ObtainSharedLock(&avc->lock,555);
1034 if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0) ||
1035 ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1036 ReleaseSharedLock(&avc->lock);
1039 UpgradeSToWLock(&avc->lock,565);
1040 hset(avc->mapDV, avc->m.DataVersion);
1041 ReleaseWriteLock(&avc->lock);
1045 osi_FlushText_really(vp)
1046 register struct vcache *vp;
1048 if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
1049 hset(vp->flushDV, vp->m.DataVersion);
1060 void osi_ReleaseVM(avc, len, credp)
1063 struct usr_ucred *credp;
1075 * Allocate the table used to implement psuedo-inodes.
1077 max_osi_files = cacheFiles + 100;
1078 osi_file_table = (osi_file_table_t *)
1079 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1080 usr_assert(osi_file_table != NULL);
1082 #ifndef NETSCAPE_NSAPI
1084 * Initialize the mutex and condition variable used to implement
1087 pthread_mutex_init(&usr_sleep_mutex, NULL);
1088 pthread_cond_init(&usr_sleep_cond, NULL);
1089 #endif /* !NETSCAPE_NSAPI */
1092 * Initialize the hash table used for sleep/wakeup
1094 for (i = 0 ; i < OSI_WAITHASH_SIZE ; i++) {
1095 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1097 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1098 osi_waithash_avail = NULL;
1101 * Initialize the AFS file table
1103 for (i = 0 ; i < MAX_OSI_FILES ; i++) {
1104 afs_FileTable[i] = NULL;
1108 * Initialize the global locks
1110 usr_mutex_init(&afs_global_lock);
1111 usr_mutex_init(&rx_global_lock);
1112 usr_mutex_init(&osi_inode_lock);
1113 usr_mutex_init(&osi_waitq_lock);
1114 usr_mutex_init(&osi_authenticate_lock);
1117 * Initialize the AFS OSI credentials
1119 afs_osi_cred = *afs_global_ucredp;
1122 /* ParseArgs is now obsolete, being handled by cmd */
1124 /*---------------------------------------------------------------------
1128 * Given the final component of a filename expected to be a data cache file,
1129 * return the integer corresponding to the file. Note: we reject names that
1130 * are not a ``V'' followed by an integer. We also reject those names having
1131 * the right format but lying outside the range [0..cacheFiles-1].
1134 * fname : Char ptr to the filename to parse.
1137 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1141 * Nothing interesting.
1145 *------------------------------------------------------------------------*/
1147 int GetVFileNumber(fname)
1150 int computedVNumber; /*The computed file number we return*/
1151 int filenameLen; /*Number of chars in filename*/
1152 int currDigit; /*Current digit being processed*/
1155 * The filename must have at least two characters, the first of which must be a ``V''
1156 * and the second of which cannot be a zero unless the file is exactly two chars long.
1158 filenameLen = strlen(fname);
1159 if (filenameLen < 2)
1161 if (fname[0] != 'V')
1163 if ((filenameLen > 2) && (fname[1] == '0'))
1167 * Scan through the characters in the given filename, failing immediately if a non-digit
1170 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1171 if (isdigit(fname[currDigit]) == 0)
1175 * All relevant characters are digits. Pull out the decimal number they represent.
1176 * Reject it if it's out of range, otherwise return it.
1178 computedVNumber = atoi(++fname);
1179 if (computedVNumber < cacheFiles)
1180 return(computedVNumber);
1185 /*---------------------------------------------------------------------
1189 * Given a full pathname for a file we need to create for the workstation AFS
1190 * cache, go ahead and create the file.
1193 * fname : Full pathname of file to create.
1196 * 0 iff the file was created,
1200 * The given cache file has been found to be missing.
1204 *------------------------------------------------------------------------*/
1206 int CreateCacheFile(fname)
1209 static char rn[] = "CreateCacheFile"; /*Routine name*/
1210 int cfd; /*File descriptor to AFS cache file*/
1211 int closeResult; /*Result of close()*/
1214 printf("%s: Creating cache file '%s'\n",
1216 cfd = open(fname, createAndTrunc, ownerRWmode);
1218 printf("%s: Can't create '%s', error return is %d (%d)\n",
1219 rn, fname, cfd, errno);
1222 closeResult = close(cfd);
1224 printf("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1232 /*---------------------------------------------------------------------
1236 * Sweep through the AFS cache directory, recording the inode number for
1237 * each valid data cache file there. Also, delete any file that doesn't beint32
1238 * in the cache directory during this sweep, and remember which of the other
1239 * residents of this directory were seen. After the sweep, we create any data
1240 * cache files that were missing.
1243 * vFilesFound : Set to the number of data cache files found.
1246 * 0 if everything went well,
1250 * This routine may be called several times. If the number of data cache files
1251 * found is less than the global cacheFiles, then the caller will need to call it
1252 * again to record the inodes of the missing zero-length data cache files created
1253 * in the previous call.
1256 * Fills up the global pathname_for_V array, may create and/or
1257 * delete files as explained above.
1258 *------------------------------------------------------------------------*/
1260 int SweepAFSCache(vFilesFound)
1263 static char rn[] = "SweepAFSCache"; /*Routine name*/
1264 char fullpn_FileToDelete[1024]; /*File to be deleted from cache*/
1265 char *fileToDelete; /*Ptr to last component of above*/
1266 DIR *cdirp; /*Ptr to cache directory structure*/
1268 struct dirent *currp; /*Current directory entry*/
1269 int vFileNum; /*Data cache file's associated number*/
1271 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1273 printf("%s: Memory Cache, no cache sweep done\n");
1279 printf("%s: Opening cache directory '%s'\n",
1282 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1283 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n",
1287 cdirp = opendir(cacheBaseDir);
1288 if (cdirp == (DIR *)0) {
1289 printf("%s: Can't open AFS cache directory, '%s'.\n",
1295 * Scan the directory entries, remembering data cache file inodes and the existance
1296 * of other important residents. Delete all files that don't belong here.
1299 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1300 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1302 for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
1305 printf("%s: Current directory entry:\n",
1307 printf("\tinode=%d, reclen=%d, name='%s'\n",
1308 currp->d_ino, currp->d_reclen, currp->d_name);
1312 * Guess current entry is for a data cache file.
1314 vFileNum = GetVFileNumber(currp->d_name);
1315 if (vFileNum >= 0) {
1317 * Found a valid data cache filename. Remember this file's name
1318 * and bump the number of files found.
1320 pathname_for_V[vFileNum] = afs_osi_Alloc(strlen(currp->d_name) +
1321 strlen(cacheBaseDir) + 2);
1322 usr_assert(pathname_for_V[vFileNum] != NULL);
1323 sprintf(pathname_for_V[vFileNum], "%s/%s",
1324 cacheBaseDir, currp->d_name);
1327 else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1329 * Found the file holding the dcache entries.
1331 missing_DCacheFile = 0;
1333 else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1335 * Found the file holding the volume info.
1337 missing_VolInfoFile = 0;
1339 else if ((strcmp(currp->d_name, ".") == 0) ||
1340 (strcmp(currp->d_name, "..") == 0) ||
1341 (strcmp(currp->d_name, "lost+found") == 0)) {
1343 * Don't do anything - this file is legit, and is to be left alone.
1348 * This file doesn't belong in the cache. Nuke it.
1350 sprintf(fileToDelete, "%s", currp->d_name);
1352 printf("%s: Deleting '%s'\n",
1353 rn, fullpn_FileToDelete);
1354 if (unlink(fullpn_FileToDelete)) {
1355 printf("%s: Can't unlink '%s', errno is %d\n",
1356 rn, fullpn_FileToDelete, errno);
1362 * Create all the cache files that are missing.
1364 if (missing_DCacheFile) {
1366 printf("%s: Creating '%s'\n",
1367 rn, fullpn_DCacheFile);
1368 if (CreateCacheFile(fullpn_DCacheFile))
1369 printf("%s: Can't create '%s'\n",
1370 rn, fullpn_DCacheFile);
1372 if (missing_VolInfoFile) {
1374 printf("%s: Creating '%s'\n",
1375 rn, fullpn_VolInfoFile);
1376 if (CreateCacheFile(fullpn_VolInfoFile))
1377 printf("%s: Can't create '%s'\n",
1378 rn, fullpn_VolInfoFile);
1381 if (*vFilesFound < cacheFiles) {
1383 * We came up short on the number of data cache files found. Scan through the inode
1384 * list and create all missing files.
1386 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1387 if (pathname_for_V[vFileNum] == (AFSD_INO_T)0) {
1388 sprintf(vFileNumber, "%d", vFileNum);
1390 printf("%s: Creating '%s'\n",
1392 if (CreateCacheFile(fullpn_VFile))
1393 printf("%s: Can't create '%s'\n",
1399 * Close the directory, return success.
1402 printf("%s: Closing cache directory.\n",
1408 static ConfigCell(aci, arock, adir)
1409 register struct afsconf_cell *aci;
1411 struct afsconf_dir *adir; {
1412 register int isHomeCell;
1414 afs_int32 cellFlags;
1415 afs_int32 hosts[MAXHOSTSPERCELL];
1417 /* figure out if this is the home cell */
1418 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1420 lookingForHomeCell = 0;
1421 cellFlags = 1; /* home cell, suid is ok */
1424 cellFlags = 2; /* not home, suid is forbidden */
1427 /* build address list */
1428 for(i=0;i<MAXHOSTSPERCELL;i++)
1429 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1431 if (aci->linkedCell) cellFlags |= 4; /* Flag that linkedCell arg exists,
1432 for upwards compatibility */
1434 /* configure one cell */
1435 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2,
1436 (long)hosts, /* server addresses */
1437 (long)aci->name, /* cell name */
1438 (long)cellFlags, /* is this the home cell? */
1439 (long)aci->linkedCell); /* Linked cell, if any */
1444 * Set the UDP port number RX uses for UDP datagrams
1446 void uafs_SetRxPort(
1449 usr_assert(usr_rx_port == 0);
1455 * Initialize the user space client.
1459 char *mountDirParam,
1461 char *cacheBaseDirParam,
1462 int cacheBlocksParam,
1463 int cacheFilesParam,
1464 int cacheStatEntriesParam,
1465 int dCacheSizeParam,
1466 int vCacheSizeParam,
1468 int closeSynchParam,
1471 int cacheFlagsParam,
1475 struct usr_proc *procp;
1476 struct usr_ucred *ucredp;
1479 int currVFile; /* Current AFS cache file number */
1480 int lookupResult; /* Result of GetLocalCellName() */
1481 int cacheIteration; /* cache verification loop counter */
1482 int vFilesFound; /* Num data cache files found in sweep */
1484 afs_int32 vfs1_type = -1;
1485 struct afs_ioctl iob;
1489 afs_int32 buffer[MAXIPADDRS];
1490 afs_int32 maskbuffer[MAXIPADDRS];
1491 afs_int32 mtubuffer[MAXIPADDRS];
1494 * Use the thread specific data to implement the user structure
1496 usr_keycreate(&afs_global_u_key, free);
1499 * Initialize the global ucred structure
1501 afs_global_ucredp = (struct usr_ucred *)
1502 afs_osi_Alloc(sizeof(struct usr_ucred));
1503 usr_assert(afs_global_ucredp != NULL);
1504 afs_global_ucredp->cr_ref = 1;
1505 afs_global_ucredp->cr_uid = geteuid();
1506 afs_global_ucredp->cr_gid = getegid();
1507 afs_global_ucredp->cr_ruid = getuid();
1508 afs_global_ucredp->cr_rgid = getgid();
1509 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1510 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1511 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1512 usr_assert(st >= 0);
1513 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1514 for (i = st ; i < NGROUPS ; i++) {
1515 afs_global_ucredp->cr_groups[i] = NOGROUP;
1519 * Initialize the global process structure
1521 afs_global_procp = (struct usr_proc *)
1522 afs_osi_Alloc(sizeof(struct usr_proc));
1523 usr_assert(afs_global_procp != NULL);
1524 afs_global_procp->p_pid = getpid();
1525 afs_global_procp->p_ppid = (pid_t)1;
1526 afs_global_procp->p_ucred = afs_global_ucredp;
1529 * Initialize the AFS mount point, default is '/afs'.
1530 * Strip duplicate/trailing slashes from mount point string.
1531 * afs_mountDirLen is set to strlen(afs_mountDir).
1533 if (mountDirParam) {
1534 sprintf(tbuffer, "%s", mountDirParam);
1536 sprintf(tbuffer, "afs");
1538 afs_mountDir[0] = '/';
1539 afs_mountDirLen = 1;
1540 for (lastchar = '/', p = &tbuffer[0] ; *p != '\0' ; p++) {
1541 if (lastchar != '/' || *p != '/') {
1542 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1545 if (lastchar == '/' && afs_mountDirLen > 1)
1547 afs_mountDir[afs_mountDirLen] = '\0';
1548 usr_assert(afs_mountDirLen > 1);
1551 * Initialize cache parameters using the input arguments
1554 cacheBlocks = cacheBlocksParam;
1555 if (cacheFilesParam != 0) {
1556 cacheFiles = cacheFilesParam;
1558 cacheFiles = cacheBlocks/10;
1560 if (cacheStatEntriesParam != 0) {
1561 cacheStatEntries = cacheStatEntriesParam;
1563 strcpy(cacheBaseDir, cacheBaseDirParam);
1564 if (nDaemons != 0) {
1565 nDaemons = nDaemonsParam;
1569 afsd_verbose = debugParam;
1570 afsd_debug = debugParam;
1571 chunkSize = chunkSizeParam;
1572 if (dCacheSizeParam != 0) {
1573 dCacheSize = dCacheSizeParam;
1575 dCacheSize = cacheFiles/2;
1577 if (vCacheSizeParam != 0) {
1578 vCacheSize = vCacheSizeParam;
1580 strcpy(confDir, confDirParam);
1581 afsd_CloseSynch = closeSynchParam;
1582 if (cacheFlagsParam >= 0) {
1583 cacheFlags = cacheFlagsParam;
1585 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1586 cacheFiles = dCacheSize;
1589 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1590 if (logFile == NULL) {
1591 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1593 strcpy(fullpn_AFSLogFile, logFile);
1596 printf("\n%s: Initializing user space AFS client\n\n", rn);
1597 printf(" mountDir: %s\n", afs_mountDir);
1598 printf(" confDir: %s\n", confDir);
1599 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1600 printf(" cacheBlocks: %d\n", cacheBlocks);
1601 printf(" cacheFiles: %d\n", cacheFiles);
1602 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1603 printf(" dCacheSize: %d\n", dCacheSize);
1604 printf(" vCacheSize: %d\n", vCacheSize);
1605 printf(" chunkSize: %d\n", chunkSize);
1606 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1607 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1608 printf(" nDaemons: %d\n", nDaemons);
1609 printf(" cacheFlags: %d\n", cacheFlags);
1610 printf(" logFile: %s\n", fullpn_AFSLogFile);
1615 * Initialize the AFS client
1620 * Pull out all the configuration info for the workstation's AFS cache and
1621 * the cellular community we're willing to let our users see.
1623 afs_cdir = afsconf_Open(confDir);
1625 printf("afsd: some file missing or bad in %s\n", confDir);
1629 lookupResult = afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1630 sizeof(afs_LclCellName));
1632 printf("%s: Can't get my home cell name! [Error is %d]\n",
1637 printf("%s: My home cell is '%s'\n",
1638 rn, afs_LclCellName);
1641 if ((logfd = fopen(fullpn_AFSLogFile,"r+")) == 0) {
1642 if (afsd_verbose) printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1643 if (CreateCacheFile(fullpn_AFSLogFile)) {
1644 printf("%s: Can't create '%s' (You may want to use the -logfile option)\n", rn, fullpn_AFSLogFile);
1651 * Create and zero the pathname table for the desired cache files.
1653 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1654 if (pathname_for_V == NULL) {
1655 printf("%s: malloc() failed for cache file table with %d entries.\n",
1659 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1661 printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n",
1662 rn, cacheFiles, (cacheFiles * sizeof(AFSD_INO_T)));
1665 * Set up all the pathnames we'll need for later.
1667 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1668 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1669 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1670 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1673 * Start the RX listener.
1676 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1677 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE);
1680 * Start the RX event handler.
1683 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1684 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1687 * Set up all the kernel processes needed for AFS.
1690 /* initialize AFS callback interface */
1692 /* parse multihomed address files */
1694 st=parseNetFiles(buffer,maskbuffer,mtubuffer,MAXIPADDRS,reason,
1695 AFSDIR_CLIENT_NETINFO_FILEPATH,
1696 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1698 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st, (long) (&buffer[0]),
1699 (long) (&maskbuffer[0]), (long) (&mtubuffer[0]));
1701 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",reason);
1707 printf("%s: Forking rx callback listener.\n", rn);
1709 if (preallocs < cacheStatEntries+50)
1710 preallocs = cacheStatEntries+50;
1711 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1714 printf("%s: Forking AFS daemon.\n", rn);
1715 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1718 printf("%s: Forking check server daemon.\n", rn);
1719 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1722 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1723 for (i=0;i<nDaemons;i++) {
1724 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1728 * Tell the kernel about each cell in the configuration.
1730 lookingForHomeCell = 1;
1732 afsconf_CellApply(afs_cdir, ConfigCell, (char *) 0);
1735 * If we're still looking for the home cell after the whole cell
1736 * configuration database has been parsed, there's something wrong.
1738 if (lookingForHomeCell) {
1739 printf("%s: Can't find home cell '%s' in cell database!\n",
1740 rn, afs_LclCellName);
1744 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n",
1746 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1749 * Tell the kernel some basic information about the workstation's cache.
1752 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1753 " %d optimum cache files, %d blocks in the cache,"
1754 " flags = 0x%x, dcache entries %d\n",
1755 rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
1757 memset(&cparams, 0, sizeof(cparams));
1758 cparams.cacheScaches = cacheStatEntries;
1759 cparams.cacheFiles = cacheFiles;
1760 cparams.cacheBlocks = cacheBlocks;
1761 cparams.cacheDcaches = dCacheSize;
1762 cparams.cacheVolumes = vCacheSize;
1763 cparams.chunkSize = chunkSize;
1764 cparams.setTimeFlag = FALSE;
1765 cparams.memCacheFlag = cacheFlags;
1766 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1767 if (afsd_CloseSynch)
1768 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1771 * Sweep the workstation AFS cache directory, remembering the inodes of
1772 * valid files and deleting extraneous files. Keep sweeping until we
1773 * have the right number of data cache files or we've swept too many
1777 printf("%s: Sweeping workstation's AFS cache directory.\n",
1780 /* Memory-cache based system doesn't need any of this */
1781 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1784 if (SweepAFSCache(&vFilesFound)) {
1785 printf("%s: Error on sweep %d of workstation AFS cache \
1786 directory.\n", rn, cacheIteration);
1790 printf("%s: %d out of %d data cache files found in sweep %d.\n",
1791 rn, vFilesFound, cacheFiles, cacheIteration);
1792 } while ((vFilesFound < cacheFiles) &&
1793 (cacheIteration < MAX_CACHE_LOOPS));
1794 } else if(afsd_verbose)
1795 printf("%s: Using memory cache, not swept\n", rn);
1798 * Pass the kernel the name of the workstation cache file holding the
1802 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
1803 rn, fullpn_DCacheFile);
1804 /* once again, meaningless for a memory-based cache. */
1805 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1806 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1811 * Pass the kernel the name of the workstation cache file holding the
1812 * volume information.
1815 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n",
1816 rn, fullpn_VolInfoFile);
1817 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO,(long)fullpn_VolInfoFile,
1821 * Pass the kernel the name of the afs logging file holding the volume
1825 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n",
1826 rn, fullpn_AFSLogFile);
1827 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1828 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG,(long)fullpn_AFSLogFile,
1832 * Give the kernel the names of the AFS files cached on the workstation's
1836 printf("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1837 rn, cacheFiles, cacheBaseDir);
1838 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1839 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1840 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1841 (long)pathname_for_V[currVFile], 0, 0, 0);
1844 #ifndef NETSCAPE_NSAPI
1846 * Copy our tokens from the kernel to the user space client
1848 for(i = 0 ; i < 200 ; i++) {
1850 * Get the i'th token from the kernel
1852 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1853 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1855 iob.in_size = sizeof(int);
1857 iob.out_size = sizeof(tbuffer);
1859 #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)
1860 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1861 #elif defined(AFS_USR_SGI_ENV)
1862 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1863 #else /* AFS_USR_AIX_ENV */
1864 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1867 usr_assert(errno == EDOM);
1872 * Now pass the token into the user space kernel
1874 rc = uafs_SetTokens(tbuffer, iob.out_size);
1875 usr_assert(rc == 0);
1877 #endif /* !NETSCAPE_NSAPI */
1880 * All the necessary info has been passed into the kernel to run an AFS
1881 * system. Give the kernel our go-ahead.
1884 printf("%s: Calling AFSOP_GO\n", rn);
1885 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1888 * At this point, we have finished passing the kernel all the info
1889 * it needs to set up the AFS. Mount the AFS root.
1891 printf("%s: All AFS daemons started.\n", rn);
1894 printf("%s: Forking trunc-cache daemon.\n", rn);
1895 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1898 * Mount the AFS filesystem
1901 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1902 usr_assert(rc == 0);
1903 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1904 usr_assert(rc == 0);
1908 * initialize the current directory to the AFS root
1910 afs_CurrentDir = afs_RootVnode;
1911 VN_HOLD(afs_CurrentDir);
1916 void uafs_Shutdown()
1923 VN_RELE(afs_CurrentDir);
1924 rc = afs_unmount(&afs_RootVfs);
1925 usr_assert(rc == 0);
1932 * Donate the current thread to the RX server pool.
1934 void uafs_RxServerProc()
1938 struct rx_call *newcall = NULL;
1940 rxi_MorePackets(2); /* alloc more packets */
1941 threadID = rxi_availProcs++;
1944 sock = OSI_NULLSOCKET;
1945 rxi_ServerProc(threadID, newcall, &sock);
1946 if (sock == OSI_NULLSOCKET) {
1951 rxi_ListenerProc(sock, &threadID, &newcall);
1952 /* assert(threadID != -1); */
1953 /* assert(newcall != NULL); */
1957 struct syscallThreadArgs {
1966 #ifdef NETSCAPE_NSAPI
1967 void syscallThread(argp)
1968 #else /* NETSCAPE_NSAPI */
1969 void *syscallThread(argp)
1970 #endif /* NETSCAPE_NSAPI */
1974 struct usr_ucred *crp;
1975 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1978 * AFS daemons run authenticated
1980 u.u_viceid = getuid();
1982 crp->cr_uid = getuid();
1983 crp->cr_ruid = getuid();
1984 crp->cr_suid = getuid();
1985 crp->cr_groups[0] = getgid();
1986 crp->cr_ngroups = 1;
1987 for (i = 1 ; i < NGROUPS ; i++) {
1988 crp->cr_groups[i] = NOGROUP;
1991 call_syscall(sysArgsP->syscall, sysArgsP->afscall,
1992 sysArgsP->param1, sysArgsP->param2,
1993 sysArgsP->param3, sysArgsP->param4);
1995 afs_osi_Free(argp, -1);
1998 fork_syscall(syscall, afscall, param1, param2, param3, param4)
1999 long syscall, afscall, param1, param2, param3, param4;
2002 struct syscallThreadArgs *sysArgsP;
2004 sysArgsP = (struct syscallThreadArgs *)
2005 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
2006 usr_assert(sysArgsP != NULL);
2007 sysArgsP->syscall = syscall;
2008 sysArgsP->afscall = afscall;
2009 sysArgsP->param1 = param1;
2010 sysArgsP->param2 = param2;
2011 sysArgsP->param3 = param3;
2012 sysArgsP->param4 = param4;
2014 usr_thread_create(&tid, syscallThread, sysArgsP);
2015 usr_thread_detach(tid);
2018 call_syscall(syscall, afscall, param1, param2, param3, param4)
2019 long syscall, afscall, param1, param2, param3, param4;
2031 a.syscall = syscall;
2032 a.afscall = afscall;
2039 u.u_ap = (char *)&a;
2041 code = Afs_syscall();
2045 int uafs_SetTokens(char *tbuffer, int tlen)
2048 struct afs_ioctl iob;
2053 iob.out = &outbuf[0];
2054 iob.out_size = sizeof(outbuf);
2055 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2063 int uafs_RPCStatsEnableProc()
2066 struct afs_ioctl iob;
2069 flag = AFSCALL_RXSTATS_ENABLE;
2070 iob.in = (char *)&flag;
2071 iob.in_size = sizeof(afs_int32);
2074 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2082 int uafs_RPCStatsDisableProc()
2085 struct afs_ioctl iob;
2088 flag = AFSCALL_RXSTATS_DISABLE;
2089 iob.in = (char *)&flag;
2090 iob.in_size = sizeof(afs_int32);
2093 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2101 int uafs_RPCStatsClearProc()
2104 struct afs_ioctl iob;
2107 flag = AFSCALL_RXSTATS_CLEAR;
2108 iob.in = (char *)&flag;
2109 iob.in_size = sizeof(afs_int32);
2112 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2120 int uafs_RPCStatsEnablePeer()
2123 struct afs_ioctl iob;
2126 flag = AFSCALL_RXSTATS_ENABLE;
2127 iob.in = (char *)&flag;
2128 iob.in_size = sizeof(afs_int32);
2131 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2139 int uafs_RPCStatsDisablePeer()
2142 struct afs_ioctl iob;
2145 flag = AFSCALL_RXSTATS_DISABLE;
2146 iob.in = (char *)&flag;
2147 iob.in_size = sizeof(afs_int32);
2150 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2158 int uafs_RPCStatsClearPeer()
2161 struct afs_ioctl iob;
2164 flag = AFSCALL_RXSTATS_CLEAR;
2165 iob.in = (char *)&flag;
2166 iob.in_size = sizeof(afs_int32);
2169 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2178 * Lookup a file or directory given its path.
2179 * Call VN_HOLD on the output vnode if successful.
2180 * Returns zero on success, error code on failure.
2182 * Note: Caller must hold the AFS global lock.
2184 int uafs_LookupName(
2186 struct usr_vnode *parentVp,
2187 struct usr_vnode **vpp,
2193 struct usr_vnode *vp;
2194 struct usr_vnode *nextVp;
2195 struct usr_vnode *linkVp;
2203 * Absolute paths must start with the AFS mount point.
2205 if (path[0] != '/') {
2208 path = uafs_afsPathName(path);
2216 * Loop through the path looking for the new directory
2218 tmpPath = afs_osi_Alloc(strlen(path)+1);
2219 usr_assert(tmpPath != NULL);
2220 strcpy(tmpPath, path);
2223 while (pathP != NULL && *pathP != '\0') {
2224 usr_assert(*pathP != '/');
2227 * terminate the current component and skip over slashes
2229 nextPathP = strchr(pathP, '/');
2230 if (nextPathP != NULL) {
2231 while (*nextPathP == '/') {
2232 *(nextPathP++) = '\0';
2237 * Don't call afs_lookup on non-directories
2239 if (vp->v_type != VDIR) {
2241 afs_osi_Free(tmpPath, strlen(path)+1);
2245 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2247 * The AFS root is its own parent
2249 nextVp = afs_RootVnode;
2252 * We need execute permission to search a directory
2254 code = afs_access(vp, VEXEC, u.u_cred);
2257 afs_osi_Free(tmpPath, strlen(path)+1);
2262 * lookup the next component in the path, we can release the
2263 * subdirectory since we hold the global lock
2266 #ifdef AFS_WEB_ENHANCEMENTS
2267 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2268 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2270 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, AFS_LOOKUP_NOEVAL);
2272 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2273 #endif /* AFS_WEB_ENHANCEMENTS */
2276 afs_osi_Free(tmpPath, strlen(path)+1);
2282 * Follow symbolic links for parent directories and
2283 * for leaves when the follow flag is set.
2285 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2287 while(nextVp->v_type == VLNK) {
2288 if (++linkCount > MAX_OSI_LINKS) {
2291 afs_osi_Free(tmpPath, strlen(path)+1);
2294 code = uafs_LookupLink(nextVp, vp, &linkVp);
2298 afs_osi_Free(tmpPath, strlen(path)+1);
2312 * Special case, nextPathP is non-null if pathname ends in slash
2314 if (nextPathP != NULL && vp->v_type != VDIR) {
2316 afs_osi_Free(tmpPath, strlen(path)+1);
2320 afs_osi_Free(tmpPath, strlen(path)+1);
2326 * Lookup the target of a symbolic link
2327 * Call VN_HOLD on the output vnode if successful.
2328 * Returns zero on success, error code on failure.
2330 * Note: Caller must hold the AFS global lock.
2332 int uafs_LookupLink(
2333 struct usr_vnode *vp,
2334 struct usr_vnode *parentVp,
2335 struct usr_vnode **vpp)
2340 struct usr_vnode *linkVp;
2342 struct iovec iov[1];
2346 pathP = afs_osi_Alloc(MAX_OSI_PATH+1);
2347 usr_assert(pathP != NULL);
2350 * set up the uio buffer
2352 iov[0].iov_base = pathP;
2353 iov[0].iov_len = MAX_OSI_PATH+1;
2354 uio.uio_iov = &iov[0];
2358 uio.uio_fmode = FREAD;
2359 uio.uio_resid = MAX_OSI_PATH+1;
2362 * Read the link data
2364 code = afs_readlink(vp, &uio, u.u_cred);
2366 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2369 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2373 * Find the target of the symbolic link
2375 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2377 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2381 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2387 * Lookup the parent of a file or directory given its path
2388 * Call VN_HOLD on the output vnode if successful.
2389 * Returns zero on success, error code on failure.
2391 * Note: Caller must hold the AFS global lock.
2393 int uafs_LookupParent(
2395 struct usr_vnode **vpp)
2400 struct usr_vnode *parentP;
2405 * Absolute path names must start with the AFS mount point.
2408 pathP = uafs_afsPathName(path);
2409 if (pathP == NULL) {
2415 * Find the length of the parent path
2418 while(len > 0 && path[len-1] == '/') {
2424 while(len > 0 && path[len-1] != '/') {
2431 pathP = afs_osi_Alloc(len);
2432 usr_assert(pathP != NULL);
2433 memcpy(pathP, path, len-1);
2434 pathP[len-1] = '\0';
2437 * look up the parent
2439 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2440 afs_osi_Free(pathP, len);
2444 if (parentP->v_type != VDIR) {
2454 * Return a pointer to the first character in the last component
2457 char *uafs_LastPath(char *path)
2462 while (len > 0 && path[len-1] == '/') {
2465 while (len > 0 && path[len-1] != '/') {
2475 * Set the working directory.
2482 retval = uafs_chdir_r(path);
2493 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2498 if (dirP->v_type != VDIR) {
2503 VN_RELE(afs_CurrentDir);
2504 afs_CurrentDir = dirP;
2509 * Create a directory.
2517 retval = uafs_mkdir_r(path, mode);
2528 struct vnode *parentP;
2530 struct usr_vattr attrs;
2532 if (uafs_IsRoot(path)) {
2537 * Look up the parent directory.
2539 nameP = uafs_LastPath(path);
2540 if (nameP != NULL) {
2541 code = uafs_LookupParent(path, &parentP);
2547 parentP = afs_CurrentDir;
2553 * Make sure the directory has at least one character
2555 if (*nameP == '\0') {
2562 * Create the directory
2564 usr_vattr_null(&attrs);
2565 attrs.va_type = VREG;
2566 attrs.va_mode = mode;
2567 attrs.va_uid = u.u_cred->cr_uid;
2568 attrs.va_gid = u.u_cred->cr_gid;
2570 code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
2581 * Return 1 if path is the AFS root, otherwise return 0
2583 int uafs_IsRoot(char *path)
2585 while(*path == '/' && *(path+1) == '/') {
2588 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2591 path += afs_mountDirLen;
2592 while (*path == '/') {
2595 if (*path != '\0') {
2603 * Note: file name may not end in a slash.
2612 retval = uafs_open_r(path, flags, mode);
2626 struct usr_vnode *fileP;
2627 struct usr_vnode *dirP;
2628 struct usr_vattr attrs;
2631 if (uafs_IsRoot(path)) {
2632 fileP = afs_RootVnode;
2636 * Look up the parent directory.
2638 nameP = uafs_LastPath(path);
2639 if (nameP != NULL) {
2640 code = uafs_LookupParent(path, &dirP);
2646 dirP = afs_CurrentDir;
2652 * Make sure the filename has at least one character
2654 if (*nameP == '\0') {
2661 * Get the VNODE for this file
2663 if (flags & O_CREAT) {
2664 usr_vattr_null(&attrs);
2665 attrs.va_type = VREG;
2666 attrs.va_mode = mode;
2667 attrs.va_uid = u.u_cred->cr_uid;
2668 attrs.va_gid = u.u_cred->cr_gid;
2669 if (flags & O_TRUNC) {
2673 code = afs_create(dirP, nameP, &attrs,
2674 (flags & O_EXCL)?usr_EXCL:usr_NONEXCL,
2675 mode, &fileP, u.u_cred);
2683 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2691 * Check whether we have access to this file
2694 if (flags & (O_RDONLY|O_RDWR)) {
2697 if (flags & (O_WRONLY|O_RDWR)) {
2700 if (!fileMode) fileMode = VREAD; /* since O_RDONLY is 0 */
2701 code = afs_access(fileP, fileMode, u.u_cred);
2709 * Get the file attributes, all we need is the size
2711 code = afs_getattr(fileP, &attrs, u.u_cred);
2721 * Setup the open flags
2724 if (flags & O_TRUNC) {
2725 openFlags |= FTRUNC;
2727 if (flags & O_APPEND) {
2728 openFlags |= FAPPEND;
2730 if (flags & O_SYNC) {
2733 if (flags & O_SYNC) {
2736 if (flags & (O_RDONLY|O_RDWR)) {
2739 if (flags & (O_WRONLY|O_RDWR)) {
2740 openFlags |= FWRITE;
2744 * Truncate if necessary
2746 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2747 usr_vattr_null(&attrs);
2749 code = afs_setattr(fileP, &attrs, u.u_cred);
2760 code = afs_open(&fileP, openFlags, u.u_cred);
2768 * Put the vnode pointer into the file table
2770 for (fd = 0 ; fd < MAX_OSI_FILES ; fd++) {
2771 if (afs_FileTable[fd] == NULL) {
2772 afs_FileTable[fd] = fileP;
2773 afs_FileFlags[fd] = openFlags;
2774 if (flags & O_APPEND) {
2775 afs_FileOffsets[fd] = attrs.va_size;
2777 afs_FileOffsets[fd] = 0;
2782 if (fd == MAX_OSI_FILES) {
2799 rc = uafs_open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2808 rc = uafs_open_r(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2822 retval = uafs_write_r(fd, buf, len);
2834 struct iovec iov[1];
2835 struct usr_vnode *fileP;
2838 * Make sure this is an open file
2840 fileP = afs_FileTable[fd];
2841 if (fileP == NULL) {
2847 * set up the uio buffer
2849 iov[0].iov_base = buf;
2850 iov[0].iov_len = len;
2851 uio.uio_iov = &iov[0];
2853 uio.uio_offset = afs_FileOffsets[fd];
2855 uio.uio_fmode = FWRITE;
2856 uio.uio_resid = len;
2862 code = afs_write(fileP, &uio, afs_FileFlags[fd], u.u_cred, 0);
2868 afs_FileOffsets[fd] = uio.uio_offset;
2869 return(len - uio.uio_resid);
2882 retval = uafs_read_r(fd, buf, len);
2894 struct iovec iov[1];
2895 struct usr_vnode *fileP;
2896 struct usr_buf *bufP;
2899 * Make sure this is an open file
2901 fileP = afs_FileTable[fd];
2902 if (fileP == NULL) {
2908 * set up the uio buffer
2910 iov[0].iov_base = buf;
2911 iov[0].iov_len = len;
2912 uio.uio_iov = &iov[0];
2914 uio.uio_offset = afs_FileOffsets[fd];
2916 uio.uio_fmode = FREAD;
2917 uio.uio_resid = len;
2922 code = afs_read(fileP, &uio, u.u_cred, 0, &bufP, 0);
2928 afs_FileOffsets[fd] = uio.uio_offset;
2929 return(len - uio.uio_resid);
2933 * Copy the attributes of a file into a stat structure.
2935 * NOTE: Caller must hold the global AFS lock.
2938 struct usr_vnode *vp,
2942 struct usr_vattr attrs;
2947 * Get the attributes
2949 code = afs_getattr(vp, &attrs, u.u_cred);
2955 * Copy the attributes, zero fields that aren't set
2957 memset((void *)stats, 0, sizeof(struct stat));
2959 stats->st_ino = attrs.va_nodeid;
2960 stats->st_mode = attrs.va_mode;
2961 stats->st_nlink = attrs.va_nlink;
2962 stats->st_uid = attrs.va_uid;
2963 stats->st_gid = attrs.va_gid;
2964 stats->st_rdev = attrs.va_rdev;
2965 stats->st_size = attrs.va_size;
2966 stats->st_atime = attrs.va_atime.tv_sec;
2967 stats->st_mtime = attrs.va_mtime.tv_sec;
2968 stats->st_ctime = attrs.va_ctime.tv_sec;
2969 stats->st_blksize = attrs.va_blocksize;
2970 stats->st_blocks = attrs.va_blocks;
2976 * Get the attributes of a file, do follow links
2984 retval = uafs_stat_r(path, buf);
2996 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3001 code = uafs_GetAttr(vp, buf);
3011 * Get the attributes of a file, don't follow links
3019 retval = uafs_lstat_r(path, buf);
3031 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3036 code = uafs_GetAttr(vp, buf);
3046 * Get the attributes of an open file
3054 retval = uafs_fstat_r(fd, buf);
3066 vp = afs_FileTable[fd];
3071 code = uafs_GetAttr(vp, buf);
3081 * change the permissions on a file
3089 retval = uafs_chmod_r(path, mode);
3100 struct usr_vattr attrs;
3102 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3107 usr_vattr_null(&attrs);
3108 attrs.va_mode = mode;
3109 code = afs_setattr(vp, &attrs, u.u_cred);
3119 * change the permissions on an open file
3127 retval = uafs_fchmod_r(fd, mode);
3138 struct usr_vattr attrs;
3140 vp = afs_FileTable[fd];
3145 usr_vattr_null(&attrs);
3146 attrs.va_mode = mode;
3147 code = afs_setattr(vp, &attrs, u.u_cred);
3164 retval = uafs_truncate_r(path, length);
3169 int uafs_truncate_r(
3175 struct usr_vattr attrs;
3177 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3182 usr_vattr_null(&attrs);
3183 attrs.va_size = length;
3184 code = afs_setattr(vp, &attrs, u.u_cred);
3194 * truncate an open file
3202 retval = uafs_ftruncate_r(fd, length);
3207 int uafs_ftruncate_r(
3213 struct usr_vattr attrs;
3215 vp = afs_FileTable[fd];
3220 usr_vattr_null(&attrs);
3221 attrs.va_size = length;
3222 code = afs_setattr(vp, &attrs, u.u_cred);
3231 * set the read/write file pointer of an open file
3240 retval = uafs_lseek_r(fd, offset, whence);
3252 struct usr_vattr attrs;
3253 struct usr_vnode *vp;
3255 vp = afs_FileTable[fd];
3262 newpos = afs_FileOffsets[fd] + offset;
3268 code = afs_getattr(vp, &attrs, u.u_cred);
3273 newpos = attrs.va_size + offset;
3283 afs_FileOffsets[fd] = newpos;
3295 retval = uafs_fsync_r(fd);
3304 struct usr_vnode *fileP;
3307 fileP = afs_FileTable[fd];
3308 if (fileP == NULL) {
3313 code = afs_fsync(fileP, u.u_cred);
3330 retval = uafs_close_r(fd);
3339 struct usr_vnode *fileP;
3341 fileP = afs_FileTable[fd];
3342 if (fileP == NULL) {
3346 afs_FileTable[fd] = NULL;
3348 code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
3359 * Create a hard link from the source to the target
3360 * Note: file names may not end in a slash.
3368 retval = uafs_link_r(existing, new);
3378 struct usr_vnode *existP;
3379 struct usr_vnode *dirP;
3382 if (uafs_IsRoot(new)) {
3387 * Look up the existing node.
3389 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3396 * Look up the parent directory.
3398 nameP = uafs_LastPath(new);
3399 if (nameP != NULL) {
3400 code = uafs_LookupParent(new, &dirP);
3407 dirP = afs_CurrentDir;
3413 * Make sure the filename has at least one character
3415 if (*nameP == '\0') {
3425 code = afs_link(existP, dirP, nameP, u.u_cred);
3436 * Create a symbolic link from the source to the target
3437 * Note: file names may not end in a slash.
3445 retval = uafs_symlink_r(target, source);
3455 struct usr_vnode *dirP;
3456 struct usr_vattr attrs;
3459 if (uafs_IsRoot(source)) {
3464 * Look up the parent directory.
3466 nameP = uafs_LastPath(source);
3467 if (nameP != NULL) {
3468 code = uafs_LookupParent(source, &dirP);
3474 dirP = afs_CurrentDir;
3480 * Make sure the filename has at least one character
3482 if (*nameP == '\0') {
3491 usr_vattr_null(&attrs);
3492 attrs.va_type = VLNK;
3493 attrs.va_mode = 0777;
3494 attrs.va_uid = u.u_cred->cr_uid;
3495 attrs.va_gid = u.u_cred->cr_gid;
3496 code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
3506 * Read a symbolic link into the buffer
3515 retval = uafs_readlink_r(path, buf, len);
3520 int uafs_readlink_r(
3526 struct usr_vnode *vp;
3528 struct iovec iov[1];
3530 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3536 if (vp->v_type != VLNK) {
3543 * set up the uio buffer
3545 iov[0].iov_base = buf;
3546 iov[0].iov_len = len;
3547 uio.uio_iov = &iov[0];
3551 uio.uio_fmode = FREAD;
3552 uio.uio_resid = len;
3557 code = afs_readlink(vp, &uio, u.u_cred);
3565 * return the number of bytes read
3567 return (len - uio.uio_resid);
3571 * Remove a file (or directory)
3572 * Note: file name may not end in a slash.
3579 retval = uafs_unlink_r(path);
3589 struct usr_vnode *fileP;
3590 struct usr_vnode *dirP;
3593 if (uafs_IsRoot(path)) {
3598 * Look up the parent directory.
3600 nameP = uafs_LastPath(path);
3601 if (nameP != NULL) {
3602 code = uafs_LookupParent(path, &dirP);
3608 dirP = afs_CurrentDir;
3614 * Make sure the filename has at least one character
3616 if (*nameP == '\0') {
3625 code = afs_remove(dirP, nameP, u.u_cred);
3636 * Rename a file (or directory)
3644 retval = uafs_rename_r(old, new);
3656 struct usr_vnode *odirP;
3657 struct usr_vnode *ndirP;
3659 if (uafs_IsRoot(new)) {
3664 * Look up the parent directories.
3666 onameP = uafs_LastPath(old);
3667 if (onameP != NULL) {
3668 code = uafs_LookupParent(old, &odirP);
3674 odirP = afs_CurrentDir;
3678 nnameP = uafs_LastPath(new);
3679 if (nnameP != NULL) {
3680 code = uafs_LookupParent(new, &ndirP);
3686 ndirP = afs_CurrentDir;
3692 * Make sure the filename has at least one character
3694 if (*onameP == '\0' || *nnameP == '\0') {
3704 code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
3716 * Remove a or directory
3717 * Note: file name may not end in a slash.
3724 retval = uafs_rmdir_r(path);
3734 struct usr_vnode *fileP;
3735 struct usr_vnode *dirP;
3738 if (uafs_IsRoot(path)) {
3743 * Look up the parent directory.
3745 nameP = uafs_LastPath(path);
3746 if (nameP != NULL) {
3747 code = uafs_LookupParent(path, &dirP);
3753 dirP = afs_CurrentDir;
3759 * Make sure the directory name has at least one character
3761 if (*nameP == '\0') {
3768 * Remove the directory
3770 code = afs_rmdir(dirP, nameP, u.u_cred);
3781 * Flush a file from the AFS cache
3787 struct afs_ioctl iob;
3794 code = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6),
3803 int uafs_FlushFile_r(
3808 retval = uafs_FlushFile(path);
3816 usr_DIR *uafs_opendir(
3821 retval = uafs_opendir_r(path);
3826 usr_DIR *uafs_opendir_r(
3830 struct usr_vnode *fileP;
3834 * Open the directory for reading
3836 fd = uafs_open_r(path, O_RDONLY, 0);
3841 fileP = afs_FileTable[fd];
3842 if (fileP == NULL) {
3846 if (fileP->v_type != VDIR) {
3853 * Set up the directory structures
3855 dirp = (usr_DIR *)afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3856 sizeof(struct usr_dirent));
3857 usr_assert(dirp != NULL);
3858 dirp->dd_buf = (char *)(dirp+1);
3868 * Read directory entries into a file system independent format.
3869 * This routine was developed to support AFS cache consistency testing.
3870 * You should use uafs_readdir instead.
3874 struct min_direct *buf,
3879 retval = uafs_getdents_r(fd, buf, len);
3884 int uafs_getdents_r(
3886 struct min_direct *buf,
3891 struct usr_vnode *vp;
3892 struct iovec iov[1];
3895 * Make sure this is an open file
3897 vp = afs_FileTable[fd];
3905 * set up the uio buffer
3907 iov[0].iov_base = (char *)buf;
3908 iov[0].iov_len = len;
3909 uio.uio_iov = &iov[0];
3911 uio.uio_offset = afs_FileOffsets[fd];
3913 uio.uio_fmode = FREAD;
3914 uio.uio_resid = len;
3917 * read the next chunk from the directory
3919 code = afs_readdir(vp, &uio, u.u_cred);
3925 afs_FileOffsets[fd] = uio.uio_offset;
3926 return(len - uio.uio_resid);
3930 * read from a directory (names only)
3932 struct usr_dirent *uafs_readdir(
3935 struct usr_dirent *retval;
3937 retval = uafs_readdir_r(dirp);
3942 struct usr_dirent *uafs_readdir_r(
3949 struct usr_vnode *vp;
3950 struct iovec iov[1];
3951 struct usr_dirent *direntP;
3952 struct min_direct *directP;
3955 * Make sure this is an open file
3957 vp = afs_FileTable[dirp->dd_fd];
3964 * If there are no entries in the stream buffer
3965 * then read another chunk
3967 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3968 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3970 * set up the uio buffer
3972 iov[0].iov_base = dirp->dd_buf;
3973 iov[0].iov_len = USR_DIRSIZE;
3974 uio.uio_iov = &iov[0];
3976 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3978 uio.uio_fmode = FREAD;
3979 uio.uio_resid = USR_DIRSIZE;
3982 * read the next chunk from the directory
3984 code = afs_readdir(vp, &uio, u.u_cred);
3989 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3991 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3993 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3997 * Check for end of file
3999 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
4003 len = ((sizeof(struct min_direct)+directP->d_namlen+4) & (~3));
4004 usr_assert(len <= dirp->dd_size);
4007 * Copy the next entry into the usr_dirent structure and advance
4009 direntP = (struct usr_dirent *)(dirp->dd_buf+USR_DIRSIZE);
4010 direntP->d_ino = directP->d_fileno;
4011 direntP->d_off = direntP->d_reclen;
4012 direntP->d_reclen = sizeof(struct usr_dirent) - MAXNAMLEN +
4013 directP->d_namlen + 1;
4014 memcpy(&direntP->d_name[0], (void *)(directP+1), directP->d_namlen);
4015 direntP->d_name[directP->d_namlen] = '\0';
4016 dirp->dd_loc += len;
4017 dirp->dd_size -= len;
4030 retval = uafs_closedir_r(dirp);
4035 int uafs_closedir_r(
4042 afs_osi_Free((char *)dirp,
4043 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4044 rc = uafs_close_r(fd);
4049 * Do AFS authentication
4058 afs_int32 password_expires = -1;
4060 usr_mutex_lock(&osi_authenticate_lock);
4061 code = ka_UserAuthenticateGeneral(
4062 KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG2, user,
4063 NULL, cell, passwd, 0, &password_expires,
4065 usr_mutex_unlock(&osi_authenticate_lock);
4077 retval = uafs_klog(user, cell, passwd, reason);
4083 * Destroy AFS credentials from the kernel cache
4089 usr_mutex_lock(&osi_authenticate_lock);
4090 code = ktc_ForgetAllTokens();
4091 usr_mutex_unlock(&osi_authenticate_lock);
4099 retval = uafs_unlog();
4105 * Strip the AFS mount point from a pathname string. Return
4106 * NULL if the path is a relative pathname or if the path
4107 * doesn't start with the AFS mount point string.
4109 char *uafs_afsPathName(char *path)
4118 for (i = 1, p = path+1; *p != '\0' ; p++) {
4119 /* Ignore duplicate slashes */
4120 if (*p == '/' && lastchar == '/')
4122 /* Is this a subdirectory of the AFS mount point? */
4123 if (afs_mountDir[i] == '\0' && *p == '/') {
4124 /* strip leading slashes */
4125 while (*(++p) == '/');
4128 /* Reject paths that are not within AFS */
4129 if (*p != afs_mountDir[i])
4134 /* Is this the AFS mount point? */
4135 if (afs_mountDir[i] == '\0') {
4136 usr_assert(*p == '\0');
4142 #ifdef AFS_WEB_ENHANCEMENTS
4145 * klog but don't allocate a new pag
4147 int uafs_klog_nopag(
4154 afs_int32 password_expires = -1;
4156 usr_mutex_lock(&osi_authenticate_lock);
4157 code = ka_UserAuthenticateGeneral(
4158 KA_USERAUTH_VERSION /*+KA_USERAUTH_DOSETPAG2*/, user,
4159 NULL, cell, passwd, 0, &password_expires,
4161 usr_mutex_unlock(&osi_authenticate_lock);
4166 * uafs_getcellstatus
4167 * get the cell status
4169 int uafs_getcellstatus(char *cell, afs_int32 *status)
4172 struct afs_ioctl iob;
4175 iob.in_size = strlen(cell)+1;
4179 rc = call_syscall(AFSCALL_PIOCTL, /*path*/0, _VICEIOCTL(35),
4193 * Get quota of volume associated with path
4195 int uafs_getvolquota(char *path, afs_int32 *BlocksInUse, afs_int32 *MaxQuota)
4198 struct afs_ioctl iob;
4199 VolumeStatus *status;
4205 iob.out_size = 1024;
4207 rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(4),
4215 status = (VolumeStatus *) buf;
4216 *BlocksInUse = status->BlocksInUse;
4217 *MaxQuota = status->MaxQuota;
4223 * Set quota of volume associated with path
4225 int uafs_setvolquota(char *path, afs_int32 MaxQuota)
4228 struct afs_ioctl iob;
4229 VolumeStatus *status;
4237 memset(buf, 0, sizeof(VolumeStatus));
4238 status = (VolumeStatus *) buf;
4239 status->MaxQuota = MaxQuota;
4240 status->MinQuota = -1;
4242 rc = call_syscall(AFSCALL_PIOCTL, path, _VICEIOCTL(5),
4254 * uafs_statmountpoint
4255 * Determine whether a dir. is a mount point or not
4256 * return 1 if mount point, 0 if not
4258 int uafs_statmountpoint(char *path)
4265 retval = uafs_statmountpoint_r(path);
4270 int uafs_statmountpoint_r(char *path)
4275 struct vrequest treq;
4278 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4284 avc = (struct vcache *) vp;
4293 * Get a list of rights for the current user on path.
4295 int uafs_getRights(char *path)
4302 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4309 afs_rights = PRSFS_READ |
4317 afs_rights = afs_getRights (vp, afs_rights, u.u_cred);
4322 #endif /* AFS_WEB_ENHANCEMENTS */
4324 #endif /* UKERNEL */