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 "afsincludes.h" /* Afs-based standard headers */
25 #include "afs_usrops.h"
26 #include "afs/afs_stats.h"
28 #include "afs/cellconfig.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(struct usr_vnode *vp, struct usr_buf *bp)
185 * I am not sure what to do with these, they assert for now
187 int iodone(struct usr_buf *bp)
192 struct usr_file *getf(int fd)
198 * Every user is a super user
200 int afs_osi_suser(void *credp)
205 int afs_suser(void *credp)
211 * These are no-ops in user space
214 void afs_osi_SetTime(osi_timeval_t *atv)
220 * xflock should never fall through, the only files we know
221 * about are AFS files
229 * ioctl should never fall through, the only files we know
230 * about are AFS files
238 * We do not support the inode related system calls
240 int afs_syscall_icreate(void)
245 int afs_syscall_iincdec(void)
250 int afs_syscall_iopen(void)
255 int afs_syscall_ireadwrite(void)
261 * these routines are referenced in the vfsops structure, but
262 * should never get called
285 * uiomove copies data between kernel buffers and uio buffers
287 int usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
294 nio = uio->uio_iovcnt;
304 while(nio > 0 && n > 0) {
305 len = MIN(n, iovp->iov_len);
306 if (rw == UIO_READ) {
307 memcpy(iovp->iov_base, ptr, len);
309 memcpy(ptr, iovp->iov_base, len);
313 uio->uio_resid -= len;
314 uio->uio_offset += len;
315 iovp->iov_base = (char *)(iovp->iov_base) + len;
316 iovp->iov_len -= len;
327 * routines to manage user credentials
329 struct usr_ucred *usr_crcopy(struct usr_ucred *credp)
331 struct usr_ucred *newcredp;
333 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
335 newcredp->cr_ref = 1;
339 struct usr_ucred *usr_crget(void)
341 struct usr_ucred *newcredp;
343 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
344 newcredp->cr_ref = 1;
348 int usr_crfree(struct usr_ucred *credp)
351 if (credp->cr_ref == 0) {
352 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
356 int usr_crhold(struct usr_ucred *credp)
361 void usr_vattr_null(struct usr_vattr *vap)
366 n = sizeof(struct usr_vattr);
374 * Initialize the thread specific data used to simulate the
375 * kernel environment for each thread. The user structure
376 * is stored in the thread specific data.
378 void uafs_InitThread(void)
381 struct usr_user *uptr;
384 * initialize the thread specific user structure. Use malloc to
385 * allocate the data block, so pthread_finish can free the buffer
386 * when this thread terminates.
388 uptr = (struct usr_user *)malloc(sizeof(struct usr_user) +
389 sizeof(struct usr_ucred));
390 usr_assert(uptr != NULL);
393 uptr->u_procp = afs_global_procp;
394 uptr->u_cred = (struct usr_ucred *)(uptr+1);
395 *uptr->u_cred = *afs_global_ucredp;
396 st = usr_setspecific(afs_global_u_key, (void *)uptr);
401 * routine to get the user structure from the thread specific data.
402 * this routine is used to implement the global 'u' structure. Initializes
403 * the thread if needed.
405 struct usr_user *get_user_struct(void)
407 struct usr_user *uptr;
409 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
413 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
415 usr_assert(uptr != NULL);
421 * Hash an address for the waithash table
423 #define WAITHASH(X) \
424 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
429 void afs_osi_Sleep(void *x)
433 int rxGlockOwner = ISAFS_RXGLOCK();
434 int glockOwner = ISAFS_GLOCK();
436 usr_mutex_lock(&osi_waitq_lock);
444 if (osi_waithash_avail == NULL) {
445 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
446 usr_cond_init(&waitp->cond);
448 waitp = osi_waithash_avail;
449 osi_waithash_avail = osi_waithash_avail->next;
453 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
454 osi_waithash_table[index].tail, next, prev);
455 waitp->expiration = 0;
456 waitp->timedNext = NULL;
457 waitp->timedPrev = NULL;
458 while (waitp->flag == 0) {
459 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
461 DLL_DELETE(waitp, osi_waithash_table[index].head,
462 osi_waithash_table[index].tail, next, prev);
463 waitp->next = osi_waithash_avail;
464 osi_waithash_avail = waitp;
465 usr_mutex_unlock(&osi_waitq_lock);
474 int afs_osi_SleepSig(void *x)
480 int afs_osi_Wakeup(void *x)
486 usr_mutex_lock(&osi_waitq_lock);
487 waitp = osi_waithash_table[index].head;
489 if (waitp->addr == x && waitp->flag == 0) {
491 usr_cond_signal(&waitp->cond);
495 usr_mutex_unlock(&osi_waitq_lock);
498 int afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
504 int rxGlockOwner = ISAFS_RXGLOCK();
505 int glockOwner = ISAFS_GLOCK();
507 tv.tv_sec = msec / 1000;
508 tv.tv_nsec = (msec % 1000) * 1000000;
509 if (handle == NULL) {
516 usr_thread_sleep(&tv);
525 usr_mutex_lock(&osi_waitq_lock);
532 index = WAITHASH((caddr_t)handle);
533 if (osi_waithash_avail == NULL) {
534 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
535 usr_cond_init(&waitp->cond);
537 waitp = osi_waithash_avail;
538 osi_waithash_avail = osi_waithash_avail->next;
540 waitp->addr = (caddr_t)handle;
542 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
543 osi_waithash_table[index].tail, next, prev);
544 tv.tv_sec += time(NULL);
545 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0)?0:1);
546 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
547 timedNext, timedPrev);
548 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
554 DLL_DELETE(waitp, osi_waithash_table[index].head,
555 osi_waithash_table[index].tail, next, prev);
556 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail,
557 timedNext, timedPrev);
558 waitp->next = osi_waithash_avail;
559 osi_waithash_avail = waitp;
560 usr_mutex_unlock(&osi_waitq_lock);
571 void afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
573 afs_osi_Wakeup(handle);
577 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
578 * to explicitly signal cond_timed_waits when their timers expire
580 int afs_osi_CheckTimedWaits(void)
585 curTime = time(NULL);
586 usr_mutex_lock(&osi_waitq_lock);
587 waitp = osi_timedwait_head;
588 while (waitp != NULL) {
589 usr_assert(waitp->expiration != 0);
590 if (waitp->expiration <= curTime) {
592 usr_cond_signal(&waitp->cond);
594 waitp = waitp->timedNext;
596 usr_mutex_unlock(&osi_waitq_lock);
600 * I-node numbers are indeces into a table containing a filename
601 * i-node structure and a vnode structure. When we create an i-node,
602 * we copy the name into the array and initialize enough of the fields
603 * in the inode and vnode structures to get the client to work.
606 struct usr_inode i_node;
609 osi_file_table_t *osi_file_table;
611 int max_osi_files = 0;
614 * Allocate a slot in the file table if there is not one there already,
615 * copy in the file name and kludge up the vnode and inode structures
617 int lookupname(char *fnamep, int segflg, int followlink,
618 struct usr_vnode **dirvpp, struct usr_vnode **compvpp)
622 struct usr_inode *ip;
623 struct usr_vnode *vp;
625 /*usr_assert(followlink == 0);*/
626 usr_assert(dirvpp == NULL);
629 * Assume relative pathnames refer to files in AFS
631 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
633 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
638 usr_mutex_lock(&osi_inode_lock);
640 for (i = 0 ; i < n_osi_files ; i++) {
641 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
642 *compvpp = &osi_file_table[i].i_node.i_vnode;
643 (*compvpp)->v_count++;
644 usr_mutex_unlock(&osi_inode_lock);
649 if (n_osi_files == max_osi_files) {
650 usr_mutex_unlock(&osi_inode_lock);
654 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep)+1);
655 usr_assert(osi_file_table[n_osi_files].name != NULL);
656 strcpy(osi_file_table[n_osi_files].name, fnamep);
657 ip = &osi_file_table[i].i_node;
659 vp->v_data = (caddr_t)ip;
662 ip->i_number = n_osi_files;
664 usr_mutex_unlock(&osi_inode_lock);
670 * open a file given its i-node number
672 void *osi_UFSOpen(afs_int32 ino)
680 if (ino > n_osi_files) {
686 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
687 usr_assert(fp != NULL);
688 fp->fd = open(osi_file_table[ino-1].name, O_RDWR|O_CREAT, 0);
691 afs_osi_Free((char *)fp, sizeof(struct osi_file));
695 rc = fstat(fp->fd, &st);
698 afs_osi_Free((void *)fp, sizeof(struct osi_file));
702 fp->size = st.st_size;
705 fp->vnode = (struct usr_vnode *)fp;
711 int osi_UFSClose(struct osi_file *fp)
721 afs_osi_Free((void *)fp, sizeof(struct osi_file));
725 afs_osi_Free((void *)fp, sizeof(struct osi_file));
730 int osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
737 rc = ftruncate(fp->fd, len);
748 int afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
758 rc = lseek(fp->fd, offset, SEEK_SET);
760 rc = lseek(fp->fd, fp->offset, SEEK_SET);
768 ret = read(fp->fd, buf, len);
775 rc = fstat(fp->fd, &st);
781 fp->size = st.st_size;
786 int afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
796 rc = lseek(fp->fd, offset, SEEK_SET);
798 rc = lseek(fp->fd, fp->offset, SEEK_SET);
806 ret = write(fp->fd, buf, len);
813 rc = fstat(fp->fd, &st);
819 fp->size = st.st_size;
824 int afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
830 rc = fstat(fp->fd, &st);
836 stp->size = st.st_size;
837 stp->blksize = st.st_blksize;
838 stp->mtime = st.st_mtime;
839 stp->atime = st.st_atime;
847 int afs_osi_VOP_RDWR(
848 struct usr_vnode *vnodeP,
849 struct usr_uio *uioP,
852 struct usr_ucred* credP)
855 struct osi_file *fp = (struct osi_file *)vnodeP;
858 * We don't support readv/writev.
860 usr_assert(uioP->uio_iovcnt == 1);
861 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
863 if (rw == UIO_WRITE) {
864 usr_assert(uioP->uio_fmode == FWRITE);
865 rc = afs_osi_Write(fp, uioP->uio_offset,
866 uioP->uio_iov[0].iov_base,
867 uioP->uio_iov[0].iov_len);
869 usr_assert(uioP->uio_fmode == FREAD);
870 rc = afs_osi_Read(fp, uioP->uio_offset,
871 uioP->uio_iov[0].iov_base,
872 uioP->uio_iov[0].iov_len);
878 uioP->uio_resid -= rc;
879 uioP->uio_offset += rc;
880 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
881 uioP->uio_iov[0].iov_len -= rc;
886 * Use malloc/free routines with check patterns before and after each block
889 static char *afs_check_string1 = "UAFS";
890 static char *afs_check_string2 = "AFS_OSI_";
892 void *afs_osi_Alloc(size_t size)
897 void afs_osi_Free(void *ptr, size_t size)
902 void afs_osi_FreeStr(char *ptr)
907 void *osi_AllocLargeSpace(size_t size)
909 AFS_STATCNT(osi_AllocLargeSpace);
910 return afs_osi_Alloc(size);
913 void osi_FreeLargeSpace(void *ptr)
915 AFS_STATCNT(osi_FreeLargeSpace);
916 afs_osi_Free(ptr, 0);
919 void *osi_AllocSmallSpace(size_t size)
921 AFS_STATCNT(osi_AllocSmallSpace);
922 return afs_osi_Alloc(size);
925 void osi_FreeSmallSpace(void *ptr)
927 AFS_STATCNT(osi_FreeSmallSpace);
928 afs_osi_Free(ptr, 0);
931 void shutdown_osi(void)
933 AFS_STATCNT(shutdown_osi);
937 void shutdown_osinet(void)
939 AFS_STATCNT(shutdown_osinet);
943 void shutdown_osifile(void)
945 AFS_STATCNT(shutdown_osifile);
949 int afs_nfsclient_init(void)
954 void shutdown_nfsclnt(void)
959 void afs_osi_Invisible(void)
964 int osi_GetTime(struct timeval *tv)
966 gettimeofday(tv, NULL);
970 int osi_SetTime(struct timeval *tv)
975 int osi_Active(struct vcache *avc)
977 AFS_STATCNT(osi_Active);
978 if (avc->opens > 0) return(1);
982 int afs_osi_MapStrategy(int (*aproc)(), struct usr_buf *bp)
984 afs_int32 returnCode;
985 returnCode = (*aproc)(bp);
989 void osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
991 ObtainSharedLock(&avc->lock,555);
992 if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0) ||
993 ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
994 ReleaseSharedLock(&avc->lock);
997 UpgradeSToWLock(&avc->lock,565);
998 hset(avc->mapDV, avc->m.DataVersion);
999 ReleaseWriteLock(&avc->lock);
1003 void osi_FlushText_really(register struct vcache *vp)
1005 if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
1006 hset(vp->flushDV, vp->m.DataVersion);
1011 int osi_SyncVM(struct vcache *avc)
1016 void osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1028 * Allocate the table used to implement psuedo-inodes.
1030 max_osi_files = cacheFiles + 100;
1031 osi_file_table = (osi_file_table_t *)
1032 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1033 usr_assert(osi_file_table != NULL);
1035 #ifndef NETSCAPE_NSAPI
1037 * Initialize the mutex and condition variable used to implement
1040 pthread_mutex_init(&usr_sleep_mutex, NULL);
1041 pthread_cond_init(&usr_sleep_cond, NULL);
1042 #endif /* !NETSCAPE_NSAPI */
1045 * Initialize the hash table used for sleep/wakeup
1047 for (i = 0 ; i < OSI_WAITHASH_SIZE ; i++) {
1048 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1050 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1051 osi_waithash_avail = NULL;
1054 * Initialize the AFS file table
1056 for (i = 0 ; i < MAX_OSI_FILES ; i++) {
1057 afs_FileTable[i] = NULL;
1061 * Initialize the global locks
1063 usr_mutex_init(&afs_global_lock);
1064 usr_mutex_init(&rx_global_lock);
1065 usr_mutex_init(&osi_inode_lock);
1066 usr_mutex_init(&osi_waitq_lock);
1067 usr_mutex_init(&osi_authenticate_lock);
1070 * Initialize the AFS OSI credentials
1072 afs_osi_cred = *afs_global_ucredp;
1075 /* ParseArgs is now obsolete, being handled by cmd */
1077 /*---------------------------------------------------------------------
1081 * Given the final component of a filename expected to be a data cache file,
1082 * return the integer corresponding to the file. Note: we reject names that
1083 * are not a ``V'' followed by an integer. We also reject those names having
1084 * the right format but lying outside the range [0..cacheFiles-1].
1087 * fname : Char ptr to the filename to parse.
1090 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1094 * Nothing interesting.
1098 *------------------------------------------------------------------------*/
1100 int GetVFileNumber(char *fname)
1102 int computedVNumber; /*The computed file number we return*/
1103 int filenameLen; /*Number of chars in filename*/
1104 int currDigit; /*Current digit being processed*/
1107 * The filename must have at least two characters, the first of which must be a ``V''
1108 * and the second of which cannot be a zero unless the file is exactly two chars long.
1110 filenameLen = strlen(fname);
1111 if (filenameLen < 2)
1113 if (fname[0] != 'V')
1115 if ((filenameLen > 2) && (fname[1] == '0'))
1119 * Scan through the characters in the given filename, failing immediately if a non-digit
1122 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1123 if (isdigit(fname[currDigit]) == 0)
1127 * All relevant characters are digits. Pull out the decimal number they represent.
1128 * Reject it if it's out of range, otherwise return it.
1130 computedVNumber = atoi(++fname);
1131 if (computedVNumber < cacheFiles)
1132 return(computedVNumber);
1137 /*---------------------------------------------------------------------
1141 * Given a full pathname for a file we need to create for the workstation AFS
1142 * cache, go ahead and create the file.
1145 * fname : Full pathname of file to create.
1148 * 0 iff the file was created,
1152 * The given cache file has been found to be missing.
1156 *------------------------------------------------------------------------*/
1158 int CreateCacheFile(char *fname)
1160 static char rn[] = "CreateCacheFile"; /*Routine name*/
1161 int cfd; /*File descriptor to AFS cache file*/
1162 int closeResult; /*Result of close()*/
1165 printf("%s: Creating cache file '%s'\n",
1167 cfd = open(fname, createAndTrunc, ownerRWmode);
1169 printf("%s: Can't create '%s', error return is %d (%d)\n",
1170 rn, fname, cfd, errno);
1173 closeResult = close(cfd);
1175 printf("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1183 /*---------------------------------------------------------------------
1187 * Sweep through the AFS cache directory, recording the inode number for
1188 * each valid data cache file there. Also, delete any file that doesn't beint32
1189 * in the cache directory during this sweep, and remember which of the other
1190 * residents of this directory were seen. After the sweep, we create any data
1191 * cache files that were missing.
1194 * vFilesFound : Set to the number of data cache files found.
1197 * 0 if everything went well,
1201 * This routine may be called several times. If the number of data cache files
1202 * found is less than the global cacheFiles, then the caller will need to call it
1203 * again to record the inodes of the missing zero-length data cache files created
1204 * in the previous call.
1207 * Fills up the global pathname_for_V array, may create and/or
1208 * delete files as explained above.
1209 *------------------------------------------------------------------------*/
1211 int SweepAFSCache(int *vFilesFound)
1213 static char rn[] = "SweepAFSCache"; /*Routine name*/
1214 char fullpn_FileToDelete[1024]; /*File to be deleted from cache*/
1215 char *fileToDelete; /*Ptr to last component of above*/
1216 DIR *cdirp; /*Ptr to cache directory structure*/
1218 struct dirent *currp; /*Current directory entry*/
1219 int vFileNum; /*Data cache file's associated number*/
1221 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1223 printf("%s: Memory Cache, no cache sweep done\n", rn);
1229 printf("%s: Opening cache directory '%s'\n",
1232 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1233 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n",
1237 cdirp = opendir(cacheBaseDir);
1238 if (cdirp == (DIR *)0) {
1239 printf("%s: Can't open AFS cache directory, '%s'.\n",
1245 * Scan the directory entries, remembering data cache file inodes and the existance
1246 * of other important residents. Delete all files that don't belong here.
1249 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1250 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1252 for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
1255 printf("%s: Current directory entry:\n",
1257 printf("\tinode=%d, reclen=%d, name='%s'\n",
1258 currp->d_ino, currp->d_reclen, currp->d_name);
1262 * Guess current entry is for a data cache file.
1264 vFileNum = GetVFileNumber(currp->d_name);
1265 if (vFileNum >= 0) {
1267 * Found a valid data cache filename. Remember this file's name
1268 * and bump the number of files found.
1270 pathname_for_V[vFileNum] = afs_osi_Alloc(strlen(currp->d_name) +
1271 strlen(cacheBaseDir) + 2);
1272 usr_assert(pathname_for_V[vFileNum] != NULL);
1273 sprintf(pathname_for_V[vFileNum], "%s/%s",
1274 cacheBaseDir, currp->d_name);
1277 else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1279 * Found the file holding the dcache entries.
1281 missing_DCacheFile = 0;
1283 else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1285 * Found the file holding the volume info.
1287 missing_VolInfoFile = 0;
1289 else if ((strcmp(currp->d_name, ".") == 0) ||
1290 (strcmp(currp->d_name, "..") == 0) ||
1291 (strcmp(currp->d_name, "lost+found") == 0)) {
1293 * Don't do anything - this file is legit, and is to be left alone.
1298 * This file doesn't belong in the cache. Nuke it.
1300 sprintf(fileToDelete, "%s", currp->d_name);
1302 printf("%s: Deleting '%s'\n",
1303 rn, fullpn_FileToDelete);
1304 if (unlink(fullpn_FileToDelete)) {
1305 printf("%s: Can't unlink '%s', errno is %d\n",
1306 rn, fullpn_FileToDelete, errno);
1312 * Create all the cache files that are missing.
1314 if (missing_DCacheFile) {
1316 printf("%s: Creating '%s'\n",
1317 rn, fullpn_DCacheFile);
1318 if (CreateCacheFile(fullpn_DCacheFile))
1319 printf("%s: Can't create '%s'\n",
1320 rn, fullpn_DCacheFile);
1322 if (missing_VolInfoFile) {
1324 printf("%s: Creating '%s'\n",
1325 rn, fullpn_VolInfoFile);
1326 if (CreateCacheFile(fullpn_VolInfoFile))
1327 printf("%s: Can't create '%s'\n",
1328 rn, fullpn_VolInfoFile);
1331 if (*vFilesFound < cacheFiles) {
1333 * We came up short on the number of data cache files found. Scan through the inode
1334 * list and create all missing files.
1336 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1337 if (pathname_for_V[vFileNum] == (AFSD_INO_T)0) {
1338 sprintf(vFileNumber, "%d", vFileNum);
1340 printf("%s: Creating '%s'\n",
1342 if (CreateCacheFile(fullpn_VFile))
1343 printf("%s: Can't create '%s'\n",
1349 * Close the directory, return success.
1352 printf("%s: Closing cache directory.\n",
1358 static ConfigCell(register struct afsconf_cell *aci, char *arock, struct afsconf_dir *adir)
1360 register int isHomeCell;
1362 afs_int32 cellFlags;
1363 afs_int32 hosts[MAXHOSTSPERCELL];
1365 /* figure out if this is the home cell */
1366 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1368 lookingForHomeCell = 0;
1369 cellFlags = 1; /* home cell, suid is ok */
1372 cellFlags = 2; /* not home, suid is forbidden */
1375 /* build address list */
1376 for(i=0;i<MAXHOSTSPERCELL;i++)
1377 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1379 if (aci->linkedCell) cellFlags |= 4; /* Flag that linkedCell arg exists,
1380 for upwards compatibility */
1382 /* configure one cell */
1383 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2,
1384 (long)hosts, /* server addresses */
1385 (long)aci->name, /* cell name */
1386 (long)cellFlags, /* is this the home cell? */
1387 (long)aci->linkedCell); /* Linked cell, if any */
1392 * Set the UDP port number RX uses for UDP datagrams
1394 void uafs_SetRxPort(int port)
1396 usr_assert(usr_rx_port == 0);
1402 * Initialize the user space client.
1406 char *mountDirParam,
1408 char *cacheBaseDirParam,
1409 int cacheBlocksParam,
1410 int cacheFilesParam,
1411 int cacheStatEntriesParam,
1412 int dCacheSizeParam,
1413 int vCacheSizeParam,
1415 int closeSynchParam,
1418 int cacheFlagsParam,
1422 struct usr_proc *procp;
1423 struct usr_ucred *ucredp;
1426 int currVFile; /* Current AFS cache file number */
1427 int lookupResult; /* Result of GetLocalCellName() */
1428 int cacheIteration; /* cache verification loop counter */
1429 int vFilesFound; /* Num data cache files found in sweep */
1431 afs_int32 vfs1_type = -1;
1432 struct afs_ioctl iob;
1436 afs_int32 buffer[MAXIPADDRS];
1437 afs_int32 maskbuffer[MAXIPADDRS];
1438 afs_int32 mtubuffer[MAXIPADDRS];
1441 * Use the thread specific data to implement the user structure
1443 usr_keycreate(&afs_global_u_key, free);
1446 * Initialize the global ucred structure
1448 afs_global_ucredp = (struct usr_ucred *)
1449 afs_osi_Alloc(sizeof(struct usr_ucred));
1450 usr_assert(afs_global_ucredp != NULL);
1451 afs_global_ucredp->cr_ref = 1;
1452 afs_global_ucredp->cr_uid = geteuid();
1453 afs_global_ucredp->cr_gid = getegid();
1454 afs_global_ucredp->cr_ruid = getuid();
1455 afs_global_ucredp->cr_rgid = getgid();
1456 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1457 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1458 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1459 usr_assert(st >= 0);
1460 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1461 for (i = st ; i < NGROUPS ; i++) {
1462 afs_global_ucredp->cr_groups[i] = NOGROUP;
1466 * Initialize the global process structure
1468 afs_global_procp = (struct usr_proc *)
1469 afs_osi_Alloc(sizeof(struct usr_proc));
1470 usr_assert(afs_global_procp != NULL);
1471 afs_global_procp->p_pid = getpid();
1472 afs_global_procp->p_ppid = (pid_t)1;
1473 afs_global_procp->p_ucred = afs_global_ucredp;
1476 * Initialize the AFS mount point, default is '/afs'.
1477 * Strip duplicate/trailing slashes from mount point string.
1478 * afs_mountDirLen is set to strlen(afs_mountDir).
1480 if (mountDirParam) {
1481 sprintf(tbuffer, "%s", mountDirParam);
1483 sprintf(tbuffer, "afs");
1485 afs_mountDir[0] = '/';
1486 afs_mountDirLen = 1;
1487 for (lastchar = '/', p = &tbuffer[0] ; *p != '\0' ; p++) {
1488 if (lastchar != '/' || *p != '/') {
1489 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1492 if (lastchar == '/' && afs_mountDirLen > 1)
1494 afs_mountDir[afs_mountDirLen] = '\0';
1495 usr_assert(afs_mountDirLen > 1);
1498 * Initialize cache parameters using the input arguments
1501 cacheBlocks = cacheBlocksParam;
1502 if (cacheFilesParam != 0) {
1503 cacheFiles = cacheFilesParam;
1505 cacheFiles = cacheBlocks/10;
1507 if (cacheStatEntriesParam != 0) {
1508 cacheStatEntries = cacheStatEntriesParam;
1510 strcpy(cacheBaseDir, cacheBaseDirParam);
1511 if (nDaemons != 0) {
1512 nDaemons = nDaemonsParam;
1516 afsd_verbose = debugParam;
1517 afsd_debug = debugParam;
1518 chunkSize = chunkSizeParam;
1519 if (dCacheSizeParam != 0) {
1520 dCacheSize = dCacheSizeParam;
1522 dCacheSize = cacheFiles/2;
1524 if (vCacheSizeParam != 0) {
1525 vCacheSize = vCacheSizeParam;
1527 strcpy(confDir, confDirParam);
1528 afsd_CloseSynch = closeSynchParam;
1529 if (cacheFlagsParam >= 0) {
1530 cacheFlags = cacheFlagsParam;
1532 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1533 cacheFiles = dCacheSize;
1536 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1537 if (logFile == NULL) {
1538 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1540 strcpy(fullpn_AFSLogFile, logFile);
1543 printf("\n%s: Initializing user space AFS client\n\n", rn);
1544 printf(" mountDir: %s\n", afs_mountDir);
1545 printf(" confDir: %s\n", confDir);
1546 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1547 printf(" cacheBlocks: %d\n", cacheBlocks);
1548 printf(" cacheFiles: %d\n", cacheFiles);
1549 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1550 printf(" dCacheSize: %d\n", dCacheSize);
1551 printf(" vCacheSize: %d\n", vCacheSize);
1552 printf(" chunkSize: %d\n", chunkSize);
1553 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1554 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1555 printf(" nDaemons: %d\n", nDaemons);
1556 printf(" cacheFlags: %d\n", cacheFlags);
1557 printf(" logFile: %s\n", fullpn_AFSLogFile);
1562 * Initialize the AFS client
1567 * Pull out all the configuration info for the workstation's AFS cache and
1568 * the cellular community we're willing to let our users see.
1570 afs_cdir = afsconf_Open(confDir);
1572 printf("afsd: some file missing or bad in %s\n", confDir);
1576 lookupResult = afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1577 sizeof(afs_LclCellName));
1579 printf("%s: Can't get my home cell name! [Error is %d]\n",
1584 printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
1588 * Set the primary cell name.
1590 call_syscall(AFSOP_SET_THISCELL, afs_LclCellName, 0, 0, 0, 0);
1592 if ((logfd = fopen(fullpn_AFSLogFile,"r+")) == 0) {
1593 if (afsd_verbose) printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1594 if (CreateCacheFile(fullpn_AFSLogFile)) {
1595 printf("%s: Can't create '%s' (You may want to use the -logfile option)\n", rn, fullpn_AFSLogFile);
1602 * Create and zero the pathname table for the desired cache files.
1604 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1605 if (pathname_for_V == NULL) {
1606 printf("%s: malloc() failed for cache file table with %d entries.\n",
1610 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1612 printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n",
1613 rn, cacheFiles, pathname_for_V, (cacheFiles * sizeof(AFSD_INO_T)));
1616 * Set up all the pathnames we'll need for later.
1618 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1619 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1620 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1621 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1624 * Start the RX listener.
1627 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1628 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE);
1631 * Start the RX event handler.
1634 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1635 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1638 * Set up all the kernel processes needed for AFS.
1641 /* initialize AFS callback interface */
1643 /* parse multihomed address files */
1645 st=parseNetFiles(buffer,maskbuffer,mtubuffer,MAXIPADDRS,reason,
1646 AFSDIR_CLIENT_NETINFO_FILEPATH,
1647 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1649 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st, (long) (&buffer[0]),
1650 (long) (&maskbuffer[0]), (long) (&mtubuffer[0]));
1652 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",reason);
1658 printf("%s: Forking rx callback listener.\n", rn);
1660 if (preallocs < cacheStatEntries+50)
1661 preallocs = cacheStatEntries+50;
1662 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1665 printf("%s: Initializing AFS daemon.\n", rn);
1666 fork_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT);
1669 printf("%s: Forking AFS daemon.\n", rn);
1670 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1673 printf("%s: Forking check server daemon.\n", rn);
1674 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1677 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1678 for (i=0;i<nDaemons;i++) {
1679 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1683 * Tell the kernel about each cell in the configuration.
1685 lookingForHomeCell = 1;
1687 afsconf_CellApply(afs_cdir, ConfigCell, NULL);
1690 * If we're still looking for the home cell after the whole cell
1691 * configuration database has been parsed, there's something wrong.
1693 if (lookingForHomeCell) {
1694 printf("%s: Can't find home cell '%s' in cell database!\n",
1695 rn, afs_LclCellName);
1699 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n",
1701 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1704 * Tell the kernel some basic information about the workstation's cache.
1707 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1708 " %d optimum cache files, %d blocks in the cache,"
1709 " flags = 0x%x, dcache entries %d\n",
1710 rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
1712 memset(&cparams, 0, sizeof(cparams));
1713 cparams.cacheScaches = cacheStatEntries;
1714 cparams.cacheFiles = cacheFiles;
1715 cparams.cacheBlocks = cacheBlocks;
1716 cparams.cacheDcaches = dCacheSize;
1717 cparams.cacheVolumes = vCacheSize;
1718 cparams.chunkSize = chunkSize;
1719 cparams.setTimeFlag = FALSE;
1720 cparams.memCacheFlag = cacheFlags;
1721 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1722 if (afsd_CloseSynch)
1723 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1726 * Sweep the workstation AFS cache directory, remembering the inodes of
1727 * valid files and deleting extraneous files. Keep sweeping until we
1728 * have the right number of data cache files or we've swept too many
1732 printf("%s: Sweeping workstation's AFS cache directory.\n",
1735 /* Memory-cache based system doesn't need any of this */
1736 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1739 if (SweepAFSCache(&vFilesFound)) {
1740 printf("%s: Error on sweep %d of workstation AFS cache \
1741 directory.\n", rn, cacheIteration);
1745 printf("%s: %d out of %d data cache files found in sweep %d.\n",
1746 rn, vFilesFound, cacheFiles, cacheIteration);
1747 } while ((vFilesFound < cacheFiles) &&
1748 (cacheIteration < MAX_CACHE_LOOPS));
1749 } else if(afsd_verbose)
1750 printf("%s: Using memory cache, not swept\n", rn);
1753 * Pass the kernel the name of the workstation cache file holding the
1757 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
1758 rn, fullpn_DCacheFile);
1759 /* once again, meaningless for a memory-based cache. */
1760 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1761 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1766 * Pass the kernel the name of the workstation cache file holding the
1767 * volume information.
1770 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n",
1771 rn, fullpn_VolInfoFile);
1772 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO,(long)fullpn_VolInfoFile,
1776 * Pass the kernel the name of the afs logging file holding the volume
1780 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n",
1781 rn, fullpn_AFSLogFile);
1782 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1783 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG,(long)fullpn_AFSLogFile,
1787 * Give the kernel the names of the AFS files cached on the workstation's
1791 printf("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1792 rn, cacheFiles, cacheBaseDir);
1793 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1794 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1795 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1796 (long)pathname_for_V[currVFile], 0, 0, 0);
1799 #ifndef NETSCAPE_NSAPI
1801 * Copy our tokens from the kernel to the user space client
1803 for(i = 0 ; i < 200 ; i++) {
1805 * Get the i'th token from the kernel
1807 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1808 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1810 iob.in_size = sizeof(int);
1812 iob.out_size = sizeof(tbuffer);
1814 #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)
1815 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1816 #elif defined(AFS_USR_SGI_ENV)
1817 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1818 #else /* AFS_USR_AIX_ENV */
1819 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1822 usr_assert(errno == EDOM);
1827 * Now pass the token into the user space kernel
1829 rc = uafs_SetTokens(tbuffer, iob.out_size);
1830 usr_assert(rc == 0);
1832 #endif /* !NETSCAPE_NSAPI */
1835 * All the necessary info has been passed into the kernel to run an AFS
1836 * system. Give the kernel our go-ahead.
1839 printf("%s: Calling AFSOP_GO\n", rn);
1840 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1843 * At this point, we have finished passing the kernel all the info
1844 * it needs to set up the AFS. Mount the AFS root.
1846 printf("%s: All AFS daemons started.\n", rn);
1849 printf("%s: Forking trunc-cache daemon.\n", rn);
1850 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1853 * Mount the AFS filesystem
1856 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1857 usr_assert(rc == 0);
1858 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1859 usr_assert(rc == 0);
1863 * initialize the current directory to the AFS root
1865 afs_CurrentDir = afs_RootVnode;
1866 VN_HOLD(afs_CurrentDir);
1871 void uafs_Shutdown(void)
1878 VN_RELE(afs_CurrentDir);
1879 rc = afs_unmount(&afs_RootVfs);
1880 usr_assert(rc == 0);
1887 * Donate the current thread to the RX server pool.
1889 void uafs_RxServerProc(void)
1893 struct rx_call *newcall = NULL;
1895 rxi_MorePackets(2); /* alloc more packets */
1896 threadID = rxi_availProcs++;
1899 sock = OSI_NULLSOCKET;
1900 rxi_ServerProc(threadID, newcall, &sock);
1901 if (sock == OSI_NULLSOCKET) {
1906 rxi_ListenerProc(sock, &threadID, &newcall);
1907 /* assert(threadID != -1); */
1908 /* assert(newcall != NULL); */
1912 struct syscallThreadArgs {
1921 #ifdef NETSCAPE_NSAPI
1922 void syscallThread(void *argp)
1923 #else /* NETSCAPE_NSAPI */
1924 void *syscallThread(void *argp)
1925 #endif /* NETSCAPE_NSAPI */
1928 struct usr_ucred *crp;
1929 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1932 * AFS daemons run authenticated
1934 u.u_viceid = getuid();
1936 crp->cr_uid = getuid();
1937 crp->cr_ruid = getuid();
1938 crp->cr_suid = getuid();
1939 crp->cr_groups[0] = getgid();
1940 crp->cr_ngroups = 1;
1941 for (i = 1 ; i < NGROUPS ; i++) {
1942 crp->cr_groups[i] = NOGROUP;
1945 call_syscall(sysArgsP->syscall, sysArgsP->afscall,
1946 sysArgsP->param1, sysArgsP->param2,
1947 sysArgsP->param3, sysArgsP->param4);
1949 afs_osi_Free(argp, -1);
1952 fork_syscall(syscall, afscall, param1, param2, param3, param4)
1953 long syscall, afscall, param1, param2, param3, param4;
1956 struct syscallThreadArgs *sysArgsP;
1958 sysArgsP = (struct syscallThreadArgs *)
1959 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1960 usr_assert(sysArgsP != NULL);
1961 sysArgsP->syscall = syscall;
1962 sysArgsP->afscall = afscall;
1963 sysArgsP->param1 = param1;
1964 sysArgsP->param2 = param2;
1965 sysArgsP->param3 = param3;
1966 sysArgsP->param4 = param4;
1968 usr_thread_create(&tid, syscallThread, sysArgsP);
1969 usr_thread_detach(tid);
1972 call_syscall(syscall, afscall, param1, param2, param3, param4)
1973 long syscall, afscall, param1, param2, param3, param4;
1985 a.syscall = syscall;
1986 a.afscall = afscall;
1993 u.u_ap = (char *)&a;
1995 code = Afs_syscall();
1999 int uafs_SetTokens(char *tbuffer, int tlen)
2002 struct afs_ioctl iob;
2007 iob.out = &outbuf[0];
2008 iob.out_size = sizeof(outbuf);
2009 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2017 int uafs_RPCStatsEnableProc(void)
2020 struct afs_ioctl iob;
2023 flag = AFSCALL_RXSTATS_ENABLE;
2024 iob.in = (char *)&flag;
2025 iob.in_size = sizeof(afs_int32);
2028 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2036 int uafs_RPCStatsDisableProc(void)
2039 struct afs_ioctl iob;
2042 flag = AFSCALL_RXSTATS_DISABLE;
2043 iob.in = (char *)&flag;
2044 iob.in_size = sizeof(afs_int32);
2047 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2055 int uafs_RPCStatsClearProc(void)
2058 struct afs_ioctl iob;
2061 flag = AFSCALL_RXSTATS_CLEAR;
2062 iob.in = (char *)&flag;
2063 iob.in_size = sizeof(afs_int32);
2066 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2074 int uafs_RPCStatsEnablePeer(void)
2077 struct afs_ioctl iob;
2080 flag = AFSCALL_RXSTATS_ENABLE;
2081 iob.in = (char *)&flag;
2082 iob.in_size = sizeof(afs_int32);
2085 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2093 int uafs_RPCStatsDisablePeer(void)
2096 struct afs_ioctl iob;
2099 flag = AFSCALL_RXSTATS_DISABLE;
2100 iob.in = (char *)&flag;
2101 iob.in_size = sizeof(afs_int32);
2104 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2112 int uafs_RPCStatsClearPeer(void)
2115 struct afs_ioctl iob;
2118 flag = AFSCALL_RXSTATS_CLEAR;
2119 iob.in = (char *)&flag;
2120 iob.in_size = sizeof(afs_int32);
2123 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2132 * Lookup a file or directory given its path.
2133 * Call VN_HOLD on the output vnode if successful.
2134 * Returns zero on success, error code on failure.
2136 * Note: Caller must hold the AFS global lock.
2138 int uafs_LookupName(
2140 struct usr_vnode *parentVp,
2141 struct usr_vnode **vpp,
2147 struct usr_vnode *vp;
2148 struct usr_vnode *nextVp;
2149 struct usr_vnode *linkVp;
2157 * Absolute paths must start with the AFS mount point.
2159 if (path[0] != '/') {
2162 path = uafs_afsPathName(path);
2170 * Loop through the path looking for the new directory
2172 tmpPath = afs_osi_Alloc(strlen(path)+1);
2173 usr_assert(tmpPath != NULL);
2174 strcpy(tmpPath, path);
2177 while (pathP != NULL && *pathP != '\0') {
2178 usr_assert(*pathP != '/');
2181 * terminate the current component and skip over slashes
2183 nextPathP = afs_strchr(pathP, '/');
2184 if (nextPathP != NULL) {
2185 while (*nextPathP == '/') {
2186 *(nextPathP++) = '\0';
2191 * Don't call afs_lookup on non-directories
2193 if (vp->v_type != VDIR) {
2195 afs_osi_Free(tmpPath, strlen(path)+1);
2199 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2201 * The AFS root is its own parent
2203 nextVp = afs_RootVnode;
2206 * We need execute permission to search a directory
2208 code = afs_access(vp, VEXEC, u.u_cred);
2211 afs_osi_Free(tmpPath, strlen(path)+1);
2216 * lookup the next component in the path, we can release the
2217 * subdirectory since we hold the global lock
2220 #ifdef AFS_WEB_ENHANCEMENTS
2221 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2222 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2224 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, AFS_LOOKUP_NOEVAL);
2226 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2227 #endif /* AFS_WEB_ENHANCEMENTS */
2230 afs_osi_Free(tmpPath, strlen(path)+1);
2236 * Follow symbolic links for parent directories and
2237 * for leaves when the follow flag is set.
2239 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2241 while(nextVp->v_type == VLNK) {
2242 if (++linkCount > MAX_OSI_LINKS) {
2245 afs_osi_Free(tmpPath, strlen(path)+1);
2248 code = uafs_LookupLink(nextVp, vp, &linkVp);
2252 afs_osi_Free(tmpPath, strlen(path)+1);
2266 * Special case, nextPathP is non-null if pathname ends in slash
2268 if (nextPathP != NULL && vp->v_type != VDIR) {
2270 afs_osi_Free(tmpPath, strlen(path)+1);
2274 afs_osi_Free(tmpPath, strlen(path)+1);
2280 * Lookup the target of a symbolic link
2281 * Call VN_HOLD on the output vnode if successful.
2282 * Returns zero on success, error code on failure.
2284 * Note: Caller must hold the AFS global lock.
2286 int uafs_LookupLink(
2287 struct usr_vnode *vp,
2288 struct usr_vnode *parentVp,
2289 struct usr_vnode **vpp)
2294 struct usr_vnode *linkVp;
2296 struct iovec iov[1];
2300 pathP = afs_osi_Alloc(MAX_OSI_PATH+1);
2301 usr_assert(pathP != NULL);
2304 * set up the uio buffer
2306 iov[0].iov_base = pathP;
2307 iov[0].iov_len = MAX_OSI_PATH+1;
2308 uio.uio_iov = &iov[0];
2312 uio.uio_fmode = FREAD;
2313 uio.uio_resid = MAX_OSI_PATH+1;
2316 * Read the link data
2318 code = afs_readlink(vp, &uio, u.u_cred);
2320 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2323 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2327 * Find the target of the symbolic link
2329 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2331 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2335 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2341 * Lookup the parent of a file or directory given its path
2342 * Call VN_HOLD on the output vnode if successful.
2343 * Returns zero on success, error code on failure.
2345 * Note: Caller must hold the AFS global lock.
2347 int uafs_LookupParent(
2349 struct usr_vnode **vpp)
2354 struct usr_vnode *parentP;
2359 * Absolute path names must start with the AFS mount point.
2362 pathP = uafs_afsPathName(path);
2363 if (pathP == NULL) {
2369 * Find the length of the parent path
2372 while(len > 0 && path[len-1] == '/') {
2378 while(len > 0 && path[len-1] != '/') {
2385 pathP = afs_osi_Alloc(len);
2386 usr_assert(pathP != NULL);
2387 memcpy(pathP, path, len-1);
2388 pathP[len-1] = '\0';
2391 * look up the parent
2393 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2394 afs_osi_Free(pathP, len);
2398 if (parentP->v_type != VDIR) {
2408 * Return a pointer to the first character in the last component
2411 char *uafs_LastPath(char *path)
2416 while (len > 0 && path[len-1] == '/') {
2419 while (len > 0 && path[len-1] != '/') {
2429 * Set the working directory.
2431 int uafs_chdir(char *path)
2435 retval = uafs_chdir_r(path);
2440 int uafs_chdir_r(char *path)
2445 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2450 if (dirP->v_type != VDIR) {
2455 VN_RELE(afs_CurrentDir);
2456 afs_CurrentDir = dirP;
2461 * Create a directory.
2463 int uafs_mkdir(char *path, int mode)
2467 retval = uafs_mkdir_r(path, mode);
2472 int uafs_mkdir_r(char *path, int mode)
2476 struct vnode *parentP;
2478 struct usr_vattr attrs;
2480 if (uafs_IsRoot(path)) {
2485 * Look up the parent directory.
2487 nameP = uafs_LastPath(path);
2488 if (nameP != NULL) {
2489 code = uafs_LookupParent(path, &parentP);
2495 parentP = afs_CurrentDir;
2501 * Make sure the directory has at least one character
2503 if (*nameP == '\0') {
2510 * Create the directory
2512 usr_vattr_null(&attrs);
2513 attrs.va_type = VREG;
2514 attrs.va_mode = mode;
2515 attrs.va_uid = u.u_cred->cr_uid;
2516 attrs.va_gid = u.u_cred->cr_gid;
2518 code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
2529 * Return 1 if path is the AFS root, otherwise return 0
2531 int uafs_IsRoot(char *path)
2533 while(*path == '/' && *(path+1) == '/') {
2536 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2539 path += afs_mountDirLen;
2540 while (*path == '/') {
2543 if (*path != '\0') {
2551 * Note: file name may not end in a slash.
2553 int uafs_open(char *path, int flags, int mode)
2557 retval = uafs_open_r(path, flags, mode);
2562 int uafs_open_r(char *path, int flags, int mode)
2568 struct usr_vnode *fileP;
2569 struct usr_vnode *dirP;
2570 struct usr_vattr attrs;
2573 if (uafs_IsRoot(path)) {
2574 fileP = afs_RootVnode;
2578 * Look up the parent directory.
2580 nameP = uafs_LastPath(path);
2581 if (nameP != NULL) {
2582 code = uafs_LookupParent(path, &dirP);
2588 dirP = afs_CurrentDir;
2594 * Make sure the filename has at least one character
2596 if (*nameP == '\0') {
2603 * Get the VNODE for this file
2605 if (flags & O_CREAT) {
2606 usr_vattr_null(&attrs);
2607 attrs.va_type = VREG;
2608 attrs.va_mode = mode;
2609 attrs.va_uid = u.u_cred->cr_uid;
2610 attrs.va_gid = u.u_cred->cr_gid;
2611 if (flags & O_TRUNC) {
2615 code = afs_create(dirP, nameP, &attrs,
2616 (flags & O_EXCL)?usr_EXCL:usr_NONEXCL,
2617 mode, &fileP, u.u_cred);
2625 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2633 * Check whether we have access to this file
2636 if (flags & (O_RDONLY|O_RDWR)) {
2639 if (flags & (O_WRONLY|O_RDWR)) {
2642 if (!fileMode) fileMode = VREAD; /* since O_RDONLY is 0 */
2643 code = afs_access(fileP, fileMode, u.u_cred);
2651 * Get the file attributes, all we need is the size
2653 code = afs_getattr(fileP, &attrs, u.u_cred);
2663 * Setup the open flags
2666 if (flags & O_TRUNC) {
2667 openFlags |= FTRUNC;
2669 if (flags & O_APPEND) {
2670 openFlags |= FAPPEND;
2672 if (flags & O_SYNC) {
2675 if (flags & O_SYNC) {
2678 if (flags & (O_RDONLY|O_RDWR)) {
2681 if (flags & (O_WRONLY|O_RDWR)) {
2682 openFlags |= FWRITE;
2686 * Truncate if necessary
2688 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2689 usr_vattr_null(&attrs);
2691 code = afs_setattr(fileP, &attrs, u.u_cred);
2702 code = afs_open(&fileP, openFlags, u.u_cred);
2710 * Put the vnode pointer into the file table
2712 for (fd = 0 ; fd < MAX_OSI_FILES ; fd++) {
2713 if (afs_FileTable[fd] == NULL) {
2714 afs_FileTable[fd] = fileP;
2715 afs_FileFlags[fd] = openFlags;
2716 if (flags & O_APPEND) {
2717 afs_FileOffsets[fd] = attrs.va_size;
2719 afs_FileOffsets[fd] = 0;
2724 if (fd == MAX_OSI_FILES) {
2736 int uafs_creat(char *path, int mode)
2739 rc = uafs_open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2743 int uafs_creat_r(char *path, int mode)
2746 rc = uafs_open_r(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2753 int uafs_write(int fd, char *buf, int len)
2757 retval = uafs_write_r(fd, buf, len);
2762 int uafs_write_r(int fd, char *buf, int len)
2766 struct iovec iov[1];
2767 struct usr_vnode *fileP;
2770 * Make sure this is an open file
2772 fileP = afs_FileTable[fd];
2773 if (fileP == NULL) {
2779 * set up the uio buffer
2781 iov[0].iov_base = buf;
2782 iov[0].iov_len = len;
2783 uio.uio_iov = &iov[0];
2785 uio.uio_offset = afs_FileOffsets[fd];
2787 uio.uio_fmode = FWRITE;
2788 uio.uio_resid = len;
2794 code = afs_write(fileP, &uio, afs_FileFlags[fd], u.u_cred, 0);
2800 afs_FileOffsets[fd] = uio.uio_offset;
2801 return(len - uio.uio_resid);
2807 int uafs_read(int fd, char *buf, int len)
2811 retval = uafs_read_r(fd, buf, len);
2816 int uafs_read_r(int fd, char *buf, int len)
2820 struct iovec iov[1];
2821 struct usr_vnode *fileP;
2822 struct usr_buf *bufP;
2825 * Make sure this is an open file
2827 fileP = afs_FileTable[fd];
2828 if (fileP == NULL) {
2834 * set up the uio buffer
2836 iov[0].iov_base = buf;
2837 iov[0].iov_len = len;
2838 uio.uio_iov = &iov[0];
2840 uio.uio_offset = afs_FileOffsets[fd];
2842 uio.uio_fmode = FREAD;
2843 uio.uio_resid = len;
2848 code = afs_read(fileP, &uio, u.u_cred, 0, &bufP, 0);
2854 afs_FileOffsets[fd] = uio.uio_offset;
2855 return(len - uio.uio_resid);
2859 * Copy the attributes of a file into a stat structure.
2861 * NOTE: Caller must hold the global AFS lock.
2863 int uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2866 struct usr_vattr attrs;
2871 * Get the attributes
2873 code = afs_getattr(vp, &attrs, u.u_cred);
2879 * Copy the attributes, zero fields that aren't set
2881 memset((void *)stats, 0, sizeof(struct stat));
2883 stats->st_ino = attrs.va_nodeid;
2884 stats->st_mode = attrs.va_mode;
2885 stats->st_nlink = attrs.va_nlink;
2886 stats->st_uid = attrs.va_uid;
2887 stats->st_gid = attrs.va_gid;
2888 stats->st_rdev = attrs.va_rdev;
2889 stats->st_size = attrs.va_size;
2890 stats->st_atime = attrs.va_atime.tv_sec;
2891 stats->st_mtime = attrs.va_mtime.tv_sec;
2892 stats->st_ctime = attrs.va_ctime.tv_sec;
2893 stats->st_blksize = attrs.va_blocksize;
2894 stats->st_blocks = attrs.va_blocks;
2900 * Get the attributes of a file, do follow links
2908 retval = uafs_stat_r(path, buf);
2920 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2925 code = uafs_GetAttr(vp, buf);
2935 * Get the attributes of a file, don't follow links
2943 retval = uafs_lstat_r(path, buf);
2955 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2960 code = uafs_GetAttr(vp, buf);
2970 * Get the attributes of an open file
2978 retval = uafs_fstat_r(fd, buf);
2990 vp = afs_FileTable[fd];
2995 code = uafs_GetAttr(vp, buf);
3005 * change the permissions on a file
3013 retval = uafs_chmod_r(path, mode);
3024 struct usr_vattr attrs;
3026 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3031 usr_vattr_null(&attrs);
3032 attrs.va_mode = mode;
3033 code = afs_setattr(vp, &attrs, u.u_cred);
3043 * change the permissions on an open file
3051 retval = uafs_fchmod_r(fd, mode);
3062 struct usr_vattr attrs;
3064 vp = afs_FileTable[fd];
3069 usr_vattr_null(&attrs);
3070 attrs.va_mode = mode;
3071 code = afs_setattr(vp, &attrs, u.u_cred);
3088 retval = uafs_truncate_r(path, length);
3093 int uafs_truncate_r(
3099 struct usr_vattr attrs;
3101 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3106 usr_vattr_null(&attrs);
3107 attrs.va_size = length;
3108 code = afs_setattr(vp, &attrs, u.u_cred);
3118 * truncate an open file
3126 retval = uafs_ftruncate_r(fd, length);
3131 int uafs_ftruncate_r(
3137 struct usr_vattr attrs;
3139 vp = afs_FileTable[fd];
3144 usr_vattr_null(&attrs);
3145 attrs.va_size = length;
3146 code = afs_setattr(vp, &attrs, u.u_cred);
3155 * set the read/write file pointer of an open file
3164 retval = uafs_lseek_r(fd, offset, whence);
3176 struct usr_vattr attrs;
3177 struct usr_vnode *vp;
3179 vp = afs_FileTable[fd];
3186 newpos = afs_FileOffsets[fd] + offset;
3192 code = afs_getattr(vp, &attrs, u.u_cred);
3197 newpos = attrs.va_size + offset;
3207 afs_FileOffsets[fd] = newpos;
3219 retval = uafs_fsync_r(fd);
3228 struct usr_vnode *fileP;
3231 fileP = afs_FileTable[fd];
3232 if (fileP == NULL) {
3237 code = afs_fsync(fileP, u.u_cred);
3254 retval = uafs_close_r(fd);
3263 struct usr_vnode *fileP;
3265 fileP = afs_FileTable[fd];
3266 if (fileP == NULL) {
3270 afs_FileTable[fd] = NULL;
3272 code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
3283 * Create a hard link from the source to the target
3284 * Note: file names may not end in a slash.
3292 retval = uafs_link_r(existing, new);
3302 struct usr_vnode *existP;
3303 struct usr_vnode *dirP;
3306 if (uafs_IsRoot(new)) {
3311 * Look up the existing node.
3313 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3320 * Look up the parent directory.
3322 nameP = uafs_LastPath(new);
3323 if (nameP != NULL) {
3324 code = uafs_LookupParent(new, &dirP);
3331 dirP = afs_CurrentDir;
3337 * Make sure the filename has at least one character
3339 if (*nameP == '\0') {
3349 code = afs_link(existP, dirP, nameP, u.u_cred);
3360 * Create a symbolic link from the source to the target
3361 * Note: file names may not end in a slash.
3369 retval = uafs_symlink_r(target, source);
3379 struct usr_vnode *dirP;
3380 struct usr_vattr attrs;
3383 if (uafs_IsRoot(source)) {
3388 * Look up the parent directory.
3390 nameP = uafs_LastPath(source);
3391 if (nameP != NULL) {
3392 code = uafs_LookupParent(source, &dirP);
3398 dirP = afs_CurrentDir;
3404 * Make sure the filename has at least one character
3406 if (*nameP == '\0') {
3415 usr_vattr_null(&attrs);
3416 attrs.va_type = VLNK;
3417 attrs.va_mode = 0777;
3418 attrs.va_uid = u.u_cred->cr_uid;
3419 attrs.va_gid = u.u_cred->cr_gid;
3420 code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
3430 * Read a symbolic link into the buffer
3439 retval = uafs_readlink_r(path, buf, len);
3444 int uafs_readlink_r(
3450 struct usr_vnode *vp;
3452 struct iovec iov[1];
3454 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3460 if (vp->v_type != VLNK) {
3467 * set up the uio buffer
3469 iov[0].iov_base = buf;
3470 iov[0].iov_len = len;
3471 uio.uio_iov = &iov[0];
3475 uio.uio_fmode = FREAD;
3476 uio.uio_resid = len;
3481 code = afs_readlink(vp, &uio, u.u_cred);
3489 * return the number of bytes read
3491 return (len - uio.uio_resid);
3495 * Remove a file (or directory)
3496 * Note: file name may not end in a slash.
3503 retval = uafs_unlink_r(path);
3513 struct usr_vnode *fileP;
3514 struct usr_vnode *dirP;
3517 if (uafs_IsRoot(path)) {
3522 * Look up the parent directory.
3524 nameP = uafs_LastPath(path);
3525 if (nameP != NULL) {
3526 code = uafs_LookupParent(path, &dirP);
3532 dirP = afs_CurrentDir;
3538 * Make sure the filename has at least one character
3540 if (*nameP == '\0') {
3549 code = afs_remove(dirP, nameP, u.u_cred);
3560 * Rename a file (or directory)
3568 retval = uafs_rename_r(old, new);
3580 struct usr_vnode *odirP;
3581 struct usr_vnode *ndirP;
3583 if (uafs_IsRoot(new)) {
3588 * Look up the parent directories.
3590 onameP = uafs_LastPath(old);
3591 if (onameP != NULL) {
3592 code = uafs_LookupParent(old, &odirP);
3598 odirP = afs_CurrentDir;
3602 nnameP = uafs_LastPath(new);
3603 if (nnameP != NULL) {
3604 code = uafs_LookupParent(new, &ndirP);
3610 ndirP = afs_CurrentDir;
3616 * Make sure the filename has at least one character
3618 if (*onameP == '\0' || *nnameP == '\0') {
3628 code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
3640 * Remove a or directory
3641 * Note: file name may not end in a slash.
3648 retval = uafs_rmdir_r(path);
3658 struct usr_vnode *fileP;
3659 struct usr_vnode *dirP;
3662 if (uafs_IsRoot(path)) {
3667 * Look up the parent directory.
3669 nameP = uafs_LastPath(path);
3670 if (nameP != NULL) {
3671 code = uafs_LookupParent(path, &dirP);
3677 dirP = afs_CurrentDir;
3683 * Make sure the directory name has at least one character
3685 if (*nameP == '\0') {
3692 * Remove the directory
3694 code = afs_rmdir(dirP, nameP, u.u_cred);
3705 * Flush a file from the AFS cache
3711 struct afs_ioctl iob;
3718 code = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6),
3727 int uafs_FlushFile_r(
3732 retval = uafs_FlushFile(path);
3740 usr_DIR *uafs_opendir(
3745 retval = uafs_opendir_r(path);
3750 usr_DIR *uafs_opendir_r(
3754 struct usr_vnode *fileP;
3758 * Open the directory for reading
3760 fd = uafs_open_r(path, O_RDONLY, 0);
3765 fileP = afs_FileTable[fd];
3766 if (fileP == NULL) {
3770 if (fileP->v_type != VDIR) {
3777 * Set up the directory structures
3779 dirp = (usr_DIR *)afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3780 sizeof(struct usr_dirent));
3781 usr_assert(dirp != NULL);
3782 dirp->dd_buf = (char *)(dirp+1);
3792 * Read directory entries into a file system independent format.
3793 * This routine was developed to support AFS cache consistency testing.
3794 * You should use uafs_readdir instead.
3798 struct min_direct *buf,
3803 retval = uafs_getdents_r(fd, buf, len);
3808 int uafs_getdents_r(
3810 struct min_direct *buf,
3815 struct usr_vnode *vp;
3816 struct iovec iov[1];
3819 * Make sure this is an open file
3821 vp = afs_FileTable[fd];
3829 * set up the uio buffer
3831 iov[0].iov_base = (char *)buf;
3832 iov[0].iov_len = len;
3833 uio.uio_iov = &iov[0];
3835 uio.uio_offset = afs_FileOffsets[fd];
3837 uio.uio_fmode = FREAD;
3838 uio.uio_resid = len;
3841 * read the next chunk from the directory
3843 code = afs_readdir(vp, &uio, u.u_cred);
3849 afs_FileOffsets[fd] = uio.uio_offset;
3850 return(len - uio.uio_resid);
3854 * read from a directory (names only)
3856 struct usr_dirent *uafs_readdir(
3859 struct usr_dirent *retval;
3861 retval = uafs_readdir_r(dirp);
3866 struct usr_dirent *uafs_readdir_r(
3873 struct usr_vnode *vp;
3874 struct iovec iov[1];
3875 struct usr_dirent *direntP;
3876 struct min_direct *directP;
3879 * Make sure this is an open file
3881 vp = afs_FileTable[dirp->dd_fd];
3888 * If there are no entries in the stream buffer
3889 * then read another chunk
3891 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3892 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3894 * set up the uio buffer
3896 iov[0].iov_base = dirp->dd_buf;
3897 iov[0].iov_len = USR_DIRSIZE;
3898 uio.uio_iov = &iov[0];
3900 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3902 uio.uio_fmode = FREAD;
3903 uio.uio_resid = USR_DIRSIZE;
3906 * read the next chunk from the directory
3908 code = afs_readdir(vp, &uio, u.u_cred);
3913 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3915 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3917 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3921 * Check for end of file
3923 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3927 len = ((sizeof(struct min_direct)+directP->d_namlen+4) & (~3));
3928 usr_assert(len <= dirp->dd_size);
3931 * Copy the next entry into the usr_dirent structure and advance
3933 direntP = (struct usr_dirent *)(dirp->dd_buf+USR_DIRSIZE);
3934 direntP->d_ino = directP->d_fileno;
3935 direntP->d_off = direntP->d_reclen;
3936 direntP->d_reclen = sizeof(struct usr_dirent) - MAXNAMLEN +
3937 directP->d_namlen + 1;
3938 memcpy(&direntP->d_name[0], (void *)(directP+1), directP->d_namlen);
3939 direntP->d_name[directP->d_namlen] = '\0';
3940 dirp->dd_loc += len;
3941 dirp->dd_size -= len;
3954 retval = uafs_closedir_r(dirp);
3959 int uafs_closedir_r(
3966 afs_osi_Free((char *)dirp,
3967 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
3968 rc = uafs_close_r(fd);
3973 * Do AFS authentication
3982 afs_int32 password_expires = -1;
3984 usr_mutex_lock(&osi_authenticate_lock);
3985 code = ka_UserAuthenticateGeneral(
3986 KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG2, user,
3987 NULL, cell, passwd, 0, &password_expires,
3989 usr_mutex_unlock(&osi_authenticate_lock);
4001 retval = uafs_klog(user, cell, passwd, reason);
4007 * Destroy AFS credentials from the kernel cache
4009 int uafs_unlog(void)
4013 usr_mutex_lock(&osi_authenticate_lock);
4014 code = ktc_ForgetAllTokens();
4015 usr_mutex_unlock(&osi_authenticate_lock);
4019 int uafs_unlog_r(void)
4023 retval = uafs_unlog();
4029 * Strip the AFS mount point from a pathname string. Return
4030 * NULL if the path is a relative pathname or if the path
4031 * doesn't start with the AFS mount point string.
4033 char *uafs_afsPathName(char *path)
4042 for (i = 1, p = path+1; *p != '\0' ; p++) {
4043 /* Ignore duplicate slashes */
4044 if (*p == '/' && lastchar == '/')
4046 /* Is this a subdirectory of the AFS mount point? */
4047 if (afs_mountDir[i] == '\0' && *p == '/') {
4048 /* strip leading slashes */
4049 while (*(++p) == '/');
4052 /* Reject paths that are not within AFS */
4053 if (*p != afs_mountDir[i])
4058 /* Is this the AFS mount point? */
4059 if (afs_mountDir[i] == '\0') {
4060 usr_assert(*p == '\0');
4066 #ifdef AFS_WEB_ENHANCEMENTS
4069 * klog but don't allocate a new pag
4071 int uafs_klog_nopag(
4078 afs_int32 password_expires = -1;
4080 usr_mutex_lock(&osi_authenticate_lock);
4081 code = ka_UserAuthenticateGeneral(
4082 KA_USERAUTH_VERSION /*+KA_USERAUTH_DOSETPAG2*/, user,
4083 NULL, cell, passwd, 0, &password_expires,
4085 usr_mutex_unlock(&osi_authenticate_lock);
4090 * uafs_getcellstatus
4091 * get the cell status
4093 int uafs_getcellstatus(char *cell, afs_int32 *status)
4096 struct afs_ioctl iob;
4099 iob.in_size = strlen(cell)+1;
4103 rc = call_syscall(AFSCALL_PIOCTL, /*path*/0, _VICEIOCTL(35),
4111 *status = (afs_int32) iob.out;
4117 * Get quota of volume associated with path
4119 int uafs_getvolquota(char *path, afs_int32 *BlocksInUse, afs_int32 *MaxQuota)
4122 struct afs_ioctl iob;
4123 VolumeStatus *status;
4129 iob.out_size = 1024;
4131 rc = call_syscall(AFSCALL_PIOCTL, (long) path, _VICEIOCTL(4),
4139 status = (VolumeStatus *) buf;
4140 *BlocksInUse = status->BlocksInUse;
4141 *MaxQuota = status->MaxQuota;
4147 * Set quota of volume associated with path
4149 int uafs_setvolquota(char *path, afs_int32 MaxQuota)
4152 struct afs_ioctl iob;
4153 VolumeStatus *status;
4161 memset(buf, 0, sizeof(VolumeStatus));
4162 status = (VolumeStatus *) buf;
4163 status->MaxQuota = MaxQuota;
4164 status->MinQuota = -1;
4166 rc = call_syscall(AFSCALL_PIOCTL, (long) path, _VICEIOCTL(5),
4178 * uafs_statmountpoint
4179 * Determine whether a dir. is a mount point or not
4180 * return 1 if mount point, 0 if not
4182 int uafs_statmountpoint(char *path)
4189 retval = uafs_statmountpoint_r(path);
4194 int uafs_statmountpoint_r(char *path)
4199 struct vrequest treq;
4202 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4217 * Get a list of rights for the current user on path.
4219 int uafs_getRights(char *path)
4226 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4233 afs_rights = PRSFS_READ |
4241 afs_rights = afs_getRights (vp, afs_rights, u.u_cred);
4246 #endif /* AFS_WEB_ENHANCEMENTS */
4248 #endif /* UKERNEL */