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(register 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(register 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);
1115 * Mount the AFS filesystem
1118 rc = afs_mount(&afs_RootVfs, NULL, NULL);
1119 usr_assert(rc == 0);
1120 rc = afs_root(&afs_RootVfs, &afs_RootVnode);
1121 usr_assert(rc == 0);
1125 * initialize the current directory to the AFS root
1127 afs_CurrentDir = afs_RootVnode;
1128 VN_HOLD(afs_CurrentDir);
1134 uafs_statvfs(struct statvfs *buf)
1140 rc = afs_statvfs(&afs_RootVfs, buf);
1160 if (afs_CurrentDir) {
1161 VN_RELE(afs_CurrentDir);
1163 rc = afs_unmount(&afs_RootVfs);
1164 usr_assert(rc == 0);
1171 * Donate the current thread to the RX server pool.
1174 uafs_RxServerProc(void)
1178 struct rx_call *newcall = NULL;
1180 rxi_MorePackets(2); /* alloc more packets */
1181 threadID = rxi_availProcs++;
1184 sock = OSI_NULLSOCKET;
1185 rxi_ServerProc(threadID, newcall, &sock);
1186 if (sock == OSI_NULLSOCKET) {
1191 rxi_ListenerProc(sock, &threadID, &newcall);
1192 /* assert(threadID != -1); */
1193 /* assert(newcall != NULL); */
1197 struct syscallThreadArgs {
1206 #ifdef NETSCAPE_NSAPI
1208 syscallThread(void *argp)
1209 #else /* NETSCAPE_NSAPI */
1211 syscallThread(void *argp)
1212 #endif /* NETSCAPE_NSAPI */
1215 struct usr_ucred *crp;
1216 struct syscallThreadArgs *sysArgsP = (struct syscallThreadArgs *)argp;
1219 * AFS daemons run authenticated
1221 get_user_struct()->u_viceid = getuid();
1222 crp = get_user_struct()->u_cred;
1223 afs_set_cr_uid(crp, getuid());
1224 afs_set_cr_ruid(crp, getuid());
1225 crp->cr_suid = getuid();
1226 crp->cr_groups[0] = getgid();
1227 crp->cr_ngroups = 1;
1228 for (i = 1; i < NGROUPS; i++) {
1229 crp->cr_groups[i] = NOGROUP;
1232 call_syscall(sysArgsP->syscall, sysArgsP->afscall, sysArgsP->param1,
1233 sysArgsP->param2, sysArgsP->param3, sysArgsP->param4);
1235 afs_osi_Free(argp, -1);
1240 fork_syscall(long syscall, long afscall, long param1, long param2,
1241 long param3, long param4)
1244 struct syscallThreadArgs *sysArgsP;
1246 sysArgsP = (struct syscallThreadArgs *)
1247 afs_osi_Alloc(sizeof(struct syscallThreadArgs));
1248 usr_assert(sysArgsP != NULL);
1249 sysArgsP->syscall = syscall;
1250 sysArgsP->afscall = afscall;
1251 sysArgsP->param1 = param1;
1252 sysArgsP->param2 = param2;
1253 sysArgsP->param3 = param3;
1254 sysArgsP->param4 = param4;
1256 usr_thread_create(&tid, syscallThread, sysArgsP);
1257 usr_thread_detach(tid);
1262 call_syscall(long syscall, long afscall, long param1, long param2,
1263 long param3, long param4)
1275 a.syscall = syscall;
1276 a.afscall = afscall;
1282 get_user_struct()->u_error = 0;
1283 get_user_struct()->u_ap = (char *)&a;
1285 code = Afs_syscall();
1290 uafs_Setup(const char *mount)
1295 static int inited = 0;
1302 if (mount && strlen(mount) > 1023) {
1303 return ENAMETOOLONG;
1307 * Initialize the AFS mount point, default is '/afs'.
1308 * Strip duplicate/trailing slashes from mount point string.
1309 * afs_mountDirLen is set to strlen(afs_mountDir).
1314 sprintf(buf, "%s", mount);
1316 afs_mountDir[0] = '/';
1317 afs_mountDirLen = 1;
1318 for (lastchar = '/', p = &buf[0]; *p != '\0'; p++) {
1319 if (lastchar != '/' || *p != '/') {
1320 afs_mountDir[afs_mountDirLen++] = lastchar = *p;
1323 if (lastchar == '/' && afs_mountDirLen > 1)
1325 afs_mountDir[afs_mountDirLen] = '\0';
1326 if (afs_mountDirLen <= 1) {
1330 /* initialize global vars and such */
1333 /* initialize cache manager foo */
1340 uafs_ParseArgs(int argc, char **argv)
1342 return afsd_parse(argc, argv);
1354 return afsd_cacheMountDir;
1358 uafs_SetTokens(char *tbuffer, int tlen)
1361 struct afs_ioctl iob;
1366 iob.out = &outbuf[0];
1367 iob.out_size = sizeof(outbuf);
1369 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(3), (long)&iob, 0, 0);
1378 uafs_RPCStatsEnableProc(void)
1381 struct afs_ioctl iob;
1384 flag = AFSCALL_RXSTATS_ENABLE;
1385 iob.in = (char *)&flag;
1386 iob.in_size = sizeof(afs_int32);
1389 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1398 uafs_RPCStatsDisableProc(void)
1401 struct afs_ioctl iob;
1404 flag = AFSCALL_RXSTATS_DISABLE;
1405 iob.in = (char *)&flag;
1406 iob.in_size = sizeof(afs_int32);
1409 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1418 uafs_RPCStatsClearProc(void)
1421 struct afs_ioctl iob;
1424 flag = AFSCALL_RXSTATS_CLEAR;
1425 iob.in = (char *)&flag;
1426 iob.in_size = sizeof(afs_int32);
1429 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(53), (long)&iob, 0, 0);
1438 uafs_RPCStatsEnablePeer(void)
1441 struct afs_ioctl iob;
1444 flag = AFSCALL_RXSTATS_ENABLE;
1445 iob.in = (char *)&flag;
1446 iob.in_size = sizeof(afs_int32);
1449 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1458 uafs_RPCStatsDisablePeer(void)
1461 struct afs_ioctl iob;
1464 flag = AFSCALL_RXSTATS_DISABLE;
1465 iob.in = (char *)&flag;
1466 iob.in_size = sizeof(afs_int32);
1469 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1478 uafs_RPCStatsClearPeer(void)
1481 struct afs_ioctl iob;
1484 flag = AFSCALL_RXSTATS_CLEAR;
1485 iob.in = (char *)&flag;
1486 iob.in_size = sizeof(afs_int32);
1489 rc = call_syscall(AFSCALL_PIOCTL, 0, _VICEIOCTL(54), (long)&iob, 0, 0);
1498 * Lookup a file or directory given its path.
1499 * Call VN_HOLD on the output vnode if successful.
1500 * Returns zero on success, error code on failure.
1502 * Note: Caller must hold the AFS global lock.
1505 uafs_LookupName(char *path, struct usr_vnode *parentVp,
1506 struct usr_vnode **vpp, int follow, int no_eval_mtpt)
1510 struct usr_vnode *vp;
1511 struct usr_vnode *nextVp;
1512 struct usr_vnode *linkVp;
1513 struct vcache *nextVc;
1516 char *nextPathP = NULL;
1521 * Absolute paths must start with the AFS mount point.
1523 if (path[0] != '/') {
1526 path = uafs_afsPathName(path);
1534 * Loop through the path looking for the new directory
1536 tmpPath = afs_osi_Alloc(strlen(path) + 1);
1537 usr_assert(tmpPath != NULL);
1538 strcpy(tmpPath, path);
1541 while (pathP != NULL && *pathP != '\0') {
1542 usr_assert(*pathP != '/');
1545 * terminate the current component and skip over slashes
1547 nextPathP = afs_strchr(pathP, '/');
1548 if (nextPathP != NULL) {
1549 while (*nextPathP == '/') {
1550 *(nextPathP++) = '\0';
1555 * Don't call afs_lookup on non-directories
1557 if (vp->v_type != VDIR) {
1559 afs_osi_Free(tmpPath, strlen(path) + 1);
1563 if (vp == afs_RootVnode && strcmp(pathP, "..") == 0) {
1565 * The AFS root is its own parent
1567 nextVp = afs_RootVnode;
1570 * We need execute permission to search a directory
1572 code = afs_access(VTOAFS(vp), VEXEC, get_user_struct()->u_cred);
1575 afs_osi_Free(tmpPath, strlen(path) + 1);
1580 * lookup the next component in the path, we can release the
1581 * subdirectory since we hold the global lock
1585 #ifdef AFS_WEB_ENHANCEMENTS
1586 if ((nextPathP != NULL && *nextPathP != '\0') || !no_eval_mtpt)
1587 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
1590 afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred,
1593 code = afs_lookup(VTOAFS(vp), pathP, &nextVc, get_user_struct()->u_cred, 0);
1594 #endif /* AFS_WEB_ENHANCEMENTS */
1596 nextVp=AFSTOV(nextVc);
1599 afs_osi_Free(tmpPath, strlen(path) + 1);
1605 * Follow symbolic links for parent directories and
1606 * for leaves when the follow flag is set.
1608 if ((nextPathP != NULL && *nextPathP != '\0') || follow) {
1610 while (nextVp->v_type == VLNK) {
1611 if (++linkCount > MAX_OSI_LINKS) {
1614 afs_osi_Free(tmpPath, strlen(path) + 1);
1617 code = uafs_LookupLink(nextVp, vp, &linkVp);
1621 afs_osi_Free(tmpPath, strlen(path) + 1);
1635 * Special case, nextPathP is non-null if pathname ends in slash
1637 if (nextPathP != NULL && vp->v_type != VDIR) {
1639 afs_osi_Free(tmpPath, strlen(path) + 1);
1643 afs_osi_Free(tmpPath, strlen(path) + 1);
1649 * Lookup the target of a symbolic link
1650 * Call VN_HOLD on the output vnode if successful.
1651 * Returns zero on success, error code on failure.
1653 * Note: Caller must hold the AFS global lock.
1656 uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
1657 struct usr_vnode **vpp)
1662 struct usr_vnode *linkVp;
1664 struct iovec iov[1];
1668 pathP = afs_osi_Alloc(MAX_OSI_PATH + 1);
1669 usr_assert(pathP != NULL);
1672 * set up the uio buffer
1674 iov[0].iov_base = pathP;
1675 iov[0].iov_len = MAX_OSI_PATH + 1;
1676 uio.uio_iov = &iov[0];
1680 uio.uio_fmode = FREAD;
1681 uio.uio_resid = MAX_OSI_PATH + 1;
1684 * Read the link data
1686 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
1688 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1691 len = MAX_OSI_PATH + 1 - uio.uio_resid;
1695 * Find the target of the symbolic link
1697 code = uafs_LookupName(pathP, parentVp, &linkVp, 1, 0);
1699 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1703 afs_osi_Free(pathP, MAX_OSI_PATH + 1);
1709 * Lookup the parent of a file or directory given its path
1710 * Call VN_HOLD on the output vnode if successful.
1711 * Returns zero on success, error code on failure.
1713 * Note: Caller must hold the AFS global lock.
1716 uafs_LookupParent(char *path, struct usr_vnode **vpp)
1721 struct usr_vnode *parentP;
1726 * Absolute path names must start with the AFS mount point.
1729 pathP = uafs_afsPathName(path);
1730 if (pathP == NULL) {
1736 * Find the length of the parent path
1739 while (len > 0 && path[len - 1] == '/') {
1745 while (len > 0 && path[len - 1] != '/') {
1752 pathP = afs_osi_Alloc(len);
1753 usr_assert(pathP != NULL);
1754 memcpy(pathP, path, len - 1);
1755 pathP[len - 1] = '\0';
1758 * look up the parent
1760 code = uafs_LookupName(pathP, afs_CurrentDir, &parentP, 1, 0);
1761 afs_osi_Free(pathP, len);
1765 if (parentP->v_type != VDIR) {
1775 * Return a pointer to the first character in the last component
1779 uafs_LastPath(char *path)
1784 while (len > 0 && path[len - 1] == '/') {
1787 while (len > 0 && path[len - 1] != '/') {
1797 * Set the working directory.
1800 uafs_chdir(char *path)
1804 retval = uafs_chdir_r(path);
1810 uafs_chdir_r(char *path)
1815 code = uafs_LookupName(path, afs_CurrentDir, &dirP, 1, 0);
1820 if (dirP->v_type != VDIR) {
1825 VN_RELE(afs_CurrentDir);
1826 afs_CurrentDir = dirP;
1831 * Create a directory.
1834 uafs_mkdir(char *path, int mode)
1838 retval = uafs_mkdir_r(path, mode);
1844 uafs_mkdir_r(char *path, int mode)
1848 struct vnode *parentP;
1849 struct vcache *dirP;
1850 struct usr_vattr attrs;
1852 if (uafs_IsRoot(path)) {
1857 * Look up the parent directory.
1859 nameP = uafs_LastPath(path);
1860 if (nameP != NULL) {
1861 code = uafs_LookupParent(path, &parentP);
1867 parentP = afs_CurrentDir;
1873 * Make sure the directory has at least one character
1875 if (*nameP == '\0') {
1882 * Create the directory
1884 usr_vattr_null(&attrs);
1885 attrs.va_type = VREG;
1886 attrs.va_mode = mode;
1887 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
1888 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
1890 code = afs_mkdir(VTOAFS(parentP), nameP, &attrs, &dirP, get_user_struct()->u_cred);
1896 VN_RELE(AFSTOV(dirP));
1901 * Return 1 if path is the AFS root, otherwise return 0
1904 uafs_IsRoot(char *path)
1906 while (*path == '/' && *(path + 1) == '/') {
1909 if (strncmp(path, afs_mountDir, afs_mountDirLen) != 0) {
1912 path += afs_mountDirLen;
1913 while (*path == '/') {
1916 if (*path != '\0') {
1924 * Note: file name may not end in a slash.
1927 uafs_open(char *path, int flags, int mode)
1931 retval = uafs_open_r(path, flags, mode);
1937 uafs_open_r(char *path, int flags, int mode)
1943 struct usr_vnode *fileP;
1944 struct usr_vnode *dirP;
1945 struct usr_vattr attrs;
1950 if (uafs_IsRoot(path)) {
1951 fileP = afs_RootVnode;
1955 * Look up the parent directory.
1957 nameP = uafs_LastPath(path);
1958 if (nameP != NULL) {
1959 code = uafs_LookupParent(path, &dirP);
1965 dirP = afs_CurrentDir;
1971 * Make sure the filename has at least one character
1973 if (*nameP == '\0') {
1980 * Get the VNODE for this file
1982 if (flags & O_CREAT) {
1983 usr_vattr_null(&attrs);
1984 attrs.va_type = VREG;
1985 attrs.va_mode = mode;
1986 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
1987 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
1988 if (flags & O_TRUNC) {
1994 afs_create(VTOAFS(dirP), nameP, &attrs,
1995 (flags & O_EXCL) ? usr_EXCL : usr_NONEXCL, mode,
1996 &vc, get_user_struct()->u_cred);
2005 code = uafs_LookupName(nameP, dirP, &fileP, 1, 0);
2013 * Check whether we have access to this file
2016 if (flags & (O_RDONLY | O_RDWR)) {
2019 if (flags & (O_WRONLY | O_RDWR)) {
2023 fileMode = VREAD; /* since O_RDONLY is 0 */
2024 code = afs_access(VTOAFS(fileP), fileMode, get_user_struct()->u_cred);
2032 * Get the file attributes, all we need is the size
2034 code = afs_getattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2044 * Setup the open flags
2047 if (flags & O_TRUNC) {
2048 openFlags |= FTRUNC;
2050 if (flags & O_APPEND) {
2051 openFlags |= FAPPEND;
2053 if (flags & O_SYNC) {
2056 if (flags & O_SYNC) {
2059 if (flags & (O_RDONLY | O_RDWR)) {
2062 if (flags & (O_WRONLY | O_RDWR)) {
2063 openFlags |= FWRITE;
2065 if ((openFlags & (FREAD | FWRITE)) == 0) {
2066 /* O_RDONLY is 0, so ... */
2071 * Truncate if necessary
2073 if ((flags & O_TRUNC) && (attrs.va_size != 0)) {
2074 usr_vattr_null(&attrs);
2075 attrs.va_mask = ATTR_SIZE;
2077 code = afs_setattr(VTOAFS(fileP), &attrs, get_user_struct()->u_cred);
2089 code = afs_open(&vc, openFlags, get_user_struct()->u_cred);
2097 * Put the vnode pointer into the file table
2099 for (fd = 0; fd < MAX_OSI_FILES; fd++) {
2100 if (afs_FileTable[fd] == NULL) {
2101 afs_FileTable[fd] = fileP;
2102 afs_FileFlags[fd] = openFlags;
2103 if (flags & O_APPEND) {
2104 afs_FileOffsets[fd] = attrs.va_size;
2106 afs_FileOffsets[fd] = 0;
2111 if (fd == MAX_OSI_FILES) {
2124 uafs_creat(char *path, int mode)
2127 rc = uafs_open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2132 uafs_creat_r(char *path, int mode)
2135 rc = uafs_open_r(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
2143 uafs_write(int fd, char *buf, int len)
2147 retval = uafs_pwrite_r(fd, buf, len, afs_FileOffsets[fd]);
2153 uafs_pwrite(int fd, char *buf, int len, off_t offset)
2157 retval = uafs_pwrite_r(fd, buf, len, offset);
2163 uafs_pwrite_r(int fd, char *buf, int len, off_t offset)
2167 struct iovec iov[1];
2168 struct usr_vnode *fileP;
2171 * Make sure this is an open file
2173 fileP = afs_FileTable[fd];
2174 if (fileP == NULL) {
2180 * set up the uio buffer
2182 iov[0].iov_base = buf;
2183 iov[0].iov_len = len;
2184 uio.uio_iov = &iov[0];
2186 uio.uio_offset = offset;
2188 uio.uio_fmode = FWRITE;
2189 uio.uio_resid = len;
2195 code = afs_write(VTOAFS(fileP), &uio, afs_FileFlags[fd], get_user_struct()->u_cred, 0);
2201 afs_FileOffsets[fd] = uio.uio_offset;
2202 return (len - uio.uio_resid);
2209 uafs_read(int fd, char *buf, int len)
2213 retval = uafs_pread_r(fd, buf, len, afs_FileOffsets[fd]);
2219 uafs_pread(int fd, char *buf, int len, off_t offset)
2223 retval = uafs_pread_r(fd, buf, len, offset);
2229 uafs_pread_r(int fd, char *buf, int len, off_t offset)
2233 struct iovec iov[1];
2234 struct usr_vnode *fileP;
2235 struct usr_buf *bufP;
2238 * Make sure this is an open file
2240 fileP = afs_FileTable[fd];
2241 if (fileP == NULL) {
2247 * set up the uio buffer
2249 iov[0].iov_base = buf;
2250 iov[0].iov_len = len;
2251 uio.uio_iov = &iov[0];
2253 uio.uio_offset = offset;
2255 uio.uio_fmode = FREAD;
2256 uio.uio_resid = len;
2261 code = afs_read(VTOAFS(fileP), &uio, get_user_struct()->u_cred, 0, &bufP, 0);
2267 afs_FileOffsets[fd] = uio.uio_offset;
2268 return (len - uio.uio_resid);
2272 * Copy the attributes of a file into a stat structure.
2274 * NOTE: Caller must hold the global AFS lock.
2277 uafs_GetAttr(struct usr_vnode *vp, struct stat *stats)
2280 struct usr_vattr attrs;
2285 * Get the attributes
2287 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2293 * Copy the attributes, zero fields that aren't set
2295 memset((void *)stats, 0, sizeof(struct stat));
2297 stats->st_ino = attrs.va_nodeid;
2298 stats->st_mode = attrs.va_mode;
2299 stats->st_nlink = attrs.va_nlink;
2300 stats->st_uid = attrs.va_uid;
2301 stats->st_gid = attrs.va_gid;
2302 stats->st_rdev = attrs.va_rdev;
2303 stats->st_size = attrs.va_size;
2304 stats->st_atime = attrs.va_atime.tv_sec;
2305 stats->st_mtime = attrs.va_mtime.tv_sec;
2306 stats->st_ctime = attrs.va_ctime.tv_sec;
2307 stats->st_blksize = attrs.va_blocksize;
2308 stats->st_blocks = attrs.va_blocks;
2314 * Get the attributes of a file, do follow links
2317 uafs_stat(char *path, struct stat *buf)
2321 retval = uafs_stat_r(path, buf);
2327 uafs_stat_r(char *path, struct stat *buf)
2332 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2337 code = uafs_GetAttr(vp, buf);
2347 * Get the attributes of a file, don't follow links
2350 uafs_lstat(char *path, struct stat *buf)
2354 retval = uafs_lstat_r(path, buf);
2360 uafs_lstat_r(char *path, struct stat *buf)
2365 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2370 code = uafs_GetAttr(vp, buf);
2380 * Get the attributes of an open file
2383 uafs_fstat(int fd, struct stat *buf)
2387 retval = uafs_fstat_r(fd, buf);
2393 uafs_fstat_r(int fd, struct stat *buf)
2398 vp = afs_FileTable[fd];
2403 code = uafs_GetAttr(vp, buf);
2412 * change the permissions on a file
2415 uafs_chmod(char *path, int mode)
2419 retval = uafs_chmod_r(path, mode);
2425 uafs_chmod_r(char *path, int mode)
2429 struct usr_vattr attrs;
2431 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2436 usr_vattr_null(&attrs);
2437 attrs.va_mask = ATTR_MODE;
2438 attrs.va_mode = mode;
2439 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2449 * change the permissions on an open file
2452 uafs_fchmod(int fd, int mode)
2456 retval = uafs_fchmod_r(fd, mode);
2462 uafs_fchmod_r(int fd, int mode)
2466 struct usr_vattr attrs;
2468 vp = afs_FileTable[fd];
2473 usr_vattr_null(&attrs);
2474 attrs.va_mask = ATTR_MODE;
2475 attrs.va_mode = mode;
2476 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2488 uafs_truncate(char *path, int length)
2492 retval = uafs_truncate_r(path, length);
2498 uafs_truncate_r(char *path, int length)
2502 struct usr_vattr attrs;
2504 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
2509 usr_vattr_null(&attrs);
2510 attrs.va_mask = ATTR_SIZE;
2511 attrs.va_size = length;
2512 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2522 * truncate an open file
2525 uafs_ftruncate(int fd, int length)
2529 retval = uafs_ftruncate_r(fd, length);
2535 uafs_ftruncate_r(int fd, int length)
2539 struct usr_vattr attrs;
2541 vp = afs_FileTable[fd];
2546 usr_vattr_null(&attrs);
2547 attrs.va_mask = ATTR_SIZE;
2548 attrs.va_size = length;
2549 code = afs_setattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2558 * set the read/write file pointer of an open file
2561 uafs_lseek(int fd, int offset, int whence)
2565 retval = uafs_lseek_r(fd, offset, whence);
2571 uafs_lseek_r(int fd, int offset, int whence)
2575 struct usr_vattr attrs;
2576 struct usr_vnode *vp;
2578 vp = afs_FileTable[fd];
2585 newpos = afs_FileOffsets[fd] + offset;
2591 code = afs_getattr(VTOAFS(vp), &attrs, get_user_struct()->u_cred);
2596 newpos = attrs.va_size + offset;
2606 afs_FileOffsets[fd] = newpos;
2618 retval = uafs_fsync_r(fd);
2624 uafs_fsync_r(int fd)
2627 struct usr_vnode *fileP;
2630 fileP = afs_FileTable[fd];
2631 if (fileP == NULL) {
2636 code = afs_fsync(VTOAFS(fileP), get_user_struct()->u_cred);
2653 retval = uafs_close_r(fd);
2659 uafs_close_r(int fd)
2662 struct usr_vnode *fileP;
2664 fileP = afs_FileTable[fd];
2665 if (fileP == NULL) {
2669 afs_FileTable[fd] = NULL;
2671 code = afs_close(VTOAFS(fileP), afs_FileFlags[fd], get_user_struct()->u_cred);
2682 * Create a hard link from the source to the target
2683 * Note: file names may not end in a slash.
2686 uafs_link(char *existing, char *new)
2690 retval = uafs_link_r(existing, new);
2696 uafs_link_r(char *existing, char *new)
2699 struct usr_vnode *existP;
2700 struct usr_vnode *dirP;
2703 if (uafs_IsRoot(new)) {
2708 * Look up the existing node.
2710 code = uafs_LookupName(existing, afs_CurrentDir, &existP, 1, 0);
2717 * Look up the parent directory.
2719 nameP = uafs_LastPath(new);
2720 if (nameP != NULL) {
2721 code = uafs_LookupParent(new, &dirP);
2728 dirP = afs_CurrentDir;
2734 * Make sure the filename has at least one character
2736 if (*nameP == '\0') {
2746 code = afs_link(VTOAFS(existP), VTOAFS(dirP), nameP, get_user_struct()->u_cred);
2757 * Create a symbolic link from the source to the target
2758 * Note: file names may not end in a slash.
2761 uafs_symlink(char *target, char *source)
2765 retval = uafs_symlink_r(target, source);
2771 uafs_symlink_r(char *target, char *source)
2774 struct usr_vnode *dirP;
2775 struct usr_vattr attrs;
2778 if (uafs_IsRoot(source)) {
2783 * Look up the parent directory.
2785 nameP = uafs_LastPath(source);
2786 if (nameP != NULL) {
2787 code = uafs_LookupParent(source, &dirP);
2793 dirP = afs_CurrentDir;
2799 * Make sure the filename has at least one character
2801 if (*nameP == '\0') {
2810 usr_vattr_null(&attrs);
2811 attrs.va_type = VLNK;
2812 attrs.va_mode = 0777;
2813 attrs.va_uid = afs_cr_uid(get_user_struct()->u_cred);
2814 attrs.va_gid = afs_cr_gid(get_user_struct()->u_cred);
2815 code = afs_symlink(VTOAFS(dirP), nameP, &attrs, target, get_user_struct()->u_cred);
2825 * Read a symbolic link into the buffer
2828 uafs_readlink(char *path, char *buf, int len)
2832 retval = uafs_readlink_r(path, buf, len);
2838 uafs_readlink_r(char *path, char *buf, int len)
2841 struct usr_vnode *vp;
2843 struct iovec iov[1];
2845 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 0);
2851 if (vp->v_type != VLNK) {
2858 * set up the uio buffer
2860 iov[0].iov_base = buf;
2861 iov[0].iov_len = len;
2862 uio.uio_iov = &iov[0];
2866 uio.uio_fmode = FREAD;
2867 uio.uio_resid = len;
2872 code = afs_readlink(VTOAFS(vp), &uio, get_user_struct()->u_cred);
2880 * return the number of bytes read
2882 return (len - uio.uio_resid);
2886 * Remove a file (or directory)
2887 * Note: file name may not end in a slash.
2890 uafs_unlink(char *path)
2894 retval = uafs_unlink_r(path);
2900 uafs_unlink_r(char *path)
2903 struct usr_vnode *dirP;
2906 if (uafs_IsRoot(path)) {
2911 * Look up the parent directory.
2913 nameP = uafs_LastPath(path);
2914 if (nameP != NULL) {
2915 code = uafs_LookupParent(path, &dirP);
2921 dirP = afs_CurrentDir;
2927 * Make sure the filename has at least one character
2929 if (*nameP == '\0') {
2938 code = afs_remove(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
2949 * Rename a file (or directory)
2952 uafs_rename(char *old, char *new)
2956 retval = uafs_rename_r(old, new);
2962 uafs_rename_r(char *old, char *new)
2967 struct usr_vnode *odirP;
2968 struct usr_vnode *ndirP;
2970 if (uafs_IsRoot(new)) {
2975 * Look up the parent directories.
2977 onameP = uafs_LastPath(old);
2978 if (onameP != NULL) {
2979 code = uafs_LookupParent(old, &odirP);
2985 odirP = afs_CurrentDir;
2989 nnameP = uafs_LastPath(new);
2990 if (nnameP != NULL) {
2991 code = uafs_LookupParent(new, &ndirP);
2997 ndirP = afs_CurrentDir;
3003 * Make sure the filename has at least one character
3005 if (*onameP == '\0' || *nnameP == '\0') {
3015 code = afs_rename(VTOAFS(odirP), onameP, VTOAFS(ndirP), nnameP, get_user_struct()->u_cred);
3027 * Remove a or directory
3028 * Note: file name may not end in a slash.
3031 uafs_rmdir(char *path)
3035 retval = uafs_rmdir_r(path);
3041 uafs_rmdir_r(char *path)
3044 struct usr_vnode *dirP;
3047 if (uafs_IsRoot(path)) {
3052 * Look up the parent directory.
3054 nameP = uafs_LastPath(path);
3055 if (nameP != NULL) {
3056 code = uafs_LookupParent(path, &dirP);
3062 dirP = afs_CurrentDir;
3068 * Make sure the directory name has at least one character
3070 if (*nameP == '\0') {
3077 * Remove the directory
3079 code = afs_rmdir(VTOAFS(dirP), nameP, get_user_struct()->u_cred);
3090 * Flush a file from the AFS cache
3093 uafs_FlushFile(char *path)
3096 struct afs_ioctl iob;
3104 call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(6), (long)&iob, 0,
3115 uafs_FlushFile_r(char *path)
3119 retval = uafs_FlushFile(path);
3128 uafs_opendir(char *path)
3132 retval = uafs_opendir_r(path);
3138 uafs_opendir_r(char *path)
3141 struct usr_vnode *fileP;
3145 * Open the directory for reading
3147 fd = uafs_open_r(path, O_RDONLY, 0);
3152 fileP = afs_FileTable[fd];
3153 if (fileP == NULL) {
3157 if (fileP->v_type != VDIR) {
3164 * Set up the directory structures
3167 (usr_DIR *) afs_osi_Alloc(sizeof(usr_DIR) + USR_DIRSIZE +
3168 sizeof(struct usr_dirent));
3169 usr_assert(dirp != NULL);
3170 dirp->dd_buf = (char *)(dirp + 1);
3180 * Read directory entries into a file system independent format.
3181 * This routine was developed to support AFS cache consistency testing.
3182 * You should use uafs_readdir instead.
3185 uafs_getdents(int fd, struct min_direct *buf, int len)
3189 retval = uafs_getdents_r(fd, buf, len);
3195 uafs_getdents_r(int fd, struct min_direct *buf, int len)
3199 struct usr_vnode *vp;
3200 struct iovec iov[1];
3203 * Make sure this is an open file
3205 vp = afs_FileTable[fd];
3213 * set up the uio buffer
3215 iov[0].iov_base = (char *)buf;
3216 iov[0].iov_len = len;
3217 uio.uio_iov = &iov[0];
3219 uio.uio_offset = afs_FileOffsets[fd];
3221 uio.uio_fmode = FREAD;
3222 uio.uio_resid = len;
3225 * read the next chunk from the directory
3227 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3233 afs_FileOffsets[fd] = uio.uio_offset;
3234 return (len - uio.uio_resid);
3238 * read from a directory (names only)
3241 uafs_readdir(usr_DIR * dirp)
3243 struct usr_dirent *retval;
3245 retval = uafs_readdir_r(dirp);
3251 uafs_readdir_r(usr_DIR * dirp)
3256 struct usr_vnode *vp;
3257 struct iovec iov[1];
3258 struct usr_dirent *direntP;
3259 struct min_direct *directP;
3267 * Make sure this is an open file
3269 vp = afs_FileTable[dirp->dd_fd];
3276 * If there are no entries in the stream buffer
3277 * then read another chunk
3279 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3280 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3282 * set up the uio buffer
3284 iov[0].iov_base = dirp->dd_buf;
3285 iov[0].iov_len = USR_DIRSIZE;
3286 uio.uio_iov = &iov[0];
3288 uio.uio_offset = afs_FileOffsets[dirp->dd_fd];
3290 uio.uio_fmode = FREAD;
3291 uio.uio_resid = USR_DIRSIZE;
3294 * read the next chunk from the directory
3296 code = afs_readdir(VTOAFS(vp), &uio, get_user_struct()->u_cred);
3301 afs_FileOffsets[dirp->dd_fd] = uio.uio_offset;
3303 dirp->dd_size = USR_DIRSIZE - iov[0].iov_len;
3305 directP = (struct min_direct *)(dirp->dd_buf + dirp->dd_loc);
3309 * Check for end of file
3311 if (dirp->dd_size == 0 || directP->d_fileno == 0) {
3315 len = ((sizeof(struct min_direct) + directP->d_namlen + 4) & (~3));
3316 usr_assert(len <= dirp->dd_size);
3319 * Copy the next entry into the usr_dirent structure and advance
3321 direntP = (struct usr_dirent *)(dirp->dd_buf + USR_DIRSIZE);
3322 direntP->d_ino = directP->d_fileno;
3323 direntP->d_off = direntP->d_reclen;
3325 sizeof(struct usr_dirent) - MAXNAMLEN + directP->d_namlen + 1;
3326 memcpy(&direntP->d_name[0], (void *)(directP + 1), directP->d_namlen);
3327 direntP->d_name[directP->d_namlen] = '\0';
3328 dirp->dd_loc += len;
3329 dirp->dd_size -= len;
3338 uafs_closedir(usr_DIR * dirp)
3342 retval = uafs_closedir_r(dirp);
3348 uafs_closedir_r(usr_DIR * dirp)
3359 afs_osi_Free((char *)dirp,
3360 sizeof(usr_DIR) + USR_DIRSIZE + sizeof(struct usr_dirent));
3361 rc = uafs_close_r(fd);
3366 * Do AFS authentication
3369 uafs_klog(char *user, char *cell, char *passwd, char **reason)
3372 afs_int32 password_expires = -1;
3374 usr_mutex_lock(&osi_authenticate_lock);
3376 ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION +
3377 KA_USERAUTH_DOSETPAG2, user, NULL, cell,
3378 passwd, 0, &password_expires, 0, reason);
3379 usr_mutex_unlock(&osi_authenticate_lock);
3384 uafs_klog_r(char *user, char *cell, char *passwd, char **reason)
3388 retval = uafs_klog(user, cell, passwd, reason);
3394 * Destroy AFS credentials from the kernel cache
3401 usr_mutex_lock(&osi_authenticate_lock);
3402 code = ktc_ForgetAllTokens();
3403 usr_mutex_unlock(&osi_authenticate_lock);
3412 retval = uafs_unlog();
3418 * Strip the AFS mount point from a pathname string. Return
3419 * NULL if the path is a relative pathname or if the path
3420 * doesn't start with the AFS mount point string.
3423 uafs_afsPathName(char *path)
3432 for (i = 1, p = path + 1; *p != '\0'; p++) {
3433 /* Ignore duplicate slashes */
3434 if (*p == '/' && lastchar == '/')
3436 /* Is this a subdirectory of the AFS mount point? */
3437 if (afs_mountDir[i] == '\0' && *p == '/') {
3438 /* strip leading slashes */
3439 while (*(++p) == '/');
3442 /* Reject paths that are not within AFS */
3443 if (*p != afs_mountDir[i])
3448 /* Is this the AFS mount point? */
3449 if (afs_mountDir[i] == '\0') {
3450 usr_assert(*p == '\0');
3456 #ifdef AFS_WEB_ENHANCEMENTS
3459 * klog but don't allocate a new pag
3462 uafs_klog_nopag(char *user, char *cell, char *passwd, char **reason)
3465 afs_int32 password_expires = -1;
3467 usr_mutex_lock(&osi_authenticate_lock);
3468 code = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION
3469 /*+KA_USERAUTH_DOSETPAG2 */ , user,
3470 NULL, cell, passwd, 0,
3471 &password_expires, 0, reason);
3472 usr_mutex_unlock(&osi_authenticate_lock);
3477 * uafs_getcellstatus
3478 * get the cell status
3481 uafs_getcellstatus(char *cell, afs_int32 * status)
3484 struct afs_ioctl iob;
3487 iob.in_size = strlen(cell) + 1;
3491 rc = call_syscall(AFSCALL_PIOCTL, /*path */ 0, _VICEIOCTL(35),
3499 *status = (intptr_t)iob.out;
3505 * Get quota of volume associated with path
3508 uafs_getvolquota(char *path, afs_int32 * BlocksInUse, afs_int32 * MaxQuota)
3511 struct afs_ioctl iob;
3512 VolumeStatus *status;
3518 iob.out_size = 1024;
3520 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(4), (long)&iob,
3528 status = (VolumeStatus *) buf;
3529 *BlocksInUse = status->BlocksInUse;
3530 *MaxQuota = status->MaxQuota;
3536 * Set quota of volume associated with path
3539 uafs_setvolquota(char *path, afs_int32 MaxQuota)
3542 struct afs_ioctl iob;
3543 VolumeStatus *status;
3551 memset(buf, 0, sizeof(VolumeStatus));
3552 status = (VolumeStatus *) buf;
3553 status->MaxQuota = MaxQuota;
3554 status->MinQuota = -1;
3556 rc = call_syscall(AFSCALL_PIOCTL, (long)path, _VICEIOCTL(5), (long)&iob,
3568 * uafs_statmountpoint
3569 * Determine whether a dir. is a mount point or not
3570 * return 1 if mount point, 0 if not
3573 uafs_statmountpoint(char *path)
3578 retval = uafs_statmountpoint_r(path);
3584 uafs_statmountpoint_r(char *path)
3591 code = uafs_LookupName(path, afs_CurrentDir, &vp, 0, 1);
3606 * Get a list of rights for the current user on path.
3609 uafs_getRights(char *path)
3616 code = uafs_LookupName(path, afs_CurrentDir, &vp, 1, 0);
3624 PRSFS_READ | PRSFS_WRITE | PRSFS_INSERT | PRSFS_LOOKUP | PRSFS_DELETE
3625 | PRSFS_LOCK | PRSFS_ADMINISTER;
3627 afs_rights = afs_getRights(VTOAFS(vp), afs_rights, get_user_struct()->u_cred);
3632 #endif /* AFS_WEB_ENHANCEMENTS */
3634 #endif /* UKERNEL */