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"
33 #include "afsd/afsd.h"
39 #ifndef AFS_CACHE_VNODE_PATH
40 #error You must compile UKERNEL code with -DAFS_CACHE_VNODE_PATH
43 #define CACHEINFOFILE "cacheinfo"
44 #define AFSLOGFILE "AFSLog"
45 #define DCACHEFILE "CacheItems"
46 #define VOLINFOFILE "VolumeItems"
47 #define CELLINFOFILE "CellItems"
51 #define MIN(A,B) ((A)<(B)?(A):(B))
54 #define MAX(A,B) ((A)>(B)?(A):(B))
57 extern int cacheDiskType;
59 char afs_LclCellName[64];
61 static struct usr_vnode *afs_FileTable[MAX_OSI_FILES];
62 static int afs_FileFlags[MAX_OSI_FILES];
63 static off_t afs_FileOffsets[MAX_OSI_FILES];
65 #define MAX_CACHE_LOOPS 4
67 static struct usr_vfs afs_RootVfs;
68 static struct usr_vnode *afs_RootVnode = NULL;
69 static struct usr_vnode *afs_CurrentDir = NULL;
71 static char afs_mountDir[1024]; /* AFS mount point */
72 static int afs_mountDirLen; /* strlen of AFS mount point */
74 struct afsconf_dir *afs_cdir; /* config dir */
76 int afs_bufferpages = 100;
78 static usr_key_t afs_global_u_key;
80 static struct usr_proc *afs_global_procp = NULL;
81 static struct usr_ucred *afs_global_ucredp = NULL;
83 struct usr_ucred afs_osi_cred, *afs_osi_credp;
84 usr_mutex_t afs_global_lock;
85 usr_thread_t afs_global_owner;
86 usr_mutex_t rx_global_lock;
87 usr_thread_t rx_global_owner;
89 static usr_mutex_t osi_dummy_lock;
90 static usr_mutex_t osi_waitq_lock;
91 static usr_mutex_t osi_authenticate_lock;
93 afs_lock_t osi_flplock;
94 afs_lock_t osi_fsplock;
96 #ifndef NETSCAPE_NSAPI
99 * Mutex and condition variable used to implement sleep
101 pthread_mutex_t usr_sleep_mutex;
102 pthread_cond_t usr_sleep_cond;
104 #endif /* !NETSCAPE_NSAPI */
106 int call_syscall(long, long, long, long, long, long);
107 int fork_syscall(long, long, long, long, long, long);
111 * Hash table mapping addresses onto wait structures for
112 * osi_Sleep/osi_Wakeup and osi_Wait/osi_Wakeup
114 typedef struct osi_wait {
118 struct osi_wait *next;
119 struct osi_wait *prev;
121 struct osi_wait *timedNext;
122 struct osi_wait *timedPrev;
126 * Head of the linked list of available waitq structures.
128 static osi_wait_t *osi_waithash_avail;
131 * List of timed waits, NSAPI does not provide a cond_timed
132 * wait, so we need to keep track of the timed waits ourselves and
133 * periodically check for expirations
135 static osi_wait_t *osi_timedwait_head;
136 static osi_wait_t *osi_timedwait_tail;
141 } osi_waithash_table[OSI_WAITHASH_SIZE];
144 * Never call afs_brelse
147 ufs_brelse(struct usr_vnode *vp, struct usr_buf *bp)
154 * I am not sure what to do with these, they assert for now
157 iodone(struct usr_buf *bp)
171 * Every user is a super user
174 afs_osi_suser(void *credp)
180 afs_suser(void *credp)
186 * These are no-ops in user space
190 afs_osi_SetTime(osi_timeval_t * atv)
196 * xflock should never fall through, the only files we know
197 * about are AFS files
207 * ioctl should never fall through, the only files we know
208 * about are AFS files
218 * We do not support the inode related system calls
221 afs_syscall_icreate(long a, long b, long c, long d, long e, long f)
228 afs_syscall_iincdec(int dev, int inode, int inode_p1, int amount)
235 afs_syscall_iopen(int dev, int inode, int usrmod)
242 afs_syscall_ireadwrite(void)
249 * these routines are referenced in the vfsops structure, but
250 * should never get called
281 * uiomove copies data between kernel buffers and uio buffers
284 usr_uiomove(char *kbuf, int n, int rw, struct usr_uio *uio)
291 nio = uio->uio_iovcnt;
301 while (nio > 0 && n > 0) {
302 len = MIN(n, iovp->iov_len);
303 if (rw == UIO_READ) {
304 memcpy(iovp->iov_base, ptr, len);
306 memcpy(ptr, iovp->iov_base, len);
310 uio->uio_resid -= len;
311 uio->uio_offset += len;
312 iovp->iov_base = (char *)(iovp->iov_base) + len;
313 iovp->iov_len -= len;
324 * routines to manage user credentials
327 usr_crcopy(struct usr_ucred *credp)
329 struct usr_ucred *newcredp;
331 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
333 newcredp->cr_ref = 1;
340 struct usr_ucred *newcredp;
342 newcredp = (struct usr_ucred *)afs_osi_Alloc(sizeof(struct usr_ucred));
343 newcredp->cr_ref = 1;
348 usr_crfree(struct usr_ucred *credp)
351 if (credp->cr_ref == 0) {
352 afs_osi_Free((char *)credp, sizeof(struct usr_ucred));
358 usr_crhold(struct usr_ucred *credp)
365 usr_vattr_null(struct usr_vattr *vap)
370 n = sizeof(struct usr_vattr);
378 * Initialize the thread specific data used to simulate the
379 * kernel environment for each thread. The user structure
380 * is stored in the thread specific data.
383 uafs_InitThread(void)
386 struct usr_user *uptr;
389 * initialize the thread specific user structure. Use malloc to
390 * allocate the data block, so pthread_finish can free the buffer
391 * when this thread terminates.
394 (struct usr_user *)malloc(sizeof(struct usr_user) +
395 sizeof(struct usr_ucred));
396 usr_assert(uptr != NULL);
399 uptr->u_procp = afs_global_procp;
400 uptr->u_cred = (struct usr_ucred *)(uptr + 1);
401 *uptr->u_cred = *afs_global_ucredp;
402 st = usr_setspecific(afs_global_u_key, (void *)uptr);
407 * routine to get the user structure from the thread specific data.
408 * this routine is used to implement the global 'u' structure. Initializes
409 * the thread if needed.
412 get_user_struct(void)
414 struct usr_user *uptr;
416 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
420 st = usr_getspecific(afs_global_u_key, (void **)&uptr);
422 usr_assert(uptr != NULL);
428 * Hash an address for the waithash table
430 #define WAITHASH(X) \
431 (((long)(X)^((long)(X)>>4)^((long)(X)<<4))&(OSI_WAITHASH_SIZE-1))
437 afs_osi_Sleep(void *x)
441 int glockOwner = ISAFS_GLOCK();
443 usr_mutex_lock(&osi_waitq_lock);
448 if (osi_waithash_avail == NULL) {
449 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
450 usr_cond_init(&waitp->cond);
452 waitp = osi_waithash_avail;
453 osi_waithash_avail = osi_waithash_avail->next;
457 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
458 osi_waithash_table[index].tail, next, prev);
459 waitp->expiration = 0;
460 waitp->timedNext = NULL;
461 waitp->timedPrev = NULL;
462 while (waitp->flag == 0) {
463 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
465 DLL_DELETE(waitp, osi_waithash_table[index].head,
466 osi_waithash_table[index].tail, next, prev);
467 waitp->next = osi_waithash_avail;
468 osi_waithash_avail = waitp;
469 usr_mutex_unlock(&osi_waitq_lock);
476 afs_osi_SleepSig(void *x)
483 afs_osi_Wakeup(void *x)
489 usr_mutex_lock(&osi_waitq_lock);
490 waitp = osi_waithash_table[index].head;
492 if (waitp->addr == x && waitp->flag == 0) {
494 usr_cond_signal(&waitp->cond);
498 usr_mutex_unlock(&osi_waitq_lock);
503 afs_osi_TimedSleep(void *event, afs_int32 ams, int aintok)
505 return afs_osi_Wait(ams, event, aintok);
509 afs_osi_Wait(afs_int32 msec, struct afs_osi_WaitHandle *handle, int intok)
515 int glockOwner = ISAFS_GLOCK();
517 tv.tv_sec = msec / 1000;
518 tv.tv_nsec = (msec % 1000) * 1000000;
519 if (handle == NULL) {
523 usr_thread_sleep(&tv);
529 usr_mutex_lock(&osi_waitq_lock);
533 index = WAITHASH((caddr_t) handle);
534 if (osi_waithash_avail == NULL) {
535 waitp = (osi_wait_t *) afs_osi_Alloc(sizeof(osi_wait_t));
536 usr_cond_init(&waitp->cond);
538 waitp = osi_waithash_avail;
539 osi_waithash_avail = osi_waithash_avail->next;
541 waitp->addr = (caddr_t) handle;
543 DLL_INSERT_TAIL(waitp, osi_waithash_table[index].head,
544 osi_waithash_table[index].tail, next, prev);
545 tv.tv_sec += time(NULL);
546 waitp->expiration = tv.tv_sec + ((tv.tv_nsec == 0) ? 0 : 1);
547 DLL_INSERT_TAIL(waitp, osi_timedwait_head, osi_timedwait_tail,
548 timedNext, timedPrev);
549 usr_cond_wait(&waitp->cond, &osi_waitq_lock);
555 DLL_DELETE(waitp, osi_waithash_table[index].head,
556 osi_waithash_table[index].tail, next, prev);
557 DLL_DELETE(waitp, osi_timedwait_head, osi_timedwait_tail, timedNext,
559 waitp->next = osi_waithash_avail;
560 osi_waithash_avail = waitp;
561 usr_mutex_unlock(&osi_waitq_lock);
570 afs_osi_CancelWait(struct afs_osi_WaitHandle *handle)
572 afs_osi_Wakeup(handle);
576 * Netscape NSAPI doesn't have a cond_timed_wait, so we need
577 * to explicitly signal cond_timed_waits when their timers expire
580 afs_osi_CheckTimedWaits(void)
585 curTime = time(NULL);
586 usr_mutex_lock(&osi_waitq_lock);
587 waitp = osi_timedwait_head;
588 while (waitp != NULL) {
589 usr_assert(waitp->expiration != 0);
590 if (waitp->expiration <= curTime) {
592 usr_cond_signal(&waitp->cond);
594 waitp = waitp->timedNext;
596 usr_mutex_unlock(&osi_waitq_lock);
601 * 'dummy' vnode, for non-AFS files. We don't actually need most vnode
602 * information for non-AFS files, so point all of them towards this vnode
605 static struct usr_vnode dummy_vnode = {
616 * Allocate a slot in the file table if there is not one there already,
617 * copy in the file name and kludge up the vnode and inode structures
620 lookupname(char *fnamep, int segflg, int followlink,
621 struct usr_vnode **compvpp)
626 * Assume relative pathnames refer to files in AFS
628 if (*fnamep != '/' || uafs_afsPathName(fnamep) != NULL) {
630 code = uafs_LookupName(fnamep, afs_CurrentDir, compvpp, 0, 0);
635 /* For non-afs files, nobody really looks at the meaningful values in the
636 * returned vnode, so we can return a 'fake' one. The vnode can be held,
637 * released, etc. and some callers check for a NULL vnode anyway, so we
638 * to return something. */
640 usr_mutex_lock(&osi_dummy_lock);
641 VN_HOLD(&dummy_vnode);
642 usr_mutex_unlock(&osi_dummy_lock);
644 *compvpp = &dummy_vnode;
650 * open a file given its i-node number
653 osi_UFSOpen(afs_dcache_id_t *ino)
662 fp = (struct osi_file *)afs_osi_Alloc(sizeof(struct osi_file));
663 usr_assert(fp != NULL);
665 usr_assert(ino->ufs);
667 fp->fd = open(ino->ufs, O_RDWR | O_CREAT, 0);
669 get_user_struct()->u_error = errno;
670 afs_osi_Free((char *)fp, sizeof(struct osi_file));
674 rc = fstat(fp->fd, &st);
676 get_user_struct()->u_error = errno;
677 afs_osi_Free((void *)fp, sizeof(struct osi_file));
681 fp->size = st.st_size;
683 fp->vnode = (struct usr_vnode *)fp;
690 osi_UFSClose(struct osi_file *fp)
699 get_user_struct()->u_error = errno;
700 afs_osi_Free((void *)fp, sizeof(struct osi_file));
704 afs_osi_Free((void *)fp, sizeof(struct osi_file));
710 osi_UFSTruncate(struct osi_file *fp, afs_int32 len)
717 rc = ftruncate(fp->fd, len);
719 get_user_struct()->u_error = errno;
729 afs_osi_Read(struct osi_file *fp, int offset, void *buf, afs_int32 len)
738 rc = lseek(fp->fd, offset, SEEK_SET);
740 rc = lseek(fp->fd, fp->offset, SEEK_SET);
743 get_user_struct()->u_error = errno;
748 ret = read(fp->fd, buf, len);
750 get_user_struct()->u_error = errno;
755 rc = fstat(fp->fd, &st);
757 get_user_struct()->u_error = errno;
761 fp->size = st.st_size;
767 afs_osi_Write(struct osi_file *fp, afs_int32 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 = write(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_Stat(struct osi_file *fp, struct osi_stat *stp)
811 rc = fstat(fp->fd, &st);
813 get_user_struct()->u_error = errno;
817 stp->size = st.st_size;
818 stp->mtime = st.st_mtime;
819 stp->atime = st.st_atime;
828 afs_osi_VOP_RDWR(struct usr_vnode *vnodeP, struct usr_uio *uioP, int rw,
829 int flags, struct usr_ucred *credP)
832 struct osi_file *fp = (struct osi_file *)vnodeP;
835 * We don't support readv/writev.
837 usr_assert(uioP->uio_iovcnt == 1);
838 usr_assert(uioP->uio_resid == uioP->uio_iov[0].iov_len);
840 if (rw == UIO_WRITE) {
841 usr_assert(uioP->uio_fmode == FWRITE);
842 rc = afs_osi_Write(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
843 uioP->uio_iov[0].iov_len);
845 usr_assert(uioP->uio_fmode == FREAD);
846 rc = afs_osi_Read(fp, uioP->uio_offset, uioP->uio_iov[0].iov_base,
847 uioP->uio_iov[0].iov_len);
850 return get_user_struct()->u_error;
853 uioP->uio_resid -= rc;
854 uioP->uio_offset += rc;
855 uioP->uio_iov[0].iov_base = (char *)(uioP->uio_iov[0].iov_base) + rc;
856 uioP->uio_iov[0].iov_len -= rc;
861 afs_osi_Alloc(size_t size)
867 afs_osi_Free(void *ptr, size_t size)
873 afs_osi_FreeStr(char *ptr)
879 osi_AllocLargeSpace(size_t size)
881 AFS_STATCNT(osi_AllocLargeSpace);
882 return afs_osi_Alloc(size);
886 osi_FreeLargeSpace(void *ptr)
888 AFS_STATCNT(osi_FreeLargeSpace);
889 afs_osi_Free(ptr, 0);
893 osi_AllocSmallSpace(size_t size)
895 AFS_STATCNT(osi_AllocSmallSpace);
896 return afs_osi_Alloc(size);
900 osi_FreeSmallSpace(void *ptr)
902 AFS_STATCNT(osi_FreeSmallSpace);
903 afs_osi_Free(ptr, 0);
909 AFS_STATCNT(shutdown_osi);
914 shutdown_osinet(void)
916 AFS_STATCNT(shutdown_osinet);
921 shutdown_osifile(void)
923 AFS_STATCNT(shutdown_osifile);
928 afs_nfsclient_init(void)
933 shutdown_nfsclnt(void)
939 afs_osi_Invisible(void)
945 afs_osi_Visible(void)
951 osi_GetTime(struct timeval *tv)
953 gettimeofday(tv, NULL);
958 osi_SetTime(struct timeval *tv)
964 osi_Active(struct vcache *avc)
966 AFS_STATCNT(osi_Active);
973 afs_osi_MapStrategy(int (*aproc) (struct usr_buf *), struct usr_buf *bp)
975 afs_int32 returnCode;
976 returnCode = (*aproc) (bp);
981 osi_FlushPages(struct vcache *avc, afs_ucred_t *credp)
983 ObtainSharedLock(&avc->lock, 555);
984 if ((hcmp((avc->f.m.DataVersion), (avc->mapDV)) <= 0)
985 || ((avc->execsOrWriters > 0) && afs_DirtyPages(avc))) {
986 ReleaseSharedLock(&avc->lock);
989 UpgradeSToWLock(&avc->lock, 565);
990 hset(avc->mapDV, avc->f.m.DataVersion);
991 ReleaseWriteLock(&avc->lock);
996 osi_FlushText_really(struct vcache *vp)
998 if (hcmp(vp->f.m.DataVersion, vp->flushDV) > 0) {
999 hset(vp->flushDV, vp->f.m.DataVersion);
1005 osi_SyncVM(struct vcache *avc)
1011 osi_ReleaseVM(struct vcache *avc, int len, struct usr_ucred *credp)
1023 * Use the thread specific data to implement the user structure
1025 usr_keycreate(&afs_global_u_key, free);
1028 * Initialize the global ucred structure
1030 afs_global_ucredp = (struct usr_ucred *)
1031 afs_osi_Alloc(sizeof(struct usr_ucred));
1032 usr_assert(afs_global_ucredp != NULL);
1033 afs_global_ucredp->cr_ref = 1;
1034 afs_set_cr_uid(afs_global_ucredp, geteuid());
1035 afs_set_cr_gid(afs_global_ucredp, getegid());
1036 afs_set_cr_ruid(afs_global_ucredp, getuid());
1037 afs_set_cr_rgid(afs_global_ucredp, getgid());
1038 afs_global_ucredp->cr_suid = afs_cr_ruid(afs_global_ucredp);
1039 afs_global_ucredp->cr_sgid = afs_cr_rgid(afs_global_ucredp);
1040 st = getgroups(NGROUPS, &afs_global_ucredp->cr_groups[0]);
1041 usr_assert(st >= 0);
1042 afs_global_ucredp->cr_ngroups = (unsigned long)st;
1043 for (i = st; i < NGROUPS; i++) {
1044 afs_global_ucredp->cr_groups[i] = NOGROUP;
1048 * Initialize the global process structure
1050 afs_global_procp = (struct usr_proc *)
1051 afs_osi_Alloc(sizeof(struct usr_proc));
1052 usr_assert(afs_global_procp != NULL);
1053 afs_global_procp->p_pid = osi_getpid();
1054 afs_global_procp->p_ppid = (pid_t) 1;
1055 afs_global_procp->p_ucred = afs_global_ucredp;
1057 #ifndef NETSCAPE_NSAPI
1059 * Initialize the mutex and condition variable used to implement
1062 pthread_mutex_init(&usr_sleep_mutex, NULL);
1063 pthread_cond_init(&usr_sleep_cond, NULL);
1064 #endif /* !NETSCAPE_NSAPI */
1067 * Initialize the hash table used for sleep/wakeup
1069 for (i = 0; i < OSI_WAITHASH_SIZE; i++) {
1070 DLL_INIT_LIST(osi_waithash_table[i].head, osi_waithash_table[i].tail);
1072 DLL_INIT_LIST(osi_timedwait_head, osi_timedwait_tail);
1073 osi_waithash_avail = NULL;
1076 * Initialize the AFS file table
1078 for (i = 0; i < MAX_OSI_FILES; i++) {
1079 afs_FileTable[i] = NULL;
1083 * Initialize the global locks
1085 usr_mutex_init(&afs_global_lock);
1086 usr_mutex_init(&rx_global_lock);
1087 usr_mutex_init(&osi_dummy_lock);
1088 usr_mutex_init(&osi_waitq_lock);
1089 usr_mutex_init(&osi_authenticate_lock);
1092 * Initialize the AFS OSI credentials
1094 afs_osi_cred = *afs_global_ucredp;
1095 afs_osi_credp = &afs_osi_cred;
1097 init_et_to_sys_error();
1101 * Set the UDP port number RX uses for UDP datagrams
1104 uafs_SetRxPort(int port)
1106 usr_assert(usr_rx_port == 0);
1111 * uafs_Init is for backwards compatibility only! Do not use it; use
1112 * uafs_Setup, uafs_ParseArgs, and uafs_Run instead.
1115 uafs_Init(char *rn, char *mountDirParam, char *confDirParam,
1116 char *cacheBaseDirParam, int cacheBlocksParam, int cacheFilesParam,
1117 int cacheStatEntriesParam, int dCacheSizeParam, int vCacheSizeParam,
1118 int chunkSizeParam, int closeSynchParam, int debugParam,
1119 int nDaemonsParam, int cacheFlagsParam, char *logFile)
1129 code = uafs_Setup(mountDirParam);
1130 usr_assert(code == 0);
1133 if (mountDirParam) {
1134 argv[argc++] = "-mountdir";
1135 argv[argc++] = mountDirParam;
1138 argv[argc++] = "-confdir";
1139 argv[argc++] = confDirParam;
1141 if (cacheBaseDirParam) {
1142 argv[argc++] = "-cachedir";
1143 argv[argc++] = cacheBaseDirParam;
1145 if (cacheBlocksParam) {
1146 snprintf(buf, sizeof(buf), "%d", cacheBlocksParam);
1148 argv[argc++] = "-blocks";
1149 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1151 if (cacheFilesParam) {
1152 snprintf(buf, sizeof(buf), "%d", cacheFilesParam);
1154 argv[argc++] = "-files";
1155 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1157 if (cacheStatEntriesParam) {
1158 snprintf(buf, sizeof(buf), "%d", cacheStatEntriesParam);
1160 argv[argc++] = "-stat";
1161 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1163 if (dCacheSizeParam) {
1164 snprintf(buf, sizeof(buf), "%d", dCacheSizeParam);
1166 argv[argc++] = "-dcache";
1167 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1169 if (vCacheSizeParam) {
1170 snprintf(buf, sizeof(buf), "%d", vCacheSizeParam);
1172 argv[argc++] = "-volumes";
1173 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1175 if (chunkSizeParam) {
1176 snprintf(buf, sizeof(buf), "%d", chunkSizeParam);
1178 argv[argc++] = "-chunksize";
1179 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1181 if (closeSynchParam) {
1182 argv[argc++] = "-waitclose";
1185 argv[argc++] = "-debug";
1187 if (nDaemonsParam) {
1188 snprintf(buf, sizeof(buf), "%d", nDaemonsParam);
1190 argv[argc++] = "-daemons";
1191 argv[argc++] = freeargv[freeargc++] = strdup(buf);
1193 if (cacheFlagsParam) {
1194 if (cacheFlagsParam & AFSCALL_INIT_MEMCACHE) {
1195 argv[argc++] = "-memcache";
1199 argv[argc++] = "-logfile";
1200 argv[argc++] = logFile;
1205 code = uafs_ParseArgs(argc, argv);
1206 usr_assert(code == 0);
1208 for (i = 0; i < freeargc; i++) {
1213 usr_assert(code == 0);
1221 * Mount the AFS filesystem
1224 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1225 usr_assert(rc == 0);
1226 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1227 usr_assert(rc == 0);
1231 * initialize the current directory to the AFS root
1233 afs_CurrentDir = afs_RootVnode;
1234 VN_HOLD(afs_CurrentDir);
1240 uafs_statvfs(struct statvfs *buf)
1246 rc = afs_statvfs(&afs_RootVfs, buf);
1266 if (afs_CurrentDir) {
1267 VN_RELE(afs_CurrentDir);
1269 rc = afs_unmount(&afs_RootVfs);
1270 usr_assert(rc == 0);
1277 * Donate the current thread to the RX server pool.
1280 uafs_RxServerProc(void)
1284 struct rx_call *newcall = NULL;
1286 rxi_MorePackets(2); /* alloc more packets */
1287 threadID = rxi_availProcs++;
1290 sock = OSI_NULLSOCKET;
1291 rxi_ServerProc(threadID, newcall, &sock);
1292 if (sock == OSI_NULLSOCKET) {
1297 rxi_ListenerProc(sock, &threadID, &newcall);
1298 /* assert(threadID != -1); */
1299 /* assert(newcall != NULL); */
1303 struct syscallThreadArgs {
1312 #ifdef NETSCAPE_NSAPI
1314 syscallThread(void *argp)
1315 #else /* NETSCAPE_NSAPI */
1317 syscallThread(void *argp)
1318 #endif /* NETSCAPE_NSAPI */
1321 struct usr_ucred *crp;
1322 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1325 * AFS daemons run authenticated
1327 get_user_struct()->u_viceid = getuid();
1328 crp = get_user_struct()->u_cred;
1329 afs_set_cr_uid(crp, getuid());
1330 afs_set_cr_ruid(crp, getuid());
1331 crp->cr_suid = getuid();
1332 crp->cr_groups[0] = getgid();
1333 crp->cr_ngroups = 1;
1334 for (i = 1; i < NGROUPS; i++) {
1335 crp->cr_groups[i] = NOGROUP;
1338 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1339 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1341 afs_osi_Free(argp, -1);
1346 fork_syscall(long syscall, long afscall, long param1, long param2,
1347 long param3, long param4)
1350 struct syscallThreadArgs *sysArgsP;
1352 sysArgsP = (struct syscallThreadArgs *)
1353 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1354 usr_assert(sysArgsP != NULL);
1355 sysArgsP->syscall = syscall;
1356 sysArgsP->afscall = afscall;
1357 sysArgsP->param1 = param1;
1358 sysArgsP->param2 = param2;
1359 sysArgsP->param3 = param3;
1360 sysArgsP->param4 = param4;
1362 usr_thread_create(&tid, syscallThread, sysArgsP);
1363 usr_thread_detach(tid);
1368 call_syscall(long syscall, long afscall, long param1, long param2,
1369 long param3, long param4)
1381 a.syscall = syscall;
1382 a.afscall = afscall;
1388 get_user_struct()->u_error = 0;
1389 get_user_struct()->u_ap = (char *)&a;
1391 code = Afs_syscall();
1396 uafs_Setup(const char *mount)
1401 static int inited = 0;
1408 if (mount && strlen(mount) > 1023) {
1409 return ENAMETOOLONG;
1413 * Initialize the AFS mount point, default is '/afs'.
1414 * Strip duplicate/trailing slashes from mount point string.
1415 * afs_mountDirLen is set to strlen(afs_mountDir).
1420 sprintf(buf, "%s", mount);
1422 afs_mountDir[0] = '/';
1423 afs_mountDirLen = 1;
1424 for (lastchar = '/', p = &buf[0]; *p != '\0'; p++) {
1425 if (lastchar != '/' || *p != '/') {
1426 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1429 if (lastchar == '/' && afs_mountDirLen > 1)
1431 afs_mountDir[afs_mountDirLen] = '\0';
1432 if (afs_mountDirLen <= 1) {
1436 /* initialize global vars and such */
1439 /* initialize cache manager foo */
1446 uafs_ParseArgs(int argc, char **argv)
1448 return afsd_parse(argc, argv);
1460 return afsd_cacheMountDir;
1464 uafs_SetTokens(char *tbuffer, int tlen)
1467 struct afs_ioctl iob;
1472 iob.out = &outbuf[0];
1473 iob.out_size = sizeof(outbuf);
1475 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
1484 uafs_RPCStatsEnableProc(void)
1487 struct afs_ioctl iob;
1490 flag = AFSCALL_RXSTATS_ENABLE;
1491 iob.in = (char *)&flag;
1492 iob.in_size = sizeof(afs_int32);
1495 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1504 uafs_RPCStatsDisableProc(void)
1507 struct afs_ioctl iob;
1510 flag = AFSCALL_RXSTATS_DISABLE;
1511 iob.in = (char *)&flag;
1512 iob.in_size = sizeof(afs_int32);
1515 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1524 uafs_RPCStatsClearProc(void)
1527 struct afs_ioctl iob;
1530 flag = AFSCALL_RXSTATS_CLEAR;
1531 iob.in = (char *)&flag;
1532 iob.in_size = sizeof(afs_int32);
1535 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1544 uafs_RPCStatsEnablePeer(void)
1547 struct afs_ioctl iob;
1550 flag = AFSCALL_RXSTATS_ENABLE;
1551 iob.in = (char *)&flag;
1552 iob.in_size = sizeof(afs_int32);
1555 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1564 uafs_RPCStatsDisablePeer(void)
1567 struct afs_ioctl iob;
1570 flag = AFSCALL_RXSTATS_DISABLE;
1571 iob.in = (char *)&flag;
1572 iob.in_size = sizeof(afs_int32);
1575 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1584 uafs_RPCStatsClearPeer(void)
1587 struct afs_ioctl iob;
1590 flag = AFSCALL_RXSTATS_CLEAR;
1591 iob.in = (char *)&flag;
1592 iob.in_size = sizeof(afs_int32);
1595 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1604 * Lookup a file or directory given its path.
1605 * Call VN_HOLD on the output vnode if successful.
1606 * Returns zero on success, error code on failure.
1608 * Note: Caller must hold the AFS global lock.
1611 uafs_LookupName(char *path, struct usr_vnode *parentVp,
1612 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
1616 struct usr_vnode *vp;
1617 struct usr_vnode *nextVp;
1618 struct usr_vnode *linkVp;
1619 struct vcache *nextVc;
1622 char *nextPathP = NULL;
1627 * Absolute paths must start with the AFS mount point.
1629 if (path[0] != '/') {
1632 path = uafs_afsPathName(path);
1640 * Loop through the path looking for the new directory
1642 tmpPath = afs_osi_Alloc(strlen(path) + 1);
1643 usr_assert(tmpPath != NULL);
1644 strcpy(tmpPath, path);
1647 while (pathP != NULL && *pathP != '\0') {
1648 usr_assert(*pathP != '/');
1651 * terminate the current component and skip over slashes
1653 nextPathP = afs_strchr(pathP, '/');
1654 if (nextPathP != NULL) {
1655 while (*nextPathP == '/') {
1656 *(nextPathP++) = '\0';
1661 * Don't call afs_lookup on non-directories
1663 if (vp->v_type != VDIR) {
1665 afs_osi_Free(tmpPath, strlen(path) + 1);
1669 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
1671 * The AFS root is its own parent
1673 nextVp = afs_RootVnode;
1676 * We need execute permission to search a directory
1678 code = afs_access(VTOAFS(vp), VEXEC, get_user_struct()->u_cred);
1681 afs_osi_Free(tmpPath, strlen(path) + 1);
1686 * lookup the next component in the path, we can release the
1687 * subdirectory since we hold the global lock
1691 #ifdef AFS_WEB_ENHANCEMENTS
1692 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
1693 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
1696 afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred,
1699 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
1700 #endif /* AFS_WEB_ENHANCEMENTS */
1702 nextVp=AFSTOV(nextVc);
1705 afs_osi_Free(tmpPath, strlen(path) + 1);
1711 * Follow symbolic links for parent directories and
1712 * for leaves when the follow flag is set.
1714 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
1716 while (nextVp->v_type == VLNK) {
1717 if (++linkCount > MAX_OSI_LINKS) {
1720 afs_osi_Free(tmpPath, strlen(path) + 1);
1723 code = uafs_LookupLink(nextVp, vp, &linkVp);
1727 afs_osi_Free(tmpPath, strlen(path) + 1);
1741 * Special case, nextPathP is non-null if pathname ends in slash
1743 if (nextPathP != NULL && vp->v_type != VDIR) {
1745 afs_osi_Free(tmpPath, strlen(path) + 1);
1749 afs_osi_Free(tmpPath, strlen(path) + 1);
1755 * Lookup the target of a symbolic link
1756 * Call VN_HOLD on the output vnode if successful.
1757 * Returns zero on success, error code on failure.
1759 * Note: Caller must hold the AFS global lock.
1762 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
1763 struct usr_vnode **vpp)
1768 struct usr_vnode *linkVp;
1770 struct iovec iov[1];
1774 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
1775 usr_assert(pathP != NULL);
1778 * set up the uio buffer
1780 iov[0].iov_base = pathP;
1781 iov[0].iov_len = MAX_OSI_PATH + 1;
1782 uio.uio_iov = &iov[0];
1786 uio.uio_fmode = FREAD;
1787 uio.uio_resid = MAX_OSI_PATH + 1;
1790 * Read the link data
1792 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
1794 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1797 len = MAX_OSI_PATH + 1 - uio.uio_resid;
1801 * Find the target of the symbolic link
1803 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
1805 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1809 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1815 * Lookup the parent of a file or directory given its path
1816 * Call VN_HOLD on the output vnode if successful.
1817 * Returns zero on success, error code on failure.
1819 * Note: Caller must hold the AFS global lock.
1822 uafs_LookupParent(char *path, struct usr_vnode **vpp)
1827 struct usr_vnode *parentP;
1832 * Absolute path names must start with the AFS mount point.
1835 pathP = uafs_afsPathName(path);
1836 if (pathP == NULL) {
1842 * Find the length of the parent path
1845 while (len > 0 && path[len - 1] == '/') {
1851 while (len > 0 && path[len - 1] != '/') {
1858 pathP = afs_osi_Alloc(len);
1859 usr_assert(pathP != NULL);
1860 memcpy(pathP, path, len - 1);
1861 pathP[len - 1] = '\0';
1864 * look up the parent
1866 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
1867 afs_osi_Free(pathP, len);
1871 if (parentP->v_type != VDIR) {
1881 * Return a pointer to the first character in the last component
1885 uafs_LastPath(char *path)
1890 while (len > 0 && path[len - 1] == '/') {
1893 while (len > 0 && path[len - 1] != '/') {
1903 * Set the working directory.
1906 uafs_chdir(char *path)
1910 retval = uafs_chdir_r(path);
1916 uafs_chdir_r(char *path)
1921 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
1926 if (dirP->v_type != VDIR) {
1931 VN_RELE(afs_CurrentDir);
1932 afs_CurrentDir = dirP;
1937 * Create a directory.
1940 uafs_mkdir(char *path, int mode)
1944 retval = uafs_mkdir_r(path, mode);
1950 uafs_mkdir_r(char *path, int mode)
1954 struct vnode *parentP;
1955 struct vcache *dirP;
1956 struct usr_vattr attrs;
1958 if (uafs_IsRoot(path)) {
1963 * Look up the parent directory.
1965 nameP = uafs_LastPath(path);
1966 if (nameP != NULL) {
1967 code = uafs_LookupParent(path, &parentP);
1973 parentP = afs_CurrentDir;
1979 * Make sure the directory has at least one character
1981 if (*nameP == '\0') {
1988 * Create the directory
1990 usr_vattr_null(&attrs);
1991 attrs.va_type = VREG;
1992 attrs.va_mode = mode;
1993 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
1994 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
1996 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, get_user_struct()->u_cred);
2002 VN_RELE(AFSTOV(dirP));
2007 * Return 1 if path is the AFS root, otherwise return 0
2010 uafs_IsRoot(char *path)
2012 while (*path == '/' && *(path + 1) == '/') {
2015 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
2018 path += afs_mountDirLen;
2019 while (*path == '/') {
2022 if (*path != '\0') {
2030 * Note: file name may not end in a slash.
2033 uafs_open(char *path, int flags, int mode)
2037 retval = uafs_open_r(path, flags, mode);
2043 uafs_open_r(char *path, int flags, int mode)
2049 struct usr_vnode *fileP;
2050 struct usr_vnode *dirP;
2051 struct usr_vattr attrs;
2056 if (uafs_IsRoot(path)) {
2057 fileP = afs_RootVnode;
2061 * Look up the parent directory.
2063 nameP = uafs_LastPath(path);
2064 if (nameP != NULL) {
2065 code = uafs_LookupParent(path, &dirP);
2071 dirP = afs_CurrentDir;
2077 * Make sure the filename has at least one character
2079 if (*nameP == '\0') {
2086 * Get the VNODE for this file
2088 if (flags & O_CREAT) {
2089 usr_vattr_null(&attrs);
2090 attrs.va_type = VREG;
2091 attrs.va_mode = mode;
2092 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2093 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2094 if (flags & O_TRUNC) {
2100 afs_create(VTOAFS(dirP), nameP, &attrs,
2101 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
2102 &vc, get_user_struct()->u_cred);
2111 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2119 * Check whether we have access to this file
2122 if (flags & (O_RDONLY | O_RDWR)) {
2125 if (flags & (O_WRONLY | O_RDWR)) {
2129 fileMode = VREAD; /* since O_RDONLY is 0 */
2130 code = afs_access(VTOAFS(fileP), fileMode, get_user_struct()->u_cred);
2138 * Get the file attributes, all we need is the size
2140 code = afs_getattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2150 * Setup the open flags
2153 if (flags & O_TRUNC) {
2154 openFlags |= FTRUNC;
2156 if (flags & O_APPEND) {
2157 openFlags |= FAPPEND;
2159 if (flags & O_SYNC) {
2162 if (flags & O_SYNC) {
2165 if (flags & (O_RDONLY | O_RDWR)) {
2168 if (flags & (O_WRONLY | O_RDWR)) {
2169 openFlags |= FWRITE;
2171 if ((openFlags & (FREAD | FWRITE)) == 0) {
2172 /* O_RDONLY is 0, so ... */
2177 * Truncate if necessary
2179 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2180 usr_vattr_null(&attrs);
2181 attrs.va_mask = ATTR_SIZE;
2183 code = afs_setattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2195 code = afs_open(&vc, openFlags, get_user_struct()->u_cred);
2203 * Put the vnode pointer into the file table
2205 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2206 if (afs_FileTable[fd] == NULL) {
2207 afs_FileTable[fd] = fileP;
2208 afs_FileFlags[fd] = openFlags;
2209 if (flags & O_APPEND) {
2210 afs_FileOffsets[fd] = attrs.va_size;
2212 afs_FileOffsets[fd] = 0;
2217 if (fd == MAX_OSI_FILES) {
2230 uafs_creat(char *path, int mode)
2233 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2238 uafs_creat_r(char *path, int mode)
2241 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2249 uafs_write(int fd, char *buf, int len)
2253 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2259 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2263 retval = uafs_pwrite_r(fd, buf, len, offset);
2269 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2273 struct iovec iov[1];
2274 struct usr_vnode *fileP;
2277 * Make sure this is an open file
2279 fileP = afs_FileTable[fd];
2280 if (fileP == NULL) {
2286 * set up the uio buffer
2288 iov[0].iov_base = buf;
2289 iov[0].iov_len = len;
2290 uio.uio_iov = &iov[0];
2292 uio.uio_offset = offset;
2294 uio.uio_fmode = FWRITE;
2295 uio.uio_resid = len;
2301 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], get_user_struct()->u_cred, 0);
2307 afs_FileOffsets[fd] = uio.uio_offset;
2308 return (len - uio.uio_resid);
2315 uafs_read(int fd, char *buf, int len)
2319 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2325 uafs_pread(int fd, char *buf, int len, off_t offset)
2329 retval = uafs_pread_r(fd, buf, len, offset);
2335 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2339 struct iovec iov[1];
2340 struct usr_vnode *fileP;
2341 struct usr_buf *bufP;
2344 * Make sure this is an open file
2346 fileP = afs_FileTable[fd];
2347 if (fileP == NULL) {
2353 * set up the uio buffer
2355 iov[0].iov_base = buf;
2356 iov[0].iov_len = len;
2357 uio.uio_iov = &iov[0];
2359 uio.uio_offset = offset;
2361 uio.uio_fmode = FREAD;
2362 uio.uio_resid = len;
2367 code = afs_read(VTOAFS(fileP), &uio, get_user_struct()->u_cred, 0, &bufP, 0);
2373 afs_FileOffsets[fd] = uio.uio_offset;
2374 return (len - uio.uio_resid);
2378 * Copy the attributes of a file into a stat structure.
2380 * NOTE: Caller must hold the global AFS lock.
2383 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2386 struct usr_vattr attrs;
2391 * Get the attributes
2393 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2399 * Copy the attributes, zero fields that aren't set
2401 memset((void *)stats, 0, sizeof(struct stat));
2403 stats->st_ino = attrs.va_nodeid;
2404 stats->st_mode = attrs.va_mode;
2405 stats->st_nlink = attrs.va_nlink;
2406 stats->st_uid = attrs.va_uid;
2407 stats->st_gid = attrs.va_gid;
2408 stats->st_rdev = attrs.va_rdev;
2409 stats->st_size = attrs.va_size;
2410 stats->st_atime = attrs.va_atime.tv_sec;
2411 stats->st_mtime = attrs.va_mtime.tv_sec;
2412 stats->st_ctime = attrs.va_ctime.tv_sec;
2413 stats->st_blksize = attrs.va_blocksize;
2414 stats->st_blocks = attrs.va_blocks;
2420 * Get the attributes of a file, do follow links
2423 uafs_stat(char *path, struct stat *buf)
2427 retval = uafs_stat_r(path, buf);
2433 uafs_stat_r(char *path, struct stat *buf)
2438 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2443 code = uafs_GetAttr(vp, buf);
2453 * Get the attributes of a file, don't follow links
2456 uafs_lstat(char *path, struct stat *buf)
2460 retval = uafs_lstat_r(path, buf);
2466 uafs_lstat_r(char *path, struct stat *buf)
2471 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2476 code = uafs_GetAttr(vp, buf);
2486 * Get the attributes of an open file
2489 uafs_fstat(int fd, struct stat *buf)
2493 retval = uafs_fstat_r(fd, buf);
2499 uafs_fstat_r(int fd, struct stat *buf)
2504 vp = afs_FileTable[fd];
2509 code = uafs_GetAttr(vp, buf);
2518 * change the permissions on a file
2521 uafs_chmod(char *path, int mode)
2525 retval = uafs_chmod_r(path, mode);
2531 uafs_chmod_r(char *path, int mode)
2535 struct usr_vattr attrs;
2537 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2542 usr_vattr_null(&attrs);
2543 attrs.va_mask = ATTR_MODE;
2544 attrs.va_mode = mode;
2545 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2555 * change the permissions on an open file
2558 uafs_fchmod(int fd, int mode)
2562 retval = uafs_fchmod_r(fd, mode);
2568 uafs_fchmod_r(int fd, int mode)
2572 struct usr_vattr attrs;
2574 vp = afs_FileTable[fd];
2579 usr_vattr_null(&attrs);
2580 attrs.va_mask = ATTR_MODE;
2581 attrs.va_mode = mode;
2582 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2594 uafs_truncate(char *path, int length)
2598 retval = uafs_truncate_r(path, length);
2604 uafs_truncate_r(char *path, int length)
2608 struct usr_vattr attrs;
2610 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2615 usr_vattr_null(&attrs);
2616 attrs.va_mask = ATTR_SIZE;
2617 attrs.va_size = length;
2618 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2628 * truncate an open file
2631 uafs_ftruncate(int fd, int length)
2635 retval = uafs_ftruncate_r(fd, length);
2641 uafs_ftruncate_r(int fd, int length)
2645 struct usr_vattr attrs;
2647 vp = afs_FileTable[fd];
2652 usr_vattr_null(&attrs);
2653 attrs.va_mask = ATTR_SIZE;
2654 attrs.va_size = length;
2655 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2664 * set the read/write file pointer of an open file
2667 uafs_lseek(int fd, int offset, int whence)
2671 retval = uafs_lseek_r(fd, offset, whence);
2677 uafs_lseek_r(int fd, int offset, int whence)
2681 struct usr_vattr attrs;
2682 struct usr_vnode *vp;
2684 vp = afs_FileTable[fd];
2691 newpos = afs_FileOffsets[fd] + offset;
2697 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2702 newpos = attrs.va_size + offset;
2712 afs_FileOffsets[fd] = newpos;
2724 retval = uafs_fsync_r(fd);
2730 uafs_fsync_r(int fd)
2733 struct usr_vnode *fileP;
2736 fileP = afs_FileTable[fd];
2737 if (fileP == NULL) {
2742 code = afs_fsync(VTOAFS(fileP), get_user_struct()->u_cred);
2759 retval = uafs_close_r(fd);
2765 uafs_close_r(int fd)
2768 struct usr_vnode *fileP;
2770 fileP = afs_FileTable[fd];
2771 if (fileP == NULL) {
2775 afs_FileTable[fd] = NULL;
2777 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], get_user_struct()->u_cred);
2788 * Create a hard link from the source to the target
2789 * Note: file names may not end in a slash.
2792 uafs_link(char *existing, char *new)
2796 retval = uafs_link_r(existing, new);
2802 uafs_link_r(char *existing, char *new)
2805 struct usr_vnode *existP;
2806 struct usr_vnode *dirP;
2809 if (uafs_IsRoot(new)) {
2814 * Look up the existing node.
2816 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
2823 * Look up the parent directory.
2825 nameP = uafs_LastPath(new);
2826 if (nameP != NULL) {
2827 code = uafs_LookupParent(new, &dirP);
2834 dirP = afs_CurrentDir;
2840 * Make sure the filename has at least one character
2842 if (*nameP == '\0') {
2852 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, get_user_struct()->u_cred);
2863 * Create a symbolic link from the source to the target
2864 * Note: file names may not end in a slash.
2867 uafs_symlink(char *target, char *source)
2871 retval = uafs_symlink_r(target, source);
2877 uafs_symlink_r(char *target, char *source)
2880 struct usr_vnode *dirP;
2881 struct usr_vattr attrs;
2884 if (uafs_IsRoot(source)) {
2889 * Look up the parent directory.
2891 nameP = uafs_LastPath(source);
2892 if (nameP != NULL) {
2893 code = uafs_LookupParent(source, &dirP);
2899 dirP = afs_CurrentDir;
2905 * Make sure the filename has at least one character
2907 if (*nameP == '\0') {
2916 usr_vattr_null(&attrs);
2917 attrs.va_type = VLNK;
2918 attrs.va_mode = 0777;
2919 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2920 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2921 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
2931 * Read a symbolic link into the buffer
2934 uafs_readlink(char *path, char *buf, int len)
2938 retval = uafs_readlink_r(path, buf, len);
2944 uafs_readlink_r(char *path, char *buf, int len)
2947 struct usr_vnode *vp;
2949 struct iovec iov[1];
2951 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2957 if (vp->v_type != VLNK) {
2964 * set up the uio buffer
2966 iov[0].iov_base = buf;
2967 iov[0].iov_len = len;
2968 uio.uio_iov = &iov[0];
2972 uio.uio_fmode = FREAD;
2973 uio.uio_resid = len;
2978 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
2986 * return the number of bytes read
2988 return (len - uio.uio_resid);
2992 * Remove a file (or directory)
2993 * Note: file name may not end in a slash.
2996 uafs_unlink(char *path)
3000 retval = uafs_unlink_r(path);
3006 uafs_unlink_r(char *path)
3009 struct usr_vnode *dirP;
3012 if (uafs_IsRoot(path)) {
3017 * Look up the parent directory.
3019 nameP = uafs_LastPath(path);
3020 if (nameP != NULL) {
3021 code = uafs_LookupParent(path, &dirP);
3027 dirP = afs_CurrentDir;
3033 * Make sure the filename has at least one character
3035 if (*nameP == '\0') {
3044 code = afs_remove(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3055 * Rename a file (or directory)
3058 uafs_rename(char *old, char *new)
3062 retval = uafs_rename_r(old, new);
3068 uafs_rename_r(char *old, char *new)
3073 struct usr_vnode *odirP;
3074 struct usr_vnode *ndirP;
3076 if (uafs_IsRoot(new)) {
3081 * Look up the parent directories.
3083 onameP = uafs_LastPath(old);
3084 if (onameP != NULL) {
3085 code = uafs_LookupParent(old, &odirP);
3091 odirP = afs_CurrentDir;
3095 nnameP = uafs_LastPath(new);
3096 if (nnameP != NULL) {
3097 code = uafs_LookupParent(new, &ndirP);
3103 ndirP = afs_CurrentDir;
3109 * Make sure the filename has at least one character
3111 if (*onameP == '\0' || *nnameP == '\0') {
3121 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, get_user_struct()->u_cred);
3133 * Remove a or directory
3134 * Note: file name may not end in a slash.
3137 uafs_rmdir(char *path)
3141 retval = uafs_rmdir_r(path);
3147 uafs_rmdir_r(char *path)
3150 struct usr_vnode *dirP;
3153 if (uafs_IsRoot(path)) {
3158 * Look up the parent directory.
3160 nameP = uafs_LastPath(path);
3161 if (nameP != NULL) {
3162 code = uafs_LookupParent(path, &dirP);
3168 dirP = afs_CurrentDir;
3174 * Make sure the directory name has at least one character
3176 if (*nameP == '\0') {
3183 * Remove the directory
3185 code = afs_rmdir(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3196 * Flush a file from the AFS cache
3199 uafs_FlushFile(char *path)
3202 struct afs_ioctl iob;
3210 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3221 uafs_FlushFile_r(char *path)
3225 retval = uafs_FlushFile(path);
3234 uafs_opendir(char *path)
3238 retval = uafs_opendir_r(path);
3244 uafs_opendir_r(char *path)
3247 struct usr_vnode *fileP;
3251 * Open the directory for reading
3253 fd = uafs_open_r(path, O_RDONLY, 0);
3258 fileP = afs_FileTable[fd];
3259 if (fileP == NULL) {
3263 if (fileP->v_type != VDIR) {
3270 * Set up the directory structures
3273 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3274 sizeof(struct usr_dirent));
3275 usr_assert(dirp != NULL);
3276 dirp->dd_buf = (char *)(dirp + 1);
3286 * Read directory entries into a file system independent format.
3287 * This routine was developed to support AFS cache consistency testing.
3288 * You should use uafs_readdir instead.
3291 uafs_getdents(int fd, struct min_direct *buf, int len)
3295 retval = uafs_getdents_r(fd, buf, len);
3301 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3305 struct usr_vnode *vp;
3306 struct iovec iov[1];
3309 * Make sure this is an open file
3311 vp = afs_FileTable[fd];
3319 * set up the uio buffer
3321 iov[0].iov_base = (char *)buf;
3322 iov[0].iov_len = len;
3323 uio.uio_iov = &iov[0];
3325 uio.uio_offset = afs_FileOffsets[fd];
3327 uio.uio_fmode = FREAD;
3328 uio.uio_resid = len;
3331 * read the next chunk from the directory
3333 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3339 afs_FileOffsets[fd] = uio.uio_offset;
3340 return (len - uio.uio_resid);
3344 * read from a directory (names only)
3347 uafs_readdir(usr_DIR * dirp)
3349 struct usr_dirent *retval;
3351 retval = uafs_readdir_r(dirp);
3357 uafs_readdir_r(usr_DIR * dirp)
3362 struct usr_vnode *vp;
3363 struct iovec iov[1];
3364 struct usr_dirent *direntP;
3365 struct min_direct *directP;
3373 * Make sure this is an open file
3375 vp = afs_FileTable[dirp->dd_fd];
3382 * If there are no entries in the stream buffer
3383 * then read another chunk
3385 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3386 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3388 * set up the uio buffer
3390 iov[0].iov_base = dirp->dd_buf;
3391 iov[0].iov_len = USR_DIRSIZE;
3392 uio.uio_iov = &iov[0];
3394 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3396 uio.uio_fmode = FREAD;
3397 uio.uio_resid = USR_DIRSIZE;
3400 * read the next chunk from the directory
3402 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3407 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3409 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3411 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3415 * Check for end of file
3417 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3421 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
3422 usr_assert(len <= dirp->dd_size);
3425 * Copy the next entry into the usr_dirent structure and advance
3427 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
3428 direntP->d_ino = directP->d_fileno;
3429 direntP->d_off = direntP->d_reclen;
3431 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
3432 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
3433 direntP->d_name[directP->d_namlen] = '\0';
3434 dirp->dd_loc += len;
3435 dirp->dd_size -= len;
3444 uafs_closedir(usr_DIR * dirp)
3448 retval = uafs_closedir_r(dirp);
3454 uafs_closedir_r(usr_DIR * dirp)
3465 afs_osi_Free((char *)dirp,
3466 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
3467 rc = uafs_close_r(fd);
3472 * Do AFS authentication
3475 uafs_klog(char *user, char *cell, char *passwd, char **reason)
3478 afs_int32 password_expires = -1;
3480 usr_mutex_lock(&osi_authenticate_lock);
3482 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
3483 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
3484 passwd, 0, &password_expires, 0, reason);
3485 usr_mutex_unlock(&osi_authenticate_lock);
3490 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
3494 retval = uafs_klog(user, cell, passwd, reason);
3500 * Destroy AFS credentials from the kernel cache
3507 usr_mutex_lock(&osi_authenticate_lock);
3508 code = ktc_ForgetAllTokens();
3509 usr_mutex_unlock(&osi_authenticate_lock);
3518 retval = uafs_unlog();
3524 * Strip the AFS mount point from a pathname string. Return
3525 * NULL if the path is a relative pathname or if the path
3526 * doesn't start with the AFS mount point string.
3529 uafs_afsPathName(char *path)
3538 for (i = 1, p = path + 1; *p != '\0'; p++) {
3539 /* Ignore duplicate slashes */
3540 if (*p == '/' && lastchar == '/')
3542 /* Is this a subdirectory of the AFS mount point? */
3543 if (afs_mountDir[i] == '\0' && *p == '/') {
3544 /* strip leading slashes */
3545 while (*(++p) == '/');
3548 /* Reject paths that are not within AFS */
3549 if (*p != afs_mountDir[i])
3554 /* Is this the AFS mount point? */
3555 if (afs_mountDir[i] == '\0') {
3556 usr_assert(*p == '\0');
3562 #ifdef AFS_WEB_ENHANCEMENTS
3565 * klog but don't allocate a new pag
3568 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
3571 afs_int32 password_expires = -1;
3573 usr_mutex_lock(&osi_authenticate_lock);
3574 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
3575 /*+KA_USERAUTH_DOSETPAG2 */ , user,
3576 NULL, cell, passwd, 0,
3577 &password_expires, 0, reason);
3578 usr_mutex_unlock(&osi_authenticate_lock);
3583 * uafs_getcellstatus
3584 * get the cell status
3587 uafs_getcellstatus(char *cell, afs_int32 * status)
3590 struct afs_ioctl iob;
3593 iob.in_size = strlen(cell) + 1;
3597 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
3605 *status = (intptr_t)iob.out;
3611 * Get quota of volume associated with path
3614 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
3617 struct afs_ioctl iob;
3618 VolumeStatus *status;
3624 iob.out_size = 1024;
3626 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
3634 status = (VolumeStatus *) buf;
3635 *BlocksInUse = status->BlocksInUse;
3636 *MaxQuota = status->MaxQuota;
3642 * Set quota of volume associated with path
3645 uafs_setvolquota(char *path, afs_int32 MaxQuota)
3648 struct afs_ioctl iob;
3649 VolumeStatus *status;
3657 memset(buf, 0, sizeof(VolumeStatus));
3658 status = (VolumeStatus *) buf;
3659 status->MaxQuota = MaxQuota;
3660 status->MinQuota = -1;
3662 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
3674 * uafs_statmountpoint
3675 * Determine whether a dir. is a mount point or not
3676 * return 1 if mount point, 0 if not
3679 uafs_statmountpoint(char *path)
3684 retval = uafs_statmountpoint_r(path);
3690 uafs_statmountpoint_r(char *path)
3697 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
3712 * Get a list of rights for the current user on path.
3715 uafs_getRights(char *path)
3722 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3730 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
3731 | PRSFS_LOCK | PRSFS_ADMINISTER;
3733 afs_rights = afs_getRights(VTOAFS(vp), afs_rights, get_user_struct()->u_cred);
3738 #endif /* AFS_WEB_ENHANCEMENTS */
3740 #endif /* UKERNEL */