3 * Copyright 2000, International Business Machines Corporation and others.
6 * This software has been released under the terms of the IBM Public
7 * License. For details, see the LICENSE file in the top-level source
8 * directory or online at http://www.openafs.org/dl/license10.html
12 * User space client specific interface glue
15 #include <afsconfig.h>
16 #include "afs/param.h"
20 #include "afs/sysincludes.h" /* Standard vendor system headers */
23 #include "afsincludes.h" /* Afs-based standard headers */
24 #include "afs_usrops.h"
25 #include "afs/afs_stats.h"
27 #include "afs/cellconfig.h"
29 #include "afs/kauth.h"
30 #include "afs/kautils.h"
31 #include "afs/afsutil.h"
32 #include "rx/rx_globals.h"
38 #ifndef AFS_CACHE_VNODE_PATH
39 #error You must compile UKERNEL code with -DAFS_CACHE_VNODE_PATH
42 #define CACHEINFOFILE "cacheinfo"
43 #define AFSLOGFILE "AFSLog"
44 #define DCACHEFILE "CacheItems"
45 #define VOLINFOFILE "VolumeItems"
46 #define CELLINFOFILE "CellItems"
50 #define MIN(A,B) ((A)<(B)?(A):(B))
53 #define MAX(A,B) ((A)>(B)?(A):(B))
56 extern int cacheDiskType;
58 char afs_LclCellName[64];
60 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
61 int afs_FileFlags[MAX_OSI_FILES];
62 off_t afs_FileOffsets[MAX_OSI_FILES];
64 #define MAX_CACHE_LOOPS 4
66 struct usr_vfs afs_RootVfs;
67 struct usr_vnode *afs_RootVnode = NULL;
68 struct usr_vnode *afs_CurrentDir = NULL;
70 afs_int32 cacheBlocks; /* Num blocks in cache */
71 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
72 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
73 char cacheBaseDir[1024]; /* AFS cache directory */
74 char confDir[1024]; /* AFS configuration directory */
75 char afs_mountDir[1024]; /* AFS mount point */
76 int afs_mountDirLen; /* strlen of AFS mount point */
77 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
78 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
79 char fullpn_CellInfoFile[1024]; /* Full pathname of CELLINFOFILE */
80 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
81 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
82 char fullpn_VFile[1024]; /* Full pathname of data cache files */
83 char *vFileNumber; /* Ptr to number in file pathname */
84 char rootVolume[64] = "root.afs"; /* AFS root volume name */
85 afs_int32 isHomeCell; /* Is current cell info for home cell */
86 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
87 int ownerRWmode = 0600; /* Read/write OK by owner */
88 static int nDaemons = 2; /* Number of background daemons */
89 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
90 static int dCacheSize = 300; /* # of dcache entries */
91 static int vCacheSize = 50; /* # of volume cache entries */
92 static int cacheFlags = 0; /* Flags to cache manager */
93 static int preallocs = 400; /* Def # of allocated memory blocks */
94 int afsd_verbose = 0; /* Are we being chatty? */
95 int afsd_debug = 0; /* Are we printing debugging info? */
96 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
98 #define AFSD_INO_T afs_uint32
99 char **pathname_for_V; /* Array of cache file pathnames */
100 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
101 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
102 int missing_CellInfoFile = 1;
103 struct afs_cacheParams cparams; /* params passed to cache manager */
104 struct afsconf_dir *afs_cdir; /* config dir */
106 int afs_bufferpages = 100;
107 int usr_udpcksum = 0;
109 usr_key_t afs_global_u_key;
111 struct usr_proc *afs_global_procp = NULL;
112 struct usr_ucred *afs_global_ucredp = NULL;
113 struct usr_sysent usr_sysent[200];
115 #ifdef AFS_USR_OSF_ENV
117 #else /* AFS_USR_OSF_ENV */
119 #endif /* AFS_USR_OSF_ENV */
121 struct usr_ucred afs_osi_cred, *afs_osi_credp;
122 usr_mutex_t afs_global_lock;
123 usr_thread_t afs_global_owner;
124 usr_mutex_t rx_global_lock;
125 usr_thread_t rx_global_owner;
126 usr_mutex_t osi_dummy_lock;
127 usr_mutex_t osi_waitq_lock;
128 usr_mutex_t osi_authenticate_lock;
130 afs_lock_t osi_flplock;
131 afs_lock_t osi_fsplock;
134 #ifndef NETSCAPE_NSAPI
137 * Mutex and condition variable used to implement sleep
139 pthread_mutex_t usr_sleep_mutex;
140 pthread_cond_t usr_sleep_cond;
142 #endif /* !NETSCAPE_NSAPI */
144 int call_syscall(long, long, long, long, long, long);
145 int fork_syscall(long, long, long, long, long, long);
149 * Hash table mapping addresses onto wait structures for
150 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
152 typedef struct osi_wait {
156 struct osi_wait *next;
157 struct osi_wait *prev;
159 struct osi_wait *timedNext;
160 struct osi_wait *timedPrev;
164 * Head of the linked list of available waitq structures.
166 osi_wait_t *osi_waithash_avail;
169 * List of timed waits, NSAPI does not provide a cond_timed
170 * wait, so we need to keep track of the timed waits ourselves and
171 * periodically check for expirations
173 osi_wait_t *osi_timedwait_head;
174 osi_wait_t *osi_timedwait_tail;
179 } osi_waithash_table[OSI_WAITHASH_SIZE];
182 * Never call afs_brelse
185 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
192 * I am not sure what to do with these, they assert for now
195 iodone(struct usr_buf *bp)
209 * Every user is a super user
212 afs_osi_suser(void *credp)
218 afs_suser(void *credp)
224 * These are no-ops in user space
228 afs_osi_SetTime(osi_timeval_t * atv)
234 * xflock should never fall through, the only files we know
235 * about are AFS files
245 * ioctl should never fall through, the only files we know
246 * about are AFS files
256 * We do not support the inode related system calls
259 afs_syscall_icreate(long a, long b, long c, long d, long e, long f)
266 afs_syscall_iincdec(int dev, int inode, int inode_p1, int amount)
273 afs_syscall_iopen(int dev, int inode, int usrmod)
280 afs_syscall_ireadwrite(void)
287 * these routines are referenced in the vfsops structure, but
288 * should never get called
319 * uiomove copies data between kernel buffers and uio buffers
322 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
329 nio = uio->uio_iovcnt;
339 while (nio > 0 && n > 0) {
340 len = MIN(n, iovp->iov_len);
341 if (rw == UIO_READ) {
342 memcpy(iovp->iov_base, ptr, len);
344 memcpy(ptr, iovp->iov_base, len);
348 uio->uio_resid -= len;
349 uio->uio_offset += len;
350 iovp->iov_base = (char *)(iovp->iov_base) + len;
351 iovp->iov_len -= len;
362 * routines to manage user credentials
365 usr_crcopy(struct usr_ucred *credp)
367 struct usr_ucred *newcredp;
369 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
371 newcredp->cr_ref = 1;
378 struct usr_ucred *newcredp;
380 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
381 newcredp->cr_ref = 1;
386 usr_crfree(struct usr_ucred *credp)
389 if (credp->cr_ref == 0) {
390 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
396 usr_crhold(struct usr_ucred *credp)
403 usr_vattr_null(struct usr_vattr *vap)
408 n = sizeof(struct usr_vattr);
416 * Initialize the thread specific data used to simulate the
417 * kernel environment for each thread. The user structure
418 * is stored in the thread specific data.
421 uafs_InitThread(void)
424 struct usr_user *uptr;
427 * initialize the thread specific user structure. Use malloc to
428 * allocate the data block, so pthread_finish can free the buffer
429 * when this thread terminates.
432 (struct usr_user *)malloc(sizeof(struct usr_user) +
433 sizeof(struct usr_ucred));
434 usr_assert(uptr != NULL);
437 uptr->u_procp = afs_global_procp;
438 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
439 *uptr->u_cred = *afs_global_ucredp;
440 st = usr_setspecific(afs_global_u_key, (void *)uptr);
445 * routine to get the user structure from the thread specific data.
446 * this routine is used to implement the global 'u' structure. Initializes
447 * the thread if needed.
450 get_user_struct(void)
452 struct usr_user *uptr;
454 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
458 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
460 usr_assert(uptr != NULL);
466 * Hash an address for the waithash table
468 #define WAITHASH(X) \
469 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
475 afs_osi_Sleep(void *x)
479 int glockOwner = ISAFS_GLOCK();
481 usr_mutex_lock(&osi_waitq_lock);
486 if (osi_waithash_avail == NULL) {
487 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
488 usr_cond_init(&waitp->cond);
490 waitp = osi_waithash_avail;
491 osi_waithash_avail = osi_waithash_avail->next;
495 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
496 osi_waithash_table[index].tail, next, prev);
497 waitp->expiration = 0;
498 waitp->timedNext = NULL;
499 waitp->timedPrev = NULL;
500 while (waitp->flag == 0) {
501 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
503 DLL_DELETE(waitp, osi_waithash_table[index].head,
504 osi_waithash_table[index].tail, next, prev);
505 waitp->next = osi_waithash_avail;
506 osi_waithash_avail = waitp;
507 usr_mutex_unlock(&osi_waitq_lock);
514 afs_osi_SleepSig(void *x)
521 afs_osi_Wakeup(void *x)
527 usr_mutex_lock(&osi_waitq_lock);
528 waitp = osi_waithash_table[index].head;
530 if (waitp->addr == x && waitp->flag == 0) {
532 usr_cond_signal(&waitp->cond);
536 usr_mutex_unlock(&osi_waitq_lock);
541 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
543 return afs_osi_Wait(ams, event, aintok);
547 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
553 int glockOwner = ISAFS_GLOCK();
555 tv.tv_sec = msec / 1000;
556 tv.tv_nsec = (msec % 1000) * 1000000;
557 if (handle == NULL) {
561 usr_thread_sleep(&tv);
567 usr_mutex_lock(&osi_waitq_lock);
571 index = WAITHASH((caddr_t) handle);
572 if (osi_waithash_avail == NULL) {
573 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
574 usr_cond_init(&waitp->cond);
576 waitp = osi_waithash_avail;
577 osi_waithash_avail = osi_waithash_avail->next;
579 waitp->addr = (caddr_t) handle;
581 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
582 osi_waithash_table[index].tail, next, prev);
583 tv.tv_sec += time(NULL);
584 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
585 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
586 timedNext, timedPrev);
587 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
593 DLL_DELETE(waitp, osi_waithash_table[index].head,
594 osi_waithash_table[index].tail, next, prev);
595 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
597 waitp->next = osi_waithash_avail;
598 osi_waithash_avail = waitp;
599 usr_mutex_unlock(&osi_waitq_lock);
608 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
610 afs_osi_Wakeup(handle);
614 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
615 * to explicitly signal cond_timed_waits when their timers expire
618 afs_osi_CheckTimedWaits(void)
623 curTime = time(NULL);
624 usr_mutex_lock(&osi_waitq_lock);
625 waitp = osi_timedwait_head;
626 while (waitp != NULL) {
627 usr_assert(waitp->expiration != 0);
628 if (waitp->expiration <= curTime) {
630 usr_cond_signal(&waitp->cond);
632 waitp = waitp->timedNext;
634 usr_mutex_unlock(&osi_waitq_lock);
639 * 'dummy' vnode, for non-AFS files. We don't actually need most vnode
640 * information for non-AFS files, so point all of them towards this vnode
643 static struct usr_vnode dummy_vnode = {
654 * Allocate a slot in the file table if there is not one there already,
655 * copy in the file name and kludge up the vnode and inode structures
658 lookupname(char *fnamep, int segflg, int followlink,
659 struct usr_vnode **compvpp)
664 * Assume relative pathnames refer to files in AFS
666 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
668 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
673 /* For non-afs files, nobody really looks at the meaningful values in the
674 * returned vnode, so we can return a 'fake' one. The vnode can be held,
675 * released, etc. and some callers check for a NULL vnode anyway, so we
676 * to return something. */
678 usr_mutex_lock(&osi_dummy_lock);
679 VN_HOLD(&dummy_vnode);
680 usr_mutex_unlock(&osi_dummy_lock);
682 *compvpp = &dummy_vnode;
688 * open a file given its i-node number
691 osi_UFSOpen(afs_dcache_id_t *ino)
700 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
701 usr_assert(fp != NULL);
703 usr_assert(ino->ufs);
705 fp->fd = open(ino->ufs, O_RDWR | O_CREAT, 0);
707 get_user_struct()->u_error = errno;
708 afs_osi_Free((char *)fp, sizeof(struct osi_file));
712 rc = fstat(fp->fd, &st);
714 get_user_struct()->u_error = errno;
715 afs_osi_Free((void *)fp, sizeof(struct osi_file));
719 fp->size = st.st_size;
721 fp->vnode = (struct usr_vnode *)fp;
728 osi_UFSClose(struct osi_file *fp)
737 get_user_struct()->u_error = errno;
738 afs_osi_Free((void *)fp, sizeof(struct osi_file));
742 afs_osi_Free((void *)fp, sizeof(struct osi_file));
748 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
755 rc = ftruncate(fp->fd, len);
757 get_user_struct()->u_error = errno;
767 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);
781 get_user_struct()->u_error = errno;
786 ret = read(fp->fd, buf, len);
788 get_user_struct()->u_error = errno;
793 rc = fstat(fp->fd, &st);
795 get_user_struct()->u_error = errno;
799 fp->size = st.st_size;
805 afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
814 rc = lseek(fp->fd, offset, SEEK_SET);
816 rc = lseek(fp->fd, fp->offset, SEEK_SET);
819 get_user_struct()->u_error = errno;
824 ret = write(fp->fd, buf, len);
826 get_user_struct()->u_error = errno;
831 rc = fstat(fp->fd, &st);
833 get_user_struct()->u_error = errno;
837 fp->size = st.st_size;
843 afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
849 rc = fstat(fp->fd, &st);
851 get_user_struct()->u_error = errno;
855 stp->size = st.st_size;
856 stp->mtime = st.st_mtime;
857 stp->atime = st.st_atime;
866 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
867 int flags, struct usr_ucred *credP)
870 struct osi_file *fp = (struct osi_file *)vnodeP;
873 * We don't support readv/writev.
875 usr_assert(uioP->uio_iovcnt == 1);
876 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
878 if (rw == UIO_WRITE) {
879 usr_assert(uioP->uio_fmode == FWRITE);
880 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
881 uioP->uio_iov[0].iov_len);
883 usr_assert(uioP->uio_fmode == FREAD);
884 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
885 uioP->uio_iov[0].iov_len);
888 return get_user_struct()->u_error;
891 uioP->uio_resid -= rc;
892 uioP->uio_offset += rc;
893 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
894 uioP->uio_iov[0].iov_len -= rc;
899 afs_osi_Alloc(size_t size)
905 afs_osi_Free(void *ptr, size_t size)
911 afs_osi_FreeStr(char *ptr)
917 osi_AllocLargeSpace(size_t size)
919 AFS_STATCNT(osi_AllocLargeSpace);
920 return afs_osi_Alloc(size);
924 osi_FreeLargeSpace(void *ptr)
926 AFS_STATCNT(osi_FreeLargeSpace);
927 afs_osi_Free(ptr, 0);
931 osi_AllocSmallSpace(size_t size)
933 AFS_STATCNT(osi_AllocSmallSpace);
934 return afs_osi_Alloc(size);
938 osi_FreeSmallSpace(void *ptr)
940 AFS_STATCNT(osi_FreeSmallSpace);
941 afs_osi_Free(ptr, 0);
947 AFS_STATCNT(shutdown_osi);
952 shutdown_osinet(void)
954 AFS_STATCNT(shutdown_osinet);
959 shutdown_osifile(void)
961 AFS_STATCNT(shutdown_osifile);
966 afs_nfsclient_init(void)
971 shutdown_nfsclnt(void)
977 afs_osi_Invisible(void)
983 afs_osi_Visible(void)
989 osi_GetTime(struct timeval *tv)
991 gettimeofday(tv, NULL);
996 osi_SetTime(struct timeval *tv)
1002 osi_Active(struct vcache *avc)
1004 AFS_STATCNT(osi_Active);
1011 afs_osi_MapStrategy(int (*aproc) (struct usr_buf *), struct usr_buf *bp)
1013 afs_int32 returnCode;
1014 returnCode = (*aproc) (bp);
1019 osi_FlushPages(register struct vcache *avc, afs_ucred_t *credp)
1021 ObtainSharedLock(&avc->lock, 555);
1022 if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
1023 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1024 ReleaseSharedLock(&avc->lock);
1027 UpgradeSToWLock(&avc->lock, 565);
1028 hset(avc->mapDV, avc->f.m.DataVersion);
1029 ReleaseWriteLock(&avc->lock);
1034 osi_FlushText_really(register struct vcache *vp)
1036 if (hcmp(vp->f.m.DataVersion, vp->flushDV) > 0) {
1037 hset(vp->flushDV, vp->f.m.DataVersion);
1043 osi_SyncVM(struct vcache *avc)
1049 osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1059 #ifndef NETSCAPE_NSAPI
1061 * Initialize the mutex and condition variable used to implement
1064 pthread_mutex_init(&usr_sleep_mutex, NULL);
1065 pthread_cond_init(&usr_sleep_cond, NULL);
1066 #endif /* !NETSCAPE_NSAPI */
1069 * Initialize the hash table used for sleep/wakeup
1071 for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
1072 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1074 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1075 osi_waithash_avail = NULL;
1078 * Initialize the AFS file table
1080 for (i = 0; i < MAX_OSI_FILES; i++) {
1081 afs_FileTable[i] = NULL;
1085 * Initialize the global locks
1087 usr_mutex_init(&afs_global_lock);
1088 usr_mutex_init(&rx_global_lock);
1089 usr_mutex_init(&osi_dummy_lock);
1090 usr_mutex_init(&osi_waitq_lock);
1091 usr_mutex_init(&osi_authenticate_lock);
1094 * Initialize the AFS OSI credentials
1096 afs_osi_cred = *afs_global_ucredp;
1097 afs_osi_credp = &afs_osi_cred;
1100 /* ParseArgs is now obsolete, being handled by cmd */
1102 /*---------------------------------------------------------------------
1106 * Given the final component of a filename expected to be a data cache file,
1107 * return the integer corresponding to the file. Note: we reject names that
1108 * are not a ``V'' followed by an integer. We also reject those names having
1109 * the right format but lying outside the range [0..cacheFiles-1].
1112 * fname : Char ptr to the filename to parse.
1115 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1119 * Nothing interesting.
1123 *------------------------------------------------------------------------*/
1126 GetVFileNumber(char *fname)
1128 int computedVNumber; /*The computed file number we return */
1129 int filenameLen; /*Number of chars in filename */
1130 int currDigit; /*Current digit being processed */
1133 * The filename must have at least two characters, the first of which must be a ``V''
1134 * and the second of which cannot be a zero unless the file is exactly two chars long.
1136 filenameLen = strlen(fname);
1137 if (filenameLen < 2)
1139 if (fname[0] != 'V')
1141 if ((filenameLen > 2) && (fname[1] == '0'))
1145 * Scan through the characters in the given filename, failing immediately if a non-digit
1148 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1149 if (isdigit(fname[currDigit]) == 0)
1153 * All relevant characters are digits. Pull out the decimal number they represent.
1154 * Reject it if it's out of range, otherwise return it.
1156 computedVNumber = atoi(++fname);
1157 if (computedVNumber < cacheFiles)
1158 return (computedVNumber);
1163 /*---------------------------------------------------------------------
1167 * Given a full pathname for a file we need to create for the workstation AFS
1168 * cache, go ahead and create the file.
1171 * fname : Full pathname of file to create.
1174 * 0 iff the file was created,
1178 * The given cache file has been found to be missing.
1182 *------------------------------------------------------------------------*/
1185 CreateCacheFile(char *fname)
1187 static char rn[] = "CreateCacheFile"; /*Routine name */
1188 int cfd; /*File descriptor to AFS cache file */
1189 int closeResult; /*Result of close() */
1192 printf("%s: Creating cache file '%s'\n", rn, fname);
1193 cfd = open(fname, createAndTrunc, ownerRWmode);
1195 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
1199 closeResult = close(cfd);
1202 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1210 /*---------------------------------------------------------------------
1214 * Sweep through the AFS cache directory, recording the inode number for
1215 * each valid data cache file there. Also, delete any file that doesn't beint32
1216 * in the cache directory during this sweep, and remember which of the other
1217 * residents of this directory were seen. After the sweep, we create any data
1218 * cache files that were missing.
1221 * vFilesFound : Set to the number of data cache files found.
1224 * 0 if everything went well,
1228 * This routine may be called several times. If the number of data cache files
1229 * found is less than the global cacheFiles, then the caller will need to call it
1230 * again to record the inodes of the missing zero-length data cache files created
1231 * in the previous call.
1234 * Fills up the global pathname_for_V array, may create and/or
1235 * delete files as explained above.
1236 *------------------------------------------------------------------------*/
1239 SweepAFSCache(int *vFilesFound)
1241 static char rn[] = "SweepAFSCache"; /*Routine name */
1242 char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
1243 char *fileToDelete; /*Ptr to last component of above */
1244 DIR *cdirp; /*Ptr to cache directory structure */
1246 struct dirent *currp; /*Current directory entry */
1247 int vFileNum; /*Data cache file's associated number */
1249 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1251 printf("%s: Memory Cache, no cache sweep done\n", rn);
1257 printf("%s: Opening cache directory '%s'\n", rn, cacheBaseDir);
1259 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1260 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
1264 cdirp = opendir(cacheBaseDir);
1265 if (cdirp == (DIR *) 0) {
1266 printf("%s: Can't open AFS cache directory, '%s'.\n", rn,
1272 * Scan the directory entries, remembering data cache file inodes and the existance
1273 * of other important residents. Delete all files that don't belong here.
1276 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1277 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1279 for (currp = readdir(cdirp); currp; currp = readdir(cdirp)) {
1281 printf("%s: Current directory entry:\n", rn);
1282 #if defined(AFS_SGI62_ENV) || defined(AFS_USR_DARWIN100_ENV)
1283 printf("\tinode=%" AFS_INT64_FMT ", reclen=%d, name='%s'\n",
1284 currp->d_ino, currp->d_reclen, currp->d_name);
1285 #elif defined(AFS_USR_DFBSD_ENV)
1286 printf("\tinode=%d, name='%s'\n", currp->d_ino,
1289 printf("\tinode=%d, reclen=%d, name='%s'\n", (int)currp->d_ino,
1290 currp->d_reclen, currp->d_name);
1295 * Guess current entry is for a data cache file.
1297 vFileNum = GetVFileNumber(currp->d_name);
1298 if (vFileNum >= 0) {
1300 * Found a valid data cache filename. Remember this file's name
1301 * and bump the number of files found.
1303 pathname_for_V[vFileNum] =
1304 afs_osi_Alloc(strlen(currp->d_name) + strlen(cacheBaseDir) +
1306 usr_assert(pathname_for_V[vFileNum] != NULL);
1307 sprintf(pathname_for_V[vFileNum], "%s/%s", cacheBaseDir,
1310 } else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1312 * Found the file holding the dcache entries.
1314 missing_DCacheFile = 0;
1315 } else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1317 * Found the file holding the volume info.
1319 missing_VolInfoFile = 0;
1320 } else if (strcmp(currp->d_name, CELLINFOFILE) == 0) {
1321 missing_CellInfoFile = 0;
1322 } else if ((strcmp(currp->d_name, ".") == 0)
1323 || (strcmp(currp->d_name, "..") == 0)
1324 || (strcmp(currp->d_name, "lost+found") == 0)) {
1326 * Don't do anything - this file is legit, and is to be left alone.
1330 * This file doesn't belong in the cache. Nuke it.
1332 sprintf(fileToDelete, "%s", currp->d_name);
1334 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
1335 if (unlink(fullpn_FileToDelete)) {
1336 printf("%s: Can't unlink '%s', errno is %d\n", rn,
1337 fullpn_FileToDelete, errno);
1343 * Create all the cache files that are missing.
1345 if (missing_DCacheFile) {
1347 printf("%s: Creating '%s'\n", rn, fullpn_DCacheFile);
1348 if (CreateCacheFile(fullpn_DCacheFile))
1349 printf("%s: Can't create '%s'\n", rn, fullpn_DCacheFile);
1351 if (missing_VolInfoFile) {
1353 printf("%s: Creating '%s'\n", rn, fullpn_VolInfoFile);
1354 if (CreateCacheFile(fullpn_VolInfoFile))
1355 printf("%s: Can't create '%s'\n", rn, fullpn_VolInfoFile);
1357 if (missing_CellInfoFile) {
1359 printf("%s: Creating '%s'\n", rn, fullpn_CellInfoFile);
1360 if (CreateCacheFile(fullpn_CellInfoFile))
1361 printf("%s: Can't create '%s'\n", rn, fullpn_CellInfoFile);
1364 if (*vFilesFound < cacheFiles) {
1366 * We came up short on the number of data cache files found. Scan through the inode
1367 * list and create all missing files.
1369 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1370 if (pathname_for_V[vFileNum] == (AFSD_INO_T) 0) {
1371 sprintf(vFileNumber, "%d", vFileNum);
1373 printf("%s: Creating '%s'\n", rn, fullpn_VFile);
1374 if (CreateCacheFile(fullpn_VFile))
1375 printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
1380 * Close the directory, return success.
1383 printf("%s: Closing cache directory.\n", rn);
1389 ConfigCell(register struct afsconf_cell *aci, void *arock,
1390 struct afsconf_dir *adir)
1392 register int isHomeCell;
1394 afs_int32 cellFlags = 0;
1395 afs_int32 hosts[MAXHOSTSPERCELL];
1397 /* figure out if this is the home cell */
1398 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1400 cellFlags = 2; /* not home, suid is forbidden */
1402 /* build address list */
1403 for (i = 0; i < MAXHOSTSPERCELL; i++)
1404 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1406 if (aci->linkedCell)
1407 cellFlags |= 4; /* Flag that linkedCell arg exists,
1408 * for upwards compatibility */
1410 /* configure one cell */
1411 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2, (long)hosts, /* server addresses */
1412 (long)aci->name, /* cell name */
1413 (long)cellFlags, /* is this the home cell? */
1414 (long)aci->linkedCell); /* Linked cell, if any */
1419 ConfigCellAlias(struct afsconf_cellalias *aca, void *arock, struct afsconf_dir *adir)
1421 call_syscall(AFSOP_ADDCELLALIAS, (long)aca->aliasName,
1422 (long)aca->realName, 0, 0, 0);
1427 * Set the UDP port number RX uses for UDP datagrams
1430 uafs_SetRxPort(int port)
1432 usr_assert(usr_rx_port == 0);
1438 * Initialize the user space client.
1441 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1442 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1443 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1444 int chunkSizeParam, int closeSynchParam, int debugParam,
1445 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1450 int currVFile; /* Current AFS cache file number */
1451 int lookupResult; /* Result of GetLocalCellName() */
1452 int cacheIteration; /* cache verification loop counter */
1453 int vFilesFound; /* Num data cache files found in sweep */
1458 afs_int32 buffer[MAXIPADDRS];
1459 afs_int32 maskbuffer[MAXIPADDRS];
1460 afs_int32 mtubuffer[MAXIPADDRS];
1463 * Use the thread specific data to implement the user structure
1465 usr_keycreate(&afs_global_u_key, free);
1468 * Initialize the global ucred structure
1470 afs_global_ucredp = (struct usr_ucred *)
1471 afs_osi_Alloc(sizeof(struct usr_ucred));
1472 usr_assert(afs_global_ucredp != NULL);
1473 afs_global_ucredp->cr_ref = 1;
1474 afs_set_cr_uid(afs_global_ucredp, geteuid());
1475 afs_set_cr_gid(afs_global_ucredp, getegid());
1476 afs_set_cr_ruid(afs_global_ucredp, getuid());
1477 afs_set_cr_rgid(afs_global_ucredp, getgid());
1478 afs_global_ucredp->cr_suid = afs_cr_ruid(afs_global_ucredp);
1479 afs_global_ucredp->cr_sgid = afs_cr_rgid(afs_global_ucredp);
1480 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1481 usr_assert(st >= 0);
1482 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1483 for (i = st; i < NGROUPS; i++) {
1484 afs_global_ucredp->cr_groups[i] = NOGROUP;
1488 * Initialize the global process structure
1490 afs_global_procp = (struct usr_proc *)
1491 afs_osi_Alloc(sizeof(struct usr_proc));
1492 usr_assert(afs_global_procp != NULL);
1493 afs_global_procp->p_pid = osi_getpid();
1494 afs_global_procp->p_ppid = (pid_t) 1;
1495 afs_global_procp->p_ucred = afs_global_ucredp;
1498 * Initialize the AFS mount point, default is '/afs'.
1499 * Strip duplicate/trailing slashes from mount point string.
1500 * afs_mountDirLen is set to strlen(afs_mountDir).
1502 if (mountDirParam) {
1503 sprintf(tbuffer, "%s", mountDirParam);
1505 sprintf(tbuffer, "afs");
1507 afs_mountDir[0] = '/';
1508 afs_mountDirLen = 1;
1509 for (lastchar = '/', p = &tbuffer[0]; *p != '\0'; p++) {
1510 if (lastchar != '/' || *p != '/') {
1511 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1514 if (lastchar == '/' && afs_mountDirLen > 1)
1516 afs_mountDir[afs_mountDirLen] = '\0';
1517 usr_assert(afs_mountDirLen > 1);
1520 * Initialize cache parameters using the input arguments
1523 cacheBlocks = cacheBlocksParam;
1524 if (cacheFilesParam != 0) {
1525 cacheFiles = cacheFilesParam;
1527 cacheFiles = cacheBlocks / 10;
1529 if (cacheStatEntriesParam != 0) {
1530 cacheStatEntries = cacheStatEntriesParam;
1532 strcpy(cacheBaseDir, cacheBaseDirParam);
1533 if (nDaemonsParam != 0) {
1534 nDaemons = nDaemonsParam;
1538 afsd_verbose = debugParam;
1539 afsd_debug = debugParam;
1540 chunkSize = chunkSizeParam;
1541 if (dCacheSizeParam != 0) {
1542 dCacheSize = dCacheSizeParam;
1544 dCacheSize = cacheFiles / 2;
1546 if (vCacheSizeParam != 0) {
1547 vCacheSize = vCacheSizeParam;
1549 strcpy(confDir, confDirParam);
1550 afsd_CloseSynch = closeSynchParam;
1551 if (cacheFlagsParam >= 0) {
1552 cacheFlags = cacheFlagsParam;
1554 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1555 cacheFiles = dCacheSize;
1558 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1559 if (logFile == NULL) {
1560 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1562 strcpy(fullpn_AFSLogFile, logFile);
1565 printf("\n%s: Initializing user space AFS client\n\n", rn);
1566 printf(" mountDir: %s\n", afs_mountDir);
1567 printf(" confDir: %s\n", confDir);
1568 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1569 printf(" cacheBlocks: %d\n", cacheBlocks);
1570 printf(" cacheFiles: %d\n", cacheFiles);
1571 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1572 printf(" dCacheSize: %d\n", dCacheSize);
1573 printf(" vCacheSize: %d\n", vCacheSize);
1574 printf(" chunkSize: %d\n", chunkSize);
1575 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1576 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1577 printf(" nDaemons: %d\n", nDaemons);
1578 printf(" cacheFlags: %d\n", cacheFlags);
1579 printf(" logFile: %s\n", fullpn_AFSLogFile);
1584 * Initialize the AFS client
1589 * Pull out all the configuration info for the workstation's AFS cache and
1590 * the cellular community we're willing to let our users see.
1592 afs_cdir = afsconf_Open(confDir);
1594 printf("afsd: some file missing or bad in %s\n", confDir);
1599 afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1600 sizeof(afs_LclCellName));
1602 printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
1606 printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
1609 if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
1611 printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1612 if (CreateCacheFile(fullpn_AFSLogFile)) {
1614 ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
1615 rn, fullpn_AFSLogFile);
1622 * Create and zero the pathname table for the desired cache files.
1624 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1625 if (pathname_for_V == NULL) {
1626 printf("%s: malloc() failed for cache file table with %d entries.\n",
1630 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1632 printf("%s: %d pathname_for_V entries at %" AFS_PTR_FMT
1633 ", %lud bytes\n", rn, cacheFiles, pathname_for_V,
1634 afs_printable_uint32_lu(cacheFiles * sizeof(AFSD_INO_T)));
1637 * Set up all the pathnames we'll need for later.
1639 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1640 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1641 sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
1642 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1643 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1645 /* initialize AFS callback interface */
1647 /* parse multihomed address files */
1649 st = parseNetFiles((afs_uint32*)buffer,(afs_uint32*) maskbuffer, (afs_uint32*)mtubuffer, MAXIPADDRS, reason,
1650 AFSDIR_CLIENT_NETINFO_FILEPATH,
1651 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1653 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st,
1654 (long)(&buffer[0]), (long)(&maskbuffer[0]),
1655 (long)(&mtubuffer[0]));
1657 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
1664 * Start the RX listener.
1667 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1668 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE, FALSE, FALSE, 0);
1671 printf("%s: Forking rx callback listener.\n", rn);
1673 if (preallocs < cacheStatEntries + 50)
1674 preallocs = cacheStatEntries + 50;
1675 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs, 0, 0, 0);
1678 * Start the RX event handler.
1681 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1682 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE, 0, 0, 0);
1685 * Set up all the kernel processes needed for AFS.
1689 printf("%s: Initializing AFS daemon.\n", rn);
1690 call_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT, 1, 0, 0, 0);
1693 * Tell the kernel some basic information about the workstation's cache.
1696 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1697 " %d optimum cache files, %d blocks in the cache,"
1698 " flags = 0x%x, dcache entries %d\n", rn, cacheStatEntries,
1699 cacheFiles, cacheBlocks, cacheFlags, dCacheSize);
1700 memset(&cparams, 0, sizeof(cparams));
1701 cparams.cacheScaches = cacheStatEntries;
1702 cparams.cacheFiles = cacheFiles;
1703 cparams.cacheBlocks = cacheBlocks;
1704 cparams.cacheDcaches = dCacheSize;
1705 cparams.cacheVolumes = vCacheSize;
1706 cparams.chunkSize = chunkSize;
1707 cparams.setTimeFlag = FALSE;
1708 cparams.memCacheFlag = cacheFlags;
1709 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1710 if (afsd_CloseSynch)
1711 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1714 * Sweep the workstation AFS cache directory, remembering the inodes of
1715 * valid files and deleting extraneous files. Keep sweeping until we
1716 * have the right number of data cache files or we've swept too many
1720 printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
1722 /* Memory-cache based system doesn't need any of this */
1723 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1726 if (SweepAFSCache(&vFilesFound)) {
1727 printf("%s: Error on sweep %d of workstation AFS cache \
1728 directory.\n", rn, cacheIteration);
1733 ("%s: %d out of %d data cache files found in sweep %d.\n",
1734 rn, vFilesFound, cacheFiles, cacheIteration);
1735 } while ((vFilesFound < cacheFiles)
1736 && (cacheIteration < MAX_CACHE_LOOPS));
1737 } else if (afsd_verbose)
1738 printf("%s: Using memory cache, not swept\n", rn);
1741 * Pass the kernel the name of the workstation cache file holding the
1745 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
1747 /* once again, meaningless for a memory-based cache. */
1748 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1749 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1752 call_syscall(AFSCALL_CALL, AFSOP_CELLINFO, (long)fullpn_CellInfoFile, 0,
1756 * Pass the kernel the name of the workstation cache file holding the
1757 * volume information.
1760 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
1761 fullpn_VolInfoFile);
1762 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO, (long)fullpn_VolInfoFile, 0,
1766 * Pass the kernel the name of the afs logging file holding the volume
1770 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
1772 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1773 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG, (long)fullpn_AFSLogFile, 0,
1777 * Tell the kernel about each cell in the configuration.
1779 afsconf_CellApply(afs_cdir, ConfigCell, NULL);
1780 afsconf_CellAliasApply(afs_cdir, ConfigCellAlias, NULL);
1783 * Set the primary cell name.
1785 call_syscall(AFSCALL_CALL, AFSOP_SET_THISCELL, (long)afs_LclCellName, 0, 0, 0);
1788 printf("%s: Forking AFS daemon.\n", rn);
1789 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS, 0, 0, 0, 0);
1792 printf("%s: Forking check server daemon.\n", rn);
1793 fork_syscall(AFSCALL_CALL, AFSOP_START_CS, 0, 0, 0, 0);
1796 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1797 for (i = 0; i < nDaemons; i++) {
1798 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG, 0, 0, 0, 0);
1802 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn, rootVolume);
1803 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1806 * Give the kernel the names of the AFS files cached on the workstation's
1811 ("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1812 rn, cacheFiles, cacheBaseDir);
1813 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1814 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1815 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1816 (long)pathname_for_V[currVFile], 0, 0, 0);
1819 /*#ifndef NETSCAPE_NSAPI*/
1821 /* this breaks solaris if the kernel-mode client has never been installed,
1822 * and it doesn't seem to work now anyway, so just disable it */
1825 * Copy our tokens from the kernel to the user space client
1827 for (i = 0; i < 200; i++) {
1829 * Get the i'th token from the kernel
1831 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1832 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1834 iob.in_size = sizeof(int);
1836 iob.out_size = sizeof(tbuffer);
1838 #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)
1839 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1840 #elif defined(AFS_USR_SGI_ENV)
1841 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1842 #else /* AFS_USR_AIX_ENV */
1843 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1846 usr_assert(errno == EDOM || errno == ENOSYS || errno == ERANGE);
1851 * Now pass the token into the user space kernel
1853 rc = uafs_SetTokens(tbuffer, iob.out_size);
1854 usr_assert(rc == 0);
1856 #endif /* !NETSCAPE_NSAPI */
1859 * All the necessary info has been passed into the kernel to run an AFS
1860 * system. Give the kernel our go-ahead.
1863 printf("%s: Calling AFSOP_GO\n", rn);
1864 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1867 * At this point, we have finished passing the kernel all the info
1868 * it needs to set up the AFS. Mount the AFS root.
1870 printf("%s: All AFS daemons started.\n", rn);
1873 printf("%s: Forking trunc-cache daemon.\n", rn);
1874 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON, 0, 0, 0, 0);
1877 * Mount the AFS filesystem
1880 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1881 usr_assert(rc == 0);
1882 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1883 usr_assert(rc == 0);
1887 * initialize the current directory to the AFS root
1889 afs_CurrentDir = afs_RootVnode;
1890 VN_HOLD(afs_CurrentDir);
1896 uafs_statvfs(struct statvfs *buf)
1902 rc = afs_statvfs(&afs_RootVfs, buf);
1922 if (afs_CurrentDir) {
1923 VN_RELE(afs_CurrentDir);
1925 rc = afs_unmount(&afs_RootVfs);
1926 usr_assert(rc == 0);
1933 * Donate the current thread to the RX server pool.
1936 uafs_RxServerProc(void)
1940 struct rx_call *newcall = NULL;
1942 rxi_MorePackets(2); /* alloc more packets */
1943 threadID = rxi_availProcs++;
1946 sock = OSI_NULLSOCKET;
1947 rxi_ServerProc(threadID, newcall, &sock);
1948 if (sock == OSI_NULLSOCKET) {
1953 rxi_ListenerProc(sock, &threadID, &newcall);
1954 /* assert(threadID != -1); */
1955 /* assert(newcall != NULL); */
1959 struct syscallThreadArgs {
1968 #ifdef NETSCAPE_NSAPI
1970 syscallThread(void *argp)
1971 #else /* NETSCAPE_NSAPI */
1973 syscallThread(void *argp)
1974 #endif /* NETSCAPE_NSAPI */
1977 struct usr_ucred *crp;
1978 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1981 * AFS daemons run authenticated
1983 get_user_struct()->u_viceid = getuid();
1984 crp = get_user_struct()->u_cred;
1985 afs_set_cr_uid(crp, getuid());
1986 afs_set_cr_ruid(crp, getuid());
1987 crp->cr_suid = getuid();
1988 crp->cr_groups[0] = getgid();
1989 crp->cr_ngroups = 1;
1990 for (i = 1; i < NGROUPS; i++) {
1991 crp->cr_groups[i] = NOGROUP;
1994 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1995 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1997 afs_osi_Free(argp, -1);
2002 fork_syscall(long syscall, long afscall, long param1, long param2,
2003 long param3, long param4)
2006 struct syscallThreadArgs *sysArgsP;
2008 sysArgsP = (struct syscallThreadArgs *)
2009 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
2010 usr_assert(sysArgsP != NULL);
2011 sysArgsP->syscall = syscall;
2012 sysArgsP->afscall = afscall;
2013 sysArgsP->param1 = param1;
2014 sysArgsP->param2 = param2;
2015 sysArgsP->param3 = param3;
2016 sysArgsP->param4 = param4;
2018 usr_thread_create(&tid, syscallThread, sysArgsP);
2019 usr_thread_detach(tid);
2024 call_syscall(long syscall, long afscall, long param1, long param2,
2025 long param3, long param4)
2037 a.syscall = syscall;
2038 a.afscall = afscall;
2044 get_user_struct()->u_error = 0;
2045 get_user_struct()->u_ap = (char *)&a;
2047 code = Afs_syscall();
2052 uafs_SetTokens(char *tbuffer, int tlen)
2055 struct afs_ioctl iob;
2060 iob.out = &outbuf[0];
2061 iob.out_size = sizeof(outbuf);
2063 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2072 uafs_RPCStatsEnableProc(void)
2075 struct afs_ioctl iob;
2078 flag = AFSCALL_RXSTATS_ENABLE;
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_RPCStatsDisableProc(void)
2095 struct afs_ioctl iob;
2098 flag = AFSCALL_RXSTATS_DISABLE;
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_RPCStatsClearProc(void)
2115 struct afs_ioctl iob;
2118 flag = AFSCALL_RXSTATS_CLEAR;
2119 iob.in = (char *)&flag;
2120 iob.in_size = sizeof(afs_int32);
2123 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2132 uafs_RPCStatsEnablePeer(void)
2135 struct afs_ioctl iob;
2138 flag = AFSCALL_RXSTATS_ENABLE;
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_RPCStatsDisablePeer(void)
2155 struct afs_ioctl iob;
2158 flag = AFSCALL_RXSTATS_DISABLE;
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 uafs_RPCStatsClearPeer(void)
2175 struct afs_ioctl iob;
2178 flag = AFSCALL_RXSTATS_CLEAR;
2179 iob.in = (char *)&flag;
2180 iob.in_size = sizeof(afs_int32);
2183 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2192 * Lookup a file or directory given its path.
2193 * Call VN_HOLD on the output vnode if successful.
2194 * Returns zero on success, error code on failure.
2196 * Note: Caller must hold the AFS global lock.
2199 uafs_LookupName(char *path, struct usr_vnode *parentVp,
2200 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
2204 struct usr_vnode *vp;
2205 struct usr_vnode *nextVp;
2206 struct usr_vnode *linkVp;
2207 struct vcache *nextVc;
2210 char *nextPathP = NULL;
2215 * Absolute paths must start with the AFS mount point.
2217 if (path[0] != '/') {
2220 path = uafs_afsPathName(path);
2228 * Loop through the path looking for the new directory
2230 tmpPath = afs_osi_Alloc(strlen(path) + 1);
2231 usr_assert(tmpPath != NULL);
2232 strcpy(tmpPath, path);
2235 while (pathP != NULL && *pathP != '\0') {
2236 usr_assert(*pathP != '/');
2239 * terminate the current component and skip over slashes
2241 nextPathP = afs_strchr(pathP, '/');
2242 if (nextPathP != NULL) {
2243 while (*nextPathP == '/') {
2244 *(nextPathP++) = '\0';
2249 * Don't call afs_lookup on non-directories
2251 if (vp->v_type != VDIR) {
2253 afs_osi_Free(tmpPath, strlen(path) + 1);
2257 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2259 * The AFS root is its own parent
2261 nextVp = afs_RootVnode;
2264 * We need execute permission to search a directory
2266 code = afs_access(VTOAFS(vp), VEXEC, get_user_struct()->u_cred);
2269 afs_osi_Free(tmpPath, strlen(path) + 1);
2274 * lookup the next component in the path, we can release the
2275 * subdirectory since we hold the global lock
2279 #ifdef AFS_WEB_ENHANCEMENTS
2280 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2281 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
2284 afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred,
2287 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
2288 #endif /* AFS_WEB_ENHANCEMENTS */
2290 nextVp=AFSTOV(nextVc);
2293 afs_osi_Free(tmpPath, strlen(path) + 1);
2299 * Follow symbolic links for parent directories and
2300 * for leaves when the follow flag is set.
2302 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2304 while (nextVp->v_type == VLNK) {
2305 if (++linkCount > MAX_OSI_LINKS) {
2308 afs_osi_Free(tmpPath, strlen(path) + 1);
2311 code = uafs_LookupLink(nextVp, vp, &linkVp);
2315 afs_osi_Free(tmpPath, strlen(path) + 1);
2329 * Special case, nextPathP is non-null if pathname ends in slash
2331 if (nextPathP != NULL && vp->v_type != VDIR) {
2333 afs_osi_Free(tmpPath, strlen(path) + 1);
2337 afs_osi_Free(tmpPath, strlen(path) + 1);
2343 * Lookup the target of a symbolic link
2344 * Call VN_HOLD on the output vnode if successful.
2345 * Returns zero on success, error code on failure.
2347 * Note: Caller must hold the AFS global lock.
2350 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
2351 struct usr_vnode **vpp)
2356 struct usr_vnode *linkVp;
2358 struct iovec iov[1];
2362 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
2363 usr_assert(pathP != NULL);
2366 * set up the uio buffer
2368 iov[0].iov_base = pathP;
2369 iov[0].iov_len = MAX_OSI_PATH + 1;
2370 uio.uio_iov = &iov[0];
2374 uio.uio_fmode = FREAD;
2375 uio.uio_resid = MAX_OSI_PATH + 1;
2378 * Read the link data
2380 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
2382 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2385 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2389 * Find the target of the symbolic link
2391 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2393 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2397 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2403 * Lookup the parent of a file or directory given its path
2404 * Call VN_HOLD on the output vnode if successful.
2405 * Returns zero on success, error code on failure.
2407 * Note: Caller must hold the AFS global lock.
2410 uafs_LookupParent(char *path, struct usr_vnode **vpp)
2415 struct usr_vnode *parentP;
2420 * Absolute path names must start with the AFS mount point.
2423 pathP = uafs_afsPathName(path);
2424 if (pathP == NULL) {
2430 * Find the length of the parent path
2433 while (len > 0 && path[len - 1] == '/') {
2439 while (len > 0 && path[len - 1] != '/') {
2446 pathP = afs_osi_Alloc(len);
2447 usr_assert(pathP != NULL);
2448 memcpy(pathP, path, len - 1);
2449 pathP[len - 1] = '\0';
2452 * look up the parent
2454 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2455 afs_osi_Free(pathP, len);
2459 if (parentP->v_type != VDIR) {
2469 * Return a pointer to the first character in the last component
2473 uafs_LastPath(char *path)
2478 while (len > 0 && path[len - 1] == '/') {
2481 while (len > 0 && path[len - 1] != '/') {
2491 * Set the working directory.
2494 uafs_chdir(char *path)
2498 retval = uafs_chdir_r(path);
2504 uafs_chdir_r(char *path)
2509 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2514 if (dirP->v_type != VDIR) {
2519 VN_RELE(afs_CurrentDir);
2520 afs_CurrentDir = dirP;
2525 * Create a directory.
2528 uafs_mkdir(char *path, int mode)
2532 retval = uafs_mkdir_r(path, mode);
2538 uafs_mkdir_r(char *path, int mode)
2542 struct vnode *parentP;
2543 struct vcache *dirP;
2544 struct usr_vattr attrs;
2546 if (uafs_IsRoot(path)) {
2551 * Look up the parent directory.
2553 nameP = uafs_LastPath(path);
2554 if (nameP != NULL) {
2555 code = uafs_LookupParent(path, &parentP);
2561 parentP = afs_CurrentDir;
2567 * Make sure the directory has at least one character
2569 if (*nameP == '\0') {
2576 * Create the directory
2578 usr_vattr_null(&attrs);
2579 attrs.va_type = VREG;
2580 attrs.va_mode = mode;
2581 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2582 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2584 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, get_user_struct()->u_cred);
2590 VN_RELE(AFSTOV(dirP));
2595 * Return 1 if path is the AFS root, otherwise return 0
2598 uafs_IsRoot(char *path)
2600 while (*path == '/' && *(path + 1) == '/') {
2603 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2606 path += afs_mountDirLen;
2607 while (*path == '/') {
2610 if (*path != '\0') {
2618 * Note: file name may not end in a slash.
2621 uafs_open(char *path, int flags, int mode)
2625 retval = uafs_open_r(path, flags, mode);
2631 uafs_open_r(char *path, int flags, int mode)
2637 struct usr_vnode *fileP;
2638 struct usr_vnode *dirP;
2639 struct usr_vattr attrs;
2644 if (uafs_IsRoot(path)) {
2645 fileP = afs_RootVnode;
2649 * Look up the parent directory.
2651 nameP = uafs_LastPath(path);
2652 if (nameP != NULL) {
2653 code = uafs_LookupParent(path, &dirP);
2659 dirP = afs_CurrentDir;
2665 * Make sure the filename has at least one character
2667 if (*nameP == '\0') {
2674 * Get the VNODE for this file
2676 if (flags & O_CREAT) {
2677 usr_vattr_null(&attrs);
2678 attrs.va_type = VREG;
2679 attrs.va_mode = mode;
2680 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2681 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2682 if (flags & O_TRUNC) {
2688 afs_create(VTOAFS(dirP), nameP, &attrs,
2689 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2690 &vc, get_user_struct()->u_cred);
2699 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2707 * Check whether we have access to this file
2710 if (flags & (O_RDONLY | O_RDWR)) {
2713 if (flags & (O_WRONLY | O_RDWR)) {
2717 fileMode = VREAD; /* since O_RDONLY is 0 */
2718 code = afs_access(VTOAFS(fileP), fileMode, get_user_struct()->u_cred);
2726 * Get the file attributes, all we need is the size
2728 code = afs_getattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2738 * Setup the open flags
2741 if (flags & O_TRUNC) {
2742 openFlags |= FTRUNC;
2744 if (flags & O_APPEND) {
2745 openFlags |= FAPPEND;
2747 if (flags & O_SYNC) {
2750 if (flags & O_SYNC) {
2753 if (flags & (O_RDONLY | O_RDWR)) {
2756 if (flags & (O_WRONLY | O_RDWR)) {
2757 openFlags |= FWRITE;
2759 if ((openFlags & (FREAD | FWRITE)) == 0) {
2760 /* O_RDONLY is 0, so ... */
2765 * Truncate if necessary
2767 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2768 usr_vattr_null(&attrs);
2769 attrs.va_mask = ATTR_SIZE;
2771 code = afs_setattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2783 code = afs_open(&vc, openFlags, get_user_struct()->u_cred);
2791 * Put the vnode pointer into the file table
2793 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2794 if (afs_FileTable[fd] == NULL) {
2795 afs_FileTable[fd] = fileP;
2796 afs_FileFlags[fd] = openFlags;
2797 if (flags & O_APPEND) {
2798 afs_FileOffsets[fd] = attrs.va_size;
2800 afs_FileOffsets[fd] = 0;
2805 if (fd == MAX_OSI_FILES) {
2818 uafs_creat(char *path, int mode)
2821 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2826 uafs_creat_r(char *path, int mode)
2829 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2837 uafs_write(int fd, char *buf, int len)
2841 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2847 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2851 retval = uafs_pwrite_r(fd, buf, len, offset);
2857 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2861 struct iovec iov[1];
2862 struct usr_vnode *fileP;
2865 * Make sure this is an open file
2867 fileP = afs_FileTable[fd];
2868 if (fileP == NULL) {
2874 * set up the uio buffer
2876 iov[0].iov_base = buf;
2877 iov[0].iov_len = len;
2878 uio.uio_iov = &iov[0];
2880 uio.uio_offset = offset;
2882 uio.uio_fmode = FWRITE;
2883 uio.uio_resid = len;
2889 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], get_user_struct()->u_cred, 0);
2895 afs_FileOffsets[fd] = uio.uio_offset;
2896 return (len - uio.uio_resid);
2903 uafs_read(int fd, char *buf, int len)
2907 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2913 uafs_pread(int fd, char *buf, int len, off_t offset)
2917 retval = uafs_pread_r(fd, buf, len, offset);
2923 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2927 struct iovec iov[1];
2928 struct usr_vnode *fileP;
2929 struct usr_buf *bufP;
2932 * Make sure this is an open file
2934 fileP = afs_FileTable[fd];
2935 if (fileP == NULL) {
2941 * set up the uio buffer
2943 iov[0].iov_base = buf;
2944 iov[0].iov_len = len;
2945 uio.uio_iov = &iov[0];
2947 uio.uio_offset = offset;
2949 uio.uio_fmode = FREAD;
2950 uio.uio_resid = len;
2955 code = afs_read(VTOAFS(fileP), &uio, get_user_struct()->u_cred, 0, &bufP, 0);
2961 afs_FileOffsets[fd] = uio.uio_offset;
2962 return (len - uio.uio_resid);
2966 * Copy the attributes of a file into a stat structure.
2968 * NOTE: Caller must hold the global AFS lock.
2971 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2974 struct usr_vattr attrs;
2979 * Get the attributes
2981 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2987 * Copy the attributes, zero fields that aren't set
2989 memset((void *)stats, 0, sizeof(struct stat));
2991 stats->st_ino = attrs.va_nodeid;
2992 stats->st_mode = attrs.va_mode;
2993 stats->st_nlink = attrs.va_nlink;
2994 stats->st_uid = attrs.va_uid;
2995 stats->st_gid = attrs.va_gid;
2996 stats->st_rdev = attrs.va_rdev;
2997 stats->st_size = attrs.va_size;
2998 stats->st_atime = attrs.va_atime.tv_sec;
2999 stats->st_mtime = attrs.va_mtime.tv_sec;
3000 stats->st_ctime = attrs.va_ctime.tv_sec;
3001 stats->st_blksize = attrs.va_blocksize;
3002 stats->st_blocks = attrs.va_blocks;
3008 * Get the attributes of a file, do follow links
3011 uafs_stat(char *path, struct stat *buf)
3015 retval = uafs_stat_r(path, buf);
3021 uafs_stat_r(char *path, struct stat *buf)
3026 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3031 code = uafs_GetAttr(vp, buf);
3041 * Get the attributes of a file, don't follow links
3044 uafs_lstat(char *path, struct stat *buf)
3048 retval = uafs_lstat_r(path, buf);
3054 uafs_lstat_r(char *path, struct stat *buf)
3059 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3064 code = uafs_GetAttr(vp, buf);
3074 * Get the attributes of an open file
3077 uafs_fstat(int fd, struct stat *buf)
3081 retval = uafs_fstat_r(fd, buf);
3087 uafs_fstat_r(int fd, struct stat *buf)
3092 vp = afs_FileTable[fd];
3097 code = uafs_GetAttr(vp, buf);
3106 * change the permissions on a file
3109 uafs_chmod(char *path, int mode)
3113 retval = uafs_chmod_r(path, mode);
3119 uafs_chmod_r(char *path, int mode)
3123 struct usr_vattr attrs;
3125 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3130 usr_vattr_null(&attrs);
3131 attrs.va_mask = ATTR_MODE;
3132 attrs.va_mode = mode;
3133 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3143 * change the permissions on an open file
3146 uafs_fchmod(int fd, int mode)
3150 retval = uafs_fchmod_r(fd, mode);
3156 uafs_fchmod_r(int fd, int mode)
3160 struct usr_vattr attrs;
3162 vp = afs_FileTable[fd];
3167 usr_vattr_null(&attrs);
3168 attrs.va_mask = ATTR_MODE;
3169 attrs.va_mode = mode;
3170 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3182 uafs_truncate(char *path, int length)
3186 retval = uafs_truncate_r(path, length);
3192 uafs_truncate_r(char *path, int length)
3196 struct usr_vattr attrs;
3198 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3203 usr_vattr_null(&attrs);
3204 attrs.va_mask = ATTR_SIZE;
3205 attrs.va_size = length;
3206 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3216 * truncate an open file
3219 uafs_ftruncate(int fd, int length)
3223 retval = uafs_ftruncate_r(fd, length);
3229 uafs_ftruncate_r(int fd, int length)
3233 struct usr_vattr attrs;
3235 vp = afs_FileTable[fd];
3240 usr_vattr_null(&attrs);
3241 attrs.va_mask = ATTR_SIZE;
3242 attrs.va_size = length;
3243 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3252 * set the read/write file pointer of an open file
3255 uafs_lseek(int fd, int offset, int whence)
3259 retval = uafs_lseek_r(fd, offset, whence);
3265 uafs_lseek_r(int fd, int offset, int whence)
3269 struct usr_vattr attrs;
3270 struct usr_vnode *vp;
3272 vp = afs_FileTable[fd];
3279 newpos = afs_FileOffsets[fd] + offset;
3285 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
3290 newpos = attrs.va_size + offset;
3300 afs_FileOffsets[fd] = newpos;
3312 retval = uafs_fsync_r(fd);
3318 uafs_fsync_r(int fd)
3321 struct usr_vnode *fileP;
3324 fileP = afs_FileTable[fd];
3325 if (fileP == NULL) {
3330 code = afs_fsync(VTOAFS(fileP), get_user_struct()->u_cred);
3347 retval = uafs_close_r(fd);
3353 uafs_close_r(int fd)
3356 struct usr_vnode *fileP;
3358 fileP = afs_FileTable[fd];
3359 if (fileP == NULL) {
3363 afs_FileTable[fd] = NULL;
3365 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], get_user_struct()->u_cred);
3376 * Create a hard link from the source to the target
3377 * Note: file names may not end in a slash.
3380 uafs_link(char *existing, char *new)
3384 retval = uafs_link_r(existing, new);
3390 uafs_link_r(char *existing, char *new)
3393 struct usr_vnode *existP;
3394 struct usr_vnode *dirP;
3397 if (uafs_IsRoot(new)) {
3402 * Look up the existing node.
3404 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3411 * Look up the parent directory.
3413 nameP = uafs_LastPath(new);
3414 if (nameP != NULL) {
3415 code = uafs_LookupParent(new, &dirP);
3422 dirP = afs_CurrentDir;
3428 * Make sure the filename has at least one character
3430 if (*nameP == '\0') {
3440 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3451 * Create a symbolic link from the source to the target
3452 * Note: file names may not end in a slash.
3455 uafs_symlink(char *target, char *source)
3459 retval = uafs_symlink_r(target, source);
3465 uafs_symlink_r(char *target, char *source)
3468 struct usr_vnode *dirP;
3469 struct usr_vattr attrs;
3472 if (uafs_IsRoot(source)) {
3477 * Look up the parent directory.
3479 nameP = uafs_LastPath(source);
3480 if (nameP != NULL) {
3481 code = uafs_LookupParent(source, &dirP);
3487 dirP = afs_CurrentDir;
3493 * Make sure the filename has at least one character
3495 if (*nameP == '\0') {
3504 usr_vattr_null(&attrs);
3505 attrs.va_type = VLNK;
3506 attrs.va_mode = 0777;
3507 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
3508 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
3509 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
3519 * Read a symbolic link into the buffer
3522 uafs_readlink(char *path, char *buf, int len)
3526 retval = uafs_readlink_r(path, buf, len);
3532 uafs_readlink_r(char *path, char *buf, int len)
3535 struct usr_vnode *vp;
3537 struct iovec iov[1];
3539 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3545 if (vp->v_type != VLNK) {
3552 * set up the uio buffer
3554 iov[0].iov_base = buf;
3555 iov[0].iov_len = len;
3556 uio.uio_iov = &iov[0];
3560 uio.uio_fmode = FREAD;
3561 uio.uio_resid = len;
3566 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3574 * return the number of bytes read
3576 return (len - uio.uio_resid);
3580 * Remove a file (or directory)
3581 * Note: file name may not end in a slash.
3584 uafs_unlink(char *path)
3588 retval = uafs_unlink_r(path);
3594 uafs_unlink_r(char *path)
3597 struct usr_vnode *dirP;
3600 if (uafs_IsRoot(path)) {
3605 * Look up the parent directory.
3607 nameP = uafs_LastPath(path);
3608 if (nameP != NULL) {
3609 code = uafs_LookupParent(path, &dirP);
3615 dirP = afs_CurrentDir;
3621 * Make sure the filename has at least one character
3623 if (*nameP == '\0') {
3632 code = afs_remove(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3643 * Rename a file (or directory)
3646 uafs_rename(char *old, char *new)
3650 retval = uafs_rename_r(old, new);
3656 uafs_rename_r(char *old, char *new)
3661 struct usr_vnode *odirP;
3662 struct usr_vnode *ndirP;
3664 if (uafs_IsRoot(new)) {
3669 * Look up the parent directories.
3671 onameP = uafs_LastPath(old);
3672 if (onameP != NULL) {
3673 code = uafs_LookupParent(old, &odirP);
3679 odirP = afs_CurrentDir;
3683 nnameP = uafs_LastPath(new);
3684 if (nnameP != NULL) {
3685 code = uafs_LookupParent(new, &ndirP);
3691 ndirP = afs_CurrentDir;
3697 * Make sure the filename has at least one character
3699 if (*onameP == '\0' || *nnameP == '\0') {
3709 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, get_user_struct()->u_cred);
3721 * Remove a or directory
3722 * Note: file name may not end in a slash.
3725 uafs_rmdir(char *path)
3729 retval = uafs_rmdir_r(path);
3735 uafs_rmdir_r(char *path)
3738 struct usr_vnode *dirP;
3741 if (uafs_IsRoot(path)) {
3746 * Look up the parent directory.
3748 nameP = uafs_LastPath(path);
3749 if (nameP != NULL) {
3750 code = uafs_LookupParent(path, &dirP);
3756 dirP = afs_CurrentDir;
3762 * Make sure the directory name has at least one character
3764 if (*nameP == '\0') {
3771 * Remove the directory
3773 code = afs_rmdir(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3784 * Flush a file from the AFS cache
3787 uafs_FlushFile(char *path)
3790 struct afs_ioctl iob;
3798 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3809 uafs_FlushFile_r(char *path)
3813 retval = uafs_FlushFile(path);
3822 uafs_opendir(char *path)
3826 retval = uafs_opendir_r(path);
3832 uafs_opendir_r(char *path)
3835 struct usr_vnode *fileP;
3839 * Open the directory for reading
3841 fd = uafs_open_r(path, O_RDONLY, 0);
3846 fileP = afs_FileTable[fd];
3847 if (fileP == NULL) {
3851 if (fileP->v_type != VDIR) {
3858 * Set up the directory structures
3861 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3862 sizeof(struct usr_dirent));
3863 usr_assert(dirp != NULL);
3864 dirp->dd_buf = (char *)(dirp + 1);
3874 * Read directory entries into a file system independent format.
3875 * This routine was developed to support AFS cache consistency testing.
3876 * You should use uafs_readdir instead.
3879 uafs_getdents(int fd, struct min_direct *buf, int len)
3883 retval = uafs_getdents_r(fd, buf, len);
3889 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3893 struct usr_vnode *vp;
3894 struct iovec iov[1];
3897 * Make sure this is an open file
3899 vp = afs_FileTable[fd];
3907 * set up the uio buffer
3909 iov[0].iov_base = (char *)buf;
3910 iov[0].iov_len = len;
3911 uio.uio_iov = &iov[0];
3913 uio.uio_offset = afs_FileOffsets[fd];
3915 uio.uio_fmode = FREAD;
3916 uio.uio_resid = len;
3919 * read the next chunk from the directory
3921 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3927 afs_FileOffsets[fd] = uio.uio_offset;
3928 return (len - uio.uio_resid);
3932 * read from a directory (names only)
3935 uafs_readdir(usr_DIR * dirp)
3937 struct usr_dirent *retval;
3939 retval = uafs_readdir_r(dirp);
3945 uafs_readdir_r(usr_DIR * dirp)
3950 struct usr_vnode *vp;
3951 struct iovec iov[1];
3952 struct usr_dirent *direntP;
3953 struct min_direct *directP;
3961 * Make sure this is an open file
3963 vp = afs_FileTable[dirp->dd_fd];
3970 * If there are no entries in the stream buffer
3971 * then read another chunk
3973 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3974 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3976 * set up the uio buffer
3978 iov[0].iov_base = dirp->dd_buf;
3979 iov[0].iov_len = USR_DIRSIZE;
3980 uio.uio_iov = &iov[0];
3982 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3984 uio.uio_fmode = FREAD;
3985 uio.uio_resid = USR_DIRSIZE;
3988 * read the next chunk from the directory
3990 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3995 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3997 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3999 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
4003 * Check for end of file
4005 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
4009 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
4010 usr_assert(len <= dirp->dd_size);
4013 * Copy the next entry into the usr_dirent structure and advance
4015 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
4016 direntP->d_ino = directP->d_fileno;
4017 direntP->d_off = direntP->d_reclen;
4019 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
4020 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
4021 direntP->d_name[directP->d_namlen] = '\0';
4022 dirp->dd_loc += len;
4023 dirp->dd_size -= len;
4032 uafs_closedir(usr_DIR * dirp)
4036 retval = uafs_closedir_r(dirp);
4042 uafs_closedir_r(usr_DIR * dirp)
4053 afs_osi_Free((char *)dirp,
4054 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
4055 rc = uafs_close_r(fd);
4060 * Do AFS authentication
4063 uafs_klog(char *user, char *cell, char *passwd, char **reason)
4066 afs_int32 password_expires = -1;
4068 usr_mutex_lock(&osi_authenticate_lock);
4070 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
4071 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
4072 passwd, 0, &password_expires, 0, reason);
4073 usr_mutex_unlock(&osi_authenticate_lock);
4078 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
4082 retval = uafs_klog(user, cell, passwd, reason);
4088 * Destroy AFS credentials from the kernel cache
4095 usr_mutex_lock(&osi_authenticate_lock);
4096 code = ktc_ForgetAllTokens();
4097 usr_mutex_unlock(&osi_authenticate_lock);
4106 retval = uafs_unlog();
4112 * Strip the AFS mount point from a pathname string. Return
4113 * NULL if the path is a relative pathname or if the path
4114 * doesn't start with the AFS mount point string.
4117 uafs_afsPathName(char *path)
4126 for (i = 1, p = path + 1; *p != '\0'; p++) {
4127 /* Ignore duplicate slashes */
4128 if (*p == '/' && lastchar == '/')
4130 /* Is this a subdirectory of the AFS mount point? */
4131 if (afs_mountDir[i] == '\0' && *p == '/') {
4132 /* strip leading slashes */
4133 while (*(++p) == '/');
4136 /* Reject paths that are not within AFS */
4137 if (*p != afs_mountDir[i])
4142 /* Is this the AFS mount point? */
4143 if (afs_mountDir[i] == '\0') {
4144 usr_assert(*p == '\0');
4150 #ifdef AFS_WEB_ENHANCEMENTS
4153 * klog but don't allocate a new pag
4156 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
4159 afs_int32 password_expires = -1;
4161 usr_mutex_lock(&osi_authenticate_lock);
4162 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
4163 /*+KA_USERAUTH_DOSETPAG2 */ , user,
4164 NULL, cell, passwd, 0,
4165 &password_expires, 0, reason);
4166 usr_mutex_unlock(&osi_authenticate_lock);
4171 * uafs_getcellstatus
4172 * get the cell status
4175 uafs_getcellstatus(char *cell, afs_int32 * status)
4178 struct afs_ioctl iob;
4181 iob.in_size = strlen(cell) + 1;
4185 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
4193 *status = (intptr_t)iob.out;
4199 * Get quota of volume associated with path
4202 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
4205 struct afs_ioctl iob;
4206 VolumeStatus *status;
4212 iob.out_size = 1024;
4214 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
4222 status = (VolumeStatus *) buf;
4223 *BlocksInUse = status->BlocksInUse;
4224 *MaxQuota = status->MaxQuota;
4230 * Set quota of volume associated with path
4233 uafs_setvolquota(char *path, afs_int32 MaxQuota)
4236 struct afs_ioctl iob;
4237 VolumeStatus *status;
4245 memset(buf, 0, sizeof(VolumeStatus));
4246 status = (VolumeStatus *) buf;
4247 status->MaxQuota = MaxQuota;
4248 status->MinQuota = -1;
4250 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
4262 * uafs_statmountpoint
4263 * Determine whether a dir. is a mount point or not
4264 * return 1 if mount point, 0 if not
4267 uafs_statmountpoint(char *path)
4272 retval = uafs_statmountpoint_r(path);
4278 uafs_statmountpoint_r(char *path)
4285 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
4300 * Get a list of rights for the current user on path.
4303 uafs_getRights(char *path)
4310 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
4318 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
4319 | PRSFS_LOCK | PRSFS_ADMINISTER;
4321 afs_rights = afs_getRights(VTOAFS(vp), afs_rights, get_user_struct()->u_cred);
4326 #endif /* AFS_WEB_ENHANCEMENTS */
4328 #endif /* UKERNEL */