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 #define CACHEINFOFILE "cacheinfo"
39 #define AFSLOGFILE "AFSLog"
40 #define DCACHEFILE "CacheItems"
41 #define VOLINFOFILE "VolumeItems"
42 #define CELLINFOFILE "CellItems"
46 #define MIN(A,B) ((A)<(B)?(A):(B))
49 #define MAX(A,B) ((A)>(B)?(A):(B))
52 extern int cacheDiskType;
54 char afs_LclCellName[64];
56 struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
57 int afs_FileFlags[MAX_OSI_FILES];
58 off_t afs_FileOffsets[MAX_OSI_FILES];
60 #define MAX_CACHE_LOOPS 4
62 struct usr_vfs afs_RootVfs;
63 struct usr_vnode *afs_RootVnode = NULL;
64 struct usr_vnode *afs_CurrentDir = NULL;
66 afs_int32 cacheBlocks; /* Num blocks in cache */
67 afs_int32 cacheFiles = 1000; /* Num files in workstation cache */
68 afs_int32 cacheStatEntries = 300; /* Num of stat cache entries */
69 char cacheBaseDir[1024]; /* AFS cache directory */
70 char confDir[1024]; /* AFS configuration directory */
71 char afs_mountDir[1024]; /* AFS mount point */
72 int afs_mountDirLen; /* strlen of AFS mount point */
73 char fullpn_DCacheFile[1024]; /* Full pathname of DCACHEFILE */
74 char fullpn_VolInfoFile[1024]; /* Full pathname of VOLINFOFILE */
75 char fullpn_CellInfoFile[1024]; /* Full pathname of CELLINFOFILE */
76 char fullpn_AFSLogFile[1024]; /* Full pathname of AFSLOGFILE */
77 char fullpn_CacheInfo[1024]; /* Full pathname of CACHEINFO */
78 char fullpn_VFile[1024]; /* Full pathname of data cache files */
79 char *vFileNumber; /* Ptr to number in file pathname */
80 char rootVolume[64] = "root.afs"; /* AFS root volume name */
81 afs_int32 isHomeCell; /* Is current cell info for home cell */
82 int createAndTrunc = O_CREAT | O_TRUNC; /* Create & truncate on open */
83 int ownerRWmode = 0600; /* Read/write OK by owner */
84 static int nDaemons = 2; /* Number of background daemons */
85 static int chunkSize = 0; /* 2^chunkSize bytes per chunk */
86 static int dCacheSize = 300; /* # of dcache entries */
87 static int vCacheSize = 50; /* # of volume cache entries */
88 static int cacheFlags = 0; /* Flags to cache manager */
89 static int preallocs = 400; /* Def # of allocated memory blocks */
90 int afsd_verbose = 0; /* Are we being chatty? */
91 int afsd_debug = 0; /* Are we printing debugging info? */
92 int afsd_CloseSynch = 0; /* Are closes synchronous or not? */
94 #define AFSD_INO_T afs_uint32
95 char **pathname_for_V; /* Array of cache file pathnames */
96 int missing_DCacheFile = 1; /* Is the DCACHEFILE missing? */
97 int missing_VolInfoFile = 1; /* Is the VOLINFOFILE missing? */
98 int missing_CellInfoFile = 1;
99 struct afs_cacheParams cparams; /* params passed to cache manager */
100 struct afsconf_dir *afs_cdir; /* config dir */
102 int afs_bufferpages = 100;
103 int usr_udpcksum = 0;
105 usr_key_t afs_global_u_key;
107 struct usr_proc *afs_global_procp = NULL;
108 struct usr_ucred *afs_global_ucredp = NULL;
109 struct usr_sysent usr_sysent[200];
111 #ifdef AFS_USR_OSF_ENV
113 #else /* AFS_USR_OSF_ENV */
115 #endif /* AFS_USR_OSF_ENV */
117 struct usr_ucred afs_osi_cred, *afs_osi_credp;
118 usr_mutex_t afs_global_lock;
119 usr_thread_t afs_global_owner;
120 usr_mutex_t rx_global_lock;
121 usr_thread_t rx_global_owner;
122 usr_mutex_t osi_inode_lock;
123 usr_mutex_t osi_waitq_lock;
124 usr_mutex_t osi_authenticate_lock;
126 afs_lock_t osi_flplock;
127 afs_lock_t osi_fsplock;
130 #ifndef NETSCAPE_NSAPI
133 * Mutex and condition variable used to implement sleep
135 pthread_mutex_t usr_sleep_mutex;
136 pthread_cond_t usr_sleep_cond;
138 #endif /* !NETSCAPE_NSAPI */
140 int call_syscall(long, long, long, long, long, long);
144 * Hash table mapping addresses onto wait structures for
145 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
147 typedef struct osi_wait {
151 struct osi_wait *next;
152 struct osi_wait *prev;
154 struct osi_wait *timedNext;
155 struct osi_wait *timedPrev;
159 * Head of the linked list of available waitq structures.
161 osi_wait_t *osi_waithash_avail;
164 * List of timed waits, NSAPI does not provide a cond_timed
165 * wait, so we need to keep track of the timed waits ourselves and
166 * periodically check for expirations
168 osi_wait_t *osi_timedwait_head;
169 osi_wait_t *osi_timedwait_tail;
174 } osi_waithash_table[OSI_WAITHASH_SIZE];
177 * Never call afs_brelse
180 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
187 * I am not sure what to do with these, they assert for now
190 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
240 * ioctl should never fall through, the only files we know
241 * about are AFS files
251 * We do not support the inode related system calls
254 afs_syscall_icreate(long a, long b, long c, long d, long e, long f)
261 afs_syscall_iincdec(int dev, int inode, int inode_p1, int amount)
268 afs_syscall_iopen(int dev, int inode, int usrmod)
275 afs_syscall_ireadwrite(void)
282 * these routines are referenced in the vfsops structure, but
283 * should never get called
314 * uiomove copies data between kernel buffers and uio buffers
317 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
324 nio = uio->uio_iovcnt;
334 while (nio > 0 && n > 0) {
335 len = MIN(n, iovp->iov_len);
336 if (rw == UIO_READ) {
337 memcpy(iovp->iov_base, ptr, len);
339 memcpy(ptr, iovp->iov_base, len);
343 uio->uio_resid -= len;
344 uio->uio_offset += len;
345 iovp->iov_base = (char *)(iovp->iov_base) + len;
346 iovp->iov_len -= len;
357 * routines to manage user credentials
360 usr_crcopy(struct usr_ucred *credp)
362 struct usr_ucred *newcredp;
364 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
366 newcredp->cr_ref = 1;
373 struct usr_ucred *newcredp;
375 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
376 newcredp->cr_ref = 1;
381 usr_crfree(struct usr_ucred *credp)
384 if (credp->cr_ref == 0) {
385 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
391 usr_crhold(struct usr_ucred *credp)
398 usr_vattr_null(struct usr_vattr *vap)
403 n = sizeof(struct usr_vattr);
411 * Initialize the thread specific data used to simulate the
412 * kernel environment for each thread. The user structure
413 * is stored in the thread specific data.
416 uafs_InitThread(void)
419 struct usr_user *uptr;
422 * initialize the thread specific user structure. Use malloc to
423 * allocate the data block, so pthread_finish can free the buffer
424 * when this thread terminates.
427 (struct usr_user *)malloc(sizeof(struct usr_user) +
428 sizeof(struct usr_ucred));
429 usr_assert(uptr != NULL);
432 uptr->u_procp = afs_global_procp;
433 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
434 *uptr->u_cred = *afs_global_ucredp;
435 st = usr_setspecific(afs_global_u_key, (void *)uptr);
440 * routine to get the user structure from the thread specific data.
441 * this routine is used to implement the global 'u' structure. Initializes
442 * the thread if needed.
445 get_user_struct(void)
447 struct usr_user *uptr;
449 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
453 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
455 usr_assert(uptr != NULL);
461 * Hash an address for the waithash table
463 #define WAITHASH(X) \
464 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
470 afs_osi_Sleep(void *x)
474 int glockOwner = ISAFS_GLOCK();
476 usr_mutex_lock(&osi_waitq_lock);
481 if (osi_waithash_avail == NULL) {
482 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
483 usr_cond_init(&waitp->cond);
485 waitp = osi_waithash_avail;
486 osi_waithash_avail = osi_waithash_avail->next;
490 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
491 osi_waithash_table[index].tail, next, prev);
492 waitp->expiration = 0;
493 waitp->timedNext = NULL;
494 waitp->timedPrev = NULL;
495 while (waitp->flag == 0) {
496 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
498 DLL_DELETE(waitp, osi_waithash_table[index].head,
499 osi_waithash_table[index].tail, next, prev);
500 waitp->next = osi_waithash_avail;
501 osi_waithash_avail = waitp;
502 usr_mutex_unlock(&osi_waitq_lock);
509 afs_osi_SleepSig(void *x)
516 afs_osi_Wakeup(void *x)
522 usr_mutex_lock(&osi_waitq_lock);
523 waitp = osi_waithash_table[index].head;
525 if (waitp->addr == x && waitp->flag == 0) {
527 usr_cond_signal(&waitp->cond);
531 usr_mutex_unlock(&osi_waitq_lock);
536 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
542 int glockOwner = ISAFS_GLOCK();
544 tv.tv_sec = msec / 1000;
545 tv.tv_nsec = (msec % 1000) * 1000000;
546 if (handle == NULL) {
550 usr_thread_sleep(&tv);
556 usr_mutex_lock(&osi_waitq_lock);
560 index = WAITHASH((caddr_t) handle);
561 if (osi_waithash_avail == NULL) {
562 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
563 usr_cond_init(&waitp->cond);
565 waitp = osi_waithash_avail;
566 osi_waithash_avail = osi_waithash_avail->next;
568 waitp->addr = (caddr_t) handle;
570 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
571 osi_waithash_table[index].tail, next, prev);
572 tv.tv_sec += time(NULL);
573 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
574 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
575 timedNext, timedPrev);
576 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
582 DLL_DELETE(waitp, osi_waithash_table[index].head,
583 osi_waithash_table[index].tail, next, prev);
584 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
586 waitp->next = osi_waithash_avail;
587 osi_waithash_avail = waitp;
588 usr_mutex_unlock(&osi_waitq_lock);
597 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
599 afs_osi_Wakeup(handle);
603 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
604 * to explicitly signal cond_timed_waits when their timers expire
607 afs_osi_CheckTimedWaits(void)
612 curTime = time(NULL);
613 usr_mutex_lock(&osi_waitq_lock);
614 waitp = osi_timedwait_head;
615 while (waitp != NULL) {
616 usr_assert(waitp->expiration != 0);
617 if (waitp->expiration <= curTime) {
619 usr_cond_signal(&waitp->cond);
621 waitp = waitp->timedNext;
623 usr_mutex_unlock(&osi_waitq_lock);
628 * I-node numbers are indeces into a table containing a filename
629 * i-node structure and a vnode structure. When we create an i-node,
630 * we copy the name into the array and initialize enough of the fields
631 * in the inode and vnode structures to get the client to work.
634 struct usr_inode i_node;
637 osi_file_table_t *osi_file_table;
639 int max_osi_files = 0;
642 * Allocate a slot in the file table if there is not one there already,
643 * copy in the file name and kludge up the vnode and inode structures
646 lookupname(char *fnamep, int segflg, int followlink,
647 struct usr_vnode **compvpp)
651 struct usr_inode *ip;
652 struct usr_vnode *vp;
654 /*usr_assert(followlink == 0); */
657 * Assume relative pathnames refer to files in AFS
659 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
661 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
666 usr_mutex_lock(&osi_inode_lock);
668 for (i = 0; i < n_osi_files; i++) {
669 if (strcmp(fnamep, osi_file_table[i].name) == 0) {
670 *compvpp = &osi_file_table[i].i_node.i_vnode;
671 (*compvpp)->v_count++;
672 usr_mutex_unlock(&osi_inode_lock);
677 if (n_osi_files == max_osi_files) {
678 usr_mutex_unlock(&osi_inode_lock);
682 osi_file_table[n_osi_files].name = afs_osi_Alloc(strlen(fnamep) + 1);
683 usr_assert(osi_file_table[n_osi_files].name != NULL);
684 strcpy(osi_file_table[n_osi_files].name, fnamep);
685 ip = &osi_file_table[i].i_node;
687 vp->v_data = (caddr_t) ip;
690 ip->i_number = n_osi_files;
692 usr_mutex_unlock(&osi_inode_lock);
698 * open a file given its i-node number
701 osi_UFSOpen(afs_dcache_id_t *ino)
709 if (ino->ufs > n_osi_files) {
715 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
716 usr_assert(fp != NULL);
717 fp->fd = open(osi_file_table[ino->ufs - 1].name, O_RDWR | O_CREAT, 0);
720 afs_osi_Free((char *)fp, sizeof(struct osi_file));
724 rc = fstat(fp->fd, &st);
727 afs_osi_Free((void *)fp, sizeof(struct osi_file));
731 fp->size = st.st_size;
734 fp->vnode = (struct usr_vnode *)fp;
741 osi_UFSClose(struct osi_file *fp)
751 afs_osi_Free((void *)fp, sizeof(struct osi_file));
755 afs_osi_Free((void *)fp, sizeof(struct osi_file));
761 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
768 rc = ftruncate(fp->fd, len);
780 afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
789 rc = lseek(fp->fd, offset, SEEK_SET);
791 rc = lseek(fp->fd, fp->offset, SEEK_SET);
799 ret = read(fp->fd, buf, len);
806 rc = fstat(fp->fd, &st);
812 fp->size = st.st_size;
818 afs_osi_Write(struct osi_file *fp, afs_int32 offset, void *buf, afs_int32 len)
827 rc = lseek(fp->fd, offset, SEEK_SET);
829 rc = lseek(fp->fd, fp->offset, SEEK_SET);
837 ret = write(fp->fd, buf, len);
844 rc = fstat(fp->fd, &st);
850 fp->size = st.st_size;
856 afs_osi_Stat(struct osi_file *fp, struct osi_stat *stp)
862 rc = fstat(fp->fd, &st);
868 stp->size = st.st_size;
869 stp->mtime = st.st_mtime;
870 stp->atime = st.st_atime;
879 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
880 int flags, struct usr_ucred *credP)
883 struct osi_file *fp = (struct osi_file *)vnodeP;
886 * We don't support readv/writev.
888 usr_assert(uioP->uio_iovcnt == 1);
889 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
891 if (rw == UIO_WRITE) {
892 usr_assert(uioP->uio_fmode == FWRITE);
893 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
894 uioP->uio_iov[0].iov_len);
896 usr_assert(uioP->uio_fmode == FREAD);
897 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
898 uioP->uio_iov[0].iov_len);
904 uioP->uio_resid -= rc;
905 uioP->uio_offset += rc;
906 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
907 uioP->uio_iov[0].iov_len -= rc;
912 afs_osi_Alloc(size_t size)
918 afs_osi_Free(void *ptr, size_t size)
924 afs_osi_FreeStr(char *ptr)
930 osi_AllocLargeSpace(size_t size)
932 AFS_STATCNT(osi_AllocLargeSpace);
933 return afs_osi_Alloc(size);
937 osi_FreeLargeSpace(void *ptr)
939 AFS_STATCNT(osi_FreeLargeSpace);
940 afs_osi_Free(ptr, 0);
944 osi_AllocSmallSpace(size_t size)
946 AFS_STATCNT(osi_AllocSmallSpace);
947 return afs_osi_Alloc(size);
951 osi_FreeSmallSpace(void *ptr)
953 AFS_STATCNT(osi_FreeSmallSpace);
954 afs_osi_Free(ptr, 0);
960 AFS_STATCNT(shutdown_osi);
965 shutdown_osinet(void)
967 AFS_STATCNT(shutdown_osinet);
972 shutdown_osifile(void)
974 AFS_STATCNT(shutdown_osifile);
979 afs_nfsclient_init(void)
984 shutdown_nfsclnt(void)
990 afs_osi_Invisible(void)
996 afs_osi_Visible(void)
1002 osi_GetTime(struct timeval *tv)
1004 gettimeofday(tv, NULL);
1009 osi_SetTime(struct timeval *tv)
1015 osi_Active(struct vcache *avc)
1017 AFS_STATCNT(osi_Active);
1024 afs_osi_MapStrategy(int (*aproc) (struct usr_buf *), struct usr_buf *bp)
1026 afs_int32 returnCode;
1027 returnCode = (*aproc) (bp);
1032 osi_FlushPages(register struct vcache *avc, struct AFS_UCRED *credp)
1034 ObtainSharedLock(&avc->lock, 555);
1035 if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
1036 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
1037 ReleaseSharedLock(&avc->lock);
1040 UpgradeSToWLock(&avc->lock, 565);
1041 hset(avc->mapDV, avc->f.m.DataVersion);
1042 ReleaseWriteLock(&avc->lock);
1047 osi_FlushText_really(register struct vcache *vp)
1049 if (hcmp(vp->f.m.DataVersion, vp->flushDV) > 0) {
1050 hset(vp->flushDV, vp->f.m.DataVersion);
1056 osi_SyncVM(struct vcache *avc)
1062 osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1073 * Allocate the table used to implement psuedo-inodes.
1075 max_osi_files = cacheFiles + 100;
1076 osi_file_table = (osi_file_table_t *)
1077 afs_osi_Alloc(max_osi_files * sizeof(osi_file_table_t));
1078 usr_assert(osi_file_table != NULL);
1080 #ifndef NETSCAPE_NSAPI
1082 * Initialize the mutex and condition variable used to implement
1085 pthread_mutex_init(&usr_sleep_mutex, NULL);
1086 pthread_cond_init(&usr_sleep_cond, NULL);
1087 #endif /* !NETSCAPE_NSAPI */
1090 * Initialize the hash table used for sleep/wakeup
1092 for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
1093 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1095 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1096 osi_waithash_avail = NULL;
1099 * Initialize the AFS file table
1101 for (i = 0; i < MAX_OSI_FILES; i++) {
1102 afs_FileTable[i] = NULL;
1106 * Initialize the global locks
1108 usr_mutex_init(&afs_global_lock);
1109 usr_mutex_init(&rx_global_lock);
1110 usr_mutex_init(&osi_inode_lock);
1111 usr_mutex_init(&osi_waitq_lock);
1112 usr_mutex_init(&osi_authenticate_lock);
1115 * Initialize the AFS OSI credentials
1117 afs_osi_cred = *afs_global_ucredp;
1118 afs_osi_credp = &afs_osi_cred;
1121 /* ParseArgs is now obsolete, being handled by cmd */
1123 /*---------------------------------------------------------------------
1127 * Given the final component of a filename expected to be a data cache file,
1128 * return the integer corresponding to the file. Note: we reject names that
1129 * are not a ``V'' followed by an integer. We also reject those names having
1130 * the right format but lying outside the range [0..cacheFiles-1].
1133 * fname : Char ptr to the filename to parse.
1136 * >= 0 iff the file is really a data cache file numbered from 0 to cacheFiles-1, or
1140 * Nothing interesting.
1144 *------------------------------------------------------------------------*/
1147 GetVFileNumber(char *fname)
1149 int computedVNumber; /*The computed file number we return */
1150 int filenameLen; /*Number of chars in filename */
1151 int currDigit; /*Current digit being processed */
1154 * The filename must have at least two characters, the first of which must be a ``V''
1155 * and the second of which cannot be a zero unless the file is exactly two chars long.
1157 filenameLen = strlen(fname);
1158 if (filenameLen < 2)
1160 if (fname[0] != 'V')
1162 if ((filenameLen > 2) && (fname[1] == '0'))
1166 * Scan through the characters in the given filename, failing immediately if a non-digit
1169 for (currDigit = 1; currDigit < filenameLen; currDigit++)
1170 if (isdigit(fname[currDigit]) == 0)
1174 * All relevant characters are digits. Pull out the decimal number they represent.
1175 * Reject it if it's out of range, otherwise return it.
1177 computedVNumber = atoi(++fname);
1178 if (computedVNumber < cacheFiles)
1179 return (computedVNumber);
1184 /*---------------------------------------------------------------------
1188 * Given a full pathname for a file we need to create for the workstation AFS
1189 * cache, go ahead and create the file.
1192 * fname : Full pathname of file to create.
1195 * 0 iff the file was created,
1199 * The given cache file has been found to be missing.
1203 *------------------------------------------------------------------------*/
1206 CreateCacheFile(char *fname)
1208 static char rn[] = "CreateCacheFile"; /*Routine name */
1209 int cfd; /*File descriptor to AFS cache file */
1210 int closeResult; /*Result of close() */
1213 printf("%s: Creating cache file '%s'\n", rn, fname);
1214 cfd = open(fname, createAndTrunc, ownerRWmode);
1216 printf("%s: Can't create '%s', error return is %d (%d)\n", rn, fname,
1220 closeResult = close(cfd);
1223 ("%s: Can't close newly-created AFS cache file '%s' (code %d)\n",
1231 /*---------------------------------------------------------------------
1235 * Sweep through the AFS cache directory, recording the inode number for
1236 * each valid data cache file there. Also, delete any file that doesn't beint32
1237 * in the cache directory during this sweep, and remember which of the other
1238 * residents of this directory were seen. After the sweep, we create any data
1239 * cache files that were missing.
1242 * vFilesFound : Set to the number of data cache files found.
1245 * 0 if everything went well,
1249 * This routine may be called several times. If the number of data cache files
1250 * found is less than the global cacheFiles, then the caller will need to call it
1251 * again to record the inodes of the missing zero-length data cache files created
1252 * in the previous call.
1255 * Fills up the global pathname_for_V array, may create and/or
1256 * delete files as explained above.
1257 *------------------------------------------------------------------------*/
1260 SweepAFSCache(int *vFilesFound)
1262 static char rn[] = "SweepAFSCache"; /*Routine name */
1263 char fullpn_FileToDelete[1024]; /*File to be deleted from cache */
1264 char *fileToDelete; /*Ptr to last component of above */
1265 DIR *cdirp; /*Ptr to cache directory structure */
1267 struct dirent *currp; /*Current directory entry */
1268 int vFileNum; /*Data cache file's associated number */
1270 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1272 printf("%s: Memory Cache, no cache sweep done\n", rn);
1278 printf("%s: Opening cache directory '%s'\n", rn, cacheBaseDir);
1280 if (chmod(cacheBaseDir, 0700)) { /* force it to be 700 */
1281 printf("%s: Can't 'chmod 0700' the cache dir, '%s'.\n", rn,
1285 cdirp = opendir(cacheBaseDir);
1286 if (cdirp == (DIR *) 0) {
1287 printf("%s: Can't open AFS cache directory, '%s'.\n", rn,
1293 * Scan the directory entries, remembering data cache file inodes and the existance
1294 * of other important residents. Delete all files that don't belong here.
1297 sprintf(fullpn_FileToDelete, "%s/", cacheBaseDir);
1298 fileToDelete = fullpn_FileToDelete + strlen(fullpn_FileToDelete);
1300 for (currp = readdir(cdirp); currp; currp = readdir(cdirp)) {
1302 printf("%s: Current directory entry:\n", rn);
1303 #if defined(AFS_USR_DFBSD_ENV)
1304 printf("\tinode=%d, name='%s'\n", currp->d_ino,
1307 printf("\tinode=%d, reclen=%d, name='%s'\n", currp->d_ino,
1308 currp->d_reclen, currp->d_name);
1313 * Guess current entry is for a data cache file.
1315 vFileNum = GetVFileNumber(currp->d_name);
1316 if (vFileNum >= 0) {
1318 * Found a valid data cache filename. Remember this file's name
1319 * and bump the number of files found.
1321 pathname_for_V[vFileNum] =
1322 afs_osi_Alloc(strlen(currp->d_name) + strlen(cacheBaseDir) +
1324 usr_assert(pathname_for_V[vFileNum] != NULL);
1325 sprintf(pathname_for_V[vFileNum], "%s/%s", cacheBaseDir,
1328 } else if (strcmp(currp->d_name, DCACHEFILE) == 0) {
1330 * Found the file holding the dcache entries.
1332 missing_DCacheFile = 0;
1333 } else if (strcmp(currp->d_name, VOLINFOFILE) == 0) {
1335 * Found the file holding the volume info.
1337 missing_VolInfoFile = 0;
1338 } else if (strcmp(currp->d_name, CELLINFOFILE) == 0) {
1339 missing_CellInfoFile = 0;
1340 } else if ((strcmp(currp->d_name, ".") == 0)
1341 || (strcmp(currp->d_name, "..") == 0)
1342 || (strcmp(currp->d_name, "lost+found") == 0)) {
1344 * Don't do anything - this file is legit, and is to be left alone.
1348 * This file doesn't belong in the cache. Nuke it.
1350 sprintf(fileToDelete, "%s", currp->d_name);
1352 printf("%s: Deleting '%s'\n", rn, fullpn_FileToDelete);
1353 if (unlink(fullpn_FileToDelete)) {
1354 printf("%s: Can't unlink '%s', errno is %d\n", rn,
1355 fullpn_FileToDelete, errno);
1361 * Create all the cache files that are missing.
1363 if (missing_DCacheFile) {
1365 printf("%s: Creating '%s'\n", rn, fullpn_DCacheFile);
1366 if (CreateCacheFile(fullpn_DCacheFile))
1367 printf("%s: Can't create '%s'\n", rn, fullpn_DCacheFile);
1369 if (missing_VolInfoFile) {
1371 printf("%s: Creating '%s'\n", rn, fullpn_VolInfoFile);
1372 if (CreateCacheFile(fullpn_VolInfoFile))
1373 printf("%s: Can't create '%s'\n", rn, fullpn_VolInfoFile);
1375 if (missing_CellInfoFile) {
1377 printf("%s: Creating '%s'\n", rn, fullpn_CellInfoFile);
1378 if (CreateCacheFile(fullpn_CellInfoFile))
1379 printf("%s: Can't create '%s'\n", rn, fullpn_CellInfoFile);
1382 if (*vFilesFound < cacheFiles) {
1384 * We came up short on the number of data cache files found. Scan through the inode
1385 * list and create all missing files.
1387 for (vFileNum = 0; vFileNum < cacheFiles; vFileNum++)
1388 if (pathname_for_V[vFileNum] == (AFSD_INO_T) 0) {
1389 sprintf(vFileNumber, "%d", vFileNum);
1391 printf("%s: Creating '%s'\n", rn, fullpn_VFile);
1392 if (CreateCacheFile(fullpn_VFile))
1393 printf("%s: Can't create '%s'\n", rn, fullpn_VFile);
1398 * Close the directory, return success.
1401 printf("%s: Closing cache directory.\n", rn);
1407 ConfigCell(register struct afsconf_cell *aci, void *arock,
1408 struct afsconf_dir *adir)
1410 register int isHomeCell;
1412 afs_int32 cellFlags = 0;
1413 afs_int32 hosts[MAXHOSTSPERCELL];
1415 /* figure out if this is the home cell */
1416 isHomeCell = (strcmp(aci->name, afs_LclCellName) == 0);
1418 cellFlags = 2; /* not home, suid is forbidden */
1420 /* build address list */
1421 for (i = 0; i < MAXHOSTSPERCELL; i++)
1422 memcpy(&hosts[i], &aci->hostAddr[i].sin_addr, sizeof(afs_int32));
1424 if (aci->linkedCell)
1425 cellFlags |= 4; /* Flag that linkedCell arg exists,
1426 * for upwards compatibility */
1428 /* configure one cell */
1429 call_syscall(AFSCALL_CALL, AFSOP_ADDCELL2, (long)hosts, /* server addresses */
1430 (long)aci->name, /* cell name */
1431 (long)cellFlags, /* is this the home cell? */
1432 (long)aci->linkedCell); /* Linked cell, if any */
1437 ConfigCellAlias(struct afsconf_cellalias *aca, void *arock, struct afsconf_dir *adir)
1439 call_syscall(AFSOP_ADDCELLALIAS, (long)aca->aliasName,
1440 (long)aca->realName, 0, 0, 0);
1445 * Set the UDP port number RX uses for UDP datagrams
1448 uafs_SetRxPort(int port)
1450 usr_assert(usr_rx_port == 0);
1456 * Initialize the user space client.
1459 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1460 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1461 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1462 int chunkSizeParam, int closeSynchParam, int debugParam,
1463 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1468 int currVFile; /* Current AFS cache file number */
1469 int lookupResult; /* Result of GetLocalCellName() */
1470 int cacheIteration; /* cache verification loop counter */
1471 int vFilesFound; /* Num data cache files found in sweep */
1476 afs_int32 buffer[MAXIPADDRS];
1477 afs_int32 maskbuffer[MAXIPADDRS];
1478 afs_int32 mtubuffer[MAXIPADDRS];
1481 * Use the thread specific data to implement the user structure
1483 usr_keycreate(&afs_global_u_key, free);
1486 * Initialize the global ucred structure
1488 afs_global_ucredp = (struct usr_ucred *)
1489 afs_osi_Alloc(sizeof(struct usr_ucred));
1490 usr_assert(afs_global_ucredp != NULL);
1491 afs_global_ucredp->cr_ref = 1;
1492 afs_global_ucredp->cr_uid = geteuid();
1493 afs_global_ucredp->cr_gid = getegid();
1494 afs_global_ucredp->cr_ruid = getuid();
1495 afs_global_ucredp->cr_rgid = getgid();
1496 afs_global_ucredp->cr_suid = afs_global_ucredp->cr_ruid;
1497 afs_global_ucredp->cr_sgid = afs_global_ucredp->cr_rgid;
1498 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1499 usr_assert(st >= 0);
1500 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1501 for (i = st; i < NGROUPS; i++) {
1502 afs_global_ucredp->cr_groups[i] = NOGROUP;
1506 * Initialize the global process structure
1508 afs_global_procp = (struct usr_proc *)
1509 afs_osi_Alloc(sizeof(struct usr_proc));
1510 usr_assert(afs_global_procp != NULL);
1511 afs_global_procp->p_pid = getpid();
1512 afs_global_procp->p_ppid = (pid_t) 1;
1513 afs_global_procp->p_ucred = afs_global_ucredp;
1516 * Initialize the AFS mount point, default is '/afs'.
1517 * Strip duplicate/trailing slashes from mount point string.
1518 * afs_mountDirLen is set to strlen(afs_mountDir).
1520 if (mountDirParam) {
1521 sprintf(tbuffer, "%s", mountDirParam);
1523 sprintf(tbuffer, "afs");
1525 afs_mountDir[0] = '/';
1526 afs_mountDirLen = 1;
1527 for (lastchar = '/', p = &tbuffer[0]; *p != '\0'; p++) {
1528 if (lastchar != '/' || *p != '/') {
1529 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1532 if (lastchar == '/' && afs_mountDirLen > 1)
1534 afs_mountDir[afs_mountDirLen] = '\0';
1535 usr_assert(afs_mountDirLen > 1);
1538 * Initialize cache parameters using the input arguments
1541 cacheBlocks = cacheBlocksParam;
1542 if (cacheFilesParam != 0) {
1543 cacheFiles = cacheFilesParam;
1545 cacheFiles = cacheBlocks / 10;
1547 if (cacheStatEntriesParam != 0) {
1548 cacheStatEntries = cacheStatEntriesParam;
1550 strcpy(cacheBaseDir, cacheBaseDirParam);
1551 if (nDaemonsParam != 0) {
1552 nDaemons = nDaemonsParam;
1556 afsd_verbose = debugParam;
1557 afsd_debug = debugParam;
1558 chunkSize = chunkSizeParam;
1559 if (dCacheSizeParam != 0) {
1560 dCacheSize = dCacheSizeParam;
1562 dCacheSize = cacheFiles / 2;
1564 if (vCacheSizeParam != 0) {
1565 vCacheSize = vCacheSizeParam;
1567 strcpy(confDir, confDirParam);
1568 afsd_CloseSynch = closeSynchParam;
1569 if (cacheFlagsParam >= 0) {
1570 cacheFlags = cacheFlagsParam;
1572 if (cacheFlags & AFSCALL_INIT_MEMCACHE) {
1573 cacheFiles = dCacheSize;
1576 sprintf(fullpn_CacheInfo, "%s/%s", confDir, CACHEINFOFILE);
1577 if (logFile == NULL) {
1578 sprintf(fullpn_AFSLogFile, "%s/%s", confDir, AFSLOGFILE);
1580 strcpy(fullpn_AFSLogFile, logFile);
1583 printf("\n%s: Initializing user space AFS client\n\n", rn);
1584 printf(" mountDir: %s\n", afs_mountDir);
1585 printf(" confDir: %s\n", confDir);
1586 printf(" cacheBaseDir: %s\n", cacheBaseDir);
1587 printf(" cacheBlocks: %d\n", cacheBlocks);
1588 printf(" cacheFiles: %d\n", cacheFiles);
1589 printf(" cacheStatEntries: %d\n", cacheStatEntries);
1590 printf(" dCacheSize: %d\n", dCacheSize);
1591 printf(" vCacheSize: %d\n", vCacheSize);
1592 printf(" chunkSize: %d\n", chunkSize);
1593 printf(" afsd_CloseSynch: %d\n", afsd_CloseSynch);
1594 printf(" afsd_debug/verbose: %d/%d\n", afsd_debug, afsd_verbose);
1595 printf(" nDaemons: %d\n", nDaemons);
1596 printf(" cacheFlags: %d\n", cacheFlags);
1597 printf(" logFile: %s\n", fullpn_AFSLogFile);
1602 * Initialize the AFS client
1607 * Pull out all the configuration info for the workstation's AFS cache and
1608 * the cellular community we're willing to let our users see.
1610 afs_cdir = afsconf_Open(confDir);
1612 printf("afsd: some file missing or bad in %s\n", confDir);
1617 afsconf_GetLocalCell(afs_cdir, afs_LclCellName,
1618 sizeof(afs_LclCellName));
1620 printf("%s: Can't get my home cell name! [Error is %d]\n", rn,
1624 printf("%s: My home cell is '%s'\n", rn, afs_LclCellName);
1627 if ((logfd = fopen(fullpn_AFSLogFile, "r+")) == 0) {
1629 printf("%s: Creating '%s'\n", rn, fullpn_AFSLogFile);
1630 if (CreateCacheFile(fullpn_AFSLogFile)) {
1632 ("%s: Can't create '%s' (You may want to use the -logfile option)\n",
1633 rn, fullpn_AFSLogFile);
1640 * Create and zero the pathname table for the desired cache files.
1642 pathname_for_V = (char **)afs_osi_Alloc(cacheFiles * sizeof(char *));
1643 if (pathname_for_V == NULL) {
1644 printf("%s: malloc() failed for cache file table with %d entries.\n",
1648 memset(pathname_for_V, 0, (cacheFiles * sizeof(char *)));
1650 printf("%s: %d pathname_for_V entries at %" AFS_PTR_FMT
1651 ", %lud bytes\n", rn, cacheFiles, pathname_for_V,
1652 afs_printable_uint32_lu(cacheFiles * sizeof(AFSD_INO_T)));
1655 * Set up all the pathnames we'll need for later.
1657 sprintf(fullpn_DCacheFile, "%s/%s", cacheBaseDir, DCACHEFILE);
1658 sprintf(fullpn_VolInfoFile, "%s/%s", cacheBaseDir, VOLINFOFILE);
1659 sprintf(fullpn_CellInfoFile, "%s/%s", cacheBaseDir, CELLINFOFILE);
1660 sprintf(fullpn_VFile, "%s/V", cacheBaseDir);
1661 vFileNumber = fullpn_VFile + strlen(fullpn_VFile);
1663 /* initialize AFS callback interface */
1665 /* parse multihomed address files */
1667 st = parseNetFiles((afs_uint32*)buffer,(afs_uint32*) maskbuffer, (afs_uint32*)mtubuffer, MAXIPADDRS, reason,
1668 AFSDIR_CLIENT_NETINFO_FILEPATH,
1669 AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
1671 call_syscall(AFSCALL_CALL, AFSOP_ADVISEADDR, st,
1672 (long)(&buffer[0]), (long)(&maskbuffer[0]),
1673 (long)(&mtubuffer[0]));
1675 printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
1682 * Start the RX listener.
1685 printf("%s: Calling AFSOP_RXLISTENER_DAEMON\n", rn);
1686 fork_syscall(AFSCALL_CALL, AFSOP_RXLISTENER_DAEMON, FALSE, FALSE, FALSE);
1689 printf("%s: Forking rx callback listener.\n", rn);
1691 if (preallocs < cacheStatEntries + 50)
1692 preallocs = cacheStatEntries + 50;
1693 fork_syscall(AFSCALL_CALL, AFSOP_START_RXCALLBACK, preallocs);
1696 * Start the RX event handler.
1699 printf("%s: Calling AFSOP_RXEVENT_DAEMON\n", rn);
1700 fork_syscall(AFSCALL_CALL, AFSOP_RXEVENT_DAEMON, FALSE);
1703 * Set up all the kernel processes needed for AFS.
1707 printf("%s: Initializing AFS daemon.\n", rn);
1708 call_syscall(AFSCALL_CALL, AFSOP_BASIC_INIT, 1, 0, 0, 0);
1711 * Tell the kernel some basic information about the workstation's cache.
1714 printf("%s: Calling AFSOP_CACHEINIT: %d stat cache entries,"
1715 " %d optimum cache files, %d blocks in the cache,"
1716 " flags = 0x%x, dcache entries %d\n", rn, cacheStatEntries,
1717 cacheFiles, cacheBlocks, cacheFlags, dCacheSize);
1718 memset(&cparams, 0, sizeof(cparams));
1719 cparams.cacheScaches = cacheStatEntries;
1720 cparams.cacheFiles = cacheFiles;
1721 cparams.cacheBlocks = cacheBlocks;
1722 cparams.cacheDcaches = dCacheSize;
1723 cparams.cacheVolumes = vCacheSize;
1724 cparams.chunkSize = chunkSize;
1725 cparams.setTimeFlag = FALSE;
1726 cparams.memCacheFlag = cacheFlags;
1727 call_syscall(AFSCALL_CALL, AFSOP_CACHEINIT, (long)&cparams, 0, 0, 0);
1728 if (afsd_CloseSynch)
1729 call_syscall(AFSCALL_CALL, AFSOP_CLOSEWAIT, 0, 0, 0, 0);
1732 * Sweep the workstation AFS cache directory, remembering the inodes of
1733 * valid files and deleting extraneous files. Keep sweeping until we
1734 * have the right number of data cache files or we've swept too many
1738 printf("%s: Sweeping workstation's AFS cache directory.\n", rn);
1740 /* Memory-cache based system doesn't need any of this */
1741 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) {
1744 if (SweepAFSCache(&vFilesFound)) {
1745 printf("%s: Error on sweep %d of workstation AFS cache \
1746 directory.\n", rn, cacheIteration);
1751 ("%s: %d out of %d data cache files found in sweep %d.\n",
1752 rn, vFilesFound, cacheFiles, cacheIteration);
1753 } while ((vFilesFound < cacheFiles)
1754 && (cacheIteration < MAX_CACHE_LOOPS));
1755 } else if (afsd_verbose)
1756 printf("%s: Using memory cache, not swept\n", rn);
1759 * Pass the kernel the name of the workstation cache file holding the
1763 printf("%s: Calling AFSOP_CACHEINFO: dcache file is '%s'\n", rn,
1765 /* once again, meaningless for a memory-based cache. */
1766 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE))
1767 call_syscall(AFSCALL_CALL, AFSOP_CACHEINFO, (long)fullpn_DCacheFile,
1770 call_syscall(AFSCALL_CALL, AFSOP_CELLINFO, (long)fullpn_CellInfoFile, 0,
1774 * Pass the kernel the name of the workstation cache file holding the
1775 * volume information.
1778 printf("%s: Calling AFSOP_VOLUMEINFO: volume info file is '%s'\n", rn,
1779 fullpn_VolInfoFile);
1780 call_syscall(AFSCALL_CALL, AFSOP_VOLUMEINFO, (long)fullpn_VolInfoFile, 0,
1784 * Pass the kernel the name of the afs logging file holding the volume
1788 printf("%s: Calling AFSOP_AFSLOG: volume info file is '%s'\n", rn,
1790 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... nor this ... */
1791 call_syscall(AFSCALL_CALL, AFSOP_AFSLOG, (long)fullpn_AFSLogFile, 0,
1795 * Tell the kernel about each cell in the configuration.
1797 afsconf_CellApply(afs_cdir, ConfigCell, NULL);
1798 afsconf_CellAliasApply(afs_cdir, ConfigCellAlias, NULL);
1801 * Set the primary cell name.
1803 call_syscall(AFSCALL_CALL, AFSOP_SET_THISCELL, (long)afs_LclCellName, 0, 0, 0);
1806 printf("%s: Forking AFS daemon.\n", rn);
1807 fork_syscall(AFSCALL_CALL, AFSOP_START_AFS);
1810 printf("%s: Forking check server daemon.\n", rn);
1811 fork_syscall(AFSCALL_CALL, AFSOP_START_CS);
1814 printf("%s: Forking %d background daemons.\n", rn, nDaemons);
1815 for (i = 0; i < nDaemons; i++) {
1816 fork_syscall(AFSCALL_CALL, AFSOP_START_BKG);
1820 printf("%s: Calling AFSOP_ROOTVOLUME with '%s'\n", rn, rootVolume);
1821 call_syscall(AFSCALL_CALL, AFSOP_ROOTVOLUME, (long)rootVolume, 0, 0, 0);
1824 * Give the kernel the names of the AFS files cached on the workstation's
1829 ("%s: Calling AFSOP_CACHEFILES for each of the %d files in '%s'\n",
1830 rn, cacheFiles, cacheBaseDir);
1831 if (!(cacheFlags & AFSCALL_INIT_MEMCACHE)) /* ... and again ... */
1832 for (currVFile = 0; currVFile < cacheFiles; currVFile++) {
1833 call_syscall(AFSCALL_CALL, AFSOP_CACHEFILE,
1834 (long)pathname_for_V[currVFile], 0, 0, 0);
1837 /*#ifndef NETSCAPE_NSAPI*/
1839 /* this breaks solaris if the kernel-mode client has never been installed,
1840 * and it doesn't seem to work now anyway, so just disable it */
1843 * Copy our tokens from the kernel to the user space client
1845 for (i = 0; i < 200; i++) {
1847 * Get the i'th token from the kernel
1849 memset((void *)&tbuffer[0], 0, sizeof(tbuffer));
1850 memcpy((void *)&tbuffer[0], (void *)&i, sizeof(int));
1852 iob.in_size = sizeof(int);
1854 iob.out_size = sizeof(tbuffer);
1856 #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)
1857 rc = syscall(AFS_SYSCALL, AFSCALL_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1858 #elif defined(AFS_USR_SGI_ENV)
1859 rc = syscall(AFS_PIOCTL, 0, _VICEIOCTL(8), &iob, 0);
1860 #else /* AFS_USR_AIX_ENV */
1861 rc = lpioctl(0, _VICEIOCTL(8), &iob, 0);
1864 usr_assert(errno == EDOM || errno == ENOSYS || errno == ERANGE);
1869 * Now pass the token into the user space kernel
1871 rc = uafs_SetTokens(tbuffer, iob.out_size);
1872 usr_assert(rc == 0);
1874 #endif /* !NETSCAPE_NSAPI */
1877 * All the necessary info has been passed into the kernel to run an AFS
1878 * system. Give the kernel our go-ahead.
1881 printf("%s: Calling AFSOP_GO\n", rn);
1882 call_syscall(AFSCALL_CALL, AFSOP_GO, FALSE, 0, 0, 0);
1885 * At this point, we have finished passing the kernel all the info
1886 * it needs to set up the AFS. Mount the AFS root.
1888 printf("%s: All AFS daemons started.\n", rn);
1891 printf("%s: Forking trunc-cache daemon.\n", rn);
1892 fork_syscall(AFSCALL_CALL, AFSOP_START_TRUNCDAEMON);
1895 * Mount the AFS filesystem
1898 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1899 usr_assert(rc == 0);
1900 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1901 usr_assert(rc == 0);
1905 * initialize the current directory to the AFS root
1907 afs_CurrentDir = afs_RootVnode;
1908 VN_HOLD(afs_CurrentDir);
1921 VN_RELE(afs_CurrentDir);
1922 rc = afs_unmount(&afs_RootVfs);
1923 usr_assert(rc == 0);
1930 * Donate the current thread to the RX server pool.
1933 uafs_RxServerProc(void)
1937 struct rx_call *newcall = NULL;
1939 rxi_MorePackets(2); /* alloc more packets */
1940 threadID = rxi_availProcs++;
1943 sock = OSI_NULLSOCKET;
1944 rxi_ServerProc(threadID, newcall, &sock);
1945 if (sock == OSI_NULLSOCKET) {
1950 rxi_ListenerProc(sock, &threadID, &newcall);
1951 /* assert(threadID != -1); */
1952 /* assert(newcall != NULL); */
1956 struct syscallThreadArgs {
1965 #ifdef NETSCAPE_NSAPI
1967 syscallThread(void *argp)
1968 #else /* NETSCAPE_NSAPI */
1970 syscallThread(void *argp)
1971 #endif /* NETSCAPE_NSAPI */
1974 struct usr_ucred *crp;
1975 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1978 * AFS daemons run authenticated
1980 u.u_viceid = getuid();
1982 crp->cr_uid = getuid();
1983 crp->cr_ruid = getuid();
1984 crp->cr_suid = getuid();
1985 crp->cr_groups[0] = getgid();
1986 crp->cr_ngroups = 1;
1987 for (i = 1; i < NGROUPS; i++) {
1988 crp->cr_groups[i] = NOGROUP;
1991 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1992 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1994 afs_osi_Free(argp, -1);
1999 fork_syscall(syscall, afscall, param1, param2, param3, param4)
2000 long syscall, afscall, param1, param2, param3, param4;
2003 struct syscallThreadArgs *sysArgsP;
2005 sysArgsP = (struct syscallThreadArgs *)
2006 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
2007 usr_assert(sysArgsP != NULL);
2008 sysArgsP->syscall = syscall;
2009 sysArgsP->afscall = afscall;
2010 sysArgsP->param1 = param1;
2011 sysArgsP->param2 = param2;
2012 sysArgsP->param3 = param3;
2013 sysArgsP->param4 = param4;
2015 usr_thread_create(&tid, syscallThread, sysArgsP);
2016 usr_thread_detach(tid);
2021 call_syscall(syscall, afscall, param1, param2, param3, param4)
2022 long syscall, afscall, param1, param2, param3, param4;
2034 a.syscall = syscall;
2035 a.afscall = afscall;
2042 u.u_ap = (char *)&a;
2044 code = Afs_syscall();
2049 uafs_SetTokens(char *tbuffer, int tlen)
2052 struct afs_ioctl iob;
2057 iob.out = &outbuf[0];
2058 iob.out_size = sizeof(outbuf);
2060 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
2069 uafs_RPCStatsEnableProc(void)
2072 struct afs_ioctl iob;
2075 flag = AFSCALL_RXSTATS_ENABLE;
2076 iob.in = (char *)&flag;
2077 iob.in_size = sizeof(afs_int32);
2080 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2089 uafs_RPCStatsDisableProc(void)
2092 struct afs_ioctl iob;
2095 flag = AFSCALL_RXSTATS_DISABLE;
2096 iob.in = (char *)&flag;
2097 iob.in_size = sizeof(afs_int32);
2100 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2109 uafs_RPCStatsClearProc(void)
2112 struct afs_ioctl iob;
2115 flag = AFSCALL_RXSTATS_CLEAR;
2116 iob.in = (char *)&flag;
2117 iob.in_size = sizeof(afs_int32);
2120 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
2129 uafs_RPCStatsEnablePeer(void)
2132 struct afs_ioctl iob;
2135 flag = AFSCALL_RXSTATS_ENABLE;
2136 iob.in = (char *)&flag;
2137 iob.in_size = sizeof(afs_int32);
2140 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2149 uafs_RPCStatsDisablePeer(void)
2152 struct afs_ioctl iob;
2155 flag = AFSCALL_RXSTATS_DISABLE;
2156 iob.in = (char *)&flag;
2157 iob.in_size = sizeof(afs_int32);
2160 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2169 uafs_RPCStatsClearPeer(void)
2172 struct afs_ioctl iob;
2175 flag = AFSCALL_RXSTATS_CLEAR;
2176 iob.in = (char *)&flag;
2177 iob.in_size = sizeof(afs_int32);
2180 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
2189 * Lookup a file or directory given its path.
2190 * Call VN_HOLD on the output vnode if successful.
2191 * Returns zero on success, error code on failure.
2193 * Note: Caller must hold the AFS global lock.
2196 uafs_LookupName(char *path, struct usr_vnode *parentVp,
2197 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
2201 struct usr_vnode *vp;
2202 struct usr_vnode *nextVp;
2203 struct usr_vnode *linkVp;
2204 struct vcache *nextVc;
2207 char *nextPathP = NULL;
2212 * Absolute paths must start with the AFS mount point.
2214 if (path[0] != '/') {
2217 path = uafs_afsPathName(path);
2225 * Loop through the path looking for the new directory
2227 tmpPath = afs_osi_Alloc(strlen(path) + 1);
2228 usr_assert(tmpPath != NULL);
2229 strcpy(tmpPath, path);
2232 while (pathP != NULL && *pathP != '\0') {
2233 usr_assert(*pathP != '/');
2236 * terminate the current component and skip over slashes
2238 nextPathP = afs_strchr(pathP, '/');
2239 if (nextPathP != NULL) {
2240 while (*nextPathP == '/') {
2241 *(nextPathP++) = '\0';
2246 * Don't call afs_lookup on non-directories
2248 if (vp->v_type != VDIR) {
2250 afs_osi_Free(tmpPath, strlen(path) + 1);
2254 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
2256 * The AFS root is its own parent
2258 nextVp = afs_RootVnode;
2261 * We need execute permission to search a directory
2263 code = afs_access(VTOAFS(vp), VEXEC, u.u_cred);
2266 afs_osi_Free(tmpPath, strlen(path) + 1);
2271 * lookup the next component in the path, we can release the
2272 * subdirectory since we hold the global lock
2276 #ifdef AFS_WEB_ENHANCEMENTS
2277 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
2278 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, u.u_cred, 0);
2281 afs_lookup(VTOAFS(vp), pathP, &nextVc, u.u_cred,
2284 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, u.u_cred, 0);
2285 #endif /* AFS_WEB_ENHANCEMENTS */
2287 nextVp=AFSTOV(nextVc);
2290 afs_osi_Free(tmpPath, strlen(path) + 1);
2296 * Follow symbolic links for parent directories and
2297 * for leaves when the follow flag is set.
2299 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
2301 while (nextVp->v_type == VLNK) {
2302 if (++linkCount > MAX_OSI_LINKS) {
2305 afs_osi_Free(tmpPath, strlen(path) + 1);
2308 code = uafs_LookupLink(nextVp, vp, &linkVp);
2312 afs_osi_Free(tmpPath, strlen(path) + 1);
2326 * Special case, nextPathP is non-null if pathname ends in slash
2328 if (nextPathP != NULL && vp->v_type != VDIR) {
2330 afs_osi_Free(tmpPath, strlen(path) + 1);
2334 afs_osi_Free(tmpPath, strlen(path) + 1);
2340 * Lookup the target of a symbolic link
2341 * Call VN_HOLD on the output vnode if successful.
2342 * Returns zero on success, error code on failure.
2344 * Note: Caller must hold the AFS global lock.
2347 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
2348 struct usr_vnode **vpp)
2353 struct usr_vnode *linkVp;
2355 struct iovec iov[1];
2359 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
2360 usr_assert(pathP != NULL);
2363 * set up the uio buffer
2365 iov[0].iov_base = pathP;
2366 iov[0].iov_len = MAX_OSI_PATH + 1;
2367 uio.uio_iov = &iov[0];
2371 uio.uio_fmode = FREAD;
2372 uio.uio_resid = MAX_OSI_PATH + 1;
2375 * Read the link data
2377 code = afs_readlink(VTOAFS(vp), &uio, u.u_cred);
2379 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2382 len = MAX_OSI_PATH + 1 - uio.uio_resid;
2386 * Find the target of the symbolic link
2388 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
2390 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2394 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
2400 * Lookup the parent of a file or directory given its path
2401 * Call VN_HOLD on the output vnode if successful.
2402 * Returns zero on success, error code on failure.
2404 * Note: Caller must hold the AFS global lock.
2407 uafs_LookupParent(char *path, struct usr_vnode **vpp)
2412 struct usr_vnode *parentP;
2417 * Absolute path names must start with the AFS mount point.
2420 pathP = uafs_afsPathName(path);
2421 if (pathP == NULL) {
2427 * Find the length of the parent path
2430 while (len > 0 && path[len - 1] == '/') {
2436 while (len > 0 && path[len - 1] != '/') {
2443 pathP = afs_osi_Alloc(len);
2444 usr_assert(pathP != NULL);
2445 memcpy(pathP, path, len - 1);
2446 pathP[len - 1] = '\0';
2449 * look up the parent
2451 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
2452 afs_osi_Free(pathP, len);
2456 if (parentP->v_type != VDIR) {
2466 * Return a pointer to the first character in the last component
2470 uafs_LastPath(char *path)
2475 while (len > 0 && path[len - 1] == '/') {
2478 while (len > 0 && path[len - 1] != '/') {
2488 * Set the working directory.
2491 uafs_chdir(char *path)
2495 retval = uafs_chdir_r(path);
2501 uafs_chdir_r(char *path)
2506 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
2511 if (dirP->v_type != VDIR) {
2516 VN_RELE(afs_CurrentDir);
2517 afs_CurrentDir = dirP;
2522 * Create a directory.
2525 uafs_mkdir(char *path, int mode)
2529 retval = uafs_mkdir_r(path, mode);
2535 uafs_mkdir_r(char *path, int mode)
2539 struct vnode *parentP;
2540 struct vcache *dirP;
2541 struct usr_vattr attrs;
2543 if (uafs_IsRoot(path)) {
2548 * Look up the parent directory.
2550 nameP = uafs_LastPath(path);
2551 if (nameP != NULL) {
2552 code = uafs_LookupParent(path, &parentP);
2558 parentP = afs_CurrentDir;
2564 * Make sure the directory has at least one character
2566 if (*nameP == '\0') {
2573 * Create the directory
2575 usr_vattr_null(&attrs);
2576 attrs.va_type = VREG;
2577 attrs.va_mode = mode;
2578 attrs.va_uid = u.u_cred->cr_uid;
2579 attrs.va_gid = u.u_cred->cr_gid;
2581 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, u.u_cred);
2587 VN_RELE(AFSTOV(dirP));
2592 * Return 1 if path is the AFS root, otherwise return 0
2595 uafs_IsRoot(char *path)
2597 while (*path == '/' && *(path + 1) == '/') {
2600 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2603 path += afs_mountDirLen;
2604 while (*path == '/') {
2607 if (*path != '\0') {
2615 * Note: file name may not end in a slash.
2618 uafs_open(char *path, int flags, int mode)
2622 retval = uafs_open_r(path, flags, mode);
2628 uafs_open_r(char *path, int flags, int mode)
2634 struct usr_vnode *fileP;
2635 struct usr_vnode *dirP;
2636 struct usr_vattr attrs;
2641 if (uafs_IsRoot(path)) {
2642 fileP = afs_RootVnode;
2646 * Look up the parent directory.
2648 nameP = uafs_LastPath(path);
2649 if (nameP != NULL) {
2650 code = uafs_LookupParent(path, &dirP);
2656 dirP = afs_CurrentDir;
2662 * Make sure the filename has at least one character
2664 if (*nameP == '\0') {
2671 * Get the VNODE for this file
2673 if (flags & O_CREAT) {
2674 usr_vattr_null(&attrs);
2675 attrs.va_type = VREG;
2676 attrs.va_mode = mode;
2677 attrs.va_uid = u.u_cred->cr_uid;
2678 attrs.va_gid = u.u_cred->cr_gid;
2679 if (flags & O_TRUNC) {
2685 afs_create(VTOAFS(dirP), nameP, &attrs,
2686 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2696 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2704 * Check whether we have access to this file
2707 if (flags & (O_RDONLY | O_RDWR)) {
2710 if (flags & (O_WRONLY | O_RDWR)) {
2714 fileMode = VREAD; /* since O_RDONLY is 0 */
2715 code = afs_access(VTOAFS(fileP), fileMode, u.u_cred);
2723 * Get the file attributes, all we need is the size
2725 code = afs_getattr(VTOAFS(fileP), &attrs, u.u_cred);
2735 * Setup the open flags
2738 if (flags & O_TRUNC) {
2739 openFlags |= FTRUNC;
2741 if (flags & O_APPEND) {
2742 openFlags |= FAPPEND;
2744 if (flags & O_SYNC) {
2747 if (flags & O_SYNC) {
2750 if (flags & (O_RDONLY | O_RDWR)) {
2753 if (flags & (O_WRONLY | O_RDWR)) {
2754 openFlags |= FWRITE;
2756 if ((openFlags & (FREAD | FWRITE)) == 0) {
2757 /* O_RDONLY is 0, so ... */
2762 * Truncate if necessary
2764 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2765 usr_vattr_null(&attrs);
2766 attrs.va_mask = ATTR_SIZE;
2768 code = afs_setattr(VTOAFS(fileP), &attrs, u.u_cred);
2780 code = afs_open(&vc, openFlags, u.u_cred);
2788 * Put the vnode pointer into the file table
2790 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2791 if (afs_FileTable[fd] == NULL) {
2792 afs_FileTable[fd] = fileP;
2793 afs_FileFlags[fd] = openFlags;
2794 if (flags & O_APPEND) {
2795 afs_FileOffsets[fd] = attrs.va_size;
2797 afs_FileOffsets[fd] = 0;
2802 if (fd == MAX_OSI_FILES) {
2815 uafs_creat(char *path, int mode)
2818 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2823 uafs_creat_r(char *path, int mode)
2826 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2834 uafs_write(int fd, char *buf, int len)
2838 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2844 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2848 retval = uafs_pwrite_r(fd, buf, len, offset);
2854 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2858 struct iovec iov[1];
2859 struct usr_vnode *fileP;
2862 * Make sure this is an open file
2864 fileP = afs_FileTable[fd];
2865 if (fileP == NULL) {
2871 * set up the uio buffer
2873 iov[0].iov_base = buf;
2874 iov[0].iov_len = len;
2875 uio.uio_iov = &iov[0];
2877 uio.uio_offset = offset;
2879 uio.uio_fmode = FWRITE;
2880 uio.uio_resid = len;
2886 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], u.u_cred, 0);
2892 afs_FileOffsets[fd] = uio.uio_offset;
2893 return (len - uio.uio_resid);
2900 uafs_read(int fd, char *buf, int len)
2904 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2910 uafs_pread(int fd, char *buf, int len, off_t offset)
2914 retval = uafs_pread_r(fd, buf, len, offset);
2920 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2924 struct iovec iov[1];
2925 struct usr_vnode *fileP;
2926 struct usr_buf *bufP;
2929 * Make sure this is an open file
2931 fileP = afs_FileTable[fd];
2932 if (fileP == NULL) {
2938 * set up the uio buffer
2940 iov[0].iov_base = buf;
2941 iov[0].iov_len = len;
2942 uio.uio_iov = &iov[0];
2944 uio.uio_offset = offset;
2946 uio.uio_fmode = FREAD;
2947 uio.uio_resid = len;
2952 code = afs_read(VTOAFS(fileP), &uio, u.u_cred, 0, &bufP, 0);
2958 afs_FileOffsets[fd] = uio.uio_offset;
2959 return (len - uio.uio_resid);
2963 * Copy the attributes of a file into a stat structure.
2965 * NOTE: Caller must hold the global AFS lock.
2968 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2971 struct usr_vattr attrs;
2976 * Get the attributes
2978 code = afs_getattr(VTOAFS(vp), &attrs, u.u_cred);
2984 * Copy the attributes, zero fields that aren't set
2986 memset((void *)stats, 0, sizeof(struct stat));
2988 stats->st_ino = attrs.va_nodeid;
2989 stats->st_mode = attrs.va_mode;
2990 stats->st_nlink = attrs.va_nlink;
2991 stats->st_uid = attrs.va_uid;
2992 stats->st_gid = attrs.va_gid;
2993 stats->st_rdev = attrs.va_rdev;
2994 stats->st_size = attrs.va_size;
2995 stats->st_atime = attrs.va_atime.tv_sec;
2996 stats->st_mtime = attrs.va_mtime.tv_sec;
2997 stats->st_ctime = attrs.va_ctime.tv_sec;
2998 stats->st_blksize = attrs.va_blocksize;
2999 stats->st_blocks = attrs.va_blocks;
3005 * Get the attributes of a file, do follow links
3008 uafs_stat(char *path, struct stat *buf)
3012 retval = uafs_stat_r(path, buf);
3018 uafs_stat_r(char *path, struct stat *buf)
3023 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3028 code = uafs_GetAttr(vp, buf);
3038 * Get the attributes of a file, don't follow links
3041 uafs_lstat(char *path, struct stat *buf)
3045 retval = uafs_lstat_r(path, buf);
3051 uafs_lstat_r(char *path, struct stat *buf)
3056 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3061 code = uafs_GetAttr(vp, buf);
3071 * Get the attributes of an open file
3074 uafs_fstat(int fd, struct stat *buf)
3078 retval = uafs_fstat_r(fd, buf);
3084 uafs_fstat_r(int fd, struct stat *buf)
3089 vp = afs_FileTable[fd];
3094 code = uafs_GetAttr(vp, buf);
3103 * change the permissions on a file
3106 uafs_chmod(char *path, int mode)
3110 retval = uafs_chmod_r(path, mode);
3116 uafs_chmod_r(char *path, int mode)
3120 struct usr_vattr attrs;
3122 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3127 usr_vattr_null(&attrs);
3128 attrs.va_mask = ATTR_MODE;
3129 attrs.va_mode = mode;
3130 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3140 * change the permissions on an open file
3143 uafs_fchmod(int fd, int mode)
3147 retval = uafs_fchmod_r(fd, mode);
3153 uafs_fchmod_r(int fd, int mode)
3157 struct usr_vattr attrs;
3159 vp = afs_FileTable[fd];
3164 usr_vattr_null(&attrs);
3165 attrs.va_mask = ATTR_MODE;
3166 attrs.va_mode = mode;
3167 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3179 uafs_truncate(char *path, int length)
3183 retval = uafs_truncate_r(path, length);
3189 uafs_truncate_r(char *path, int length)
3193 struct usr_vattr attrs;
3195 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3200 usr_vattr_null(&attrs);
3201 attrs.va_mask = ATTR_SIZE;
3202 attrs.va_size = length;
3203 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3213 * truncate an open file
3216 uafs_ftruncate(int fd, int length)
3220 retval = uafs_ftruncate_r(fd, length);
3226 uafs_ftruncate_r(int fd, int length)
3230 struct usr_vattr attrs;
3232 vp = afs_FileTable[fd];
3237 usr_vattr_null(&attrs);
3238 attrs.va_mask = ATTR_SIZE;
3239 attrs.va_size = length;
3240 code = afs_setattr(VTOAFS(vp), &attrs, u.u_cred);
3249 * set the read/write file pointer of an open file
3252 uafs_lseek(int fd, int offset, int whence)
3256 retval = uafs_lseek_r(fd, offset, whence);
3262 uafs_lseek_r(int fd, int offset, int whence)
3266 struct usr_vattr attrs;
3267 struct usr_vnode *vp;
3269 vp = afs_FileTable[fd];
3276 newpos = afs_FileOffsets[fd] + offset;
3282 code = afs_getattr(VTOAFS(vp), &attrs, u.u_cred);
3287 newpos = attrs.va_size + offset;
3297 afs_FileOffsets[fd] = newpos;
3309 retval = uafs_fsync_r(fd);
3315 uafs_fsync_r(int fd)
3318 struct usr_vnode *fileP;
3321 fileP = afs_FileTable[fd];
3322 if (fileP == NULL) {
3327 code = afs_fsync(VTOAFS(fileP), u.u_cred);
3344 retval = uafs_close_r(fd);
3350 uafs_close_r(int fd)
3353 struct usr_vnode *fileP;
3355 fileP = afs_FileTable[fd];
3356 if (fileP == NULL) {
3360 afs_FileTable[fd] = NULL;
3362 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], u.u_cred);
3373 * Create a hard link from the source to the target
3374 * Note: file names may not end in a slash.
3377 uafs_link(char *existing, char *new)
3381 retval = uafs_link_r(existing, new);
3387 uafs_link_r(char *existing, char *new)
3390 struct usr_vnode *existP;
3391 struct usr_vnode *dirP;
3394 if (uafs_IsRoot(new)) {
3399 * Look up the existing node.
3401 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
3408 * Look up the parent directory.
3410 nameP = uafs_LastPath(new);
3411 if (nameP != NULL) {
3412 code = uafs_LookupParent(new, &dirP);
3419 dirP = afs_CurrentDir;
3425 * Make sure the filename has at least one character
3427 if (*nameP == '\0') {
3437 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, u.u_cred);
3448 * Create a symbolic link from the source to the target
3449 * Note: file names may not end in a slash.
3452 uafs_symlink(char *target, char *source)
3456 retval = uafs_symlink_r(target, source);
3462 uafs_symlink_r(char *target, char *source)
3465 struct usr_vnode *dirP;
3466 struct usr_vattr attrs;
3469 if (uafs_IsRoot(source)) {
3474 * Look up the parent directory.
3476 nameP = uafs_LastPath(source);
3477 if (nameP != NULL) {
3478 code = uafs_LookupParent(source, &dirP);
3484 dirP = afs_CurrentDir;
3490 * Make sure the filename has at least one character
3492 if (*nameP == '\0') {
3501 usr_vattr_null(&attrs);
3502 attrs.va_type = VLNK;
3503 attrs.va_mode = 0777;
3504 attrs.va_uid = u.u_cred->cr_uid;
3505 attrs.va_gid = u.u_cred->cr_gid;
3506 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, u.u_cred);
3516 * Read a symbolic link into the buffer
3519 uafs_readlink(char *path, char *buf, int len)
3523 retval = uafs_readlink_r(path, buf, len);
3529 uafs_readlink_r(char *path, char *buf, int len)
3532 struct usr_vnode *vp;
3534 struct iovec iov[1];
3536 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
3542 if (vp->v_type != VLNK) {
3549 * set up the uio buffer
3551 iov[0].iov_base = buf;
3552 iov[0].iov_len = len;
3553 uio.uio_iov = &iov[0];
3557 uio.uio_fmode = FREAD;
3558 uio.uio_resid = len;
3563 code = afs_readlink(VTOAFS(vp), &uio, u.u_cred);
3571 * return the number of bytes read
3573 return (len - uio.uio_resid);
3577 * Remove a file (or directory)
3578 * Note: file name may not end in a slash.
3581 uafs_unlink(char *path)
3585 retval = uafs_unlink_r(path);
3591 uafs_unlink_r(char *path)
3594 struct usr_vnode *dirP;
3597 if (uafs_IsRoot(path)) {
3602 * Look up the parent directory.
3604 nameP = uafs_LastPath(path);
3605 if (nameP != NULL) {
3606 code = uafs_LookupParent(path, &dirP);
3612 dirP = afs_CurrentDir;
3618 * Make sure the filename has at least one character
3620 if (*nameP == '\0') {
3629 code = afs_remove(VTOAFS(dirP), nameP, u.u_cred);
3640 * Rename a file (or directory)
3643 uafs_rename(char *old, char *new)
3647 retval = uafs_rename_r(old, new);
3653 uafs_rename_r(char *old, char *new)
3658 struct usr_vnode *odirP;
3659 struct usr_vnode *ndirP;
3661 if (uafs_IsRoot(new)) {
3666 * Look up the parent directories.
3668 onameP = uafs_LastPath(old);
3669 if (onameP != NULL) {
3670 code = uafs_LookupParent(old, &odirP);
3676 odirP = afs_CurrentDir;
3680 nnameP = uafs_LastPath(new);
3681 if (nnameP != NULL) {
3682 code = uafs_LookupParent(new, &ndirP);
3688 ndirP = afs_CurrentDir;
3694 * Make sure the filename has at least one character
3696 if (*onameP == '\0' || *nnameP == '\0') {
3706 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, u.u_cred);
3718 * Remove a or directory
3719 * Note: file name may not end in a slash.
3722 uafs_rmdir(char *path)
3726 retval = uafs_rmdir_r(path);
3732 uafs_rmdir_r(char *path)
3735 struct usr_vnode *dirP;
3738 if (uafs_IsRoot(path)) {
3743 * Look up the parent directory.
3745 nameP = uafs_LastPath(path);
3746 if (nameP != NULL) {
3747 code = uafs_LookupParent(path, &dirP);
3753 dirP = afs_CurrentDir;
3759 * Make sure the directory name has at least one character
3761 if (*nameP == '\0') {
3768 * Remove the directory
3770 code = afs_rmdir(VTOAFS(dirP), nameP, u.u_cred);
3781 * Flush a file from the AFS cache
3784 uafs_FlushFile(char *path)
3787 struct afs_ioctl iob;
3795 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3806 uafs_FlushFile_r(char *path)
3810 retval = uafs_FlushFile(path);
3819 uafs_opendir(char *path)
3823 retval = uafs_opendir_r(path);
3829 uafs_opendir_r(char *path)
3832 struct usr_vnode *fileP;
3836 * Open the directory for reading
3838 fd = uafs_open_r(path, O_RDONLY, 0);
3843 fileP = afs_FileTable[fd];
3844 if (fileP == NULL) {
3848 if (fileP->v_type != VDIR) {
3855 * Set up the directory structures
3858 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3859 sizeof(struct usr_dirent));
3860 usr_assert(dirp != NULL);
3861 dirp->dd_buf = (char *)(dirp + 1);
3871 * Read directory entries into a file system independent format.
3872 * This routine was developed to support AFS cache consistency testing.
3873 * You should use uafs_readdir instead.
3876 uafs_getdents(int fd, struct min_direct *buf, int len)