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"
23 #include "afs/sysincludes.h" /* Standard vendor system headers */
25 #include "afsincludes.h" /* Afs-based standard headers */
26 #include "afs_usrops.h"
27 #include "afs/afs_stats.h"
29 #include "afs/cellconfig.h"
31 #include "afs/kautils.h"
32 #include "afs/afsutil.h"
33 #include "rx/rx_globals.h"
39 #define CACHEINFOFILE "cacheinfo"
40 #define AFSLOGFILE "AFSLog"
41 #define DCACHEFILE "CacheItems"
42 #define VOLINFOFILE "VolumeItems"
43 #define CELLINFOFILE "CellItems"
47 #define MIN(A,B) ((A)<(B)?(A):(B))
50 #define MAX(A,B) ((A)>(B)?(A):(B))
53 extern int cacheDiskType;
55 char afs_LclCellName[64];
57 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
58 int afs_FileFlags[MAX_OSI_FILES];
59 int afs_FileOffsets[MAX_OSI_FILES];
61 #define MAX_CACHE_LOOPS 4
63 struct usr_vfs afs_RootVfs;
64 struct usr_vnode *afs_RootVnode = NULL;
65 struct usr_vnode *afs_CurrentDir = NULL;
67 afs_int32 cacheBlocks; /* Num blocks in cache */
68 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
69 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
70 char cacheBaseDir[1024]; /* AFS cache directory */
71 char confDir[1024]; /* AFS configuration directory */
72 char afs_mountDir[1024]; /* AFS mount point */
73 int afs_mountDirLen; /* strlen of AFS mount point */
74 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
75 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
76 char fullpn_CellInfoFile[1024]; /* Full pathname of CELLINFOFILE */
77 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
78 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
79 char fullpn_VFile[1024]; /* Full pathname of data cache files */
80 char *vFileNumber; /* Ptr to number in file pathname */
81 char rootVolume[64] = "root.afs"; /* AFS root volume name */
82 afs_int32 isHomeCell; /* Is current cell info for home cell */
83 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
84 int ownerRWmode = 0600; /* Read/write OK by owner */
85 static int nDaemons = 2; /* Number of background daemons */
86 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
87 static int dCacheSize = 300; /* # of dcache entries */
88 static int vCacheSize = 50; /* # of volume cache entries */
89 static int cacheFlags = 0; /* Flags to cache manager */
90 static int preallocs = 400; /* Def # of allocated memory blocks */
91 int afsd_verbose = 0; /* Are we being chatty? */
92 int afsd_debug = 0; /* Are we printing debugging info? */
93 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
95 #define AFSD_INO_T afs_uint32
96 char **pathname_for_V; /* Array of cache file pathnames */
97 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
98 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
99 int missing_CellInfoFile = 1;
100 struct afs_cacheParams cparams; /* params passed to cache manager */
101 struct afsconf_dir *afs_cdir; /* config dir */
103 static int HandleMTab();
105 int afs_bufferpages = 100;
106 int usr_udpcksum = 0;
108 usr_key_t afs_global_u_key;
110 struct usr_proc *afs_global_procp;
111 struct usr_ucred *afs_global_ucredp;
112 struct usr_sysent usr_sysent[200];
114 #ifdef AFS_USR_OSF_ENV
116 #else /* AFS_USR_OSF_ENV */
118 #endif /* AFS_USR_OSF_ENV */
120 struct usr_ucred afs_osi_cred, *afs_osi_credp;
121 usr_mutex_t afs_global_lock;
122 usr_thread_t afs_global_owner;
123 usr_mutex_t rx_global_lock;
124 usr_thread_t rx_global_owner;
125 usr_mutex_t osi_inode_lock;
126 usr_mutex_t osi_waitq_lock;
127 usr_mutex_t osi_authenticate_lock;
129 afs_lock_t osi_flplock;
130 afs_lock_t osi_fsplock;
133 #ifndef NETSCAPE_NSAPI
136 * Mutex and condition variable used to implement sleep
138 pthread_mutex_t usr_sleep_mutex;
139 pthread_cond_t usr_sleep_cond;
141 #endif /* !NETSCAPE_NSAPI */
143 int call_syscall(long, long, long, long, long, long);
147 * Hash table mapping addresses onto wait structures for
148 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
150 typedef struct osi_wait {
154 struct osi_wait *next;
155 struct osi_wait *prev;
157 struct osi_wait *timedNext;
158 struct osi_wait *timedPrev;
162 * Head of the linked list of available waitq structures.
164 osi_wait_t *osi_waithash_avail;
167 * List of timed waits, NSAPI does not provide a cond_timed
168 * wait, so we need to keep track of the timed waits ourselves and
169 * periodically check for expirations
171 osi_wait_t *osi_timedwait_head;
172 osi_wait_t *osi_timedwait_tail;
177 } osi_waithash_table[OSI_WAITHASH_SIZE];
180 * Never call afs_brelse
183 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
189 * I am not sure what to do with these, they assert for now
192 iodone(struct usr_buf *bp)
204 * Every user is a super user
207 afs_osi_suser(void *credp)
213 afs_suser(void *credp)
219 * These are no-ops in user space
223 afs_osi_SetTime(osi_timeval_t * atv)
229 * xflock should never fall through, the only files we know
230 * about are AFS files
239 * ioctl should never fall through, the only files we know
240 * about are AFS files
249 * We do not support the inode related system calls
252 afs_syscall_icreate(void)
258 afs_syscall_iincdec(void)
264 afs_syscall_iopen(void)
270 afs_syscall_ireadwrite(void)
276 * these routines are referenced in the vfsops structure, but
277 * should never get called
304 * uiomove copies data between kernel buffers and uio buffers
307 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
314 nio = uio->uio_iovcnt;
324 while (nio > 0 && n > 0) {
325 len = MIN(n, iovp->iov_len);
326 if (rw == UIO_READ) {
327 memcpy(iovp->iov_base, ptr, len);
329 memcpy(ptr, iovp->iov_base, len);
333 uio->uio_resid -= len;
334 uio->uio_offset += len;
335 iovp->iov_base = (char *)(iovp->iov_base) + len;
336 iovp->iov_len -= len;
347 * routines to manage user credentials
350 usr_crcopy(struct usr_ucred *credp)
352 struct usr_ucred *newcredp;
354 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
356 newcredp->cr_ref = 1;
363 struct usr_ucred *newcredp;
365 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
366 newcredp->cr_ref = 1;
371 usr_crfree(struct usr_ucred *credp)
374 if (credp->cr_ref == 0) {
375 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
380 usr_crhold(struct usr_ucred *credp)
386 usr_vattr_null(struct usr_vattr *vap)
391 n = sizeof(struct usr_vattr);
399 * Initialize the thread specific data used to simulate the
400 * kernel environment for each thread. The user structure
401 * is stored in the thread specific data.
404 uafs_InitThread(void)
407 struct usr_user *uptr;
410 * initialize the thread specific user structure. Use malloc to
411 * allocate the data block, so pthread_finish can free the buffer
412 * when this thread terminates.
415 (struct usr_user *)malloc(sizeof(struct usr_user) +
416 sizeof(struct usr_ucred));
417 usr_assert(uptr != NULL);
420 uptr->u_procp = afs_global_procp;
421 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
422 *uptr->u_cred = *afs_global_ucredp;
423 st = usr_setspecific(afs_global_u_key, (void *)uptr);
428 * routine to get the user structure from the thread specific data.
429 * this routine is used to implement the global 'u' structure. Initializes
430 * the thread if needed.
433 get_user_struct(void)
435 struct usr_user *uptr;
437 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
441 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
443 usr_assert(uptr != NULL);
449 * Hash an address for the waithash table
451 #define WAITHASH(X) \
452 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
458 afs_osi_Sleep(void *x)
462 int glockOwner = ISAFS_GLOCK();
464 usr_mutex_lock(&osi_waitq_lock);
469 if (osi_waithash_avail == NULL) {
470 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
471 usr_cond_init(&waitp->cond);
473 waitp = osi_waithash_avail;
474 osi_waithash_avail = osi_waithash_avail->next;
478 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
479 osi_waithash_table[index].tail, next, prev);
480 waitp->expiration = 0;
481 waitp->timedNext = NULL;
482 waitp->timedPrev = NULL;
483 while (waitp->flag == 0) {
484 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
486 DLL_DELETE(waitp, osi_waithash_table[index].head,
487 osi_waithash_table[index].tail, next, prev);
488 waitp->next = osi_waithash_avail;
489 osi_waithash_avail = waitp;
490 usr_mutex_unlock(&osi_waitq_lock);
497 afs_osi_SleepSig(void *x)
504 afs_osi_Wakeup(void *x)
510 usr_mutex_lock(&osi_waitq_lock);
511 waitp = osi_waithash_table[index].head;
513 if (waitp->addr == x && waitp->flag == 0) {
515 usr_cond_signal(&waitp->cond);
519 usr_mutex_unlock(&osi_waitq_lock);
523 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
529 int glockOwner = ISAFS_GLOCK();
531 tv.tv_sec = msec / 1000;
532 tv.tv_nsec = (msec % 1000) * 1000000;
533 if (handle == NULL) {
537 usr_thread_sleep(&tv);
543 usr_mutex_lock(&osi_waitq_lock);
547 index = WAITHASH((caddr_t) handle);
548 if (osi_waithash_avail == NULL) {
549 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
550 usr_cond_init(&waitp->cond);
552 waitp = osi_waithash_avail;
553 osi_waithash_avail = osi_waithash_avail->next;
555 waitp->addr = (caddr_t) handle;
557 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
558 osi_waithash_table[index].tail, next, prev);
559 tv.tv_sec += time(NULL);
560 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
561 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
562 timedNext, timedPrev);
563 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
569 DLL_DELETE(waitp, osi_waithash_table[index].head,
570 osi_waithash_table[index].tail, next, prev);
571 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
573 waitp->next = osi_waithash_avail;
574 osi_waithash_avail = waitp;
575 usr_mutex_unlock(&osi_waitq_lock);
584 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
586 afs_osi_Wakeup(handle);
590 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
591 * to explicitly signal cond_timed_waits when their timers expire
594 afs_osi_CheckTimedWaits(void)
599 curTime = time(NULL);
600 usr_mutex_lock(&osi_waitq_lock);
601 waitp = osi_timedwait_head;
602 while (waitp != NULL) {
603 usr_assert(waitp->expiration != 0);
604 if (waitp->expiration <= curTime) {
606 usr_cond_signal(&waitp->cond);
608 waitp = waitp->timedNext;
610 usr_mutex_unlock(&osi_waitq_lock);
614 * I-node numbers are indeces into a table containing a filename
615 * i-node structure and a vnode structure. When we create an i-node,
616 * we copy the name into the array and initialize enough of the fields
617 * in the inode and vnode structures to get the client to work.
620 struct usr_inode i_node;
623 osi_file_table_t *osi_file_table;
625 int max_osi_files = 0;
628 * Allocate a slot in the file table if there is not one there already,
629 * copy in the file name and kludge up the vnode and inode structures
632 lookupname(char *fnamep, int segflg, int followlink,
633 struct usr_vnode **compvpp)
637 struct usr_inode *ip;
638 struct usr_vnode *vp;
640 /*usr_assert(followlink == 0); */
643 * Assume relative pathnames refer to files in AFS
645 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
647 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
652 usr_mutex_lock(&osi_inode_lock);
654 for (i = 0; i < n_osi_files; i++) {
655 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
656 *compvpp = &osi_file_table[i].i_node.i_vnode;
657 (*compvpp)->v_count++;
658 usr_mutex_unlock(&osi_inode_lock);
663 if (n_osi_files == max_osi_files) {
664 usr_mutex_unlock(&osi_inode_lock);
668 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep) + 1);
669 usr_assert(osi_file_table[n_osi_files].name != NULL);
670 strcpy(osi_file_table[n_osi_files].name, fnamep);
671 ip = &osi_file_table[i].i_node;
673 vp->v_data = (caddr_t) ip;
676 ip->i_number = n_osi_files;
678 usr_mutex_unlock(&osi_inode_lock);
684 * open a file given its i-node number
687 osi_UFSOpen(afs_int32 ino)
695 if (ino > n_osi_files) {
701 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
702 usr_assert(fp != NULL);
703 fp->fd = open(osi_file_table[ino - 1].name, O_RDWR | O_CREAT, 0);
706 afs_osi_Free((char *)fp, sizeof(struct osi_file));
710 rc = fstat(fp->fd, &st);
713 afs_osi_Free((void *)fp, sizeof(struct osi_file));
717 fp->size = st.st_size;
720 fp->vnode = (struct usr_vnode *)fp;
727 osi_UFSClose(struct osi_file *fp)
737 afs_osi_Free((void *)fp, sizeof(struct osi_file));
741 afs_osi_Free((void *)fp, sizeof(struct osi_file));
747 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
754 rc = ftruncate(fp->fd, len);
766 afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
776 rc = lseek(fp->fd, offset, SEEK_SET);
778 rc = lseek(fp->fd, fp->offset, SEEK_SET);
786 ret = read(fp->fd, buf, len);
793 rc = fstat(fp->fd, &st);
799 fp->size = st.st_size;
805 afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
815 rc = lseek(fp->fd, offset, SEEK_SET);
817 rc = lseek(fp->fd, fp->offset, SEEK_SET);
825 ret = write(fp->fd, buf, len);
832 rc = fstat(fp->fd, &st);
838 fp->size = st.st_size;
844 afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
850 rc = fstat(fp->fd, &st);
856 stp->size = st.st_size;
857 stp->mtime = st.st_mtime;
858 stp->atime = st.st_atime;
867 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
868 int flags, struct usr_ucred *credP)
871 struct osi_file *fp = (struct osi_file *)vnodeP;
874 * We don't support readv/writev.
876 usr_assert(uioP->uio_iovcnt == 1);
877 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
879 if (rw == UIO_WRITE) {
880 usr_assert(uioP->uio_fmode == FWRITE);
881 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
882 uioP->uio_iov[0].iov_len);
884 usr_assert(uioP->uio_fmode == FREAD);
885 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
886 uioP->uio_iov[0].iov_len);
892 uioP->uio_resid -= rc;
893 uioP->uio_offset += rc;
894 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
895 uioP->uio_iov[0].iov_len -= rc;
900 * Use malloc/free routines with check patterns before and after each block
903 static char *afs_check_string1 = "UAFS";
904 static char *afs_check_string2 = "AFS_OSI_";
907 afs_osi_Alloc(size_t size)
913 afs_osi_Free(void *ptr, size_t size)
919 afs_osi_FreeStr(char *ptr)
925 osi_AllocLargeSpace(size_t size)
927 AFS_STATCNT(osi_AllocLargeSpace);
928 return afs_osi_Alloc(size);
932 osi_FreeLargeSpace(void *ptr)
934 AFS_STATCNT(osi_FreeLargeSpace);
935 afs_osi_Free(ptr, 0);
939 osi_AllocSmallSpace(size_t size)
941 AFS_STATCNT(osi_AllocSmallSpace);
942 return afs_osi_Alloc(size);
946 osi_FreeSmallSpace(void *ptr)
948 AFS_STATCNT(osi_FreeSmallSpace);
949 afs_osi_Free(ptr, 0);
955 AFS_STATCNT(shutdown_osi);
960 shutdown_osinet(void)
962 AFS_STATCNT(shutdown_osinet);
967 shutdown_osifile(void)
969 AFS_STATCNT(shutdown_osifile);
974 afs_nfsclient_init(void)
979 shutdown_nfsclnt(void)
985 afs_osi_Invisible(void)
991 osi_GetTime(struct timeval *tv)
993 gettimeofday(tv, NULL);
998 osi_SetTime(struct timeval *tv)
1004 osi_Active(struct vcache *avc)
1006 AFS_STATCNT(osi_Active);
1013 afs_osi_MapStrategy(int (*aproc) (), struct usr_buf *bp)
1015 afs_int32 returnCode;
1016 returnCode = (*aproc) (bp);
1021 osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
1023 ObtainSharedLock(&avc->lock, 555);
1024 if ((hcmp((avc->m.DataVersion), (avc->mapDV)) <= 0)
1025 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1026 ReleaseSharedLock(&avc->lock);
1029 UpgradeSToWLock(&avc->lock, 565);
1030 hset(avc->mapDV, avc->m.DataVersion);
1031 ReleaseWriteLock(&avc->lock);
1036 osi_FlushText_really(register struct vcache *vp)
1038 if (hcmp(vp->m.DataVersion, vp->flushDV) > 0) {
1039 hset(vp->flushDV, vp->m.DataVersion);
1045 osi_SyncVM(struct vcache *avc)
1051 osi_ReleaseVM(struct vcache *avc, int len, 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;
1109 afs_osi_credp = &afs_osi_cred;
1112 /* ParseArgs is now obsolete, being handled by cmd */
1114 /*---------------------------------------------------------------------
1118 * Given the final component of a filename expected to be a data cache file,
1119 * return the integer corresponding to the file. Note: we reject names that
1120 * are not a ``V'' followed by an integer. We also reject those names having
1121 * the right format but lying outside the range [0..cacheFiles-1].
1124 * fname : Char ptr to the filename to parse.
1127 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1131 * Nothing interesting.
1135 *------------------------------------------------------------------------*/
1138 GetVFileNumber(char *fname)
1140 int computedVNumber; /*The computed file number we return */
1141 int filenameLen; /*Number of chars in filename */
1142 int currDigit; /*Current digit being processed */
1145 * The filename must have at least two characters, the first of which must be a ``V''
1146 * and the second of which cannot be a zero unless the file is exactly two chars long.
1148 filenameLen = strlen(fname);
1149 if (filenameLen < 2)
1151 if (fname[0] != 'V')
1153 if ((filenameLen > 2) && (fname[1] == '0'))
1157 * Scan through the characters in the given filename, failing immediately if a non-digit
1160 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1161 if (isdigit(fname[currDigit]) == 0)
1165 * All relevant characters are digits. Pull out the decimal number they represent.
1166 * Reject it if it's out of range, otherwise return it.
1168 computedVNumber = atoi(++fname);
1169 if (computedVNumber < cacheFiles)
1170 return (computedVNumber);
1175 /*---------------------------------------------------------------------
1179 * Given a full pathname for a file we need to create for the workstation AFS
1180 * cache, go ahead and create the file.
1183 * fname : Full pathname of file to create.
1186 * 0 iff the file was created,
1190 * The given cache file has been found to be missing.
1194 *------------------------------------------------------------------------*/
1197 CreateCacheFile(char *fname)
1199 static char rn[] = "CreateCacheFile"; /*Routine name */
1200 int cfd; /*File descriptor to AFS cache file */
1201 int closeResult; /*Result of close() */
1204 printf("%s: Creating cache file '%s'\n", rn, fname);
1205 cfd = open(fname, createAndTrunc, ownerRWmode);
1207 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
1211 closeResult = close(cfd);
1214 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1222 /*---------------------------------------------------------------------
1226 * Sweep through the AFS cache directory, recording the inode number for
1227 * each valid data cache file there. Also, delete any file that doesn't beint32
1228 * in the cache directory during this sweep, and remember which of the other
1229 * residents of this directory were seen. After the sweep, we create any data
1230 * cache files that were missing.
1233 * vFilesFound : Set to the number of data cache files found.
1236 * 0 if everything went well,
1240 * This routine may be called several times. If the number of data cache files
1241 * found is less than the global cacheFiles, then the caller will need to call it
1242 * again to record the inodes of the missing zero-length data cache files created
1243 * in the previous call.
1246 * Fills up the global pathname_for_V array, may create and/or
1247 * delete files as explained above.
1248 *------------------------------------------------------------------------*/
1251 SweepAFSCache(int *vFilesFound)
1253 static char rn[] = "SweepAFSCache"; /*Routine name */
1254 char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
1255 char *fileToDelete; /*Ptr to last component of above */
1256 DIR *cdirp; /*Ptr to cache directory structure */
1258 struct dirent *currp; /*Current directory entry */
1259 int vFileNum; /*Data cache file's associated number */
1261 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1263 printf("%s: Memory Cache, no cache sweep done\n", rn);
1269 printf("%s: Opening cache directory '%s'\n", rn, cacheBaseDir);
1271 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1272 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
1276 cdirp = opendir(cacheBaseDir);
1277 if (cdirp == (DIR *) 0) {
1278 printf("%s: Can't open AFS cache directory, '%s'.\n", rn,
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)) {
1293 printf("%s: Current directory entry:\n", rn);
1294 printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
1295 currp->d_reclen, currp->d_name);
1299 * Guess current entry is for a data cache file.
1301 vFileNum = GetVFileNumber(currp->d_name);
1302 if (vFileNum >= 0) {
1304 * Found a valid data cache filename. Remember this file's name
1305 * and bump the number of files found.
1307 pathname_for_V[vFileNum] =
1308 afs_osi_Alloc(strlen(currp->d_name) + strlen(cacheBaseDir) +
1310 usr_assert(pathname_for_V[vFileNum] != NULL);
1311 sprintf(pathname_for_V[vFileNum], "%s/%s", cacheBaseDir,
1314 } else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1316 * Found the file holding the dcache entries.
1318 missing_DCacheFile = 0;
1319 } else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1321 * Found the file holding the volume info.
1323 missing_VolInfoFile = 0;
1324 } else if (strcmp(currp->d_name, CELLINFOFILE) == 0) {
1325 missing_CellInfoFile = 0;
1326 } else if ((strcmp(currp->d_name, ".") == 0)
1327 || (strcmp(currp->d_name, "..") == 0)
1328 || (strcmp(currp->d_name, "lost+found") == 0)) {
1330 * Don't do anything - this file is legit, and is to be left alone.
1334 * This file doesn't belong in the cache. Nuke it.
1336 sprintf(fileToDelete, "%s", currp->d_name);
1338 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
1339 if (unlink(fullpn_FileToDelete)) {
1340 printf("%s: Can't unlink '%s', errno is %d\n", rn,
1341 fullpn_FileToDelete, errno);
1347 * Create all the cache files that are missing.
1349 if (missing_DCacheFile) {
1351 printf("%s: Creating '%s'\n", rn, fullpn_DCacheFile);
1352 if (CreateCacheFile(fullpn_DCacheFile))
1353 printf("%s: Can't create '%s'\n", rn, fullpn_DCacheFile);
1355 if (missing_VolInfoFile) {
1357 printf("%s: Creating '%s'\n", rn, fullpn_VolInfoFile);
1358 if (CreateCacheFile(fullpn_VolInfoFile))
1359 printf("%s: Can't create '%s'\n", rn, fullpn_VolInfoFile);
1361 if (missing_CellInfoFile) {
1363 printf("%s: Creating '%s'\n", rn, fullpn_CellInfoFile);
1364 if (CreateCacheFile(fullpn_CellInfoFile))
1365 printf("%s: Can't create '%s'\n", rn, fullpn_CellInfoFile);
1368 if (*vFilesFound < cacheFiles) {
1370 * We came up short on the number of data cache files found. Scan through the inode
1371 * list and create all missing files.
1373 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1374 if (pathname_for_V[vFileNum] == (AFSD_INO_T) 0) {
1375 sprintf(vFileNumber, "%d", vFileNum);
1377 printf("%s: Creating '%s'\n", rn, fullpn_VFile);
1378 if (CreateCacheFile(fullpn_VFile))
1379 printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
1384 * Close the directory, return success.
1387 printf("%s: Closing cache directory.\n", rn);
1393 ConfigCell(register struct afsconf_cell *aci, char *arock,
1394 struct afsconf_dir *adir)
1396 register int isHomeCell;
1398 afs_int32 cellFlags = 0;
1399 afs_int32 hosts[MAXHOSTSPERCELL];
1401 /* figure out if this is the home cell */
1402 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1404 cellFlags = 2; /* not home, suid is forbidden */
1406 /* build address list */
1407 for (i = 0; i < MAXHOSTSPERCELL; i++)
1408 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1410 if (aci->linkedCell)
1411 cellFlags |= 4; /* Flag that linkedCell arg exists,
1412 * for upwards compatibility */
1414 /* configure one cell */
1415 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2, (long)hosts, /* server addresses */
1416 (long)aci->name, /* cell name */
1417 (long)cellFlags, /* is this the home cell? */
1418 (long)aci->linkedCell); /* Linked cell, if any */
1423 ConfigCellAlias(aca, arock, adir)
1424 struct afsconf_cellalias *aca;
1426 struct afsconf_dir *adir;
1428 call_syscall(AFSOP_ADDCELLALIAS, (long)aca->aliasName,
1429 (long)aca->realName, 0, 0, 0);
1434 * Set the UDP port number RX uses for UDP datagrams
1437 uafs_SetRxPort(int port)
1439 usr_assert(usr_rx_port == 0);
1445 * Initialize the user space client.
1448 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1449 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1450 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1451 int chunkSizeParam, int closeSynchParam, int debugParam,
1452 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1455 struct usr_proc *procp;
1456 struct usr_ucred *ucredp;
1459 int currVFile; /* Current AFS cache file number */
1460 int lookupResult; /* Result of GetLocalCellName() */
1461 int cacheIteration; /* cache verification loop counter */
1462 int vFilesFound; /* Num data cache files found in sweep */
1464 afs_int32 vfs1_type = -1;
1465 struct afs_ioctl iob;
1469 afs_int32 buffer[MAXIPADDRS];
1470 afs_int32 maskbuffer[MAXIPADDRS];
1471 afs_int32 mtubuffer[MAXIPADDRS];
1474 * Use the thread specific data to implement the user structure
1476 usr_keycreate(&afs_global_u_key, free);
1479 * Initialize the global ucred structure
1481 afs_global_ucredp = (struct usr_ucred *)
1482 afs_osi_Alloc(sizeof(struct usr_ucred));
1483 usr_assert(afs_global_ucredp != NULL);
1484 afs_global_ucredp->cr_ref = 1;
1485 afs_global_ucredp->cr_uid = geteuid();
1486 afs_global_ucredp->cr_gid = getegid();
1487 afs_global_ucredp->cr_ruid = getuid();
1488 afs_global_ucredp->cr_rgid = getgid();
1489 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1490 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1491 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1492 usr_assert(st >= 0);
1493 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1494 for (i = st; i < NGROUPS; i++) {
1495 afs_global_ucredp->cr_groups[i] = NOGROUP;
1499 * Initialize the global process structure
1501 afs_global_procp = (struct usr_proc *)
1502 afs_osi_Alloc(sizeof(struct usr_proc));
1503 usr_assert(afs_global_procp != NULL);
1504 afs_global_procp->p_pid = getpid();
1505 afs_global_procp->p_ppid = (pid_t) 1;
1506 afs_global_procp->p_ucred = afs_global_ucredp;
1509 * Initialize the AFS mount point, default is '/afs'.
1510 * Strip duplicate/trailing slashes from mount point string.
1511 * afs_mountDirLen is set to strlen(afs_mountDir).
1513 if (mountDirParam) {
1514 sprintf(tbuffer, "%s", mountDirParam);
1516 sprintf(tbuffer, "afs");
1518 afs_mountDir[0] = '/';
1519 afs_mountDirLen = 1;
1520 for (lastchar = '/', p = &tbuffer[0]; *p != '\0'; p++) {
1521 if (lastchar != '/' || *p != '/') {
1522 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1525 if (lastchar == '/' && afs_mountDirLen > 1)
1527 afs_mountDir[afs_mountDirLen] = '\0';
1528 usr_assert(afs_mountDirLen > 1);
1531 * Initialize cache parameters using the input arguments
1534 cacheBlocks = cacheBlocksParam;
1535 if (cacheFilesParam != 0) {
1536 cacheFiles = cacheFilesParam;
1538 cacheFiles = cacheBlocks / 10;
1540 if (cacheStatEntriesParam != 0) {
1541 cacheStatEntries = cacheStatEntriesParam;
1543 strcpy(cacheBaseDir, cacheBaseDirParam);
1544 if (nDaemons != 0) {
1545 nDaemons = nDaemonsParam;
1549 afsd_verbose = debugParam;
1550 afsd_debug = debugParam;
1551 chunkSize = chunkSizeParam;
1552 if (dCacheSizeParam != 0) {
1553 dCacheSize = dCacheSizeParam;
1555 dCacheSize = cacheFiles / 2;
1557 if (vCacheSizeParam != 0) {
1558 vCacheSize = vCacheSizeParam;
1560 strcpy(confDir, confDirParam);
1561 afsd_CloseSynch = closeSynchParam;
1562 if (cacheFlagsParam >= 0) {
1563 cacheFlags = cacheFlagsParam;
1565 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1566 cacheFiles = dCacheSize;
1569 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1570 if (logFile == NULL) {
1571 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1573 strcpy(fullpn_AFSLogFile, logFile);
1576 printf("\n%s: Initializing user space AFS client\n\n", rn);
1577 printf(" mountDir: %s\n", afs_mountDir);
1578 printf(" confDir: %s\n", confDir);
1579 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1580 printf(" cacheBlocks: %d\n", cacheBlocks);
1581 printf(" cacheFiles: %d\n", cacheFiles);
1582 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1583 printf(" dCacheSize: %d\n", dCacheSize);
1584 printf(" vCacheSize: %d\n", vCacheSize);
1585 printf(" chunkSize: %d\n", chunkSize);
1586 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1587 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1588 printf(" nDaemons: %d\n", nDaemons);
1589 printf(" cacheFlags: %d\n", cacheFlags);
1590 printf(" logFile: %s\n", fullpn_AFSLogFile);
1595 * Initialize the AFS client
1600 * Pull out all the configuration info for the workstation's AFS cache and
1601 * the cellular community we're willing to let our users see.
1603 afs_cdir = afsconf_Open(confDir);
1605 printf("afsd: some file missing or bad in %s\n", confDir);
1610 afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1611 sizeof(afs_LclCellName));
1613 printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
1617 printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
1621 * Set the primary cell name.
1623 call_syscall(AFSOP_SET_THISCELL, (long)afs_LclCellName, 0, 0, 0, 0);
1625 if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
1627 printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1628 if (CreateCacheFile(fullpn_AFSLogFile)) {
1630 ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
1631 rn, fullpn_AFSLogFile);
1638 * Create and zero the pathname table for the desired cache files.
1640 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1641 if (pathname_for_V == NULL) {
1642 printf("%s: malloc() failed for cache file table with %d entries.\n",
1646 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1648 printf("%s: %d pathname_for_V entries at 0x%x, %d bytes\n", rn,
1649 cacheFiles, pathname_for_V, (cacheFiles * sizeof(AFSD_INO_T)));
1652 * Set up all the pathnames we'll need for later.
1654 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1655 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1656 sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
1657 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1658 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1661 * Start the RX listener.
1664 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1665 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE, FALSE, FALSE);
1668 * Start the RX event handler.
1671 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1672 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1675 * Set up all the kernel processes needed for AFS.
1678 /* initialize AFS callback interface */
1680 /* parse multihomed address files */
1682 st = parseNetFiles((afs_uint32*)buffer,(afs_uint32*) maskbuffer, (afs_uint32*)mtubuffer, MAXIPADDRS, reason,
1683 AFSDIR_CLIENT_NETINFO_FILEPATH,
1684 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1686 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st,
1687 (long)(&buffer[0]), (long)(&maskbuffer[0]),
1688 (long)(&mtubuffer[0]));
1690 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
1697 printf("%s: Forking rx callback listener.\n", rn);
1699 if (preallocs < cacheStatEntries + 50)
1700 preallocs = cacheStatEntries + 50;
1701 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1704 printf("%s: Initializing AFS daemon.\n", rn);
1705 call_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT, 1, 0, 0, 0);
1708 * Tell the kernel some basic information about the workstation's cache.
1711 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1712 " %d optimum cache files, %d blocks in the cache,"
1713 " flags = 0x%x, dcache entries %d\n", rn, cacheStatEntries,
1714 cacheFiles, cacheBlocks, cacheFlags, dCacheSize);
1715 memset(&cparams, 0, sizeof(cparams));
1716 cparams.cacheScaches = cacheStatEntries;
1717 cparams.cacheFiles = cacheFiles;
1718 cparams.cacheBlocks = cacheBlocks;
1719 cparams.cacheDcaches = dCacheSize;
1720 cparams.cacheVolumes = vCacheSize;
1721 cparams.chunkSize = chunkSize;
1722 cparams.setTimeFlag = FALSE;
1723 cparams.memCacheFlag = cacheFlags;
1724 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1725 if (afsd_CloseSynch)
1726 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1729 * Sweep the workstation AFS cache directory, remembering the inodes of
1730 * valid files and deleting extraneous files. Keep sweeping until we
1731 * have the right number of data cache files or we've swept too many
1735 printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
1737 /* Memory-cache based system doesn't need any of this */
1738 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1741 if (SweepAFSCache(&vFilesFound)) {
1742 printf("%s: Error on sweep %d of workstation AFS cache \
1743 directory.\n", rn, cacheIteration);
1748 ("%s: %d out of %d data cache files found in sweep %d.\n",
1749 rn, vFilesFound, cacheFiles, cacheIteration);
1750 } while ((vFilesFound < cacheFiles)
1751 && (cacheIteration < MAX_CACHE_LOOPS));
1752 } else if (afsd_verbose)
1753 printf("%s: Using memory cache, not swept\n", rn);
1756 * Pass the kernel the name of the workstation cache file holding the
1760 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
1762 /* once again, meaningless for a memory-based cache. */
1763 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1764 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1767 call_syscall(AFSCALL_CALL, AFSOP_CELLINFO, (long)fullpn_CellInfoFile, 0,
1771 * Pass the kernel the name of the workstation cache file holding the
1772 * volume information.
1775 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
1776 fullpn_VolInfoFile);
1777 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO, (long)fullpn_VolInfoFile, 0,
1781 * Pass the kernel the name of the afs logging file holding the volume
1785 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
1787 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1788 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG, (long)fullpn_AFSLogFile, 0,
1792 * Tell the kernel about each cell in the configuration.
1794 afsconf_CellApply(afs_cdir, ConfigCell, NULL);
1795 afsconf_CellAliasApply(afs_cdir, ConfigCellAlias, NULL);
1798 printf("%s: Forking AFS daemon.\n", rn);
1799 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1802 printf("%s: Forking check server daemon.\n", rn);
1803 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1806 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1807 for (i = 0; i < nDaemons; i++) {
1808 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1812 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn, rootVolume);
1813 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1816 * Give the kernel the names of the AFS files cached on the workstation's
1821 ("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1822 rn, cacheFiles, cacheBaseDir);
1823 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1824 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1825 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1826 (long)pathname_for_V[currVFile], 0, 0, 0);
1829 #ifndef NETSCAPE_NSAPI
1831 * Copy our tokens from the kernel to the user space client
1833 for (i = 0; i < 200; i++) {
1835 * Get the i'th token from the kernel
1837 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1838 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1840 iob.in_size = sizeof(int);
1842 iob.out_size = sizeof(tbuffer);
1844 #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)
1845 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1846 #elif defined(AFS_USR_SGI_ENV)
1847 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1848 #else /* AFS_USR_AIX_ENV */
1849 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1852 usr_assert(errno == EDOM || errno == ENOSYS);
1857 * Now pass the token into the user space kernel
1859 rc = uafs_SetTokens(tbuffer, iob.out_size);
1860 usr_assert(rc == 0);
1862 #endif /* !NETSCAPE_NSAPI */
1865 * All the necessary info has been passed into the kernel to run an AFS
1866 * system. Give the kernel our go-ahead.
1869 printf("%s: Calling AFSOP_GO\n", rn);
1870 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1873 * At this point, we have finished passing the kernel all the info
1874 * it needs to set up the AFS. Mount the AFS root.
1876 printf("%s: All AFS daemons started.\n", rn);
1879 printf("%s: Forking trunc-cache daemon.\n", rn);
1880 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1883 * Mount the AFS filesystem
1886 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1887 usr_assert(rc == 0);
1888 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1889 usr_assert(rc == 0);
1893 * initialize the current directory to the AFS root
1895 afs_CurrentDir = afs_RootVnode;
1896 VN_HOLD(afs_CurrentDir);
1909 VN_RELE(afs_CurrentDir);
1910 rc = afs_unmount(&afs_RootVfs);
1911 usr_assert(rc == 0);
1918 * Donate the current thread to the RX server pool.
1921 uafs_RxServerProc(void)
1925 struct rx_call *newcall = NULL;
1927 rxi_MorePackets(2); /* alloc more packets */
1928 threadID = rxi_availProcs++;
1931 sock = OSI_NULLSOCKET;
1932 rxi_ServerProc(threadID, newcall, &sock);
1933 if (sock == OSI_NULLSOCKET) {
1938 rxi_ListenerProc(sock, &threadID, &newcall);
1939 /* assert(threadID != -1); */
1940 /* assert(newcall != NULL); */
1944 struct syscallThreadArgs {
1953 #ifdef NETSCAPE_NSAPI
1955 syscallThread(void *argp)
1956 #else /* NETSCAPE_NSAPI */
1958 syscallThread(void *argp)
1959 #endif /* NETSCAPE_NSAPI */
1962 struct usr_ucred *crp;
1963 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1966 * AFS daemons run authenticated
1968 u.u_viceid = getuid();
1970 crp->cr_uid = getuid();
1971 crp->cr_ruid = getuid();
1972 crp->cr_suid = getuid();
1973 crp->cr_groups[0] = getgid();
1974 crp->cr_ngroups = 1;
1975 for (i = 1; i < NGROUPS; i++) {
1976 crp->cr_groups[i] = NOGROUP;
1979 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1980 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1982 afs_osi_Free(argp, -1);
1985 fork_syscall(syscall, afscall, param1, param2, param3, param4)
1986 long syscall, afscall, param1, param2, param3, param4;
1989 struct syscallThreadArgs *sysArgsP;
1991 sysArgsP = (struct syscallThreadArgs *)
1992 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1993 usr_assert(sysArgsP != NULL);
1994 sysArgsP->syscall = syscall;
1995 sysArgsP->afscall = afscall;
1996 sysArgsP->param1 = param1;
1997 sysArgsP->param2 = param2;
1998 sysArgsP->param3 = param3;
1999 sysArgsP->param4 = param4;
2001 usr_thread_create(&tid, syscallThread, sysArgsP);
2002 usr_thread_detach(tid);
2005 call_syscall(syscall, afscall, param1, param2, param3, param4)
2006 long syscall, afscall, param1, param2, param3, param4;
2018 a.syscall = syscall;
2019 a.afscall = afscall;
2026 u.u_ap = (char *)&a;
2028 code = Afs_syscall();
2033 uafs_SetTokens(char *tbuffer, int tlen)
2036 struct afs_ioctl iob;
2041 iob.out = &outbuf[0];
2042 iob.out_size = sizeof(outbuf);
2043 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2052 uafs_RPCStatsEnableProc(void)
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);
2072 uafs_RPCStatsDisableProc(void)
2075 struct afs_ioctl iob;
2078 flag = AFSCALL_RXSTATS_DISABLE;
2079 iob.in = (char *)&flag;
2080 iob.in_size = sizeof(afs_int32);
2083 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2092 uafs_RPCStatsClearProc(void)
2095 struct afs_ioctl iob;
2098 flag = AFSCALL_RXSTATS_CLEAR;
2099 iob.in = (char *)&flag;
2100 iob.in_size = sizeof(afs_int32);
2103 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2112 uafs_RPCStatsEnablePeer(void)
2115 struct afs_ioctl iob;
2118 flag = AFSCALL_RXSTATS_ENABLE;
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 uafs_RPCStatsDisablePeer(void)
2135 struct afs_ioctl iob;
2138 flag = AFSCALL_RXSTATS_DISABLE;
2139 iob.in = (char *)&flag;
2140 iob.in_size = sizeof(afs_int32);
2143 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2152 uafs_RPCStatsClearPeer(void)
2155 struct afs_ioctl iob;
2158 flag = AFSCALL_RXSTATS_CLEAR;
2159 iob.in = (char *)&flag;
2160 iob.in_size = sizeof(afs_int32);
2163 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2172 * Lookup a file or directory given its path.
2173 * Call VN_HOLD on the output vnode if successful.
2174 * Returns zero on success, error code on failure.
2176 * Note: Caller must hold the AFS global lock.
2179 uafs_LookupName(char *path, struct usr_vnode *parentVp,
2180 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
2184 struct usr_vnode *vp;
2185 struct usr_vnode *nextVp;
2186 struct usr_vnode *linkVp;
2194 * Absolute paths must start with the AFS mount point.
2196 if (path[0] != '/') {
2199 path = uafs_afsPathName(path);
2207 * Loop through the path looking for the new directory
2209 tmpPath = afs_osi_Alloc(strlen(path) + 1);
2210 usr_assert(tmpPath != NULL);
2211 strcpy(tmpPath, path);
2214 while (pathP != NULL && *pathP != '\0') {
2215 usr_assert(*pathP != '/');
2218 * terminate the current component and skip over slashes
2220 nextPathP = afs_strchr(pathP, '/');
2221 if (nextPathP != NULL) {
2222 while (*nextPathP == '/') {
2223 *(nextPathP++) = '\0';
2228 * Don't call afs_lookup on non-directories
2230 if (vp->v_type != VDIR) {
2232 afs_osi_Free(tmpPath, strlen(path) + 1);
2236 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2238 * The AFS root is its own parent
2240 nextVp = afs_RootVnode;
2243 * We need execute permission to search a directory
2245 code = afs_access(VTOAFS(vp), VEXEC, u.u_cred);
2248 afs_osi_Free(tmpPath, strlen(path) + 1);
2253 * lookup the next component in the path, we can release the
2254 * subdirectory since we hold the global lock
2257 #ifdef AFS_WEB_ENHANCEMENTS
2258 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2259 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2262 afs_lookup(vp, pathP, &nextVp, u.u_cred,
2265 code = afs_lookup(vp, pathP, &nextVp, u.u_cred, 0);
2266 #endif /* AFS_WEB_ENHANCEMENTS */
2269 afs_osi_Free(tmpPath, strlen(path) + 1);
2275 * Follow symbolic links for parent directories and
2276 * for leaves when the follow flag is set.
2278 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2280 while (nextVp->v_type == VLNK) {
2281 if (++linkCount > MAX_OSI_LINKS) {
2284 afs_osi_Free(tmpPath, strlen(path) + 1);
2287 code = uafs_LookupLink(nextVp, vp, &linkVp);
2291 afs_osi_Free(tmpPath, strlen(path) + 1);
2305 * Special case, nextPathP is non-null if pathname ends in slash
2307 if (nextPathP != NULL && vp->v_type != VDIR) {
2309 afs_osi_Free(tmpPath, strlen(path) + 1);
2313 afs_osi_Free(tmpPath, strlen(path) + 1);
2319 * Lookup the target of a symbolic link
2320 * Call VN_HOLD on the output vnode if successful.
2321 * Returns zero on success, error code on failure.
2323 * Note: Caller must hold the AFS global lock.
2326 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
2327 struct usr_vnode **vpp)
2332 struct usr_vnode *linkVp;
2334 struct iovec iov[1];
2338 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
2339 usr_assert(pathP != NULL);
2342 * set up the uio buffer
2344 iov[0].iov_base = pathP;
2345 iov[0].iov_len = MAX_OSI_PATH + 1;
2346 uio.uio_iov = &iov[0];
2350 uio.uio_fmode = FREAD;
2351 uio.uio_resid = MAX_OSI_PATH + 1;
2354 * Read the link data
2356 code = afs_readlink(vp, &uio, u.u_cred);
2358 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2361 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2365 * Find the target of the symbolic link
2367 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2369 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2373 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2379 * Lookup the parent of a file or directory given its path
2380 * Call VN_HOLD on the output vnode if successful.
2381 * Returns zero on success, error code on failure.
2383 * Note: Caller must hold the AFS global lock.
2386 uafs_LookupParent(char *path, struct usr_vnode **vpp)
2391 struct usr_vnode *parentP;
2396 * Absolute path names must start with the AFS mount point.
2399 pathP = uafs_afsPathName(path);
2400 if (pathP == NULL) {
2406 * Find the length of the parent path
2409 while (len > 0 && path[len - 1] == '/') {
2415 while (len > 0 && path[len - 1] != '/') {
2422 pathP = afs_osi_Alloc(len);
2423 usr_assert(pathP != NULL);
2424 memcpy(pathP, path, len - 1);
2425 pathP[len - 1] = '\0';
2428 * look up the parent
2430 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2431 afs_osi_Free(pathP, len);
2435 if (parentP->v_type != VDIR) {
2445 * Return a pointer to the first character in the last component
2449 uafs_LastPath(char *path)
2454 while (len > 0 && path[len - 1] == '/') {
2457 while (len > 0 && path[len - 1] != '/') {
2467 * Set the working directory.
2470 uafs_chdir(char *path)
2474 retval = uafs_chdir_r(path);
2480 uafs_chdir_r(char *path)
2485 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2490 if (dirP->v_type != VDIR) {
2495 VN_RELE(afs_CurrentDir);
2496 afs_CurrentDir = dirP;
2501 * Create a directory.
2504 uafs_mkdir(char *path, int mode)
2508 retval = uafs_mkdir_r(path, mode);
2514 uafs_mkdir_r(char *path, int mode)
2518 struct vnode *parentP;
2520 struct usr_vattr attrs;
2522 if (uafs_IsRoot(path)) {
2527 * Look up the parent directory.
2529 nameP = uafs_LastPath(path);
2530 if (nameP != NULL) {
2531 code = uafs_LookupParent(path, &parentP);
2537 parentP = afs_CurrentDir;
2543 * Make sure the directory has at least one character
2545 if (*nameP == '\0') {
2552 * Create the directory
2554 usr_vattr_null(&attrs);
2555 attrs.va_type = VREG;
2556 attrs.va_mode = mode;
2557 attrs.va_uid = u.u_cred->cr_uid;
2558 attrs.va_gid = u.u_cred->cr_gid;
2560 code = afs_mkdir(parentP, nameP, &attrs, &dirP, u.u_cred);
2571 * Return 1 if path is the AFS root, otherwise return 0
2574 uafs_IsRoot(char *path)
2576 while (*path == '/' && *(path + 1) == '/') {
2579 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2582 path += afs_mountDirLen;
2583 while (*path == '/') {
2586 if (*path != '\0') {
2594 * Note: file name may not end in a slash.
2597 uafs_open(char *path, int flags, int mode)
2601 retval = uafs_open_r(path, flags, mode);
2607 uafs_open_r(char *path, int flags, int mode)
2613 struct usr_vnode *fileP;
2614 struct usr_vnode *dirP;
2615 struct usr_vattr attrs;
2620 if (uafs_IsRoot(path)) {
2621 fileP = afs_RootVnode;
2625 * Look up the parent directory.
2627 nameP = uafs_LastPath(path);
2628 if (nameP != NULL) {
2629 code = uafs_LookupParent(path, &dirP);
2635 dirP = afs_CurrentDir;
2641 * Make sure the filename has at least one character
2643 if (*nameP == '\0') {
2650 * Get the VNODE for this file
2652 if (flags & O_CREAT) {
2653 usr_vattr_null(&attrs);
2654 attrs.va_type = VREG;
2655 attrs.va_mode = mode;
2656 attrs.va_uid = u.u_cred->cr_uid;
2657 attrs.va_gid = u.u_cred->cr_gid;
2658 if (flags & O_TRUNC) {
2664 afs_create(VTOAFS(dirP), nameP, &attrs,
2665 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2674 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2682 * Check whether we have access to this file
2685 if (flags & (O_RDONLY | O_RDWR)) {
2688 if (flags & (O_WRONLY | O_RDWR)) {
2692 fileMode = VREAD; /* since O_RDONLY is 0 */
2693 code = afs_access(VTOAFS(fileP), fileMode, u.u_cred);
2701 * Get the file attributes, all we need is the size
2703 code = afs_getattr(VTOAFS(fileP), &attrs, u.u_cred);
2713 * Setup the open flags
2716 if (flags & O_TRUNC) {
2717 openFlags |= FTRUNC;
2719 if (flags & O_APPEND) {
2720 openFlags |= FAPPEND;
2722 if (flags & O_SYNC) {
2725 if (flags & O_SYNC) {
2728 if (flags & (O_RDONLY | O_RDWR)) {
2731 if (flags & (O_WRONLY | O_RDWR)) {
2732 openFlags |= FWRITE;
2734 if ((openFlags & (FREAD | FWRITE)) == 0) {
2735 /* O_RDONLY is 0, so ... */
2740 * Truncate if necessary
2742 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2743 usr_vattr_null(&attrs);
2745 code = afs_setattr(VTOAFS(fileP), &attrs, u.u_cred);
2757 code = afs_open(&vc, openFlags, u.u_cred);
2765 * Put the vnode pointer into the file table
2767 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2768 if (afs_FileTable[fd] == NULL) {
2769 afs_FileTable[fd] = fileP;
2770 afs_FileFlags[fd] = openFlags;
2771 if (flags & O_APPEND) {
2772 afs_FileOffsets[fd] = attrs.va_size;
2774 afs_FileOffsets[fd] = 0;
2779 if (fd == MAX_OSI_FILES) {
2792 uafs_creat(char *path, int mode)
2795 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2800 uafs_creat_r(char *path, int mode)
2803 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2811 uafs_write(int fd, char *buf, int len)
2815 retval = uafs_write_r(fd, buf, len);
2821 uafs_write_r(int fd, char *buf, int len)
2825 struct iovec iov[1];
2826 struct usr_vnode *fileP;
2829 * Make sure this is an open file
2831 fileP = afs_FileTable[fd];
2832 if (fileP == NULL) {
2838 * set up the uio buffer
2840 iov[0].iov_base = buf;
2841 iov[0].iov_len = len;
2842 uio.uio_iov = &iov[0];
2844 uio.uio_offset = afs_FileOffsets[fd];
2846 uio.uio_fmode = FWRITE;
2847 uio.uio_resid = len;
2853 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], u.u_cred, 0);
2859 afs_FileOffsets[fd] = uio.uio_offset;
2860 return (len - uio.uio_resid);
2867 uafs_read(int fd, char *buf, int len)
2871 retval = uafs_read_r(fd, buf, len);
2877 uafs_read_r(int fd, char *buf, int len)
2881 struct iovec iov[1];
2882 struct usr_vnode *fileP;
2883 struct usr_buf *bufP;
2886 * Make sure this is an open file
2888 fileP = afs_FileTable[fd];
2889 if (fileP == NULL) {
2895 * set up the uio buffer
2897 iov[0].iov_base = buf;
2898 iov[0].iov_len = len;
2899 uio.uio_iov = &iov[0];
2901 uio.uio_offset = afs_FileOffsets[fd];
2903 uio.uio_fmode = FREAD;
2904 uio.uio_resid = len;
2909 code = afs_read(VTOAFS(fileP), &uio, u.u_cred, 0, &bufP, 0);
2915 afs_FileOffsets[fd] = uio.uio_offset;
2916 return (len - uio.uio_resid);
2920 * Copy the attributes of a file into a stat structure.
2922 * NOTE: Caller must hold the global AFS lock.
2925 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2928 struct usr_vattr attrs;
2933 * Get the attributes
2935 code = afs_getattr(VTOAFS(vp), &attrs, u.u_cred);
2941 * Copy the attributes, zero fields that aren't set
2943 memset((void *)stats, 0, sizeof(struct stat));
2945 stats->st_ino = attrs.va_nodeid;
2946 stats->st_mode = attrs.va_mode;
2947 stats->st_nlink = attrs.va_nlink;
2948 stats->st_uid = attrs.va_uid;
2949 stats->st_gid = attrs.va_gid;
2950 stats->st_rdev = attrs.va_rdev;
2951 stats->st_size = attrs.va_size;
2952 stats->st_atime = attrs.va_atime.tv_sec;
2953 stats->st_mtime = attrs.va_mtime.tv_sec;
2954 stats->st_ctime = attrs.va_ctime.tv_sec;
2955 stats->st_blksize = attrs.va_blocksize;
2956 stats->st_blocks = attrs.va_blocks;
2962 * Get the attributes of a file, do follow links
2965 uafs_stat(char *path, struct stat *buf)
2969 retval = uafs_stat_r(path, buf);
2975 uafs_stat_r(char *path, struct stat *buf)
2980 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2985 code = uafs_GetAttr(vp, buf);
2995 * Get the attributes of a file, don't follow links
2998 uafs_lstat(char *path, struct stat *buf)
3002 retval = uafs_lstat_r(path, buf);
3008 uafs_lstat_r(char *path, struct stat *buf)
3013 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3018 code = uafs_GetAttr(vp, buf);
3028 * Get the attributes of an open file
3031 uafs_fstat(int fd, struct stat *buf)
3035 retval = uafs_fstat_r(fd, buf);
3041 uafs_fstat_r(int fd, struct stat *buf)
3046 vp = afs_FileTable[fd];
3051 code = uafs_GetAttr(vp, buf);
3060 * change the permissions on a file
3063 uafs_chmod(char *path, int mode)
3067 retval = uafs_chmod_r(path, mode);
3073 uafs_chmod_r(char *path, int mode)
3077 struct usr_vattr attrs;
3079 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3084 usr_vattr_null(&attrs);
3085 attrs.va_mode = mode;
3086 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3096 * change the permissions on an open file
3099 uafs_fchmod(int fd, int mode)
3103 retval = uafs_fchmod_r(fd, mode);
3109 uafs_fchmod_r(int fd, int mode)
3113 struct usr_vattr attrs;
3115 vp = afs_FileTable[fd];
3120 usr_vattr_null(&attrs);
3121 attrs.va_mode = mode;
3122 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3134 uafs_truncate(char *path, int length)
3138 retval = uafs_truncate_r(path, length);
3144 uafs_truncate_r(char *path, int length)
3148 struct usr_vattr attrs;
3150 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3155 usr_vattr_null(&attrs);
3156 attrs.va_size = length;
3157 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3167 * truncate an open file
3170 uafs_ftruncate(int fd, int length)
3174 retval = uafs_ftruncate_r(fd, length);
3180 uafs_ftruncate_r(int fd, int length)
3184 struct usr_vattr attrs;
3186 vp = afs_FileTable[fd];
3191 usr_vattr_null(&attrs);
3192 attrs.va_size = length;
3193 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3202 * set the read/write file pointer of an open file
3205 uafs_lseek(int fd, int offset, int whence)
3209 retval = uafs_lseek_r(fd, offset, whence);
3215 uafs_lseek_r(int fd, int offset, int whence)
3219 struct usr_vattr attrs;
3220 struct usr_vnode *vp;
3222 vp = afs_FileTable[fd];
3229 newpos = afs_FileOffsets[fd] + offset;
3235 code = afs_getattr(VTOAFS(vp), &attrs, u.u_cred);
3240 newpos = attrs.va_size + offset;
3250 afs_FileOffsets[fd] = newpos;
3262 retval = uafs_fsync_r(fd);
3268 uafs_fsync_r(int fd)
3271 struct usr_vnode *fileP;
3274 fileP = afs_FileTable[fd];
3275 if (fileP == NULL) {
3280 code = afs_fsync(fileP, u.u_cred);
3297 retval = uafs_close_r(fd);
3303 uafs_close_r(int fd)
3306 struct usr_vnode *fileP;
3308 fileP = afs_FileTable[fd];
3309 if (fileP == NULL) {
3313 afs_FileTable[fd] = NULL;
3315 code = afs_close(fileP, afs_FileFlags[fd], u.u_cred);
3326 * Create a hard link from the source to the target
3327 * Note: file names may not end in a slash.
3330 uafs_link(char *existing, char *new)
3334 retval = uafs_link_r(existing, new);
3340 uafs_link_r(char *existing, char *new)
3343 struct usr_vnode *existP;
3344 struct usr_vnode *dirP;
3347 if (uafs_IsRoot(new)) {
3352 * Look up the existing node.
3354 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3361 * Look up the parent directory.
3363 nameP = uafs_LastPath(new);
3364 if (nameP != NULL) {
3365 code = uafs_LookupParent(new, &dirP);
3372 dirP = afs_CurrentDir;
3378 * Make sure the filename has at least one character
3380 if (*nameP == '\0') {
3390 code = afs_link(existP, dirP, nameP, u.u_cred);
3401 * Create a symbolic link from the source to the target
3402 * Note: file names may not end in a slash.
3405 uafs_symlink(char *target, char *source)
3409 retval = uafs_symlink_r(target, source);
3415 uafs_symlink_r(char *target, char *source)
3418 struct usr_vnode *dirP;
3419 struct usr_vattr attrs;
3422 if (uafs_IsRoot(source)) {
3427 * Look up the parent directory.
3429 nameP = uafs_LastPath(source);
3430 if (nameP != NULL) {
3431 code = uafs_LookupParent(source, &dirP);
3437 dirP = afs_CurrentDir;
3443 * Make sure the filename has at least one character
3445 if (*nameP == '\0') {
3454 usr_vattr_null(&attrs);
3455 attrs.va_type = VLNK;
3456 attrs.va_mode = 0777;
3457 attrs.va_uid = u.u_cred->cr_uid;
3458 attrs.va_gid = u.u_cred->cr_gid;
3459 code = afs_symlink(dirP, nameP, &attrs, target, u.u_cred);
3469 * Read a symbolic link into the buffer
3472 uafs_readlink(char *path, char *buf, int len)
3476 retval = uafs_readlink_r(path, buf, len);
3482 uafs_readlink_r(char *path, char *buf, int len)
3485 struct usr_vnode *vp;
3487 struct iovec iov[1];
3489 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3495 if (vp->v_type != VLNK) {
3502 * set up the uio buffer
3504 iov[0].iov_base = buf;
3505 iov[0].iov_len = len;
3506 uio.uio_iov = &iov[0];
3510 uio.uio_fmode = FREAD;
3511 uio.uio_resid = len;
3516 code = afs_readlink(vp, &uio, u.u_cred);
3524 * return the number of bytes read
3526 return (len - uio.uio_resid);
3530 * Remove a file (or directory)
3531 * Note: file name may not end in a slash.
3534 uafs_unlink(char *path)
3538 retval = uafs_unlink_r(path);
3544 uafs_unlink_r(char *path)
3548 struct usr_vnode *fileP;
3549 struct usr_vnode *dirP;
3552 if (uafs_IsRoot(path)) {
3557 * Look up the parent directory.
3559 nameP = uafs_LastPath(path);
3560 if (nameP != NULL) {
3561 code = uafs_LookupParent(path, &dirP);
3567 dirP = afs_CurrentDir;
3573 * Make sure the filename has at least one character
3575 if (*nameP == '\0') {
3584 code = afs_remove(dirP, nameP, u.u_cred);
3595 * Rename a file (or directory)
3598 uafs_rename(char *old, char *new)
3602 retval = uafs_rename_r(old, new);
3608 uafs_rename_r(char *old, char *new)
3613 struct usr_vnode *odirP;
3614 struct usr_vnode *ndirP;
3616 if (uafs_IsRoot(new)) {
3621 * Look up the parent directories.
3623 onameP = uafs_LastPath(old);
3624 if (onameP != NULL) {
3625 code = uafs_LookupParent(old, &odirP);
3631 odirP = afs_CurrentDir;
3635 nnameP = uafs_LastPath(new);
3636 if (nnameP != NULL) {
3637 code = uafs_LookupParent(new, &ndirP);
3643 ndirP = afs_CurrentDir;
3649 * Make sure the filename has at least one character
3651 if (*onameP == '\0' || *nnameP == '\0') {
3661 code = afs_rename(odirP, onameP, ndirP, nnameP, u.u_cred);
3673 * Remove a or directory
3674 * Note: file name may not end in a slash.
3677 uafs_rmdir(char *path)
3681 retval = uafs_rmdir_r(path);
3687 uafs_rmdir_r(char *path)
3691 struct usr_vnode *fileP;
3692 struct usr_vnode *dirP;
3695 if (uafs_IsRoot(path)) {
3700 * Look up the parent directory.
3702 nameP = uafs_LastPath(path);
3703 if (nameP != NULL) {
3704 code = uafs_LookupParent(path, &dirP);
3710 dirP = afs_CurrentDir;
3716 * Make sure the directory name has at least one character
3718 if (*nameP == '\0') {
3725 * Remove the directory
3727 code = afs_rmdir(dirP, nameP, u.u_cred);
3738 * Flush a file from the AFS cache
3741 uafs_FlushFile(char *path)
3744 struct afs_ioctl iob;
3752 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3763 uafs_FlushFile_r(char *path)
3767 retval = uafs_FlushFile(path);
3776 uafs_opendir(char *path)
3780 retval = uafs_opendir_r(path);
3786 uafs_opendir_r(char *path)
3789 struct usr_vnode *fileP;
3793 * Open the directory for reading
3795 fd = uafs_open_r(path, O_RDONLY, 0);
3800 fileP = afs_FileTable[fd];
3801 if (fileP == NULL) {
3805 if (fileP->v_type != VDIR) {
3812 * Set up the directory structures
3815 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3816 sizeof(struct usr_dirent));
3817 usr_assert(dirp != NULL);
3818 dirp->dd_buf = (char *)(dirp + 1);
3828 * Read directory entries into a file system independent format.
3829 * This routine was developed to support AFS cache consistency testing.
3830 * You should use uafs_readdir instead.
3833 uafs_getdents(int fd, struct min_direct *buf, int len)
3837 retval = uafs_getdents_r(fd, buf, len);
3843 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3847 struct usr_vnode *vp;
3848 struct iovec iov[1];
3851 * Make sure this is an open file
3853 vp = afs_FileTable[fd];
3861 * set up the uio buffer
3863 iov[0].iov_base = (char *)buf;
3864 iov[0].iov_len = len;
3865 uio.uio_iov = &iov[0];
3867 uio.uio_offset = afs_FileOffsets[fd];
3869 uio.uio_fmode = FREAD;
3870 uio.uio_resid = len;
3873 * read the next chunk from the directory
3875 code = afs_readdir(vp, &uio, u.u_cred);
3881 afs_FileOffsets[fd] = uio.uio_offset;
3882 return (len - uio.uio_resid);
3886 * read from a directory (names only)
3889 uafs_readdir(usr_DIR * dirp)
3891 struct usr_dirent *retval;
3893 retval = uafs_readdir_r(dirp);
3899 uafs_readdir_r(usr_DIR * dirp)
3905 struct usr_vnode *vp;
3906 struct iovec iov[1];
3907 struct usr_dirent *direntP;
3908 struct min_direct *directP;
3911 * Make sure this is an open file
3913 vp = afs_FileTable[dirp->dd_fd];
3920 * If there are no entries in the stream buffer
3921 * then read another chunk
3923 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3924 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3926 * set up the uio buffer
3928 iov[0].iov_base = dirp->dd_buf;
3929 iov[0].iov_len = USR_DIRSIZE;
3930 uio.uio_iov = &iov[0];
3932 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3934 uio.uio_fmode = FREAD;
3935 uio.uio_resid = USR_DIRSIZE;
3938 * read the next chunk from the directory
3940 code = afs_readdir(vp, &uio, u.u_cred);
3945 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3947 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3949 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3953 * Check for end of file
3955 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3959 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
3960 usr_assert(len <= dirp->dd_size);
3963 * Copy the next entry into the usr_dirent structure and advance
3965 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
3966 direntP->d_ino = directP->d_fileno;
3967 direntP->d_off = direntP->d_reclen;
3969 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
3970 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
3971 direntP->d_name[directP->d_namlen] = '\0';
3972 dirp->dd_loc += len;
3973 dirp->dd_size -= len;
3982 uafs_closedir(usr_DIR * dirp)
3986 retval = uafs_closedir_r(dirp);
3992 uafs_closedir_r(usr_DIR * dirp)
3998 afs_osi_Free((char *)dirp,
3999 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4000 rc = uafs_close_r(fd);
4005 * Do AFS authentication
4008 uafs_klog(char *user, char *cell, char *passwd, char **reason)
4011 afs_int32 password_expires = -1;
4013 usr_mutex_lock(&osi_authenticate_lock);
4015 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
4016 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
4017 passwd, 0, &password_expires, 0, reason);
4018 usr_mutex_unlock(&osi_authenticate_lock);
4023 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
4027 retval = uafs_klog(user, cell, passwd, reason);
4033 * Destroy AFS credentials from the kernel cache
4040 usr_mutex_lock(&osi_authenticate_lock);
4041 code = ktc_ForgetAllTokens();
4042 usr_mutex_unlock(&osi_authenticate_lock);
4051 retval = uafs_unlog();
4057 * Strip the AFS mount point from a pathname string. Return
4058 * NULL if the path is a relative pathname or if the path
4059 * doesn't start with the AFS mount point string.
4062 uafs_afsPathName(char *path)
4071 for (i = 1, p = path + 1; *p != '\0'; p++) {
4072 /* Ignore duplicate slashes */
4073 if (*p == '/' && lastchar == '/')
4075 /* Is this a subdirectory of the AFS mount point? */
4076 if (afs_mountDir[i] == '\0' && *p == '/') {
4077 /* strip leading slashes */
4078 while (*(++p) == '/');
4081 /* Reject paths that are not within AFS */
4082 if (*p != afs_mountDir[i])
4087 /* Is this the AFS mount point? */
4088 if (afs_mountDir[i] == '\0') {
4089 usr_assert(*p == '\0');
4095 #ifdef AFS_WEB_ENHANCEMENTS
4098 * klog but don't allocate a new pag
4101 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
4104 afs_int32 password_expires = -1;
4106 usr_mutex_lock(&osi_authenticate_lock);
4107 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
4108 /*+KA_USERAUTH_DOSETPAG2 */ , user,
4109 NULL, cell, passwd, 0,
4110 &password_expires, 0, reason);
4111 usr_mutex_unlock(&osi_authenticate_lock);
4116 * uafs_getcellstatus
4117 * get the cell status
4120 uafs_getcellstatus(char *cell, afs_int32 * status)
4123 struct afs_ioctl iob;
4126 iob.in_size = strlen(cell) + 1;
4130 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
4138 *status = (afs_int32) iob.out;
4144 * Get quota of volume associated with path
4147 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
4150 struct afs_ioctl iob;
4151 VolumeStatus *status;
4157 iob.out_size = 1024;
4159 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
4167 status = (VolumeStatus *) buf;
4168 *BlocksInUse = status->BlocksInUse;
4169 *MaxQuota = status->MaxQuota;
4175 * Set quota of volume associated with path
4178 uafs_setvolquota(char *path, afs_int32 MaxQuota)
4181 struct afs_ioctl iob;
4182 VolumeStatus *status;
4190 memset(buf, 0, sizeof(VolumeStatus));
4191 status = (VolumeStatus *) buf;
4192 status->MaxQuota = MaxQuota;
4193 status->MinQuota = -1;
4195 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
4207 * uafs_statmountpoint
4208 * Determine whether a dir. is a mount point or not
4209 * return 1 if mount point, 0 if not
4212 uafs_statmountpoint(char *path)
4219 retval = uafs_statmountpoint_r(path);
4225 uafs_statmountpoint_r(char *path)
4230 struct vrequest treq;
4233 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4248 * Get a list of rights for the current user on path.
4251 uafs_getRights(char *path)
4258 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4266 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
4267 | PRSFS_LOCK | PRSFS_ADMINISTER;
4269 afs_rights = afs_getRights(vp, afs_rights, u.u_cred);
4274 #endif /* AFS_WEB_ENHANCEMENTS */
4276 #endif /* UKERNEL */