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 "../afs/param.h" /* Should be always first */
18 #include "../afs/sysincludes.h" /* Standard vendor system headers */
20 #include "../afs/afsincludes.h" /* Afs-based standard headers */
21 #include "../afs/afs_usrops.h"
22 #include "../afs/afs_stats.h"
23 #include "../afs/auth.h"
24 #include "../afs/cellconfig.h"
25 #include "../afs/vice.h"
26 #include "../afs/kautils.h"
27 #include "../afs/afsutil.h"
28 #include "../rx/rx_globals.h"
34 #define CACHEINFOFILE "cacheinfo"
35 #define AFSLOGFILE "AFSLog"
36 #define DCACHEFILE "CacheItems"
37 #define VOLINFOFILE "VolumeItems"
41 #define MIN(A,B) ((A)<(B)?(A):(B))
44 #define MAX(A,B) ((A)>(B)?(A):(B))
47 extern int cacheDiskType;
49 char afs_LclCellName[64];
51 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
52 int afs_FileFlags[MAX_OSI_FILES];
53 int afs_FileOffsets[MAX_OSI_FILES];
55 #define MAX_CACHE_LOOPS 4
57 struct usr_vfs afs_RootVfs;
58 struct usr_vnode *afs_RootVnode = NULL;
59 struct usr_vnode *afs_CurrentDir = NULL;
61 afs_int32 cacheBlocks; /* Num blocks in cache */
62 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
63 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
64 char cacheBaseDir[1024]; /* AFS cache directory */
65 char confDir[1024]; /* AFS configuration directory */
66 char afs_mountDir[1024]; /* AFS mount point */
67 int afs_mountDirLen; /* strlen of AFS mount point */
68 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
69 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
70 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
71 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
72 char fullpn_VFile[1024]; /* Full pathname of data cache files */
73 char *vFileNumber; /* Ptr to number in file pathname */
74 char rootVolume[64] = "root.afs"; /* AFS root volume name */
75 afs_int32 isHomeCell; /* Is current cell info for home cell */
76 afs_int32 lookingForHomeCell; /* Are we still looking for home cell */
77 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
78 int ownerRWmode = 0600; /* Read/write OK by owner */
79 static int nDaemons = 2; /* Number of background daemons */
80 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
81 static int dCacheSize = 300; /* # of dcache entries */
82 static int vCacheSize = 50; /* # of volume cache entries */
83 static int cacheFlags = 0; /* Flags to cache manager */
84 static int preallocs = 400; /* Def # of allocated memory blocks */
85 int afsd_verbose = 0; /* Are we being chatty? */
86 int afsd_debug = 0; /* Are we printing debugging info? */
87 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
89 #define AFSD_INO_T afs_uint32
90 char **pathname_for_V; /* Array of cache file pathnames */
91 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
92 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
93 struct afs_cacheParams cparams; /* params passed to cache manager */
94 struct afsconf_dir *afs_cdir; /* config dir */
96 static int HandleMTab();
98 int afs_bufferpages = 100;
101 usr_key_t afs_global_u_key;
103 struct usr_proc *afs_global_procp;
104 struct usr_ucred *afs_global_ucredp;
105 struct usr_sysent usr_sysent[200];
107 #ifdef AFS_USR_OSF_ENV
109 #else /* AFS_USR_OSF_ENV */
111 #endif /* AFS_USR_OSF_ENV */
113 struct usr_ucred afs_osi_cred;
114 usr_mutex_t afs_global_lock;
115 usr_thread_t afs_global_owner;
116 usr_mutex_t rx_global_lock;
117 usr_thread_t rx_global_owner;
118 usr_mutex_t osi_inode_lock;
119 usr_mutex_t osi_waitq_lock;
120 usr_mutex_t osi_authenticate_lock;
122 afs_lock_t osi_flplock;
123 afs_lock_t osi_fsplock;
126 #ifndef NETSCAPE_NSAPI
129 * Mutex and condition variable used to implement sleep
131 pthread_mutex_t usr_sleep_mutex;
132 pthread_cond_t usr_sleep_cond;
134 #endif /* !NETSCAPE_NSAPI */
136 int call_syscall(long, long, long, long, long, long);
140 * Hash table mapping addresses onto wait structures for
141 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
143 typedef struct osi_wait {
147 struct osi_wait *next;
148 struct osi_wait *prev;
150 struct osi_wait *timedNext;
151 struct osi_wait *timedPrev;
155 * Head of the linked list of available waitq structures.
157 osi_wait_t *osi_waithash_avail;
160 * List of timed waits, NSAPI does not provide a cond_timed
161 * wait, so we need to keep track of the timed waits ourselves and
162 * periodically check for expirations
164 osi_wait_t *osi_timedwait_head;
165 osi_wait_t *osi_timedwait_tail;
170 } osi_waithash_table[OSI_WAITHASH_SIZE];
173 * Never call afs_brelse
175 int ufs_brelse(vp, bp)
176 struct usr_vnode *vp;
183 * I am not sure what to do with these, they assert for now
191 struct usr_file *getf(fd)
198 * Every user is a super user
200 int afs_osi_suser(credp)
201 struct usr_ucred *credp;
207 struct usr_ucred *credp;
213 * These are no-ops in user space
216 int afs_osi_SetTime(atv)
223 * xflock should never fall through, the only files we know
224 * about are AFS files
232 * ioctl should never fall through, the only files we know
233 * about are AFS files
241 * We do not support the inode related system calls
243 int afs_syscall_icreate()
248 int afs_syscall_iincdec()
253 int afs_syscall_iopen()
258 int afs_syscall_ireadwrite()
264 * these routines are referenced in the vfsops structure, but
265 * should never get called
288 * uiomove copies data between kernel buffers and uio buffers
290 int usr_uiomove(kbuf, n, rw, uio)
301 nio = uio->uio_iovcnt;
311 while(nio > 0 && n > 0) {
312 len = MIN(n, iovp->iov_len);
313 if (rw == UIO_READ) {
314 memcpy(iovp->iov_base, ptr, len);
316 memcpy(ptr, iovp->iov_base, len);
320 uio->uio_resid -= len;
321 uio->uio_offset += len;
322 iovp->iov_base = (char *)(iovp->iov_base) + len;
323 iovp->iov_len -= len;
334 * routines to manage user credentials
336 struct usr_ucred *usr_crcopy(credp)
337 struct usr_ucred *credp;
339 struct usr_ucred *newcredp;
341 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
343 newcredp->cr_ref = 1;
347 struct usr_ucred *usr_crget()
349 struct usr_ucred *newcredp;
351 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
352 newcredp->cr_ref = 1;
356 int usr_crfree(credp)
357 struct usr_ucred *credp;
360 if (credp->cr_ref == 0) {
361 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
365 int usr_crhold(credp)
366 struct usr_ucred *credp;
371 void usr_vattr_null(vap)
372 struct usr_vattr *vap;
377 n = sizeof(struct usr_vattr);
385 * Initialize the thread specific data used to simulate the
386 * kernel environment for each thread. The user structure
387 * is stored in the thread specific data.
389 void uafs_InitThread()
392 struct usr_user *uptr;
395 * initialize the thread specific user structure. Use malloc to
396 * allocate the data block, so pthread_finish can free the buffer
397 * when this thread terminates.
399 uptr = (struct usr_user *)malloc(sizeof(struct usr_user) +
400 sizeof(struct usr_ucred));
401 usr_assert(uptr != NULL);
404 uptr->u_procp = afs_global_procp;
405 uptr->u_cred = (struct usr_ucred *)(uptr+1);
406 *uptr->u_cred = *afs_global_ucredp;
407 st = usr_setspecific(afs_global_u_key, (void *)uptr);
412 * routine to get the user structure from the thread specific data.
413 * this routine is used to implement the global 'u' structure. Initializes
414 * the thread if needed.
416 struct usr_user *get_user_struct()
418 struct usr_user *uptr;
420 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
424 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
426 usr_assert(uptr != NULL);
432 * Hash an address for the waithash table
434 #define WAITHASH(X) \
435 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
445 int rxGlockOwner = ISAFS_RXGLOCK();
446 int glockOwner = ISAFS_GLOCK();
448 usr_mutex_lock(&osi_waitq_lock);
456 if (osi_waithash_avail == NULL) {
457 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
458 usr_cond_init(&waitp->cond);
460 waitp = osi_waithash_avail;
461 osi_waithash_avail = osi_waithash_avail->next;
465 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
466 osi_waithash_table[index].tail, next, prev);
467 waitp->expiration = 0;
468 waitp->timedNext = NULL;
469 waitp->timedPrev = NULL;
470 while (waitp->flag == 0) {
471 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
473 DLL_DELETE(waitp, osi_waithash_table[index].head,
474 osi_waithash_table[index].tail, next, prev);
475 waitp->next = osi_waithash_avail;
476 osi_waithash_avail = waitp;
477 usr_mutex_unlock(&osi_waitq_lock);
486 int afs_osi_Wakeup(x)
493 usr_mutex_lock(&osi_waitq_lock);
494 waitp = osi_waithash_table[index].head;
496 if (waitp->addr == x && waitp->flag == 0) {
498 usr_cond_signal(&waitp->cond);
502 usr_mutex_unlock(&osi_waitq_lock);
505 int afs_osi_Wait(msec, handle, intok)
507 struct afs_osi_WaitHandle *handle;
514 int rxGlockOwner = ISAFS_RXGLOCK();
515 int glockOwner = ISAFS_GLOCK();
517 tv.tv_sec = msec / 1000;
518 tv.tv_nsec = (msec % 1000) * 1000000;
519 if (handle == NULL) {
526 usr_thread_sleep(&tv);
535 usr_mutex_lock(&osi_waitq_lock);
542 index = WAITHASH((caddr_t)handle);
543 if (osi_waithash_avail == NULL) {
544 waitp = (osi_wait_t *)afs_osi_Alloc(sizeof(osi_wait_t));
545 usr_cond_init(&waitp->cond);
547 waitp = osi_waithash_avail;
548 osi_waithash_avail = osi_waithash_avail->next;
550 waitp->addr = (caddr_t)handle;
552 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
553 osi_waithash_table[index].tail, next, prev);
554 tv.tv_sec += time(NULL);
555 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0)?0:1);
556 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
557 timedNext, timedPrev);
558 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
564 DLL_DELETE(waitp, osi_waithash_table[index].head,
565 osi_waithash_table[index].tail, next, prev);
566 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail,
567 timedNext, timedPrev);
568 waitp->next = osi_waithash_avail;
569 osi_waithash_avail = waitp;
570 usr_mutex_unlock(&osi_waitq_lock);
581 void afs_osi_CancelWait(handle)
582 struct afs_osi_WaitHandle *handle;
584 afs_osi_Wakeup((caddr_t)handle);
588 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
589 * to explicitly signal cond_timed_waits when their timers expire
591 int afs_osi_CheckTimedWaits()
596 curTime = time(NULL);
597 usr_mutex_lock(&osi_waitq_lock);
598 waitp = osi_timedwait_head;
599 while (waitp != NULL) {
600 usr_assert(waitp->expiration != 0);
601 if (waitp->expiration <= curTime) {
603 usr_cond_signal(&waitp->cond);
605 waitp = waitp->timedNext;
607 usr_mutex_unlock(&osi_waitq_lock);
611 * I-node numbers are indeces into a table containing a filename
612 * i-node structure and a vnode structure. When we create an i-node,
613 * we copy the name into the array and initialize enough of the fields
614 * in the inode and vnode structures to get the client to work.
617 struct usr_inode i_node;
620 osi_file_table_t *osi_file_table;
622 int max_osi_files = 0;
625 * Allocate a slot in the file table if there is not one there already,
626 * copy in the file name and kludge up the vnode and inode structures
628 int lookupname(fnamep, segflg, followlink, dirvpp, compvpp)
632 struct usr_vnode **dirvpp;
633 struct usr_vnode **compvpp;
637 struct usr_inode *ip;
638 struct usr_vnode *vp;
640 usr_assert(followlink == 0);
641 usr_assert(dirvpp == NULL);
644 * Assume relative pathnames refer to files in AFS
646 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
648 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0);
653 usr_mutex_lock(&osi_inode_lock);
655 for (i = 0 ; i < n_osi_files ; i++) {
656 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
657 *compvpp = &osi_file_table[i].i_node.i_vnode;
658 (*compvpp)->v_count++;
659 usr_mutex_unlock(&osi_inode_lock);
664 if (n_osi_files == max_osi_files) {
665 usr_mutex_unlock(&osi_inode_lock);
669 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep)+1);
670 usr_assert(osi_file_table[n_osi_files].name != NULL);
671 strcpy(osi_file_table[n_osi_files].name, fnamep);
672 ip = &osi_file_table[i].i_node;
674 vp->v_data = (caddr_t)ip;
677 ip->i_number = n_osi_files;
679 usr_mutex_unlock(&osi_inode_lock);
685 * open a file given its i-node number
687 void *osi_UFSOpen(ino)
696 if (ino > n_osi_files) {
702 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
703 usr_assert(fp != NULL);
704 fp->fd = open(osi_file_table[ino-1].name, O_RDWR|O_CREAT, 0);
707 afs_osi_Free((char *)fp, sizeof(struct osi_file));
711 rc = fstat(fp->fd, &st);
714 afs_osi_Free((void *)fp, sizeof(struct osi_file));
718 fp->size = st.st_size;
721 fp->vnode = (struct usr_vnode *)fp;
738 afs_osi_Free((void *)fp, sizeof(struct osi_file));
742 afs_osi_Free((void *)fp, sizeof(struct osi_file));
747 int osi_UFSTruncate(fp, len)
756 rc = ftruncate(fp->fd, len);
767 int afs_osi_Read(fp, offset, buf, len)
781 rc = lseek(fp->fd, offset, SEEK_SET);
783 rc = lseek(fp->fd, fp->offset, SEEK_SET);
791 ret = read(fp->fd, buf, len);
798 rc = fstat(fp->fd, &st);
804 fp->size = st.st_size;
809 int afs_osi_Write(fp, offset, buf, len)
823 rc = lseek(fp->fd, offset, SEEK_SET);
825 rc = lseek(fp->fd, fp->offset, SEEK_SET);
833 ret = write(fp->fd, buf, len);
840 rc = fstat(fp->fd, &st);
846 fp->size = st.st_size;
851 int afs_osi_Stat(fp, stp)
853 struct osi_stat *stp;
859 rc = fstat(fp->fd, &st);
865 stp->size = st.st_size;
866 stp->blksize = st.st_blksize;
867 stp->mtime = st.st_mtime;
868 stp->atime = st.st_atime;
876 int afs_osi_VOP_RDWR(
877 struct usr_vnode *vnodeP,
878 struct usr_uio *uioP,
881 struct usr_ucred* credP)
884 struct osi_file *fp = (struct osi_file *)vnodeP;
887 * We don't support readv/writev.
889 usr_assert(uioP->uio_iovcnt == 1);
890 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
892 if (rw == UIO_WRITE) {
893 usr_assert(uioP->uio_fmode == FWRITE);
894 rc = afs_osi_Write(fp, uioP->uio_offset,
895 uioP->uio_iov[0].iov_base,
896 uioP->uio_iov[0].iov_len);
898 usr_assert(uioP->uio_fmode == FREAD);
899 rc = afs_osi_Read(fp, uioP->uio_offset,
900 uioP->uio_iov[0].iov_base,
901 uioP->uio_iov[0].iov_len);
907 uioP->uio_resid -= rc;
908 uioP->uio_offset += rc;
909 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
910 uioP->uio_iov[0].iov_len -= rc;
915 * Use malloc/free routines with check patterns before and after each block
918 static char *afs_check_string1 = "UAFS";
919 static char *afs_check_string2 = "AFS_OSI_";
921 void *afs_osi_Alloc(size_t size)
926 void afs_osi_Free(void *ptr, size_t size)
931 void *osi_AllocLargeSpace(size_t size)
933 AFS_STATCNT(osi_AllocLargeSpace);
934 return afs_osi_Alloc(size);
937 void osi_FreeLargeSpace(void *ptr)
939 AFS_STATCNT(osi_FreeLargeSpace);
940 afs_osi_Free(ptr, 0);
943 void *osi_AllocSmallSpace(size_t size)
945 AFS_STATCNT(osi_AllocSmallSpace);
946 return afs_osi_Alloc(size);
949 void osi_FreeSmallSpace(void *ptr)
951 AFS_STATCNT(osi_FreeSmallSpace);
952 afs_osi_Free(ptr, 0);
957 AFS_STATCNT(shutdown_osi);
961 void shutdown_osinet()
963 AFS_STATCNT(shutdown_osinet);
967 void shutdown_osifile()
969 AFS_STATCNT(shutdown_osifile);
973 int afs_nfsclient_init()
978 void shutdown_nfsclnt()
983 int afs_osi_Invisible()
991 gettimeofday(tv, NULL);
1004 AFS_STATCNT(osi_Active);
1005 if (avc->opens > 0) return(1);
1009 int afs_osi_MapStrategy(aproc, bp)
1013 afs_int32 returnCode;
1014 returnCode = (*aproc)(bp);
1018 osi_FlushPages(avc, credp)
1019 register struct vcache *avc;
1020 struct AFS_UCRED *credp;
1022 ObtainSharedLock(&avc->lock,555);
1023 if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0) ||
1024 ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1025 ReleaseSharedLock(&avc->lock);
1028 UpgradeSToWLock(&avc->lock,565);
1029 hset(avc->mapDV, avc->m.DataVersion);
1030 ReleaseWriteLock(&avc->lock);
1034 osi_FlushText_really(vp)
1035 register struct vcache *vp;
1037 if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
1038 hset(vp->flushDV, vp->m.DataVersion);
1049 void osi_ReleaseVM(avc, len, credp)
1052 struct usr_ucred *credp;
1064 * Allocate the table used to implement psuedo-inodes.
1066 max_osi_files = cacheFiles + 100;
1067 osi_file_table = (osi_file_table_t *)
1068 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1069 usr_assert(osi_file_table != NULL);
1071 #ifndef NETSCAPE_NSAPI
1073 * Initialize the mutex and condition variable used to implement
1076 pthread_mutex_init(&usr_sleep_mutex, NULL);
1077 pthread_cond_init(&usr_sleep_cond, NULL);
1078 #endif /* !NETSCAPE_NSAPI */
1081 * Initialize the hash table used for sleep/wakeup
1083 for (i = 0 ; i < OSI_WAITHASH_SIZE ; i++) {
1084 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1086 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1087 osi_waithash_avail = NULL;
1090 * Initialize the AFS file table
1092 for (i = 0 ; i < MAX_OSI_FILES ; i++) {
1093 afs_FileTable[i] = NULL;
1097 * Initialize the global locks
1099 usr_mutex_init(&afs_global_lock);
1100 usr_mutex_init(&rx_global_lock);
1101 usr_mutex_init(&osi_inode_lock);
1102 usr_mutex_init(&osi_waitq_lock);
1103 usr_mutex_init(&osi_authenticate_lock);
1106 * Initialize the AFS OSI credentials
1108 afs_osi_cred = *afs_global_ucredp;
1111 /* ParseArgs is now obsolete, being handled by cmd */
1113 /*---------------------------------------------------------------------
1117 * Given the final component of a filename expected to be a data cache file,
1118 * return the integer corresponding to the file. Note: we reject names that
1119 * are not a ``V'' followed by an integer. We also reject those names having
1120 * the right format but lying outside the range [0..cacheFiles-1].
1123 * fname : Char ptr to the filename to parse.
1126 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1130 * Nothing interesting.
1134 *------------------------------------------------------------------------*/
1136 int GetVFileNumber(fname)
1139 int computedVNumber; /*The computed file number we return*/
1140 int filenameLen; /*Number of chars in filename*/
1141 int currDigit; /*Current digit being processed*/
1144 * The filename must have at least two characters, the first of which must be a ``V''
1145 * and the second of which cannot be a zero unless the file is exactly two chars long.
1147 filenameLen = strlen(fname);
1148 if (filenameLen < 2)
1150 if (fname[0] != 'V')
1152 if ((filenameLen > 2) && (fname[1] == '0'))
1156 * Scan through the characters in the given filename, failing immediately if a non-digit
1159 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1160 if (isdigit(fname[currDigit]) == 0)
1164 * All relevant characters are digits. Pull out the decimal number they represent.
1165 * Reject it if it's out of range, otherwise return it.
1167 computedVNumber = atoi(++fname);
1168 if (computedVNumber < cacheFiles)
1169 return(computedVNumber);
1174 /*---------------------------------------------------------------------
1178 * Given a full pathname for a file we need to create for the workstation AFS
1179 * cache, go ahead and create the file.
1182 * fname : Full pathname of file to create.
1185 * 0 iff the file was created,
1189 * The given cache file has been found to be missing.
1193 *------------------------------------------------------------------------*/
1195 int CreateCacheFile(fname)
1198 static char rn[] = "CreateCacheFile"; /*Routine name*/
1199 int cfd; /*File descriptor to AFS cache file*/
1200 int closeResult; /*Result of close()*/
1203 printf("%s: Creating cache file '%s'\n",
1205 cfd = open(fname, createAndTrunc, ownerRWmode);
1207 printf("%s: Can't create '%s', error return is %d (%d)\n",
1208 rn, fname, cfd, errno);
1211 closeResult = close(cfd);
1213 printf("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1221 /*---------------------------------------------------------------------
1225 * Sweep through the AFS cache directory, recording the inode number for
1226 * each valid data cache file there. Also, delete any file that doesn't beint32
1227 * in the cache directory during this sweep, and remember which of the other
1228 * residents of this directory were seen. After the sweep, we create any data
1229 * cache files that were missing.
1232 * vFilesFound : Set to the number of data cache files found.
1235 * 0 if everything went well,
1239 * This routine may be called several times. If the number of data cache files
1240 * found is less than the global cacheFiles, then the caller will need to call it
1241 * again to record the inodes of the missing zero-length data cache files created
1242 * in the previous call.
1245 * Fills up the global pathname_for_V array, may create and/or
1246 * delete files as explained above.
1247 *------------------------------------------------------------------------*/
1249 int SweepAFSCache(vFilesFound)
1252 static char rn[] = "SweepAFSCache"; /*Routine name*/
1253 char fullpn_FileToDelete[1024]; /*File to be deleted from cache*/
1254 char *fileToDelete; /*Ptr to last component of above*/
1255 DIR *cdirp; /*Ptr to cache directory structure*/
1257 struct dirent *currp; /*Current directory entry*/
1258 int vFileNum; /*Data cache file's associated number*/
1260 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1262 printf("%s: Memory Cache, no cache sweep done\n");
1268 printf("%s: Opening cache directory '%s'\n",
1271 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1272 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n",
1276 cdirp = opendir(cacheBaseDir);
1277 if (cdirp == (DIR *)0) {
1278 printf("%s: Can't open AFS cache directory, '%s'.\n",
1284 * Scan the directory entries, remembering data cache file inodes and the existance
1285 * of other important residents. Delete all files that don't belong here.
1288 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1289 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1291 for (currp = readdir(cdirp); currp; currp = readdir(cdirp))
1294 printf("%s: Current directory entry:\n",
1296 printf("\tinode=%d, reclen=%d, name='%s'\n",
1297 currp->d_ino, currp->d_reclen, currp->d_name);
1301 * Guess current entry is for a data cache file.
1303 vFileNum = GetVFileNumber(currp->d_name);
1304 if (vFileNum >= 0) {
1306 * Found a valid data cache filename. Remember this file's name
1307 * and bump the number of files found.
1309 pathname_for_V[vFileNum] = afs_osi_Alloc(strlen(currp->d_name) +
1310 strlen(cacheBaseDir) + 2);
1311 usr_assert(pathname_for_V[vFileNum] != NULL);
1312 sprintf(pathname_for_V[vFileNum], "%s/%s",
1313 cacheBaseDir, currp->d_name);
1316 else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1318 * Found the file holding the dcache entries.
1320 missing_DCacheFile = 0;
1322 else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1324 * Found the file holding the volume info.
1326 missing_VolInfoFile = 0;
1328 else if ((strcmp(currp->d_name, ".") == 0) ||
1329 (strcmp(currp->d_name, "..") == 0) ||
1330 (strcmp(currp->d_name, "lost+found") == 0)) {
1332 * Don't do anything - this file is legit, and is to be left alone.
1337 * This file doesn't belong in the cache. Nuke it.
1339 sprintf(fileToDelete, "%s", currp->d_name);
1341 printf("%s: Deleting '%s'\n",
1342 rn, fullpn_FileToDelete);
1343 if (unlink(fullpn_FileToDelete)) {
1344 printf("%s: Can't unlink '%s', errno is %d\n",
1345 rn, fullpn_FileToDelete, errno);
1351 * Create all the cache files that are missing.
1353 if (missing_DCacheFile) {
1355 printf("%s: Creating '%s'\n",
1356 rn, fullpn_DCacheFile);
1357 if (CreateCacheFile(fullpn_DCacheFile))
1358 printf("%s: Can't create '%s'\n",
1359 rn, fullpn_DCacheFile);
1361 if (missing_VolInfoFile) {
1363 printf("%s: Creating '%s'\n",
1364 rn, fullpn_VolInfoFile);
1365 if (CreateCacheFile(fullpn_VolInfoFile))
1366 printf("%s: Can't create '%s'\n",
1367 rn, fullpn_VolInfoFile);
1370 if (*vFilesFound < cacheFiles) {
1372 * We came up short on the number of data cache files found. Scan through the inode
1373 * list and create all missing files.
1375 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1376 if (pathname_for_V[vFileNum] == (AFSD_INO_T)0) {
1377 sprintf(vFileNumber, "%d", vFileNum);
1379 printf("%s: Creating '%s'\n",
1381 if (CreateCacheFile(fullpn_VFile))
1382 printf("%s: Can't create '%s'\n",
1388 * Close the directory, return success.
1391 printf("%s: Closing cache directory.\n",
1397 static ConfigCell(aci, arock, adir)
1398 register struct afsconf_cell *aci;
1400 struct afsconf_dir *adir; {
1401 register int isHomeCell;
1403 afs_int32 cellFlags;
1404 afs_int32 hosts[MAXHOSTSPERCELL];
1406 /* figure out if this is the home cell */
1407 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1409 lookingForHomeCell = 0;
1410 cellFlags = 1; /* home cell, suid is ok */
1413 cellFlags = 2; /* not home, suid is forbidden */
1416 /* build address list */
1417 for(i=0;i<MAXHOSTSPERCELL;i++)
1418 bcopy(&aci->hostAddr[i].sin_addr, &hosts[i], sizeof(afs_int32));
1420 if (aci->linkedCell) cellFlags |= 4; /* Flag that linkedCell arg exists,
1421 for upwards compatibility */
1423 /* configure one cell */
1424 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2,
1425 (long)hosts, /* server addresses */
1426 (long)aci->name, /* cell name */
1427 (long)cellFlags, /* is this the home cell? */
1428 (long)aci->linkedCell); /* Linked cell, if any */
1433 * Set the UDP port number RX uses for UDP datagrams
1435 void uafs_SetRxPort(
1438 usr_assert(usr_rx_port == 0);
1444 * Initialize the user space client.
1448 char *mountDirParam,
1450 char *cacheBaseDirParam,
1451 int cacheBlocksParam,
1452 int cacheFilesParam,
1453 int cacheStatEntriesParam,
1454 int dCacheSizeParam,
1455 int vCacheSizeParam,
1457 int closeSynchParam,
1460 int cacheFlagsParam,
1464 struct usr_proc *procp;
1465 struct usr_ucred *ucredp;
1468 int currVFile; /* Current AFS cache file number */
1469 int lookupResult; /* Result of GetLocalCellName() */
1470 int cacheIteration; /* cache verification loop counter */
1471 int vFilesFound; /* Num data cache files found in sweep */
1473 afs_int32 vfs1_type = -1;
1474 struct afs_ioctl iob;
1478 afs_int32 buffer[MAXIPADDRS];
1479 afs_int32 maskbuffer[MAXIPADDRS];
1480 afs_int32 mtubuffer[MAXIPADDRS];
1483 * Use the thread specific data to implement the user structure
1485 usr_keycreate(&afs_global_u_key, free);
1488 * Initialize the global ucred structure
1490 afs_global_ucredp = (struct usr_ucred *)
1491 afs_osi_Alloc(sizeof(struct usr_ucred));
1492 usr_assert(afs_global_ucredp != NULL);
1493 afs_global_ucredp->cr_ref = 1;
1494 afs_global_ucredp->cr_uid = geteuid();
1495 afs_global_ucredp->cr_gid = getegid();
1496 afs_global_ucredp->cr_ruid = getuid();
1497 afs_global_ucredp->cr_rgid = getgid();
1498 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1499 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1500 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1501 usr_assert(st >= 0);
1502 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1503 for (i = st ; i < NGROUPS ; i++) {
1504 afs_global_ucredp->cr_groups[i] = NOGROUP;
1508 * Initialize the global process structure
1510 afs_global_procp = (struct usr_proc *)
1511 afs_osi_Alloc(sizeof(struct usr_proc));
1512 usr_assert(afs_global_procp != NULL);
1513 afs_global_procp->p_pid = getpid();
1514 afs_global_procp->p_ppid = (pid_t)1;
1515 afs_global_procp->p_ucred = afs_global_ucredp;
1518 * Initialize the AFS mount point, default is '/afs'.
1519 * Strip duplicate/trailing slashes from mount point string.
1520 * afs_mountDirLen is set to strlen(afs_mountDir).
1522 if (mountDirParam) {
1523 sprintf(tbuffer, "%s", mountDirParam);
1525 sprintf(tbuffer, "afs");
1527 afs_mountDir[0] = '/';
1528 afs_mountDirLen = 1;
1529 for (lastchar = '/', p = &tbuffer[0] ; *p != '\0' ; p++) {
1530 if (lastchar != '/' || *p != '/') {
1531 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1534 if (lastchar == '/' && afs_mountDirLen > 1)
1536 afs_mountDir[afs_mountDirLen] = '\0';
1537 usr_assert(afs_mountDirLen > 1);
1540 * Initialize cache parameters using the input arguments
1543 cacheBlocks = cacheBlocksParam;
1544 if (cacheFilesParam != 0) {
1545 cacheFiles = cacheFilesParam;
1547 cacheFiles = cacheBlocks/10;
1549 if (cacheStatEntriesParam != 0) {
1550 cacheStatEntries = cacheStatEntriesParam;
1552 strcpy(cacheBaseDir, cacheBaseDirParam);
1553 if (nDaemons != 0) {
1554 nDaemons = nDaemonsParam;
1558 afsd_verbose = debugParam;
1559 afsd_debug = debugParam;
1560 chunkSize = chunkSizeParam;
1561 if (dCacheSizeParam != 0) {
1562 dCacheSize = dCacheSizeParam;
1564 dCacheSize = cacheFiles/2;
1566 if (vCacheSizeParam != 0) {
1567 vCacheSize = vCacheSizeParam;
1569 strcpy(confDir, confDirParam);
1570 afsd_CloseSynch = closeSynchParam;
1571 if (cacheFlagsParam >= 0) {
1572 cacheFlags = cacheFlagsParam;
1574 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1575 cacheFiles = dCacheSize;
1578 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1579 if (logFile == NULL) {
1580 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1582 strcpy(fullpn_AFSLogFile, logFile);
1585 printf("\n%s: Initializing user space AFS client\n\n", rn);
1586 printf(" mountDir: %s\n", afs_mountDir);
1587 printf(" confDir: %s\n", confDir);
1588 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1589 printf(" cacheBlocks: %d\n", cacheBlocks);
1590 printf(" cacheFiles: %d\n", cacheFiles);
1591 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1592 printf(" dCacheSize: %d\n", dCacheSize);
1593 printf(" vCacheSize: %d\n", vCacheSize);
1594 printf(" chunkSize: %d\n", chunkSize);
1595 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1596 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1597 printf(" nDaemons: %d\n", nDaemons);
1598 printf(" cacheFlags: %d\n", cacheFlags);
1599 printf(" logFile: %s\n", fullpn_AFSLogFile);
1604 * Initialize the AFS client
1609 * Pull out all the configuration info for the workstation's AFS cache and
1610 * the cellular community we're willing to let our users see.
1612 afs_cdir = afsconf_Open(confDir);
1614 printf("afsd: some file missing or bad in %s\n", confDir);
1618 lookupResult = afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1619 sizeof(afs_LclCellName));
1621 printf("%s: Can't get my home cell name! [Error is %d]\n",
1626 printf("%s: My home cell is '%s'\n",
1627 rn, afs_LclCellName);
1630 if ((logfd = fopen(fullpn_AFSLogFile,"r+")) == 0) {
1631 if (afsd_verbose) printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1632 if (CreateCacheFile(fullpn_AFSLogFile)) {
1633 printf("%s: Can't create '%s' (You may want to use the -logfile option)\n", rn, fullpn_AFSLogFile);
1640 * Create and zero the pathname table for the desired cache files.
1642 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1643 if (pathname_for_V == NULL) {
1644 printf("%s: malloc() failed for cache file table with %d entries.\n",
1648 bzero(pathname_for_V, (cacheFiles * sizeof(char *)));
1650 printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n",
1651 rn, cacheFiles, (cacheFiles * sizeof(AFSD_INO_T)));
1654 * Set up all the pathnames we'll need for later.
1656 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1657 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1658 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1659 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1662 * Start the RX listener.
1665 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1666 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE);
1669 * Start the RX event handler.
1672 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1673 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1676 * Set up all the kernel processes needed for AFS.
1679 /* initialize AFS callback interface */
1681 /* parse multihomed address files */
1683 st=parseNetFiles(buffer,maskbuffer,mtubuffer,MAXIPADDRS,reason,
1684 AFSDIR_CLIENT_NETINFO_FILEPATH,
1685 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1687 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st, (long) (&buffer[0]),
1688 (long) (&maskbuffer[0]), (long) (&mtubuffer[0]));
1690 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",reason);
1696 printf("%s: Forking rx callback listener.\n", rn);
1698 if (preallocs < cacheStatEntries+50)
1699 preallocs = cacheStatEntries+50;
1700 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1703 printf("%s: Forking AFS daemon.\n", rn);
1704 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1707 printf("%s: Forking check server daemon.\n", rn);
1708 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1711 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1712 for (i=0;i<nDaemons;i++) {
1713 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1717 * Tell the kernel about each cell in the configuration.
1719 lookingForHomeCell = 1;
1721 afsconf_CellApply(afs_cdir, ConfigCell, (char *) 0);
1724 * If we're still looking for the home cell after the whole cell
1725 * configuration database has been parsed, there's something wrong.
1727 if (lookingForHomeCell) {
1728 printf("%s: Can't find home cell '%s' in cell database!\n",
1729 rn, afs_LclCellName);
1733 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n",
1735 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1738 * Tell the kernel some basic information about the workstation's cache.
1741 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1742 " %d optimum cache files, %d blocks in the cache,"
1743 " flags = 0x%x, dcache entries %d\n",
1744 rn, cacheStatEntries, cacheFiles, cacheBlocks, cacheFlags,
1746 bzero(&cparams, sizeof(cparams));
1747 cparams.cacheScaches = cacheStatEntries;
1748 cparams.cacheFiles = cacheFiles;
1749 cparams.cacheBlocks = cacheBlocks;
1750 cparams.cacheDcaches = dCacheSize;
1751 cparams.cacheVolumes = vCacheSize;
1752 cparams.chunkSize = chunkSize;
1753 cparams.setTimeFlag = FALSE;
1754 cparams.memCacheFlag = cacheFlags;
1755 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1756 if (afsd_CloseSynch)
1757 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1760 * Sweep the workstation AFS cache directory, remembering the inodes of
1761 * valid files and deleting extraneous files. Keep sweeping until we
1762 * have the right number of data cache files or we've swept too many
1766 printf("%s: Sweeping workstation's AFS cache directory.\n",
1769 /* Memory-cache based system doesn't need any of this */
1770 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1773 if (SweepAFSCache(&vFilesFound)) {
1774 printf("%s: Error on sweep %d of workstation AFS cache \
1775 directory.\n", rn, cacheIteration);
1779 printf("%s: %d out of %d data cache files found in sweep %d.\n",
1780 rn, vFilesFound, cacheFiles, cacheIteration);
1781 } while ((vFilesFound < cacheFiles) &&
1782 (cacheIteration < MAX_CACHE_LOOPS));
1783 } else if(afsd_verbose)
1784 printf("%s: Using memory cache, not swept\n", rn);
1787 * Pass the kernel the name of the workstation cache file holding the
1791 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n",
1792 rn, fullpn_DCacheFile);
1793 /* once again, meaningless for a memory-based cache. */
1794 if(!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1795 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1800 * Pass the kernel the name of the workstation cache file holding the
1801 * volume information.
1804 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n",
1805 rn, fullpn_VolInfoFile);
1806 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO,(long)fullpn_VolInfoFile,
1810 * Pass the kernel the name of the afs logging file holding the volume
1814 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n",
1815 rn, fullpn_AFSLogFile);
1816 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1817 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG,(long)fullpn_AFSLogFile,
1821 * Give the kernel the names of the AFS files cached on the workstation's
1825 printf("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1826 rn, cacheFiles, cacheBaseDir);
1827 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1828 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1829 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1830 (long)pathname_for_V[currVFile], 0, 0, 0);
1833 #ifndef NETSCAPE_NSAPI
1835 * Copy our tokens from the kernel to the user space client
1837 for(i = 0 ; i < 200 ; i++) {
1839 * Get the i'th token from the kernel
1841 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1842 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1844 iob.in_size = sizeof(int);
1846 iob.out_size = sizeof(tbuffer);
1848 #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)
1849 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1850 #elif defined(AFS_USR_SGI_ENV)
1851 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1852 #else /* AFS_USR_AIX_ENV */
1853 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1856 usr_assert(errno == EDOM);
1861 * Now pass the token into the user space kernel
1863 rc = uafs_SetTokens(tbuffer, iob.out_size);
1864 usr_assert(rc == 0);
1866 #endif /* !NETSCAPE_NSAPI */
1869 * All the necessary info has been passed into the kernel to run an AFS
1870 * system. Give the kernel our go-ahead.
1873 printf("%s: Calling AFSOP_GO\n", rn);
1874 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1877 * At this point, we have finished passing the kernel all the info
1878 * it needs to set up the AFS. Mount the AFS root.
1880 printf("%s: All AFS daemons started.\n", rn);
1883 printf("%s: Forking trunc-cache daemon.\n", rn);
1884 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1887 * Mount the AFS filesystem
1890 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1891 usr_assert(rc == 0);
1892 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1893 usr_assert(rc == 0);
1897 * initialize the current directory to the AFS root
1899 afs_CurrentDir = afs_RootVnode;
1900 VN_HOLD(afs_CurrentDir);
1905 void uafs_Shutdown()
1912 VN_RELE(afs_CurrentDir);
1913 rc = afs_unmount(&afs_RootVfs);
1914 usr_assert(rc == 0);
1921 * Donate the current thread to the RX server pool.
1923 void uafs_RxServerProc()
1927 struct rx_call *newcall = NULL;
1929 rxi_MorePackets(2); /* alloc more packets */
1930 threadID = rxi_availProcs++;
1933 sock = OSI_NULLSOCKET;
1934 rxi_ServerProc(threadID, newcall, &sock);
1935 if (sock == OSI_NULLSOCKET) {
1940 rxi_ListenerProc(sock, &threadID, &newcall);
1941 /* assert(threadID != -1); */
1942 /* assert(newcall != NULL); */
1946 struct syscallThreadArgs {
1955 #ifdef NETSCAPE_NSAPI
1956 void syscallThread(argp)
1957 #else /* NETSCAPE_NSAPI */
1958 void *syscallThread(argp)
1959 #endif /* NETSCAPE_NSAPI */
1963 struct usr_ucred *crp;
1964 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1967 * AFS daemons run authenticated
1969 u.u_viceid = getuid();
1971 crp->cr_uid = getuid();
1972 crp->cr_ruid = getuid();
1973 crp->cr_suid = getuid();
1974 crp->cr_groups[0] = getgid();
1975 crp->cr_ngroups = 1;
1976 for (i = 1 ; i < NGROUPS ; i++) {
1977 crp->cr_groups[i] = NOGROUP;
1980 call_syscall(sysArgsP->syscall, sysArgsP->afscall,
1981 sysArgsP->param1, sysArgsP->param2,
1982 sysArgsP->param3, sysArgsP->param4);
1984 afs_osi_Free(argp, -1);
1987 fork_syscall(syscall, afscall, param1, param2, param3, param4)
1988 long syscall, afscall, param1, param2, param3, param4;
1991 struct syscallThreadArgs *sysArgsP;
1993 sysArgsP = (struct syscallThreadArgs *)
1994 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1995 usr_assert(sysArgsP != NULL);
1996 sysArgsP->syscall = syscall;
1997 sysArgsP->afscall = afscall;
1998 sysArgsP->param1 = param1;
1999 sysArgsP->param2 = param2;
2000 sysArgsP->param3 = param3;
2001 sysArgsP->param4 = param4;
2003 usr_thread_create(&tid, syscallThread, sysArgsP);
2004 usr_thread_detach(tid);
2007 call_syscall(syscall, afscall, param1, param2, param3, param4)
2008 long syscall, afscall, param1, param2, param3, param4;
2020 a.syscall = syscall;
2021 a.afscall = afscall;
2028 u.u_ap = (char *)&a;
2030 code = Afs_syscall();
2034 int uafs_SetTokens(char *tbuffer, int tlen)
2037 struct afs_ioctl iob;
2042 iob.out = &outbuf[0];
2043 iob.out_size = sizeof(outbuf);
2044 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2052 int uafs_RPCStatsEnableProc()
2055 struct afs_ioctl iob;
2058 flag = AFSCALL_RXSTATS_ENABLE;
2059 iob.in = (char *)&flag;
2060 iob.in_size = sizeof(afs_int32);
2063 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2071 int uafs_RPCStatsDisableProc()
2074 struct afs_ioctl iob;
2077 flag = AFSCALL_RXSTATS_DISABLE;
2078 iob.in = (char *)&flag;
2079 iob.in_size = sizeof(afs_int32);
2082 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2090 int uafs_RPCStatsClearProc()
2093 struct afs_ioctl iob;
2096 flag = AFSCALL_RXSTATS_CLEAR;
2097 iob.in = (char *)&flag;
2098 iob.in_size = sizeof(afs_int32);
2101 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2109 int uafs_RPCStatsEnablePeer()
2112 struct afs_ioctl iob;
2115 flag = AFSCALL_RXSTATS_ENABLE;
2116 iob.in = (char *)&flag;
2117 iob.in_size = sizeof(afs_int32);
2120 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2128 int uafs_RPCStatsDisablePeer()
2131 struct afs_ioctl iob;
2134 flag = AFSCALL_RXSTATS_DISABLE;
2135 iob.in = (char *)&flag;
2136 iob.in_size = sizeof(afs_int32);
2139 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2147 int uafs_RPCStatsClearPeer()
2150 struct afs_ioctl iob;
2153 flag = AFSCALL_RXSTATS_CLEAR;
2154 iob.in = (char *)&flag;
2155 iob.in_size = sizeof(afs_int32);
2158 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2167 * Lookup a file or directory given its path.
2168 * Call VN_HOLD on the output vnode if successful.
2169 * Returns zero on success, error code on failure.
2171 * Note: Caller must hold the AFS global lock.
2173 int uafs_LookupName(
2175 struct usr_vnode *parentVp,
2176 struct usr_vnode **vpp,
2181 struct usr_vnode *vp;
2182 struct usr_vnode *nextVp;
2183 struct usr_vnode *linkVp;
2191 * Absolute paths must start with the AFS mount point.
2193 if (path[0] != '/') {
2196 path = uafs_afsPathName(path);
2204 * Loop through the path looking for the new directory
2206 tmpPath = afs_osi_Alloc(strlen(path)+1);
2207 usr_assert(tmpPath != NULL);
2208 strcpy(tmpPath, path);
2211 while (pathP != NULL && *pathP != '\0') {
2212 usr_assert(*pathP != '/');
2215 * terminate the current component and skip over slashes
2217 nextPathP = strchr(pathP, '/');
2218 if (nextPathP != NULL) {
2219 while (*nextPathP == '/') {
2220 *(nextPathP++) = '\0';
2225 * Don't call afs_lookup on non-directories
2227 if (vp->v_type != VDIR) {
2229 afs_osi_Free(tmpPath, strlen(path)+1);
2233 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2235 * The AFS root is its own parent
2237 nextVp = afs_RootVnode;
2240 * We need execute permission to search a directory
2242 code = afs_access(vp, VEXEC, u.u_cred);
2245 afs_osi_Free(tmpPath, strlen(path)+1);
2250 * lookup the next component in the path, we can release the
2251 * subdirectory since we hold the global lock
2254 code = afs_lookup(vp, pathP, &nextVp, u.u_cred);
2257 afs_osi_Free(tmpPath, strlen(path)+1);
2263 * Follow symbolic links for parent directories and
2264 * for leaves when the follow flag is set.
2266 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2268 while(nextVp->v_type == VLNK) {
2269 if (++linkCount > MAX_OSI_LINKS) {
2272 afs_osi_Free(tmpPath, strlen(path)+1);
2275 code = uafs_LookupLink(nextVp, vp, &linkVp);
2279 afs_osi_Free(tmpPath, strlen(path)+1);
2293 * Special case, nextPathP is non-null if pathname ends in slash
2295 if (nextPathP != NULL && vp->v_type != VDIR) {
2297 afs_osi_Free(tmpPath, strlen(path)+1);
2301 afs_osi_Free(tmpPath, strlen(path)+1);
2307 * Lookup the target of a symbolic link
2308 * Call VN_HOLD on the output vnode if successful.
2309 * Returns zero on success, error code on failure.
2311 * Note: Caller must hold the AFS global lock.
2313 int uafs_LookupLink(
2314 struct usr_vnode *vp,
2315 struct usr_vnode *parentVp,
2316 struct usr_vnode **vpp)
2321 struct usr_vnode *linkVp;
2323 struct iovec iov[1];
2327 pathP = afs_osi_Alloc(MAX_OSI_PATH+1);
2328 usr_assert(pathP != NULL);
2331 * set up the uio buffer
2333 iov[0].iov_base = pathP;
2334 iov[0].iov_len = MAX_OSI_PATH+1;
2335 uio.uio_iov = &iov[0];
2339 uio.uio_fmode = FREAD;
2340 uio.uio_resid = MAX_OSI_PATH+1;
2343 * Read the link data
2345 code = afs_readlink(vp, &uio, u.u_cred);
2347 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2350 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2354 * Find the target of the symbolic link
2356 code = uafs_LookupName(pathP, parentVp, &linkVp, 1);
2358 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2362 afs_osi_Free(pathP, MAX_OSI_PATH+1);
2368 * Lookup the parent of a file or directory given its path
2369 * Call VN_HOLD on the output vnode if successful.
2370 * Returns zero on success, error code on failure.
2372 * Note: Caller must hold the AFS global lock.
2374 int uafs_LookupParent(
2376 struct usr_vnode **vpp)
2381 struct usr_vnode *parentP;
2386 * Absolute path names must start with the AFS mount point.
2389 pathP = uafs_afsPathName(path);
2390 if (pathP == NULL) {
2396 * Find the length of the parent path
2399 while(len > 0 && path[len-1] == '/') {
2405 while(len > 0 && path[len-1] != '/') {
2412 pathP = afs_osi_Alloc(len);
2413 usr_assert(pathP != NULL);
2414 memcpy(pathP, path, len-1);
2415 pathP[len-1] = '\0';
2418 * look up the parent
2420 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1);
2421 afs_osi_Free(pathP, len);
2425 if (parentP->v_type != VDIR) {
2435 * Return a pointer to the first character in the last component
2438 char *uafs_LastPath(char *path)
2443 while (len > 0 && path[len-1] == '/') {
2446 while (len > 0 && path[len-1] != '/') {
2456 * Set the working directory.
2463 retval = uafs_chdir_r(path);
2474 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1);
2479 if (dirP->v_type != VDIR) {
2484 VN_RELE(afs_CurrentDir);
2485 afs_CurrentDir = dirP;
2490 * Create a directory.
2498 retval = uafs_mkdir_r(path, mode);
2509 struct vnode *parentP;
2511 struct usr_vattr attrs;
2513 if (uafs_IsRoot(path)) {
2518 * Look up the parent directory.
2520 nameP = uafs_LastPath(path);
2521 if (nameP != NULL) {
2522 code = uafs_LookupParent(path, &parentP);
2528 parentP = afs_CurrentDir;
2534 * Make sure the directory has at least one character
2536 if (*nameP == '\0') {
2543 * Create the directory
2545 usr_vattr_null(&attrs);
2546 attrs.va_type = VREG;
2547 attrs.va_mode = mode;
2548 attrs.va_uid = u.u_cred->cr_uid;
2549 attrs.va_gid = u.u_cred->cr_gid;
2551 code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
2562 * Return 1 if path is the AFS root, otherwise return 0
2564 int uafs_IsRoot(char *path)
2566 while(*path == '/' && *(path+1) == '/') {
2569 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2572 path += afs_mountDirLen;
2573 while (*path == '/') {
2576 if (*path != '\0') {
2584 * Note: file name may not end in a slash.
2593 retval = uafs_open_r(path, flags, mode);
2607 struct usr_vnode *fileP;
2608 struct usr_vnode *dirP;
2609 struct usr_vattr attrs;
2612 if (uafs_IsRoot(path)) {
2613 fileP = afs_RootVnode;
2617 * Look up the parent directory.
2619 nameP = uafs_LastPath(path);
2620 if (nameP != NULL) {
2621 code = uafs_LookupParent(path, &dirP);
2627 dirP = afs_CurrentDir;
2633 * Make sure the filename has at least one character
2635 if (*nameP == '\0') {
2642 * Get the VNODE for this file
2644 if (flags & O_CREAT) {
2645 usr_vattr_null(&attrs);
2646 attrs.va_type = VREG;
2647 attrs.va_mode = mode;
2648 attrs.va_uid = u.u_cred->cr_uid;
2649 attrs.va_gid = u.u_cred->cr_gid;
2650 if (flags & O_TRUNC) {
2654 code = afs_create(dirP, nameP, &attrs,
2655 (flags & O_EXCL)?usr_EXCL:usr_NONEXCL,
2656 mode, &fileP, u.u_cred);
2664 code = uafs_LookupName(nameP, dirP, &fileP, 1);
2672 * Check whether we have access to this file
2675 if (flags & (O_RDONLY|O_RDWR)) {
2678 if (flags & (O_WRONLY|O_RDWR)) {
2681 code = afs_access(fileP, fileMode, u.u_cred);
2689 * Get the file attributes, all we need is the size
2691 code = afs_getattr(fileP, &attrs, u.u_cred);
2701 * Setup the open flags
2704 if (flags & O_TRUNC) {
2705 openFlags |= FTRUNC;
2707 if (flags & O_APPEND) {
2708 openFlags |= FAPPEND;
2710 if (flags & O_SYNC) {
2713 if (flags & O_SYNC) {
2716 if (flags & (O_RDONLY|O_RDWR)) {
2719 if (flags & (O_WRONLY|O_RDWR)) {
2720 openFlags |= FWRITE;
2724 * Truncate if necessary
2726 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2727 usr_vattr_null(&attrs);
2729 code = afs_setattr(fileP, &attrs, u.u_cred);
2740 code = afs_open(&fileP, openFlags, u.u_cred);
2748 * Put the vnode pointer into the file table
2750 for (fd = 0 ; fd < MAX_OSI_FILES ; fd++) {
2751 if (afs_FileTable[fd] == NULL) {
2752 afs_FileTable[fd] = fileP;
2753 afs_FileFlags[fd] = openFlags;
2754 if (flags & O_APPEND) {
2755 afs_FileOffsets[fd] = attrs.va_size;
2757 afs_FileOffsets[fd] = 0;
2762 if (fd == MAX_OSI_FILES) {
2779 rc = uafs_open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2788 rc = uafs_open_r(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
2802 retval = uafs_write_r(fd, buf, len);
2814 struct iovec iov[1];
2815 struct usr_vnode *fileP;
2818 * Make sure this is an open file
2820 fileP = afs_FileTable[fd];
2821 if (fileP == NULL) {
2827 * set up the uio buffer
2829 iov[0].iov_base = buf;
2830 iov[0].iov_len = len;
2831 uio.uio_iov = &iov[0];
2833 uio.uio_offset = afs_FileOffsets[fd];
2835 uio.uio_fmode = FWRITE;
2836 uio.uio_resid = len;
2842 code = afs_write(fileP, &uio, afs_FileFlags[fd], u.u_cred, 0);
2848 afs_FileOffsets[fd] = uio.uio_offset;
2849 return(len - uio.uio_resid);
2862 retval = uafs_read_r(fd, buf, len);
2874 struct iovec iov[1];
2875 struct usr_vnode *fileP;
2876 struct usr_buf *bufP;
2879 * Make sure this is an open file
2881 fileP = afs_FileTable[fd];
2882 if (fileP == NULL) {
2888 * set up the uio buffer
2890 iov[0].iov_base = buf;
2891 iov[0].iov_len = len;
2892 uio.uio_iov = &iov[0];
2894 uio.uio_offset = afs_FileOffsets[fd];
2896 uio.uio_fmode = FREAD;
2897 uio.uio_resid = len;
2902 code = afs_read(fileP, &uio, u.u_cred, 0, &bufP, 0);
2908 afs_FileOffsets[fd] = uio.uio_offset;
2909 return(len - uio.uio_resid);
2913 * Copy the attributes of a file into a stat structure.
2915 * NOTE: Caller must hold the global AFS lock.
2918 struct usr_vnode *vp,
2922 struct usr_vattr attrs;
2927 * Get the attributes
2929 code = afs_getattr(vp, &attrs, u.u_cred);
2935 * Copy the attributes, zero fields that aren't set
2937 memset((void *)stats, 0, sizeof(struct stat));
2939 stats->st_ino = attrs.va_nodeid;
2940 stats->st_mode = attrs.va_mode;
2941 stats->st_nlink = attrs.va_nlink;
2942 stats->st_uid = attrs.va_uid;
2943 stats->st_gid = attrs.va_gid;
2944 stats->st_rdev = attrs.va_rdev;
2945 stats->st_size = attrs.va_size;
2946 stats->st_atime = attrs.va_atime.tv_sec;
2947 stats->st_mtime = attrs.va_mtime.tv_sec;
2948 stats->st_ctime = attrs.va_ctime.tv_sec;
2949 stats->st_blksize = attrs.va_blocksize;
2950 stats->st_blocks = attrs.va_blocks;
2956 * Get the attributes of a file, do follow links
2964 retval = uafs_stat_r(path, buf);
2976 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
2981 code = uafs_GetAttr(vp, buf);
2991 * Get the attributes of a file, don't follow links
2999 retval = uafs_lstat_r(path, buf);
3011 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0);
3016 code = uafs_GetAttr(vp, buf);
3026 * Get the attributes of an open file
3034 retval = uafs_fstat_r(fd, buf);
3046 vp = afs_FileTable[fd];
3051 code = uafs_GetAttr(vp, buf);
3061 * change the permissions on a file
3069 retval = uafs_chmod_r(path, mode);
3080 struct usr_vattr attrs;
3082 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
3087 usr_vattr_null(&attrs);
3088 attrs.va_mode = mode;
3089 code = afs_setattr(vp, &attrs, u.u_cred);
3099 * change the permissions on an open file
3107 retval = uafs_fchmod_r(fd, mode);
3118 struct usr_vattr attrs;
3120 vp = afs_FileTable[fd];
3125 usr_vattr_null(&attrs);
3126 attrs.va_mode = mode;
3127 code = afs_setattr(vp, &attrs, u.u_cred);
3144 retval = uafs_truncate_r(path, length);
3149 int uafs_truncate_r(
3155 struct usr_vattr attrs;
3157 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1);
3162 usr_vattr_null(&attrs);
3163 attrs.va_size = length;
3164 code = afs_setattr(vp, &attrs, u.u_cred);
3174 * truncate an open file
3182 retval = uafs_ftruncate_r(fd, length);
3187 int uafs_ftruncate_r(
3193 struct usr_vattr attrs;
3195 vp = afs_FileTable[fd];
3200 usr_vattr_null(&attrs);
3201 attrs.va_size = length;
3202 code = afs_setattr(vp, &attrs, u.u_cred);
3211 * set the read/write file pointer of an open file
3220 retval = uafs_lseek_r(fd, offset, whence);
3232 struct usr_vattr attrs;
3233 struct usr_vnode *vp;
3235 vp = afs_FileTable[fd];
3242 newpos = afs_FileOffsets[fd] + offset;
3248 code = afs_getattr(vp, &attrs, u.u_cred);
3253 newpos = attrs.va_size + offset;
3263 afs_FileOffsets[fd] = newpos;
3275 retval = uafs_fsync_r(fd);
3284 struct usr_vnode *fileP;
3287 fileP = afs_FileTable[fd];
3288 if (fileP == NULL) {
3293 code = afs_fsync(fileP, u.u_cred);
3310 retval = uafs_close_r(fd);
3319 struct usr_vnode *fileP;
3321 fileP = afs_FileTable[fd];
3322 if (fileP == NULL) {
3326 afs_FileTable[fd] = NULL;
3328 code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
3339 * Create a hard link from the source to the target
3340 * Note: file names may not end in a slash.
3348 retval = uafs_link_r(existing, new);
3358 struct usr_vnode *existP;
3359 struct usr_vnode *dirP;
3362 if (uafs_IsRoot(new)) {
3367 * Look up the existing node.
3369 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1);
3376 * Look up the parent directory.
3378 nameP = uafs_LastPath(new);
3379 if (nameP != NULL) {
3380 code = uafs_LookupParent(new, &dirP);
3387 dirP = afs_CurrentDir;
3393 * Make sure the filename has at least one character
3395 if (*nameP == '\0') {
3405 code = afs_link(existP, dirP, nameP, u.u_cred);
3416 * Create a symbolic link from the source to the target
3417 * Note: file names may not end in a slash.
3425 retval = uafs_symlink_r(target, source);
3435 struct usr_vnode *dirP;
3436 struct usr_vattr attrs;
3439 if (uafs_IsRoot(source)) {
3444 * Look up the parent directory.
3446 nameP = uafs_LastPath(source);
3447 if (nameP != NULL) {
3448 code = uafs_LookupParent(source, &dirP);
3454 dirP = afs_CurrentDir;
3460 * Make sure the filename has at least one character
3462 if (*nameP == '\0') {
3471 usr_vattr_null(&attrs);
3472 attrs.va_type = VLNK;
3473 attrs.va_mode = 0777;
3474 attrs.va_uid = u.u_cred->cr_uid;
3475 attrs.va_gid = u.u_cred->cr_gid;
3476 code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
3486 * Read a symbolic link into the buffer
3495 retval = uafs_readlink_r(path, buf, len);
3500 int uafs_readlink_r(
3506 struct usr_vnode *vp;
3508 struct iovec iov[1];
3510 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0);
3516 if (vp->v_type != VLNK) {
3523 * set up the uio buffer
3525 iov[0].iov_base = buf;
3526 iov[0].iov_len = len;
3527 uio.uio_iov = &iov[0];
3531 uio.uio_fmode = FREAD;
3532 uio.uio_resid = len;
3537 code = afs_readlink(vp, &uio, u.u_cred);
3545 * return the number of bytes read
3547 return (len - uio.uio_resid);
3551 * Remove a file (or directory)
3552 * Note: file name may not end in a slash.
3559 retval = uafs_unlink_r(path);
3569 struct usr_vnode *fileP;
3570 struct usr_vnode *dirP;
3573 if (uafs_IsRoot(path)) {
3578 * Look up the parent directory.
3580 nameP = uafs_LastPath(path);
3581 if (nameP != NULL) {
3582 code = uafs_LookupParent(path, &dirP);
3588 dirP = afs_CurrentDir;
3594 * Make sure the filename has at least one character
3596 if (*nameP == '\0') {
3605 code = afs_remove(dirP, nameP, u.u_cred);
3616 * Rename a file (or directory)
3624 retval = uafs_rename_r(old, new);
3636 struct usr_vnode *odirP;
3637 struct usr_vnode *ndirP;
3639 if (uafs_IsRoot(new)) {
3644 * Look up the parent directories.
3646 onameP = uafs_LastPath(old);
3647 if (onameP != NULL) {
3648 code = uafs_LookupParent(old, &odirP);
3654 odirP = afs_CurrentDir;
3658 nnameP = uafs_LastPath(new);
3659 if (nnameP != NULL) {
3660 code = uafs_LookupParent(new, &ndirP);
3666 ndirP = afs_CurrentDir;
3672 * Make sure the filename has at least one character
3674 if (*onameP == '\0' || *nnameP == '\0') {
3684 code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
3696 * Remove a or directory
3697 * Note: file name may not end in a slash.
3704 retval = uafs_rmdir_r(path);
3714 struct usr_vnode *fileP;
3715 struct usr_vnode *dirP;
3718 if (uafs_IsRoot(path)) {
3723 * Look up the parent directory.
3725 nameP = uafs_LastPath(path);
3726 if (nameP != NULL) {
3727 code = uafs_LookupParent(path, &dirP);
3733 dirP = afs_CurrentDir;
3739 * Make sure the directory name has at least one character
3741 if (*nameP == '\0') {
3748 * Remove the directory
3750 code = afs_rmdir(dirP, nameP, u.u_cred);
3761 * Flush a file from the AFS cache
3767 struct afs_ioctl iob;
3774 code = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6),
3783 int uafs_FlushFile_r(
3788 retval = uafs_FlushFile(path);
3796 usr_DIR *uafs_opendir(
3801 retval = uafs_opendir_r(path);
3806 usr_DIR *uafs_opendir_r(
3813 * Open the directory for reading
3815 fd = uafs_open_r(path, O_RDONLY, 0);
3821 * Set up the directory structures
3823 dirp = (usr_DIR *)afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3824 sizeof(struct usr_dirent));
3825 usr_assert(dirp != NULL);
3826 dirp->dd_buf = (char *)(dirp+1);
3836 * Read directory entries into a file system independent format.
3837 * This routine was developed to support AFS cache consistency testing.
3838 * You should use uafs_readdir instead.
3842 struct min_direct *buf,
3847 retval = uafs_getdents_r(fd, buf, len);
3852 int uafs_getdents_r(
3854 struct min_direct *buf,
3859 struct usr_vnode *vp;
3860 struct iovec iov[1];
3863 * Make sure this is an open file
3865 vp = afs_FileTable[fd];
3873 * set up the uio buffer
3875 iov[0].iov_base = (char *)buf;
3876 iov[0].iov_len = len;
3877 uio.uio_iov = &iov[0];
3879 uio.uio_offset = afs_FileOffsets[fd];
3881 uio.uio_fmode = FREAD;
3882 uio.uio_resid = len;
3885 * read the next chunk from the directory
3887 code = afs_readdir(vp, &uio, u.u_cred);
3893 afs_FileOffsets[fd] = uio.uio_offset;
3894 return(len - uio.uio_resid);
3898 * read from a directory (names only)
3900 struct usr_dirent *uafs_readdir(
3903 struct usr_dirent *retval;
3905 retval = uafs_readdir_r(dirp);
3910 struct usr_dirent *uafs_readdir_r(
3917 struct usr_vnode *vp;
3918 struct iovec iov[1];
3919 struct usr_dirent *direntP;
3920 struct min_direct *directP;
3923 * Make sure this is an open file
3925 vp = afs_FileTable[dirp->dd_fd];
3932 * If there are no entries in the stream buffer
3933 * then read another chunk
3935 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3936 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3938 * set up the uio buffer
3940 iov[0].iov_base = dirp->dd_buf;
3941 iov[0].iov_len = USR_DIRSIZE;
3942 uio.uio_iov = &iov[0];
3944 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3946 uio.uio_fmode = FREAD;
3947 uio.uio_resid = USR_DIRSIZE;
3950 * read the next chunk from the directory
3952 code = afs_readdir(vp, &uio, u.u_cred);
3957 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3959 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3961 directP = (struct min_direct *)(dirp->dd_buf+dirp->dd_loc);
3965 * Check for end of file
3967 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3971 len = ((sizeof(struct min_direct)+directP->d_namlen+4) & (~3));
3972 usr_assert(len <= dirp->dd_size);
3975 * Copy the next entry into the usr_dirent structure and advance
3977 direntP = (struct usr_dirent *)(dirp->dd_buf+USR_DIRSIZE);
3978 direntP->d_ino = directP->d_fileno;
3979 direntP->d_off = direntP->d_reclen;
3980 direntP->d_reclen = sizeof(struct usr_dirent) - MAXNAMLEN +
3981 directP->d_namlen + 1;
3982 memcpy(&direntP->d_name[0], (void *)(directP+1), directP->d_namlen);
3983 direntP->d_name[directP->d_namlen] = '\0';
3984 dirp->dd_loc += len;
3985 dirp->dd_size -= len;
3998 retval = uafs_closedir_r(dirp);
4003 int uafs_closedir_r(
4010 afs_osi_Free((char *)dirp,
4011 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4012 rc = uafs_close_r(fd);
4017 * Do AFS authentication
4026 afs_int32 password_expires = -1;
4028 usr_mutex_lock(&osi_authenticate_lock);
4029 code = ka_UserAuthenticateGeneral(
4030 KA_USERAUTH_VERSION+KA_USERAUTH_DOSETPAG2, user,
4031 NULL, cell, passwd, 0, &password_expires,
4033 usr_mutex_unlock(&osi_authenticate_lock);
4045 retval = uafs_klog(user, cell, passwd, reason);
4051 * Destroy AFS credentials from the kernel cache
4057 usr_mutex_lock(&osi_authenticate_lock);
4058 code = ktc_ForgetAllTokens();
4059 usr_mutex_unlock(&osi_authenticate_lock);
4067 retval = uafs_unlog();
4073 * Strip the AFS mount point from a pathname string. Return
4074 * NULL if the path is a relative pathname or if the path
4075 * doesn't start with the AFS mount point string.
4077 char *uafs_afsPathName(char *path)
4086 for (i = 1, p = path+1; *p != '\0' ; p++) {
4087 /* Ignore duplicate slashes */
4088 if (*p == '/' && lastchar == '/')
4090 /* Is this a subdirectory of the AFS mount point? */
4091 if (afs_mountDir[i] == '\0' && *p == '/') {
4092 /* strip leading slashes */
4093 while (*(++p) == '/');
4096 /* Reject paths that are not within AFS */
4097 if (*p != afs_mountDir[i])
4102 /* Is this the AFS mount point? */
4103 if (afs_mountDir[i] == '\0') {
4104 usr_assert(*p == '\0');
4110 #endif /* UKERNEL */