2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include "../afs/param.h"
15 #include "../afs/sysincludes.h" /* Standard vendor system headers */
16 #include "../afs/afsincludes.h" /* Afs-based standard headers */
17 #include "../afs/afs_stats.h" /* afs statistics */
18 #include "../afs/vice.h"
19 #include "../rx/rx_globals.h"
21 struct VenusFid afs_rootFid;
22 afs_int32 afs_waitForever=0;
23 short afs_waitForeverCount = 0;
24 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE; /* show all messages */
26 #define DECL_PIOCTL(x) static int x(struct vcache *avc, int afun, struct vrequest *areq, \
27 char *ain, char *aout, afs_int32 ainSize, afs_int32 *aoutSize, \
28 struct AFS_UCRED **acred)
30 /* Prototypes for pioctl routines */
33 DECL_PIOCTL(PStoreBehind);
38 DECL_PIOCTL(PGetFileCell);
39 DECL_PIOCTL(PGetWSCell);
40 DECL_PIOCTL(PGetUserCell);
41 DECL_PIOCTL(PSetTokens);
42 DECL_PIOCTL(PGetVolumeStatus);
43 DECL_PIOCTL(PSetVolumeStatus);
45 DECL_PIOCTL(PNewStatMount);
46 DECL_PIOCTL(PGetTokens);
48 DECL_PIOCTL(PMariner);
49 DECL_PIOCTL(PCheckServers);
50 DECL_PIOCTL(PCheckVolNames);
51 DECL_PIOCTL(PCheckAuth);
52 DECL_PIOCTL(PFindVolume);
53 DECL_PIOCTL(PViceAccess);
54 DECL_PIOCTL(PSetCacheSize);
55 DECL_PIOCTL(PGetCacheSize);
56 DECL_PIOCTL(PRemoveCallBack);
57 DECL_PIOCTL(PNewCell);
58 DECL_PIOCTL(PNewAlias);
59 DECL_PIOCTL(PListCells);
60 DECL_PIOCTL(PListAliases);
61 DECL_PIOCTL(PRemoveMount);
62 DECL_PIOCTL(PVenusLogging);
63 DECL_PIOCTL(PGetCellStatus);
64 DECL_PIOCTL(PSetCellStatus);
65 DECL_PIOCTL(PFlushVolumeData);
66 DECL_PIOCTL(PGetVnodeXStatus);
67 DECL_PIOCTL(PSetSysName);
68 DECL_PIOCTL(PSetSPrefs);
69 DECL_PIOCTL(PSetSPrefs33);
70 DECL_PIOCTL(PGetSPrefs);
71 DECL_PIOCTL(PExportAfs);
73 DECL_PIOCTL(PTwiddleRx);
74 DECL_PIOCTL(PGetInitParams);
75 DECL_PIOCTL(PGetRxkcrypt);
76 DECL_PIOCTL(PSetRxkcrypt);
77 DECL_PIOCTL(PGetCPrefs);
78 DECL_PIOCTL(PSetCPrefs);
79 DECL_PIOCTL(PFlushMount);
80 DECL_PIOCTL(PRxStatProc);
81 DECL_PIOCTL(PRxStatPeer);
82 DECL_PIOCTL(PPrefetchFromTape);
83 DECL_PIOCTL(PResidencyCmd);
85 /* Prototypes for private routines */
86 static int HandleClientContext(struct afs_ioctl *ablob, int *com,
87 struct AFS_UCRED **acred, struct AFS_UCRED *credp);
88 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata);
89 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
90 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred);
91 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred);
94 static int (*(VpioctlSw[]))() = {
99 PGetVolumeStatus, /* 4 */
100 PSetVolumeStatus, /* 5 */
105 PCheckServers, /* 10 */
106 PCheckVolNames, /* 11 */
108 PBogus, /* 13 -- used to be quick check time */
110 PBogus, /* 15 -- prefetch is now special-cased; see pioctl code! */
111 PBogus, /* 16 -- used to be testing code */
112 PNoop, /* 17 -- used to be enable group */
113 PNoop, /* 18 -- used to be disable group */
114 PBogus, /* 19 -- used to be list group */
115 PViceAccess, /* 20 */
116 PUnlog, /* 21 -- unlog *is* unpag in this system */
117 PGetFID, /* 22 -- get file ID */
118 PBogus, /* 23 -- used to be waitforever */
119 PSetCacheSize, /* 24 */
120 PRemoveCallBack, /* 25 -- flush only the callback */
123 PRemoveMount, /* 28 -- delete mount point */
124 PNewStatMount, /* 29 -- new style mount point stat */
125 PGetFileCell, /* 30 -- get cell name for input file */
126 PGetWSCell, /* 31 -- get cell name for workstation */
127 PMariner, /* 32 - set/get mariner host */
128 PGetUserCell, /* 33 -- get cell name for user */
129 PVenusLogging, /* 34 -- Enable/Disable logging */
130 PGetCellStatus, /* 35 */
131 PSetCellStatus, /* 36 */
132 PFlushVolumeData, /* 37 -- flush all data from a volume */
133 PSetSysName, /* 38 - Set system name */
134 PExportAfs, /* 39 - Export Afs to remote nfs clients */
135 PGetCacheSize, /* 40 - get cache size and usage */
136 PGetVnodeXStatus, /* 41 - get vcache's special status */
137 PSetSPrefs33, /* 42 - Set CM Server preferences... */
138 PGetSPrefs, /* 43 - Get CM Server preferences... */
139 PGag, /* 44 - turn off/on all CM messages */
140 PTwiddleRx, /* 45 - adjust some RX params */
141 PSetSPrefs, /* 46 - Set CM Server preferences... */
142 PStoreBehind, /* 47 - set degree of store behind to be done */
143 PGCPAGs, /* 48 - disable automatic pag gc-ing */
144 PGetInitParams, /* 49 - get initial cm params */
145 PGetCPrefs, /* 50 - get client interface addresses */
146 PSetCPrefs, /* 51 - set client interface addresses */
147 PFlushMount, /* 52 - flush mount symlink data */
148 PRxStatProc, /* 53 - control process RX statistics */
149 PRxStatPeer, /* 54 - control peer RX statistics */
150 PGetRxkcrypt, /* 55 -- Get rxkad encryption flag */
151 PSetRxkcrypt, /* 56 -- Set rxkad encryption flag */
152 PBogus, /* 57 -- arla: set file prio */
153 PBogus, /* 58 -- arla: fallback getfh */
154 PBogus, /* 59 -- arla: fallback fhopen */
155 PBogus, /* 60 -- arla: controls xfsdebug */
156 PBogus, /* 61 -- arla: controls arla debug */
157 PBogus, /* 62 -- arla: debug interface */
158 PBogus, /* 63 -- arla: print xfs status */
159 PBogus, /* 64 -- arla: force cache check */
160 PBogus, /* 65 -- arla: break callback */
161 PPrefetchFromTape, /* 66 -- MR-AFS: prefetch file from tape */
162 PResidencyCmd, /* 67 -- MR-AFS: generic commnd interface */
163 PBogus, /* 68 -- arla: fetch stats */
166 static int (*(CpioctlSw[]))() = {
168 PNewAlias, /* 1 -- create new cell alias */
169 PListAliases, /* 2 -- list cell aliases */
172 #define PSetClientContext 99 /* Special pioctl to setup caller's creds */
173 int afs_nobody = NFS_NOBODY;
176 afs_ioctl32_to_afs_ioctl(const struct afs_ioctl32 *src, struct afs_ioctl *dst)
178 dst->in = (char *)(unsigned long)src->in;
179 dst->out = (char *)(unsigned long)src->out;
180 dst->in_size = src->in_size;
181 dst->out_size = src->out_size;
185 * If you need to change copyin_afs_ioctl(), you may also need to change
190 copyin_afs_ioctl(caddr_t cmarg, struct afs_ioctl *dst)
194 #if defined(AFS_HPUX_64BIT_ENV)
195 struct afs_ioctl32 dst32;
197 if (is_32bit(u.u_procp)) /* is_32bit() in proc_iface.h */
199 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
201 afs_ioctl32_to_afs_ioctl(&dst32, dst);
204 #endif /* defined(AFS_HPUX_64BIT_ENV) */
206 #if defined(AFS_SUN57_64BIT_ENV)
207 struct afs_ioctl32 dst32;
209 if (get_udatamodel() == DATAMODEL_ILP32) {
210 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
212 afs_ioctl32_to_afs_ioctl(&dst32, dst);
215 #endif /* defined(AFS_SUN57_64BIT_ENV) */
217 #if defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64)
218 struct afs_ioctl32 dst32;
220 if (!ABI_IS_64BIT(get_current_abi()))
222 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
224 afs_ioctl32_to_afs_ioctl(&dst32, dst);
227 #endif /* defined(AFS_SGI_ENV) && (_MIPS_SZLONG==64) */
229 #if defined(AFS_LINUX_64BIT_KERNEL) && !defined(AFS_ALPHA_LINUX20_ENV) && !defined(AFS_IA64_LINUX20_ENV)
230 struct afs_ioctl32 dst32;
232 #ifdef AFS_SPARC64_LINUX24_ENV
233 if (current->thread.flags & SPARC_FLAG_32BIT)
234 #elif AFS_SPARC64_LINUX20_ENV
235 if (current->tss.flags & SPARC_FLAG_32BIT)
237 #error Not done for this linux type
238 #endif /* AFS_SPARC64_LINUX20_ENV */
240 AFS_COPYIN(cmarg, (caddr_t) &dst32, sizeof dst32, code);
242 afs_ioctl32_to_afs_ioctl(&dst32, dst);
245 #endif /* defined(AFS_LINUX_64BIT_KERNEL) */
247 AFS_COPYIN(cmarg, (caddr_t) dst, sizeof *dst, code);
251 int HandleIoctl(register struct vcache *avc, register afs_int32 acom, struct afs_ioctl *adata)
253 register afs_int32 code;
256 AFS_STATCNT(HandleIoctl);
258 switch(acom & 0xff) {
260 avc->states |= CSafeStore;
264 /* case 2 used to be abort store, but this is no longer provided,
265 since it is impossible to implement under normal Unix.
269 /* return the name of the cell this file is open on */
270 register struct cell *tcell;
271 register afs_int32 i;
273 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
275 i = strlen(tcell->cellName) + 1; /* bytes to copy out */
277 if (i > adata->out_size) {
278 /* 0 means we're not interested in the output */
279 if (adata->out_size != 0) code = EFAULT;
283 AFS_COPYOUT(tcell->cellName, adata->out, i, code);
285 afs_PutCell(tcell, READ_LOCK);
291 case 49: /* VIOC_GETINITPARAMS */
292 if (adata->out_size < sizeof(struct cm_initparams)) {
296 AFS_COPYOUT(&cm_initParams, adata->out,
297 sizeof(struct cm_initparams), code);
306 return code; /* so far, none implemented */
311 /* For aix we don't temporarily bypass ioctl(2) but rather do our
312 * thing directly in the vnode layer call, VNOP_IOCTL; thus afs_ioctl
313 * is now called from afs_gn_ioctl.
315 int afs_ioctl(struct vcache *tvc, int cmd, int arg)
317 struct afs_ioctl data;
320 AFS_STATCNT(afs_ioctl);
321 if (((cmd >> 8) & 0xff) == 'V') {
322 /* This is a VICEIOCTL call */
323 AFS_COPYIN(arg, (caddr_t) &data, sizeof(data), error);
326 error = HandleIoctl(tvc, cmd, &data);
329 /* No-op call; just return. */
333 #endif /* AFS_AIX_ENV */
335 #if defined(AFS_SGI_ENV)
336 afs_ioctl(OSI_VN_DECL(tvc), int cmd, void * arg, int flag, cred_t *cr, rval_t *rvalp
342 struct afs_ioctl data;
348 AFS_STATCNT(afs_ioctl);
349 if (((cmd >> 8) & 0xff) == 'V') {
350 /* This is a VICEIOCTL call */
351 error = copyin_afs_ioctl(arg, &data);
354 locked = ISAFS_GLOCK();
357 error = HandleIoctl(tvc, cmd, &data);
362 /* No-op call; just return. */
366 #endif /* AFS_SGI_ENV */
369 /* unlike most calls here, this one uses u.u_error to return error conditions,
370 since this is really an intercepted chapter 2 call, rather than a vnode
373 /* AFS_HPUX102 and up uses VNODE ioctl instead */
374 #ifndef AFS_HPUX102_ENV
375 #if !defined(AFS_SGI_ENV)
377 kioctl(fdes, com, arg, ext)
384 } u_uap, *uap = &u_uap;
388 struct afs_ioctl_sys {
394 afs_xioctl (uap, rvp)
395 struct afs_ioctl_sys *uap;
400 afs_xioctl (p, args, retval)
409 } *uap = (struct a *)args;
410 #else /* AFS_OSF_ENV */
411 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
417 afs_xioctl(p, uap, retval)
419 register struct ioctl_args *uap;
423 #ifdef AFS_LINUX22_ENV
424 struct afs_ioctl_sys {
428 asmlinkage int afs_xioctl(struct inode *ip, struct file *fp,
429 unsigned int com, unsigned long arg)
431 struct afs_ioctl_sys ua, *uap = &ua;
433 int afs_xioctl (void)
439 } *uap = (struct a *)u.u_ap;
440 #endif /* AFS_LINUX22_ENV */
441 #endif /* AFS_DARWIN_ENV || AFS_FBSD_ENV */
442 #endif /* AFS_OSF_ENV */
443 #endif /* AFS_SUN5_ENV */
445 #ifndef AFS_LINUX22_ENV
446 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
449 register struct file *fd;
452 #if defined(AFS_FBSD_ENV)
453 register struct filedesc *fdp;
455 register struct vcache *tvc;
456 register int ioctlDone = 0, code = 0;
458 AFS_STATCNT(afs_xioctl);
459 #if defined(AFS_FBSD_ENV)
461 if ((u_int)uap->fd >= fdp->fd_nfiles ||
462 (fd = fdp->fd_ofiles[uap->fd]) == NULL)
464 if ((fd->f_flag & (FREAD | FWRITE)) == 0)
467 #if defined(AFS_DARWIN_ENV)
468 if ((code=fdgetf(p, uap->fd, &fd)))
471 #ifdef AFS_LINUX22_ENV
479 if (setuerror(getf(uap->fd, &fd))) {
485 if (code = getf(&fd, uap->fd, FILE_FLAGS_NULL, &u.u_file_state))
487 #else /* AFS_OSF_ENV */
489 #if defined(AFS_SUN57_ENV)
491 if (!fd) return(EBADF);
492 #elif defined(AFS_SUN54_ENV)
494 if (!fd) return(EBADF);
496 if (code = getf(uap->fd, &fd)) {
509 /* first determine whether this is any sort of vnode */
510 #ifdef AFS_LINUX22_ENV
515 if (fd->f_vnode->v_type == VREG || fd->f_vnode->v_type == VDIR) {
517 if (fd->f_type == DTYPE_VNODE) {
519 /* good, this is a vnode; next see if it is an AFS vnode */
520 #if defined(AFS_AIX32_ENV) || defined(AFS_SUN5_ENV)
521 tvc = VTOAFS(fd->f_vnode); /* valid, given a vnode */
523 tvc = VTOAFS((struct vnode*)fd->f_data); /* valid, given a vnode */
525 #endif /* AFS_LINUX22_ENV */
526 if (tvc && IsAfsVnode(AFSTOV(tvc))) {
528 tvc = VTOAFS(afs_gntovn((struct gnode *) tvc));
529 if (!tvc) { /* shouldn't happen with held gnodes */
534 /* This is an AFS vnode */
535 if (((uap->com >> 8) & 0xff) == 'V') {
536 register struct afs_ioctl *datap;
538 datap = (struct afs_ioctl *) osi_AllocSmallSpace(AFS_SMALLOCSIZ);
539 AFS_COPYIN((char *)uap->arg, (caddr_t) datap, sizeof (struct afs_ioctl), code);
541 osi_FreeSmallSpace(datap);
543 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
546 #if defined(AFS_SUN5_ENV)
561 #else /* AFS_OSF_ENV */
565 #ifdef AFS_LINUX22_ENV
575 code = HandleIoctl(tvc, uap->com, datap);
576 osi_FreeSmallSpace(datap);
590 #if defined(AFS_LINUX22_ENV)
600 code = okioctl(fdes, com, arg, ext);
604 okioctl(fdes, com, arg, ext);
606 #if defined(AFS_SUN5_ENV)
607 #if defined(AFS_SUN57_ENV)
609 #elif defined(AFS_SUN54_ENV)
614 code = ioctl(uap, rvp);
616 #if defined(AFS_FBSD_ENV)
617 return ioctl(p, uap);
619 #if defined(AFS_DARWIN_ENV)
620 return ioctl(p, uap, retval);
623 code = ioctl(p, args, retval);
630 #else /* AFS_OSF_ENV */
631 #ifndef AFS_LINUX22_ENV
650 #ifdef AFS_LINUX22_ENV
653 #if !defined(AFS_OSF_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
656 #if defined(AFS_AIX32_ENV) && !defined(AFS_AIX41_ENV)
657 return (getuerror() ? -1 : u.u_ioctlrv);
659 return getuerror() ? -1 : 0;
662 #endif /* AFS_LINUX22_ENV */
663 #endif /* AFS_SUN5_ENV */
664 #if defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
668 #endif /* AFS_SGI_ENV */
669 #endif /* AFS_HPUX102_ENV */
671 #if defined(AFS_SGI_ENV)
672 /* "pioctl" system call entry point; just pass argument to the parameterized
681 afs_pioctl(struct pioctlargs *uap, rval_t *rvp)
685 AFS_STATCNT(afs_pioctl);
687 code = afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow);
695 #endif /* AFS_SGI_ENV */
698 afs_pioctl(p, args, retval)
708 } *uap = (struct a *) args;
710 AFS_STATCNT(afs_pioctl);
711 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow));
714 #else /* AFS_OSF_ENV */
715 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
716 afs_pioctl(p, args, retval)
726 } *uap = (struct a *) args;
728 AFS_STATCNT(afs_pioctl);
729 return (afs_syscall_pioctl(uap->path, uap->cmd, uap->cmarg, uap->follow, p->p_cred->pc_ucred));
732 #else /* AFS_OSF_ENV */
736 /* macro to avoid adding any more #ifdef's to pioctl code. */
737 #if defined(AFS_LINUX22_ENV) || defined(AFS_AIX41_ENV)
738 #define PIOCTL_FREE_CRED() crfree(credp)
740 #define PIOCTL_FREE_CRED()
744 afs_syscall_pioctl(path, com, cmarg, follow, rvp, credp)
746 struct AFS_UCRED *credp;
748 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
749 afs_syscall_pioctl(path, com, cmarg, follow, credp)
750 struct AFS_UCRED *credp;
752 afs_syscall_pioctl(path, com, cmarg, follow)
760 struct afs_ioctl data;
761 struct AFS_UCRED *tmpcred, *foreigncreds = 0;
762 register afs_int32 code = 0;
768 struct ucred *credp = crref(); /* don't free until done! */
770 #ifdef AFS_LINUX22_ENV
771 cred_t *credp = crref(); /* don't free until done! */
775 AFS_STATCNT(afs_syscall_pioctl);
776 if (follow) follow = 1; /* compat. with old venus */
777 code = copyin_afs_ioctl(cmarg, &data);
780 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
787 if ((com & 0xff) == PSetClientContext) {
788 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
789 return EINVAL; /* Not handling these yet. */
791 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV)
792 code = HandleClientContext(&data, &com, &foreigncreds, credp);
794 #if defined(AFS_HPUX101_ENV)
795 code=HandleClientContext(&data, &com, &foreigncreds, p_cred(u.u_procp));
798 code = HandleClientContext(&data, &com, &foreigncreds, OSI_GET_CURRENT_CRED());
800 code = HandleClientContext(&data, &com, &foreigncreds, u.u_cred);
801 #endif /* AFS_SGI_ENV */
807 crfree(foreigncreds);
810 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
813 return (setuerror(code), code);
817 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
820 * We could have done without temporary setting the u.u_cred below
821 * (foreigncreds could be passed as param the pioctl modules)
822 * but calls such as afs_osi_suser() doesn't allow that since it
823 * references u.u_cred directly. We could, of course, do something
824 * like afs_osi_suser(cred) which, I think, is better since it
825 * generalizes and supports multi cred environments...
829 credp = foreigncreds;
832 tmpcred = crref(); /* XXX */
835 #if defined(AFS_HPUX101_ENV)
836 tmpcred = p_cred(u.u_procp);
837 set_p_cred(u.u_procp, foreigncreds);
840 tmpcred = OSI_GET_CURRENT_CRED();
841 OSI_SET_CURRENT_CRED(foreigncreds);
844 u.u_cred = foreigncreds;
845 #endif /* AFS_SGI64_ENV */
846 #endif /* AFS_HPUX101_ENV */
851 if ((com & 0xff) == 15) {
852 /* special case prefetch so entire pathname eval occurs in helper process.
853 otherwise, the pioctl call is essentially useless */
854 #if defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
855 code = Prefetch(path, &data, follow,
856 foreigncreds ? foreigncreds : credp);
858 #if defined(AFS_HPUX101_ENV)
859 code = Prefetch(path, &data, follow, p_cred(u.u_procp));
862 code = Prefetch(path, &data, follow, OSI_GET_CURRENT_CRED());
864 code = Prefetch(path, &data, follow, u.u_cred);
865 #endif /* AFS_SGI64_ENV */
866 #endif /* AFS_HPUX101_ENV */
868 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
871 crset(tmpcred); /* restore original credentials */
873 #if defined(AFS_HPUX101_ENV)
874 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
878 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
880 u.u_cred = tmpcred; /* restore original credentials */
883 #endif /* AFS_HPUX101_ENV */
884 crfree(foreigncreds);
887 #endif /* AFS_LINUX22_ENV */
889 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
892 return (setuerror(code), code);
898 code = lookupname(path, USR, follow, NULL, &vp,
899 foreigncreds ? foreigncreds : credp);
901 #ifdef AFS_LINUX22_ENV
902 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &dp);
904 vp = (struct vnode *)dp->d_inode;
906 code = gop_lookupname(path, AFS_UIOUSER, follow, NULL, &vp);
907 #endif /* AFS_LINUX22_ENV */
908 #endif /* AFS_AIX41_ENV */
911 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
914 crset(tmpcred); /* restore original credentials */
916 #if defined(AFS_HPUX101_ENV)
917 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
919 #if !defined(AFS_SUN5_ENV)
921 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
923 u.u_cred = tmpcred; /* restore original credentials */
924 #endif /* AFS_SGI64_ENV */
926 #endif /* AFS_HPUX101_ENV */
927 crfree(foreigncreds);
930 #endif /* AFS_LINUX22_ENV */
932 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
935 return(setuerror(code), code);
941 /* now make the call if we were passed no file, or were passed an AFS file */
942 if (!vp || IsAfsVnode(vp)) {
944 /* Ultrix 4.0: can't get vcache entry unless we've got an AFS gnode.
945 * So, we must test in this part of the code. Also, must arrange to
946 * GRELE the original gnode pointer when we're done, since in Ultrix 4.0,
947 * we hold gnodes, whose references hold our vcache entries.
950 gp = vp; /* remember for "put" */
951 vp = (struct vnode *) afs_gntovn(vp); /* get vcache from gp */
956 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
960 struct ucred *cred1, *cred2;
963 cred1 = cred2 = foreigncreds;
965 cred1 = cred2 = credp;
967 code = afs_HandlePioctl(vp, com, &data, follow, &cred1);
968 if (cred1 != cred2) {
969 /* something changed the creds */
974 #if defined(AFS_HPUX101_ENV)
976 struct ucred *cred = p_cred(u.u_procp);
977 code = afs_HandlePioctl(vp, com, &data, follow, &cred);
983 credp = OSI_GET_CURRENT_CRED();
984 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
987 #if defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
988 code = afs_HandlePioctl(vp, com, &data, follow, &credp);
990 code = afs_HandlePioctl(vp, com, &data, follow, &u.u_cred);
992 #endif /* AFS_SGI_ENV */
993 #endif /* AFS_HPUX101_ENV */
994 #endif /* AFS_AIX41_ENV */
995 #endif /* AFS_SUN5_ENV */
997 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
998 code = EINVAL; /* not in /afs */
1010 #if !defined(AFS_LINUX22_ENV) && !defined(AFS_DARWIN_ENV) && !defined(AFS_FBSD_ENV)
1012 #ifdef AFS_AIX41_ENV
1015 #if defined(AFS_HPUX101_ENV)
1016 set_p_cred(u.u_procp, tmpcred); /* restore original credentials */
1018 #ifndef AFS_SUN5_ENV
1020 OSI_SET_CURRENT_CRED(tmpcred); /* restore original credentials */
1022 u.u_cred = tmpcred; /* restore original credentials */
1023 #endif /* ASF_SGI64_ENV */
1025 #endif /* AFS_HPUX101_ENV */
1026 crfree(foreigncreds);
1029 #endif /* AFS_LINUX22_ENV */
1031 #ifdef AFS_LINUX22_ENV
1034 AFS_RELE(vp); /* put vnode back */
1038 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1043 return (getuerror());
1048 int afs_HandlePioctl(struct vcache *avc, afs_int32 acom,
1049 register struct afs_ioctl *ablob, int afollow, struct AFS_UCRED **acred)
1051 struct vrequest treq;
1052 register afs_int32 code;
1053 register afs_int32 function, device;
1054 afs_int32 inSize, outSize;
1055 char *inData, *outData;
1056 int (*(*pioctlSw))();
1058 struct afs_fakestat_state fakestate;
1060 afs_Trace3(afs_iclSetp, CM_TRACE_PIOCTL, ICL_TYPE_INT32, acom & 0xff,
1061 ICL_TYPE_POINTER, avc, ICL_TYPE_INT32, afollow);
1062 AFS_STATCNT(HandlePioctl);
1063 if ((code = afs_InitReq(&treq, *acred))) return code;
1064 afs_InitFakeStat(&fakestate);
1066 code = afs_EvalFakeStat(&avc, &fakestate, &treq);
1068 afs_PutFakeStat(&fakestate);
1072 device = (acom & 0xff00) >> 8;
1074 case 'V': /* Original pioctl's */
1075 pioctlSw = VpioctlSw;
1076 pioctlSwSize = sizeof(VpioctlSw);
1078 case 'C': /* Coordinated/common pioctl's */
1079 pioctlSw = CpioctlSw;
1080 pioctlSwSize = sizeof(CpioctlSw);
1083 afs_PutFakeStat(&fakestate);
1086 function = acom & 0xff;
1087 if (function >= (pioctlSwSize / sizeof(char *))) {
1088 afs_PutFakeStat(&fakestate);
1089 return EINVAL; /* out of range */
1091 inSize = ablob->in_size;
1092 if (inSize >= PIGGYSIZE) return E2BIG;
1093 inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1095 AFS_COPYIN(ablob->in, inData, inSize, code);
1096 inData[inSize]='\0';
1100 osi_FreeLargeSpace(inData);
1101 afs_PutFakeStat(&fakestate);
1104 outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
1106 code = (*pioctlSw[function])(avc, function, &treq, inData, outData, inSize, &outSize, acred);
1107 osi_FreeLargeSpace(inData);
1108 if (code == 0 && ablob->out_size > 0) {
1109 if (outSize > ablob->out_size) outSize = ablob->out_size;
1110 if (outSize >= PIGGYSIZE) code = E2BIG;
1112 outData[outSize]='\0';
1113 AFS_COPYOUT(outData, ablob->out, outSize, code);
1116 osi_FreeLargeSpace(outData);
1117 afs_PutFakeStat(&fakestate);
1118 return afs_CheckCode(code, &treq, 41);
1121 DECL_PIOCTL(PGetFID)
1123 register afs_int32 code;
1125 AFS_STATCNT(PGetFID);
1126 if (!avc) return EINVAL;
1127 memcpy(aout, (char *)&avc->fid, sizeof(struct VenusFid));
1128 *aoutSize = sizeof(struct VenusFid);
1132 DECL_PIOCTL(PSetAcl)
1134 register afs_int32 code;
1136 struct AFSOpaque acl;
1137 struct AFSVolSync tsync;
1138 struct AFSFetchStatus OutStatus;
1141 AFS_STATCNT(PSetAcl);
1144 if ((acl.AFSOpaque_len = strlen(ain)+1) > 1000)
1147 acl.AFSOpaque_val = ain;
1149 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1151 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_STOREACL);
1153 code = RXAFS_StoreACL(tconn->id, (struct AFSFid *) &avc->fid.Fid,
1154 &acl, &OutStatus, &tsync);
1160 (afs_Analyze(tconn, code, &avc->fid, areq,
1161 AFS_STATS_FS_RPCIDX_STOREACL, SHARED_LOCK, NULL));
1163 /* now we've forgotten all of the access info */
1164 ObtainWriteLock(&afs_xcbhash, 455);
1166 afs_DequeueCallback(avc);
1167 avc->states &= ~(CStatd | CUnique);
1168 ReleaseWriteLock(&afs_xcbhash);
1169 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
1170 osi_dnlc_purgedp(avc);
1174 int afs_defaultAsynchrony = 0;
1176 DECL_PIOCTL(PStoreBehind)
1179 struct sbstruct *sbr;
1181 sbr = (struct sbstruct *)ain;
1182 if (sbr->sb_default != -1) {
1183 if (afs_osi_suser(*acred))
1184 afs_defaultAsynchrony = sbr->sb_default;
1188 if (avc && (sbr->sb_thisfile != -1)) {
1189 if (afs_AccessOK(avc, PRSFS_WRITE | PRSFS_ADMINISTER,
1190 areq, DONT_CHECK_MODE_BITS))
1191 avc->asynchrony = sbr->sb_thisfile;
1195 *aoutSize = sizeof(struct sbstruct);
1196 sbr = (struct sbstruct *)aout;
1197 sbr->sb_default = afs_defaultAsynchrony;
1199 sbr->sb_thisfile = avc->asynchrony;
1205 DECL_PIOCTL(PGCPAGs)
1207 if (!afs_osi_suser(*acred)) {
1210 afs_gcpags = AFS_GCPAGS_USERDISABLED;
1214 DECL_PIOCTL(PGetAcl)
1216 struct AFSOpaque acl;
1217 struct AFSVolSync tsync;
1218 struct AFSFetchStatus OutStatus;
1224 AFS_STATCNT(PGetAcl);
1225 if (!avc) return EINVAL;
1226 Fid.Volume = avc->fid.Fid.Volume;
1227 Fid.Vnode = avc->fid.Fid.Vnode;
1228 Fid.Unique = avc->fid.Fid.Unique;
1229 if (avc->states & CForeign) {
1231 * For a dfs xlator acl we have a special hack so that the
1232 * xlator will distinguish which type of acl will return. So
1233 * we currently use the top 2-bytes (vals 0-4) to tell which
1234 * type of acl to bring back. Horrible hack but this will
1235 * cause the least number of changes to code size and interfaces.
1237 if (Fid.Vnode & 0xc0000000)
1239 Fid.Vnode |= (ainSize << 30);
1241 acl.AFSOpaque_val = aout;
1243 tconn = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1246 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_FETCHACL);
1248 code = RXAFS_FetchACL(tconn->id, &Fid,
1249 &acl, &OutStatus, &tsync);
1255 (afs_Analyze(tconn, code, &avc->fid, areq,
1256 AFS_STATS_FS_RPCIDX_FETCHACL,
1257 SHARED_LOCK, NULL));
1260 *aoutSize = (acl.AFSOpaque_len == 0 ? 1 : acl.AFSOpaque_len);
1273 AFS_STATCNT(PBogus);
1277 DECL_PIOCTL(PGetFileCell)
1279 register struct cell *tcell;
1281 AFS_STATCNT(PGetFileCell);
1282 if (!avc) return EINVAL;
1283 tcell = afs_GetCell(avc->fid.Cell, READ_LOCK);
1284 if (!tcell) return ESRCH;
1285 strcpy(aout, tcell->cellName);
1286 afs_PutCell(tcell, READ_LOCK);
1287 *aoutSize = strlen(aout) + 1;
1291 DECL_PIOCTL(PGetWSCell)
1293 register struct cell *tcell=0, *cellOne=0;
1294 register struct afs_q *cq, *tq;
1296 AFS_STATCNT(PGetWSCell);
1297 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1298 return EIO; /* Inappropriate ioctl for device */
1300 ObtainReadLock(&afs_xcell);
1303 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
1304 tcell = QTOC(cq); tq = QNext(cq);
1305 if (tcell->states & CPrimary) break;
1306 if (tcell->cell == 1) cellOne = tcell;
1309 ReleaseReadLock(&afs_xcell);
1310 if (!tcell) { /* no primary cell, use cell #1 */
1311 if (!cellOne) return ESRCH;
1314 strcpy(aout, tcell->cellName);
1315 *aoutSize = strlen(aout) + 1;
1319 DECL_PIOCTL(PGetUserCell)
1321 register afs_int32 i;
1322 register struct unixuser *tu;
1323 register struct cell *tcell;
1325 AFS_STATCNT(PGetUserCell);
1326 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1327 return EIO; /* Inappropriate ioctl for device */
1329 /* return the cell name of the primary cell for this user */
1330 i = UHash(areq->uid);
1331 ObtainWriteLock(&afs_xuser,224);
1332 for(tu = afs_users[i]; tu; tu = tu->next) {
1333 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1335 ReleaseWriteLock(&afs_xuser);
1340 tcell = afs_GetCell(tu->cell, READ_LOCK);
1341 afs_PutUser(tu, WRITE_LOCK);
1342 if (!tcell) return ESRCH;
1344 strcpy(aout, tcell->cellName);
1345 afs_PutCell(tcell, READ_LOCK);
1346 *aoutSize = strlen(aout)+1; /* 1 for the null */
1350 ReleaseWriteLock(&afs_xuser);
1357 DECL_PIOCTL(PSetTokens)
1360 register struct unixuser *tu;
1361 struct ClearToken clear;
1362 register struct cell *tcell;
1365 struct vrequest treq;
1366 afs_int32 flag, set_parent_pag = 0;
1368 AFS_STATCNT(PSetTokens);
1369 if (!afs_resourceinit_flag) {
1372 memcpy((char *)&i, ain, sizeof(afs_int32));
1373 ain += sizeof(afs_int32);
1374 stp = ain; /* remember where the ticket is */
1375 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1377 ain += i; /* skip over ticket */
1378 memcpy((char *)&i, ain, sizeof(afs_int32));
1379 ain += sizeof(afs_int32);
1380 if (i != sizeof(struct ClearToken)) {
1383 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1384 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1385 ain += sizeof(struct ClearToken);
1386 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1387 /* still stuff left? we've got primary flag and cell name. Set these */
1388 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1389 ain += sizeof(afs_int32); /* skip id field */
1390 /* rest is cell name, look it up */
1391 /* some versions of gcc appear to need != 0 in order to get this right */
1392 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1396 tcell = afs_GetCellByName(ain, READ_LOCK);
1405 /* default to cell 1, primary id */
1406 flag = 1; /* primary id */
1407 i = 1; /* cell number */
1408 tcell = afs_GetCell(1, READ_LOCK);
1409 if (!tcell) goto nocell;
1411 afs_PutCell(tcell, READ_LOCK);
1412 if (set_parent_pag) {
1414 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1415 #if defined(AFS_DARWIN_ENV)
1416 struct proc *p=current_proc(); /* XXX */
1418 struct proc *p=curproc; /* XXX */
1420 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1421 p->p_pid, p->p_comm);
1422 if (!setpag(p, acred, -1, &pag, 1)) {
1425 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1427 if (!setpag(acred, -1, &pag, 1)) {
1430 afs_InitReq(&treq, *acred);
1434 /* now we just set the tokens */
1435 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1436 tu->vid = clear.ViceId;
1437 if (tu->stp != NULL) {
1438 afs_osi_Free(tu->stp, tu->stLen);
1440 tu->stp = (char *) afs_osi_Alloc(stLen);
1442 memcpy(tu->stp, stp, stLen);
1445 afs_stats_cmfullperf.authent.TicketUpdates++;
1446 afs_ComputePAGStats();
1447 #endif /* AFS_NOSTATS */
1448 tu->states |= UHasTokens;
1449 tu->states &= ~UTokensBad;
1450 afs_SetPrimary(tu, flag);
1451 tu->tokenTime =osi_Time();
1452 afs_ResetUserConns(tu);
1453 afs_PutUser(tu, WRITE_LOCK);
1468 DECL_PIOCTL(PGetVolumeStatus)
1471 char offLineMsg[256];
1473 register struct conn *tc;
1474 register afs_int32 code;
1475 struct VolumeStatus volstat;
1477 char *Name, *OfflineMsg, *MOTD;
1480 AFS_STATCNT(PGetVolumeStatus);
1481 if (!avc) return EINVAL;
1483 OfflineMsg = offLineMsg;
1486 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1488 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1490 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1491 &Name, &OfflineMsg, &MOTD);
1497 (afs_Analyze(tc, code, &avc->fid, areq,
1498 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1499 SHARED_LOCK, NULL));
1501 if (code) return code;
1502 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1504 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1505 cp += sizeof(VolumeStatus);
1506 strcpy(cp, volName);
1507 cp += strlen(volName)+1;
1508 strcpy(cp, offLineMsg);
1509 cp += strlen(offLineMsg)+1;
1511 cp += strlen(motd)+1;
1512 *aoutSize = (cp - aout);
1516 DECL_PIOCTL(PSetVolumeStatus)
1519 char offLineMsg[256];
1521 register struct conn *tc;
1522 register afs_int32 code;
1523 struct AFSFetchVolumeStatus volstat;
1524 struct AFSStoreVolumeStatus storeStat;
1525 register struct volume *tvp;
1529 AFS_STATCNT(PSetVolumeStatus);
1530 if (!avc) return EINVAL;
1532 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1534 if (tvp->states & (VRO | VBackup)) {
1535 afs_PutVolume(tvp, READ_LOCK);
1538 afs_PutVolume(tvp, READ_LOCK);
1541 /* Copy the junk out, using cp as a roving pointer. */
1543 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1544 cp += sizeof(AFSFetchVolumeStatus);
1545 if (strlen(cp) >= sizeof(volName))
1547 strcpy(volName, cp);
1548 cp += strlen(volName)+1;
1549 if (strlen(cp) >= sizeof(offLineMsg))
1551 strcpy(offLineMsg, cp);
1552 cp += strlen(offLineMsg)+1;
1553 if (strlen(cp) >= sizeof(motd))
1557 if (volstat.MinQuota != -1) {
1558 storeStat.MinQuota = volstat.MinQuota;
1559 storeStat.Mask |= AFS_SETMINQUOTA;
1561 if (volstat.MaxQuota != -1) {
1562 storeStat.MaxQuota = volstat.MaxQuota;
1563 storeStat.Mask |= AFS_SETMAXQUOTA;
1566 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1568 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1570 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1571 &storeStat, volName, offLineMsg, motd);
1577 (afs_Analyze(tc, code, &avc->fid, areq,
1578 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1579 SHARED_LOCK, NULL));
1581 if (code) return code;
1582 /* we are sending parms back to make compat. with prev system. should
1583 change interface later to not ask for current status, just set new status */
1585 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1586 cp += sizeof(VolumeStatus);
1587 strcpy(cp, volName);
1588 cp += strlen(volName)+1;
1589 strcpy(cp, offLineMsg);
1590 cp += strlen(offLineMsg)+1;
1592 cp += strlen(motd)+1;
1593 *aoutSize = cp - aout;
1599 AFS_STATCNT(PFlush);
1600 if (!avc) return EINVAL;
1601 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1602 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1604 ObtainWriteLock(&avc->lock,225);
1605 ObtainWriteLock(&afs_xcbhash, 456);
1606 afs_DequeueCallback(avc);
1607 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1608 ReleaseWriteLock(&afs_xcbhash);
1609 /* now find the disk cache entries */
1610 afs_TryToSmush(avc, *acred, 1);
1611 osi_dnlc_purgedp(avc);
1612 afs_symhint_inval(avc);
1613 if (avc->linkData && !(avc->states & CCore)) {
1614 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1615 avc->linkData = NULL;
1617 ReleaseWriteLock(&avc->lock);
1618 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1619 afs_BozonUnlock(&avc->pvnLock, avc);
1624 DECL_PIOCTL(PNewStatMount)
1626 register afs_int32 code;
1627 register struct vcache *tvc;
1628 register struct dcache *tdc;
1629 struct VenusFid tfid;
1631 struct sysname_info sysState;
1632 afs_size_t offset, len;
1634 AFS_STATCNT(PNewStatMount);
1635 if (!avc) return EINVAL;
1636 code = afs_VerifyVCache(avc, areq);
1637 if (code) return code;
1638 if (vType(avc) != VDIR) {
1641 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1642 if (!tdc) return ENOENT;
1643 Check_AtSys(avc, ain, &sysState, areq);
1644 ObtainReadLock(&tdc->lock);
1646 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1647 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1648 ReleaseReadLock(&tdc->lock);
1649 afs_PutDCache(tdc); /* we're done with the data */
1650 bufp = sysState.name;
1654 tfid.Cell = avc->fid.Cell;
1655 tfid.Fid.Volume = avc->fid.Fid.Volume;
1656 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1657 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1659 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1665 if (tvc->mvstat != 1) {
1670 ObtainWriteLock(&tvc->lock,226);
1671 code = afs_HandleLink(tvc, areq);
1673 if (tvc->linkData) {
1674 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1677 /* we have the data */
1678 strcpy(aout, tvc->linkData);
1679 *aoutSize = strlen(tvc->linkData)+1;
1684 ReleaseWriteLock(&tvc->lock);
1687 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1691 DECL_PIOCTL(PGetTokens)
1693 register struct cell *tcell;
1694 register afs_int32 i;
1695 register struct unixuser *tu;
1700 AFS_STATCNT(PGetTokens);
1701 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1702 return EIO; /* Inappropriate ioctl for device */
1704 /* weird interface. If input parameter is present, it is an integer and
1705 we're supposed to return the parm'th tokens for this unix uid.
1706 If not present, we just return tokens for cell 1.
1707 If counter out of bounds, return EDOM.
1708 If no tokens for the particular cell, return ENOTCONN.
1709 Also, if this mysterious parm is present, we return, along with the
1710 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1711 at the end, in that order.
1713 if ((newStyle = (ainSize > 0))) {
1714 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1716 i = UHash(areq->uid);
1717 ObtainReadLock(&afs_xuser);
1718 for(tu = afs_users[i]; tu; tu=tu->next) {
1720 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1721 if (iterator-- == 0) break; /* are we done yet? */
1725 if (tu->uid == areq->uid && tu->cell == 1) break;
1730 * No need to hold a read lock on each user entry
1734 ReleaseReadLock(&afs_xuser);
1739 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1740 tu->states |= (UTokensBad | UNeedsReset);
1741 afs_PutUser(tu, READ_LOCK);
1744 /* use iterator for temp */
1746 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1747 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1748 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1749 cp += sizeof(afs_int32);
1750 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1752 iterator = sizeof(struct ClearToken);
1753 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1754 cp += sizeof(afs_int32);
1755 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1756 cp += sizeof(struct ClearToken);
1758 /* put out primary id and cell name, too */
1759 iterator = (tu->states & UPrimary ? 1 : 0);
1760 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1761 cp += sizeof(afs_int32);
1762 tcell = afs_GetCell(tu->cell, READ_LOCK);
1764 strcpy(cp, tcell->cellName);
1765 cp += strlen(tcell->cellName)+1;
1766 afs_PutCell(tcell, READ_LOCK);
1770 *aoutSize = cp - aout;
1771 afs_PutUser(tu, READ_LOCK);
1777 register afs_int32 i;
1778 register struct unixuser *tu;
1780 AFS_STATCNT(PUnlog);
1781 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1782 return EIO; /* Inappropriate ioctl for device */
1784 i = UHash(areq->uid);
1785 ObtainWriteLock(&afs_xuser,227);
1786 for(tu=afs_users[i]; tu; tu=tu->next) {
1787 if (tu->uid == areq->uid) {
1789 tu->states &= ~UHasTokens;
1790 /* security is not having to say you're sorry */
1791 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1793 ReleaseWriteLock(&afs_xuser);
1794 /* We have to drop the lock over the call to afs_ResetUserConns, since
1795 * it obtains the afs_xvcache lock. We could also keep the lock, and
1796 * modify ResetUserConns to take parm saying we obtained the lock
1797 * already, but that is overkill. By keeping the "tu" pointer
1798 * held over the released lock, we guarantee that we won't lose our
1799 * place, and that we'll pass over every user conn that existed when
1800 * we began this call.
1802 afs_ResetUserConns(tu);
1804 ObtainWriteLock(&afs_xuser,228);
1806 /* set the expire times to 0, causes
1807 * afs_GCUserData to remove this entry
1809 tu->ct.EndTimestamp = 0;
1811 #endif /* UKERNEL */
1814 ReleaseWriteLock(&afs_xuser);
1818 DECL_PIOCTL(PMariner)
1820 afs_int32 newHostAddr;
1821 afs_int32 oldHostAddr;
1823 AFS_STATCNT(PMariner);
1825 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1827 oldHostAddr = 0xffffffff; /* disabled */
1829 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1830 if (newHostAddr == 0xffffffff) {
1831 /* disable mariner operations */
1834 else if (newHostAddr) {
1836 afs_marinerHost = newHostAddr;
1838 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1839 *aoutSize = sizeof(afs_int32);
1843 DECL_PIOCTL(PCheckServers)
1845 register char *cp = 0;
1847 register struct server *ts;
1848 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1850 struct chservinfo *pcheck;
1852 AFS_STATCNT(PCheckServers);
1854 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1855 return EIO; /* Inappropriate ioctl for device */
1857 if (*lp == 0x12345678) { /* For afs3.3 version */
1858 pcheck=(struct chservinfo *)ain;
1859 if (pcheck->tinterval >= 0) {
1861 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1862 *aoutSize = sizeof(afs_int32);
1863 if (pcheck->tinterval > 0) {
1864 if (!afs_osi_suser(*acred))
1866 PROBE_INTERVAL=pcheck->tinterval;
1872 temp=pcheck->tflags;
1873 cp = pcheck->tbuffer;
1874 } else { /* For pre afs3.3 versions */
1875 memcpy((char *)&temp, ain, sizeof(afs_int32));
1876 cp = ain+sizeof(afs_int32);
1877 if (ainSize > sizeof(afs_int32))
1882 * 1: fast check, don't contact servers.
1883 * 2: local cell only.
1886 /* have cell name, too */
1887 cellp = afs_GetCellByName(cp, READ_LOCK);
1888 if (!cellp) return ENOENT;
1891 if (!cellp && (temp & 2)) {
1892 /* use local cell */
1893 cellp = afs_GetCell(1, READ_LOCK);
1895 if (!(temp & 1)) { /* if not fast, call server checker routine */
1896 afs_CheckServers(1, cellp); /* check down servers */
1897 afs_CheckServers(0, cellp); /* check up servers */
1899 /* now return the current down server list */
1901 ObtainReadLock(&afs_xserver);
1902 for(i=0;i<NSERVERS;i++) {
1903 for(ts = afs_servers[i]; ts; ts=ts->next) {
1904 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1905 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1906 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1907 cp += sizeof(afs_int32);
1911 ReleaseReadLock(&afs_xserver);
1912 if (cellp) afs_PutCell(cellp, READ_LOCK);
1913 *aoutSize = cp - aout;
1917 DECL_PIOCTL(PCheckVolNames)
1919 AFS_STATCNT(PCheckVolNames);
1920 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1921 return EIO; /* Inappropriate ioctl for device */
1923 afs_CheckRootVolume();
1924 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1925 AFS_VOLCHECK_EXPIRED |
1927 AFS_VOLCHECK_MTPTS);
1931 DECL_PIOCTL(PCheckAuth)
1936 struct unixuser *tu;
1939 AFS_STATCNT(PCheckAuth);
1940 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1941 return EIO; /* Inappropriate ioctl for device */
1944 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1945 if (!tu) retValue = EACCES;
1947 /* we have a user */
1948 ObtainReadLock(&afs_xsrvAddr);
1949 ObtainReadLock(&afs_xconn);
1951 /* any tokens set? */
1952 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1953 /* all connections in cell 1 working? */
1954 for(i=0;i<NSERVERS;i++) {
1955 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1956 for (tc = sa->conns; tc; tc=tc->next) {
1957 if (tc->user == tu && (tu->states & UTokensBad))
1962 ReleaseReadLock(&afs_xsrvAddr);
1963 ReleaseReadLock(&afs_xconn);
1964 afs_PutUser(tu, READ_LOCK);
1966 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1967 *aoutSize = sizeof(afs_int32);
1971 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1974 register afs_int32 code;
1975 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1981 AFS_STATCNT(Prefetch);
1982 if (!apath) return EINVAL;
1983 tp = osi_AllocLargeSpace(1024);
1984 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1986 osi_FreeLargeSpace(tp);
1989 if (afs_BBusy()) { /* do this as late as possible */
1990 osi_FreeLargeSpace(tp);
1991 return EWOULDBLOCK; /* pretty close */
1993 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1994 (afs_size_t) 0, (afs_size_t) 0, tp);
1998 DECL_PIOCTL(PFindVolume)
2000 register struct volume *tvp;
2001 register struct server *ts;
2002 register afs_int32 i;
2005 AFS_STATCNT(PFindVolume);
2006 if (!avc) return EINVAL;
2007 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
2010 for(i=0;i<MAXHOSTS;i++) {
2011 ts = tvp->serverHost[i];
2013 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
2014 cp += sizeof(afs_int32);
2017 /* still room for terminating NULL, add it on */
2018 ainSize = 0; /* reuse vbl */
2019 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2020 cp += sizeof(afs_int32);
2022 *aoutSize = cp - aout;
2023 afs_PutVolume(tvp, READ_LOCK);
2029 DECL_PIOCTL(PViceAccess)
2031 register afs_int32 code;
2034 AFS_STATCNT(PViceAccess);
2035 if (!avc) return EINVAL;
2036 code = afs_VerifyVCache(avc, areq);
2037 if (code) return code;
2038 memcpy((char *)&temp, ain, sizeof(afs_int32));
2039 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2044 DECL_PIOCTL(PSetCacheSize)
2049 AFS_STATCNT(PSetCacheSize);
2050 if (!afs_osi_suser(*acred))
2052 /* too many things are setup initially in mem cache version */
2053 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2054 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2055 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2057 if (newValue < afs_min_cache)
2058 afs_cacheBlocks = afs_min_cache;
2060 afs_cacheBlocks = newValue;
2062 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2063 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2064 afs_MaybeWakeupTruncateDaemon();
2065 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2066 afs_osi_Wait(1000, 0, 0);
2067 afs_MaybeWakeupTruncateDaemon();
2072 #define MAXGCSTATS 16
2073 DECL_PIOCTL(PGetCacheSize)
2075 afs_int32 results[MAXGCSTATS];
2077 AFS_STATCNT(PGetCacheSize);
2078 memset((char *)results, 0, sizeof(results));
2079 results[0] = afs_cacheBlocks;
2080 results[1] = afs_blocksUsed;
2081 memcpy(aout, (char *)results, sizeof(results));
2082 *aoutSize = sizeof(results);
2086 DECL_PIOCTL(PRemoveCallBack)
2088 register struct conn *tc;
2089 register afs_int32 code;
2090 struct AFSCallBack CallBacks_Array[1];
2091 struct AFSCBFids theFids;
2092 struct AFSCBs theCBs;
2095 AFS_STATCNT(PRemoveCallBack);
2096 if (!avc) return EINVAL;
2097 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2098 ObtainWriteLock(&avc->lock,229);
2099 theFids.AFSCBFids_len = 1;
2100 theCBs.AFSCBs_len = 1;
2101 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2102 theCBs.AFSCBs_val = CallBacks_Array;
2103 CallBacks_Array[0].CallBackType = CB_DROPPED;
2104 if (avc->callback) {
2106 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2108 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2110 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2114 /* don't set code on failure since we wouldn't use it */
2116 (afs_Analyze(tc, code, &avc->fid, areq,
2117 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2118 SHARED_LOCK, NULL));
2120 ObtainWriteLock(&afs_xcbhash, 457);
2121 afs_DequeueCallback(avc);
2123 avc->states &= ~(CStatd | CUnique);
2124 ReleaseWriteLock(&afs_xcbhash);
2125 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2126 osi_dnlc_purgedp(avc);
2128 ReleaseWriteLock(&avc->lock);
2132 DECL_PIOCTL(PNewCell)
2134 /* create a new cell */
2135 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2136 register struct cell *tcell;
2137 char *newcell=0, *linkedcell=0, *tp= ain;
2138 register afs_int32 code, linkedstate=0, ls;
2139 u_short fsport = 0, vlport = 0;
2142 AFS_STATCNT(PNewCell);
2143 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2144 return EIO; /* Inappropriate ioctl for device */
2146 if (!afs_osi_suser(*acred))
2149 memcpy((char *)&magic, tp, sizeof(afs_int32));
2150 tp += sizeof(afs_int32);
2151 if (magic != 0x12345678)
2154 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2155 * server addresses while the 3.5 fs newcell command passes
2156 * MAXHOSTS. To figure out which is which, check if the cellname
2159 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2160 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2162 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2163 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2164 tp += (scount * sizeof(afs_int32));
2166 lp = (afs_int32 *)tp;
2169 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2170 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2171 tp += (3 * sizeof(afs_int32));
2173 if ((ls = *lp) & 1) {
2174 linkedcell = tp + strlen(newcell)+1;
2175 linkedstate |= CLinkedCell;
2178 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2179 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport, vlport, (int)0, NULL);
2183 DECL_PIOCTL(PNewAlias)
2185 /* create a new cell alias */
2186 register struct cell *tcell;
2188 register afs_int32 code;
2189 char *realName, *aliasName;
2190 register struct afs_q *cq, *tq;
2192 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2193 return EIO; /* Inappropriate ioctl for device */
2195 if (!afs_osi_suser(*acred))
2199 tp += strlen(aliasName) + 1;
2203 * Prevent user from shooting themselves in the foot -- don't allow
2204 * creation of aliases when a real cell already exists with that name.
2206 ObtainReadLock(&afs_xcell);
2207 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2208 tcell = QTOC(cq); tq = QNext(cq);
2209 if ((afs_strcasecmp(tcell->cellName, aliasName) == 0) &&
2210 !(tcell->states & CAlias)) {
2211 ReleaseReadLock(&afs_xcell);
2215 ReleaseReadLock(&afs_xcell);
2217 code = afs_NewCell(aliasName, 0, CAlias, 0, 0, 0, 0, realName);
2222 DECL_PIOCTL(PListCells)
2224 afs_int32 whichCell;
2225 register struct cell *tcell=0;
2226 register afs_int32 i;
2227 register char *cp, *tp = ain;
2228 register struct afs_q *cq, *tq;
2230 AFS_STATCNT(PListCells);
2231 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2232 return EIO; /* Inappropriate ioctl for device */
2234 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2235 tp += sizeof(afs_int32);
2236 tcell = afs_GetRealCellByIndex(whichCell, READ_LOCK, 0);
2239 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2240 for(i=0;i<MAXCELLHOSTS;i++) {
2241 if (tcell->cellHosts[i] == 0) break;
2242 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2243 cp += sizeof(afs_int32);
2245 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2246 strcpy(cp, tcell->cellName);
2247 cp += strlen(tcell->cellName)+1;
2248 *aoutSize = cp - aout;
2250 if (tcell) return 0;
2254 DECL_PIOCTL(PListAliases)
2256 afs_int32 whichAlias;
2257 register struct cell *tcell=0;
2258 register char *cp, *tp = ain;
2259 register struct afs_q *cq, *tq;
2261 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2262 return EIO; /* Inappropriate ioctl for device */
2263 if (ainSize < sizeof(afs_int32))
2266 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2267 tp += sizeof(afs_int32);
2269 ObtainReadLock(&afs_xcell);
2270 for (cq = CellLRU.next; cq != &CellLRU; cq = tq) {
2271 tcell = QTOC(cq); tq = QNext(cq);
2272 if (!(tcell->states & CAlias)) {
2276 if (whichAlias == 0) break;
2282 strcpy(cp, tcell->cellName);
2283 cp += strlen(tcell->cellName)+1;
2284 strcpy(cp, tcell->realName);
2285 cp += strlen(tcell->realName)+1;
2286 *aoutSize = cp - aout;
2288 ReleaseReadLock(&afs_xcell);
2289 if (tcell) return 0;
2293 DECL_PIOCTL(PRemoveMount)
2295 register afs_int32 code;
2297 struct sysname_info sysState;
2298 afs_size_t offset, len;
2299 register struct conn *tc;
2300 register struct dcache *tdc;
2301 register struct vcache *tvc;
2302 struct AFSFetchStatus OutDirStatus;
2303 struct VenusFid tfid;
2304 struct AFSVolSync tsync;
2308 /* "ain" is the name of the file in this dir to remove */
2310 AFS_STATCNT(PRemoveMount);
2311 if (!avc) return EINVAL;
2312 code = afs_VerifyVCache(avc, areq);
2313 if (code) return code;
2314 if (vType(avc) != VDIR) return ENOTDIR;
2316 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2317 if (!tdc) return ENOENT;
2318 Check_AtSys(avc, ain, &sysState, areq);
2319 ObtainReadLock(&tdc->lock);
2321 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2322 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2323 ReleaseReadLock(&tdc->lock);
2324 bufp = sysState.name;
2329 tfid.Cell = avc->fid.Cell;
2330 tfid.Fid.Volume = avc->fid.Fid.Volume;
2331 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2332 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2334 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2341 if (tvc->mvstat != 1) {
2347 ObtainWriteLock(&tvc->lock,230);
2348 code = afs_HandleLink(tvc, areq);
2350 if (tvc->linkData) {
2351 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2356 ReleaseWriteLock(&tvc->lock);
2357 osi_dnlc_purgedp(tvc);
2363 ObtainWriteLock(&avc->lock,231);
2364 osi_dnlc_remove(avc, bufp, tvc);
2366 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2368 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2370 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2371 bufp, &OutDirStatus, &tsync);
2377 (afs_Analyze(tc, code, &avc->fid, areq,
2378 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2379 SHARED_LOCK, NULL));
2382 if (tdc) afs_PutDCache(tdc);
2383 ReleaseWriteLock(&avc->lock);
2387 /* we have the thing in the cache */
2388 ObtainWriteLock(&tdc->lock, 661);
2389 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2390 /* we can do it locally */
2391 code = afs_dir_Delete(&tdc->f.inode, bufp);
2393 ZapDCE(tdc); /* surprise error -- invalid value */
2394 DZap(&tdc->f.inode);
2397 ReleaseWriteLock(&tdc->lock);
2398 afs_PutDCache(tdc); /* drop ref count */
2400 avc->states &= ~CUnique; /* For the dfs xlator */
2401 ReleaseWriteLock(&avc->lock);
2404 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2408 DECL_PIOCTL(PVenusLogging)
2410 return EINVAL; /* OBSOLETE */
2413 DECL_PIOCTL(PGetCellStatus)
2415 register struct cell *tcell;
2418 AFS_STATCNT(PGetCellStatus);
2419 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2420 return EIO; /* Inappropriate ioctl for device */
2422 tcell = afs_GetCellByName(ain, READ_LOCK);
2423 if (!tcell) return ENOENT;
2424 temp = tcell->states;
2425 afs_PutCell(tcell, READ_LOCK);
2426 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2427 *aoutSize = sizeof(afs_int32);
2431 DECL_PIOCTL(PSetCellStatus)
2433 register struct cell *tcell;
2436 if (!afs_osi_suser(*acred))
2438 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2439 return EIO; /* Inappropriate ioctl for device */
2441 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2442 if (!tcell) return ENOENT;
2443 memcpy((char *)&temp, ain, sizeof(afs_int32));
2445 tcell->states |= CNoSUID;
2447 tcell->states &= ~CNoSUID;
2448 afs_PutCell(tcell, WRITE_LOCK);
2452 DECL_PIOCTL(PFlushVolumeData)
2454 register afs_int32 i;
2455 register struct dcache *tdc;
2456 register struct vcache *tvc;
2457 register struct volume *tv;
2458 afs_int32 cell, volume;
2460 AFS_STATCNT(PFlushVolumeData);
2463 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2464 return EIO; /* Inappropriate ioctl for device */
2466 volume = avc->fid.Fid.Volume; /* who to zap */
2467 cell = avc->fid.Cell;
2470 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2471 * the vcaches associated with the volume.
2473 ObtainReadLock(&afs_xvcache);
2474 for(i = 0; i < VCSIZE; i++) {
2475 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2476 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2477 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2478 VN_HOLD(AFSTOV(tvc));
2480 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2486 ReleaseReadLock(&afs_xvcache);
2487 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2488 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2490 ObtainWriteLock(&tvc->lock,232);
2492 ObtainWriteLock(&afs_xcbhash, 458);
2493 afs_DequeueCallback(tvc);
2494 tvc->states &= ~(CStatd | CDirty);
2495 ReleaseWriteLock(&afs_xcbhash);
2496 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2497 osi_dnlc_purgedp(tvc);
2498 afs_TryToSmush(tvc, *acred, 1);
2499 ReleaseWriteLock(&tvc->lock);
2500 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2501 afs_BozonUnlock(&tvc->pvnLock, tvc);
2503 ObtainReadLock(&afs_xvcache);
2504 /* our tvc ptr is still good until now */
2509 ReleaseReadLock(&afs_xvcache);
2512 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2513 for(i=0;i<afs_cacheFiles;i++) {
2514 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2515 tdc = afs_GetDSlot(i, NULL);
2516 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2517 ReleaseReadLock(&tdc->tlock);
2518 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2519 if (! (afs_indexFlags[i] & IFDataMod)) {
2520 /* if the file is modified, but has a ref cnt of only 1, then
2521 someone probably has the file open and is writing into it.
2522 Better to skip flushing such a file, it will be brought back
2523 immediately on the next write anyway.
2525 If we *must* flush, then this code has to be rearranged to call
2526 afs_storeAllSegments() first */
2527 afs_FlushDCache(tdc);
2531 ReleaseReadLock(&tdc->tlock);
2533 afs_PutDCache(tdc); /* bumped by getdslot */
2535 MReleaseWriteLock(&afs_xdcache);
2537 ObtainReadLock(&afs_xvolume);
2538 for (i=0;i<NVOLS;i++) {
2539 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2540 if (tv->volume == volume) {
2541 afs_ResetVolumeInfo(tv);
2546 ReleaseReadLock(&afs_xvolume);
2548 /* probably, a user is doing this, probably, because things are screwed up.
2549 * maybe it's the dnlc's fault? */
2556 DECL_PIOCTL(PGetVnodeXStatus)
2558 register afs_int32 code;
2559 struct vcxstat stat;
2562 /* AFS_STATCNT(PGetVnodeXStatus); */
2563 if (!avc) return EINVAL;
2564 code = afs_VerifyVCache(avc, areq);
2565 if (code) return code;
2566 if (vType(avc) == VDIR)
2567 mode = PRSFS_LOOKUP;
2570 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2572 stat.fid = avc->fid;
2573 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2574 stat.lock = avc->lock;
2575 stat.parentVnode = avc->parentVnode;
2576 stat.parentUnique = avc->parentUnique;
2577 hset(stat.flushDV, avc->flushDV);
2578 hset(stat.mapDV, avc->mapDV);
2579 stat.truncPos = avc->truncPos;
2580 { /* just grab the first two - won't break anything... */
2581 struct axscache *ac;
2583 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2584 stat.randomUid[i] = ac->uid;
2585 stat.randomAccess[i] = ac->axess;
2588 stat.callback = afs_data_pointer_to_int32(avc->callback);
2589 stat.cbExpires = avc->cbExpires;
2590 stat.anyAccess = avc->anyAccess;
2591 stat.opens = avc->opens;
2592 stat.execsOrWriters = avc->execsOrWriters;
2593 stat.flockCount = avc->flockCount;
2594 stat.mvstat = avc->mvstat;
2595 stat.states = avc->states;
2596 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2597 *aoutSize = sizeof(struct vcxstat);
2602 /* We require root for local sysname changes, but not for remote */
2603 /* (since we don't really believe remote uids anyway) */
2604 /* outname[] shouldn't really be needed- this is left as an excercise */
2605 /* for the reader. */
2606 DECL_PIOCTL(PSetSysName)
2608 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2609 int setsysname, foundname=0;
2610 register struct afs_exporter *exporter;
2611 register struct unixuser *au;
2612 register afs_int32 pag, error;
2616 AFS_STATCNT(PSetSysName);
2617 if (!afs_globalVFS) {
2618 /* Afsd is NOT running; disable it */
2619 #if defined(AFS_SUN5_ENV) || defined(AFS_OSF_ENV) || defined(AFS_SGI64_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2622 return (setuerror(EINVAL), EINVAL);
2625 memset(inname, 0, MAXSYSNAME);
2626 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2627 ain += sizeof(afs_int32);
2631 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2633 for(cp = ain,count = 0;count < setsysname;count++) {
2634 /* won't go past end of ain since maxsysname*num < ain length */
2636 if (t >= MAXSYSNAME || t <= 0)
2638 /* check for names that can shoot us in the foot */
2639 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2645 /* inname gets first entry in case we're being a translater */
2647 memcpy(inname, ain, t+1); /* include terminating null */
2650 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2651 pag = PagInCred(*acred);
2653 return EINVAL; /* Better than panicing */
2655 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2656 return EINVAL; /* Better than panicing */
2658 if (!(exporter = au->exporter)) {
2659 afs_PutUser(au, READ_LOCK);
2660 return EINVAL; /* Better than panicing */
2662 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2664 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2666 afs_PutUser(au, READ_LOCK);
2671 afs_PutUser(au, READ_LOCK);
2674 /* Not xlating, so local case */
2675 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2676 if (!setsysname) { /* user just wants the info */
2677 strcpy(outname, afs_sysname);
2678 foundname = afs_sysnamecount;
2679 } else { /* Local guy; only root can change sysname */
2680 if (!afs_osi_suser(*acred))
2683 /* clear @sys entries from the dnlc, once afs_lookup can
2684 do lookups of @sys entries and thinks it can trust them */
2685 /* privs ok, store the entry, ... */
2686 strcpy(afs_sysname, inname);
2687 if (setsysname > 1) { /* ... or list */
2689 for(count=1; count < setsysname;++count) {
2690 if (!afs_sysnamelist[count])
2691 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2693 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2697 afs_sysnamecount = setsysname;
2701 cp = aout; /* not changing so report back the count and ... */
2702 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2703 cp += sizeof(afs_int32);
2705 strcpy(cp, outname); /* ... the entry, ... */
2706 cp += strlen(outname)+1;
2707 for(count=1; count < foundname; ++count) { /* ... or list. */
2708 /* Note: we don't support @sys lists for exporters */
2709 if (!afs_sysnamelist[count])
2710 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2711 t = strlen(afs_sysnamelist[count]);
2712 if (t >= MAXSYSNAME)
2713 osi_Panic("PSetSysName: sysname entry garbled\n");
2714 strcpy(cp, afs_sysnamelist[count]);
2718 *aoutSize = cp - aout;
2723 /* sequential search through the list of touched cells is not a good
2724 * long-term solution here. For small n, though, it should be just
2725 * fine. Should consider special-casing the local cell for large n.
2726 * Likewise for PSetSPrefs.
2728 * s - number of ids in array l[] -- NOT index of last id
2729 * l - array of cell ids which have volumes that need to be sorted
2730 * vlonly - sort vl servers or file servers?
2732 static void ReSortCells(int s, afs_int32 l[], int vlonly)
2740 ObtainWriteLock(&afs_xcell,300);
2742 tcell = afs_GetCellNoLock(l[k], WRITE_LOCK);
2743 if (!tcell) continue;
2744 afs_SortServers(tcell->cellHosts, MAXCELLHOSTS);
2745 afs_PutCell(tcell, WRITE_LOCK);
2747 ReleaseWriteLock(&afs_xcell);
2751 ObtainReadLock(&afs_xvolume);
2752 for (i= 0; i< NVOLS; i++) {
2753 for (j=afs_volumes[i];j;j=j->next) {
2755 if (j->cell == l[k]) {
2756 ObtainWriteLock(&j->lock,233);
2757 afs_SortServers(j->serverHost, MAXHOSTS);
2758 ReleaseWriteLock(&j->lock);
2763 ReleaseReadLock(&afs_xvolume);
2767 static int debugsetsp = 0;
2768 static int afs_setsprefs(sp, num, vlonly)
2771 unsigned int vlonly;
2774 int i,j,k,matches,touchedSize;
2775 struct server *srvr = NULL;
2776 afs_int32 touched[34];
2780 for (k=0; k < num; sp++, k++) {
2782 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2785 ObtainReadLock(&afs_xserver);
2787 i = SHash(sp->host.s_addr);
2788 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2789 if (sa->sa_ip == sp->host.s_addr) {
2791 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2792 || (sa->sa_portal == AFS_FSPORT);
2793 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2800 if (sa && matches) { /* found one! */
2802 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2804 sa->sa_iprank = sp->rank + afs_randomMod15();
2805 afs_SortOneServer(sa->server);
2808 /* if we don't know yet what cell it's in, this is moot */
2809 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cell; j--)
2810 /* is it in our list of touched cells ? */ ;
2811 if (j < 0) { /* no, it's not */
2812 touched[touchedSize++] = srvr->cell->cell;
2813 if (touchedSize >= 32) { /* watch for ovrflow */
2814 ReleaseReadLock(&afs_xserver);
2815 ReSortCells(touchedSize, touched, vlonly);
2817 ObtainReadLock(&afs_xserver);
2823 ReleaseReadLock(&afs_xserver);
2824 /* if we didn't find one, start to create one. */
2825 /* Note that it doesn't have a cell yet... */
2827 afs_uint32 temp = sp->host.s_addr;
2828 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2829 WRITE_LOCK, (afsUUID *)0,0);
2830 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2831 afs_PutServer(srvr, WRITE_LOCK);
2833 } /* for all cited preferences */
2835 ReSortCells(touchedSize, touched, vlonly);
2839 /* Note that this may only be performed by the local root user.
2841 DECL_PIOCTL(PSetSPrefs)
2843 struct setspref *ssp;
2844 AFS_STATCNT(PSetSPrefs);
2846 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2847 return EIO; /* Inappropriate ioctl for device */
2849 if (!afs_osi_suser(*acred))
2852 if (ainSize < sizeof(struct setspref))
2855 ssp = (struct setspref *)ain;
2856 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2859 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2860 (ssp->flags & DBservers));
2864 DECL_PIOCTL(PSetSPrefs33)
2867 AFS_STATCNT(PSetSPrefs);
2868 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2869 return EIO; /* Inappropriate ioctl for device */
2872 if (!afs_osi_suser(*acred))
2875 sp = (struct spref *)ain;
2876 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2880 /* some notes on the following code...
2881 * in the hash table of server structs, all servers with the same IP address
2882 * will be on the same overflow chain.
2883 * This could be sped slightly in some circumstances by having it cache the
2884 * immediately previous slot in the hash table and some supporting information
2885 * Only reports file servers now.
2887 DECL_PIOCTL(PGetSPrefs)
2889 struct sprefrequest *spin; /* input */
2890 struct sprefinfo *spout; /* output */
2891 struct spref *srvout; /* one output component */
2892 int i,j; /* counters for hash table traversal */
2893 struct server *srvr; /* one of CM's server structs */
2896 int vlonly; /* just return vlservers ? */
2899 AFS_STATCNT(PGetSPrefs);
2900 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2901 return EIO; /* Inappropriate ioctl for device */
2904 if (ainSize < sizeof (struct sprefrequest_33)) {
2908 spin = ((struct sprefrequest *) ain);
2911 if (ainSize > sizeof (struct sprefrequest_33)) {
2912 vlonly = (spin->flags & DBservers);
2916 /* struct sprefinfo includes 1 server struct... that size gets added
2917 * in during the loop that follows.
2919 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2920 spout = (struct sprefinfo *) aout;
2921 spout->next_offset = spin->offset;
2922 spout->num_servers = 0;
2923 srvout = spout->servers;
2925 ObtainReadLock(&afs_xserver);
2926 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2927 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2928 if (spin->offset > (unsigned short)i) {
2929 continue; /* catch up to where we left off */
2931 spout->next_offset++;
2934 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2935 || (sa->sa_portal == AFS_FSPORT);
2937 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2938 /* only report ranks for vl servers */
2942 srvout->host.s_addr = sa->sa_ip;
2943 srvout->rank = sa->sa_iprank;
2944 *aoutSize += sizeof(struct spref);
2945 spout->num_servers++;
2948 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2949 ReleaseReadLock(&afs_xserver); /* no more room! */
2954 ReleaseReadLock(&afs_xserver);
2956 spout->next_offset = 0; /* start over from the beginning next time */
2960 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2961 int afs_NFSRootOnly = 1;
2962 DECL_PIOCTL(PExportAfs)
2964 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2965 register struct afs_exporter *exporter;
2967 AFS_STATCNT(PExportAfs);
2968 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2969 type = handleValue >> 24;
2974 exporter = exporter_find(type);
2976 export = handleValue & 3;
2977 changestate = handleValue & 0xff;
2978 smounts = (handleValue >> 2) & 3;
2979 pwsync = (handleValue >> 4) & 3;
2980 convmode = (handleValue >> 6) & 3;
2982 changestate = (handleValue >> 16) & 0x1;
2983 convmode = (handleValue >> 16) & 0x2;
2984 pwsync = (handleValue >> 16) & 0x4;
2985 smounts = (handleValue >> 16) & 0x8;
2986 export = handleValue & 0xff;
2989 /* Failed finding desired exporter; */
2993 handleValue = exporter->exp_states;
2994 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2995 *aoutSize = sizeof(afs_int32);
2997 if (!afs_osi_suser(*acred))
2998 return EACCES; /* Only superuser can do this */
3002 exporter->exp_states |= EXP_EXPORTED;
3004 exporter->exp_states &= ~EXP_EXPORTED;
3008 exporter->exp_states |= EXP_UNIXMODE;
3010 exporter->exp_states &= ~EXP_UNIXMODE;
3014 exporter->exp_states |= EXP_PWSYNC;
3016 exporter->exp_states &= ~EXP_PWSYNC;
3020 afs_NFSRootOnly = 0;
3021 exporter->exp_states |= EXP_SUBMOUNTS;
3023 afs_NFSRootOnly = 1;
3024 exporter->exp_states &= ~EXP_SUBMOUNTS;
3027 handleValue = exporter->exp_states;
3028 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
3029 *aoutSize = sizeof(afs_int32);
3032 exporter->exp_states |= EXP_EXPORTED;
3034 exporter->exp_states &= ~EXP_EXPORTED;
3036 exporter->exp_states |= EXP_UNIXMODE;
3038 exporter->exp_states &= ~EXP_UNIXMODE;
3040 exporter->exp_states |= EXP_PWSYNC;
3042 exporter->exp_states &= ~EXP_PWSYNC;
3044 afs_NFSRootOnly = 0;
3045 exporter->exp_states |= EXP_SUBMOUNTS;
3047 afs_NFSRootOnly = 1;
3048 exporter->exp_states &= ~EXP_SUBMOUNTS;
3058 struct gaginfo *gagflags;
3060 if (!afs_osi_suser(*acred))
3063 gagflags = (struct gaginfo *) ain;
3064 afs_showflags = gagflags->showflags;
3070 DECL_PIOCTL(PTwiddleRx)
3072 struct rxparams *rxp;
3074 if (!afs_osi_suser(*acred))
3077 rxp = (struct rxparams *) ain;
3079 if (rxp->rx_initReceiveWindow)
3080 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3081 if (rxp->rx_maxReceiveWindow)
3082 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3083 if (rxp->rx_initSendWindow)
3084 rx_initSendWindow = rxp->rx_initSendWindow;
3085 if (rxp->rx_maxSendWindow)
3086 rx_maxSendWindow = rxp->rx_maxSendWindow;
3087 if (rxp->rxi_nSendFrags)
3088 rxi_nSendFrags = rxp->rxi_nSendFrags;
3089 if (rxp->rxi_nRecvFrags)
3090 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3091 if (rxp->rxi_OrphanFragSize)
3092 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3093 if (rxp->rx_maxReceiveSize)
3095 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3096 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3098 if (rxp->rx_MyMaxSendSize)
3099 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3104 DECL_PIOCTL(PGetInitParams)
3106 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3109 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3110 *aoutSize = sizeof(struct cm_initparams);
3114 #ifdef AFS_SGI65_ENV
3115 /* They took crget() from us, so fake it. */
3116 static cred_t *crget(void)
3119 cr = crdup(get_current_cred());
3120 memset((char*)cr, 0, sizeof(cred_t));
3121 #if CELL || CELL_PREPARE
3128 DECL_PIOCTL(PGetRxkcrypt)
3130 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3131 *aoutSize=sizeof(afs_int32);
3135 DECL_PIOCTL(PSetRxkcrypt)
3139 if (!afs_osi_suser(*acred))
3141 if (ainSize != sizeof(afs_int32) || ain == NULL)
3143 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3144 /* if new mappings added later this will need to be changed */
3145 if (tmpval != 0 && tmpval != 1)
3152 * Create new credentials to correspond to a remote user with given
3153 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3154 * provide pioctl (and other) services to foreign clients (i.e. nfs
3155 * clients) by using this call to `become' the client.
3158 #define PIOCTL_HEADER 6
3159 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3161 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3162 return EINVAL; /* NFS trans not supported for Ultrix */
3165 afs_uint32 hostaddr;
3166 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3167 struct afs_exporter *exporter, *outexporter;
3168 struct AFS_UCRED *newcred;
3169 struct unixuser *au;
3171 #if defined(AFS_SGIMP_ENV)
3172 osi_Assert(ISAFS_GLOCK());
3174 AFS_STATCNT(HandleClientContext);
3175 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3176 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3177 return EINVAL; /* Too small to be good */
3179 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3180 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3182 osi_FreeLargeSpace(inData);
3186 /* Extract information for remote user */
3187 hostaddr = *((afs_uint32 *)ain);
3188 ain += sizeof(hostaddr);
3189 uid = *((afs_uint32 *)ain);
3191 g0 = *((afs_uint32 *)ain);
3193 g1 = *((afs_uint32 *)ain);
3195 *com = *((afs_uint32 *)ain);
3196 ain += sizeof(afs_int32);
3197 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3200 * Of course, one must be root for most of these functions, but
3201 * we'll allow (for knfs) you to set things if the pag is 0 and
3202 * you're setting tokens or unlogging.
3205 if (!afs_osi_suser(credp)) {
3207 #ifndef AFS_SGI64_ENV
3208 /* Since SGI's suser() returns explicit failure after the call.. */
3212 /* check for acceptable opcodes for normal folks, which are, so far,
3213 * set tokens and unlog.
3215 if (i != 9 && i != 3 && i != 38 && i != 8) {
3216 osi_FreeLargeSpace(inData);
3221 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3222 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3223 osi_FreeLargeSpace(inData);
3226 * We map uid 0 to nobody to match the mapping that the nfs
3227 * server does and to ensure that the suser() calls in the afs
3228 * code fails for remote client roots.
3230 uid = afs_nobody; /* NFS_NOBODY == -2 */
3233 #ifdef AFS_AIX41_ENV
3236 newcred->cr_gid = RMTUSER_REQ;
3237 newcred->cr_groups[0] = g0;
3238 newcred->cr_groups[1] = g1;
3240 newcred->cr_ngrps = 2;
3242 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3243 newcred->cr_ngroups = 2;
3245 for (i=2; i<NGROUPS; i++)
3246 newcred->cr_groups[i] = NOGROUP;
3249 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3250 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3252 if (!(exporter = exporter_find(exporter_type))) {
3253 /* Exporter wasn't initialized or an invalid exporter type */
3257 if (exporter->exp_states & EXP_PWSYNC) {
3258 if (uid != credp->cr_uid) {
3260 return ENOEXEC; /* XXX Find a better errno XXX */
3263 newcred->cr_uid = uid; /* Only temporary */
3264 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3265 /* The client's pag is the only unique identifier for it */
3266 newcred->cr_uid = pag;
3268 if (!code && *com == PSETPAG) {
3269 /* Special case for 'setpag' */
3270 afs_uint32 pagvalue = genpag();
3272 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3274 * Note that we leave the 'outexporter' struct held so it won't
3277 au->exporter = outexporter;
3278 if (ablob->out_size >= 4) {
3279 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3281 afs_PutUser(au, WRITE_LOCK);
3282 if (code) return code;
3283 return PSETPAG; /* Special return for setpag */
3285 EXP_RELE(outexporter);
3288 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3291 /* get all interface addresses of this client */
3293 DECL_PIOCTL(PGetCPrefs)
3295 struct sprefrequest *spin; /* input */
3296 struct sprefinfo *spout; /* output */
3297 struct spref *srvout; /* one output component */
3301 AFS_STATCNT(PGetCPrefs);
3302 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3303 return EIO; /* Inappropriate ioctl for device */
3305 if ( ainSize < sizeof (struct sprefrequest ))
3308 spin = (struct sprefrequest *) ain;
3309 spout = (struct sprefinfo *) aout;
3311 maxNumber = spin->num_servers; /* max addrs this time */
3312 srvout = spout->servers;
3314 ObtainReadLock(&afs_xinterface);
3316 /* copy out the client interface information from the
3317 ** kernel data structure "interface" to the output buffer
3319 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3320 && ( j< maxNumber) ; i++, j++, srvout++)
3321 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3323 spout->num_servers = j;
3324 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3326 if ( i >= afs_cb_interface.numberOfInterfaces )
3327 spout->next_offset = 0; /* start from beginning again */
3329 spout->next_offset = spin->offset + j;
3331 ReleaseReadLock(&afs_xinterface);
3335 DECL_PIOCTL(PSetCPrefs)
3337 struct setspref *sin;
3340 AFS_STATCNT(PSetCPrefs);
3341 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3342 return EIO; /* Inappropriate ioctl for device */
3344 sin = (struct setspref *)ain;
3346 if ( ainSize < sizeof(struct setspref) )
3348 #if 0 /* num_servers is unsigned */
3349 if ( sin->num_servers < 0 )
3352 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3355 ObtainWriteLock(&afs_xinterface, 412);
3356 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3357 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3358 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3360 ReleaseWriteLock(&afs_xinterface);
3364 DECL_PIOCTL(PFlushMount)
3366 register afs_int32 code;
3367 register struct vcache *tvc;
3368 register struct dcache *tdc;
3369 struct VenusFid tfid;
3371 struct sysname_info sysState;
3372 afs_size_t offset, len;
3374 AFS_STATCNT(PFlushMount);
3375 if (!avc) return EINVAL;
3376 code = afs_VerifyVCache(avc, areq);
3377 if (code) return code;
3378 if (vType(avc) != VDIR) {
3381 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3382 if (!tdc) return ENOENT;
3383 Check_AtSys(avc, ain, &sysState, areq);
3384 ObtainReadLock(&tdc->lock);
3386 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3387 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3388 ReleaseReadLock(&tdc->lock);
3389 afs_PutDCache(tdc); /* we're done with the data */
3390 bufp = sysState.name;
3394 tfid.Cell = avc->fid.Cell;
3395 tfid.Fid.Volume = avc->fid.Fid.Volume;
3396 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3397 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3399 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3405 if (tvc->mvstat != 1) {
3410 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3411 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3413 ObtainWriteLock(&tvc->lock,649);
3414 ObtainWriteLock(&afs_xcbhash, 650);
3415 afs_DequeueCallback(tvc);
3416 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3417 ReleaseWriteLock(&afs_xcbhash);
3418 /* now find the disk cache entries */
3419 afs_TryToSmush(tvc, *acred, 1);
3420 osi_dnlc_purgedp(tvc);
3421 afs_symhint_inval(tvc);
3422 if (tvc->linkData && !(tvc->states & CCore)) {
3423 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3424 tvc->linkData = NULL;
3426 ReleaseWriteLock(&tvc->lock);
3427 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3428 afs_BozonUnlock(&tvc->pvnLock, tvc);
3432 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3436 DECL_PIOCTL(PRxStatProc)
3441 if (!afs_osi_suser(*acred)) {
3445 if (ainSize != sizeof(afs_int32)) {
3449 memcpy((char *)&flags, ain, sizeof(afs_int32));
3450 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3454 if (flags & AFSCALL_RXSTATS_ENABLE) {
3455 rx_enableProcessRPCStats();
3457 if (flags & AFSCALL_RXSTATS_DISABLE) {
3458 rx_disableProcessRPCStats();
3460 if (flags & AFSCALL_RXSTATS_CLEAR) {
3461 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3469 DECL_PIOCTL(PRxStatPeer)
3474 if (!afs_osi_suser(*acred)) {
3478 if (ainSize != sizeof(afs_int32)) {
3482 memcpy((char *)&flags, ain, sizeof(afs_int32));
3483 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3487 if (flags & AFSCALL_RXSTATS_ENABLE) {
3488 rx_enablePeerRPCStats();
3490 if (flags & AFSCALL_RXSTATS_DISABLE) {
3491 rx_disablePeerRPCStats();
3493 if (flags & AFSCALL_RXSTATS_CLEAR) {
3494 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3501 DECL_PIOCTL(PPrefetchFromTape)
3503 register afs_int32 code, code1;
3506 struct rx_call *tcall;
3507 struct AFSVolSync tsync;
3508 struct AFSFetchStatus OutStatus;
3509 struct AFSCallBack CallBack;
3510 struct VenusFid tfid;
3515 AFS_STATCNT(PSetAcl);
3519 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3520 Fid = (struct AFSFid *) ain;
3522 Fid = &avc->fid.Fid;
3523 tfid.Cell = avc->fid.Cell;
3524 tfid.Fid.Volume = Fid->Volume;
3525 tfid.Fid.Vnode = Fid->Vnode;
3526 tfid.Fid.Unique = Fid->Unique;
3528 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3530 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3531 ICL_TYPE_POINTER, tvc,
3532 ICL_TYPE_FID, &tfid,
3533 ICL_TYPE_FID, &avc->fid);
3536 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3537 ICL_TYPE_POINTER, tvc,
3538 ICL_TYPE_FID, &tfid,
3539 ICL_TYPE_FID, &tvc->fid);
3542 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3546 tcall = rx_NewCall(tc->id);
3547 code = StartRXAFS_FetchData(tcall,
3548 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3550 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3551 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3553 code1 = rx_EndCall(tcall, code);
3558 (afs_Analyze(tc, code, &tvc->fid, areq,
3559 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3561 /* This call is done only to have the callback things handled correctly */
3562 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3566 *aoutSize = sizeof(afs_int32);
3571 DECL_PIOCTL(PResidencyCmd)
3573 register afs_int32 code;
3576 struct ResidencyCmdInputs *Inputs;
3577 struct ResidencyCmdOutputs *Outputs;
3578 struct VenusFid tfid;
3581 Inputs = (struct ResidencyCmdInputs *) ain;
3582 Outputs = (struct ResidencyCmdOutputs *) aout;
3583 if (!avc) return EINVAL;
3584 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3588 Fid = &avc->fid.Fid;
3590 tfid.Cell = avc->fid.Cell;
3591 tfid.Fid.Volume = Fid->Volume;
3592 tfid.Fid.Vnode = Fid->Vnode;
3593 tfid.Fid.Unique = Fid->Unique;
3595 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3596 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3597 ICL_TYPE_POINTER, tvc,
3598 ICL_TYPE_INT32, Inputs->command,
3599 ICL_TYPE_FID, &tfid);
3603 if (Inputs->command) {
3605 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3608 code = RXAFS_ResidencyCmd(tc->id, Fid,
3610 (struct ResidencyCmdOutputs *) aout);
3615 (afs_Analyze(tc, code, &tvc->fid, areq,
3616 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3618 /* This call is done to have the callback things handled correctly */
3619 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3620 } else { /* just a status request, return also link data */
3622 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3623 Outputs->chars[0] = 0;
3624 if (vType(tvc) == VLNK) {
3625 ObtainWriteLock(&tvc->lock,555);
3626 if (afs_HandleLink(tvc, areq) == 0)
3627 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3628 ReleaseWriteLock(&tvc->lock);
3635 *aoutSize = sizeof(struct ResidencyCmdOutputs);