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 struct cell *tcell = NULL;
1295 AFS_STATCNT(PGetWSCell);
1296 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1297 return EIO; /* Inappropriate ioctl for device */
1299 tcell = afs_GetPrimaryCell(READ_LOCK);
1300 if (!tcell) /* no primary cell? */
1302 strcpy(aout, tcell->cellName);
1303 *aoutSize = strlen(aout) + 1;
1304 afs_PutCell(tcell, READ_LOCK);
1308 DECL_PIOCTL(PGetUserCell)
1310 register afs_int32 i;
1311 register struct unixuser *tu;
1312 register struct cell *tcell;
1314 AFS_STATCNT(PGetUserCell);
1315 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1316 return EIO; /* Inappropriate ioctl for device */
1318 /* return the cell name of the primary cell for this user */
1319 i = UHash(areq->uid);
1320 ObtainWriteLock(&afs_xuser,224);
1321 for(tu = afs_users[i]; tu; tu = tu->next) {
1322 if (tu->uid == areq->uid && (tu->states & UPrimary)) {
1324 ReleaseWriteLock(&afs_xuser);
1329 tcell = afs_GetCell(tu->cell, READ_LOCK);
1330 afs_PutUser(tu, WRITE_LOCK);
1331 if (!tcell) return ESRCH;
1333 strcpy(aout, tcell->cellName);
1334 afs_PutCell(tcell, READ_LOCK);
1335 *aoutSize = strlen(aout)+1; /* 1 for the null */
1339 ReleaseWriteLock(&afs_xuser);
1346 DECL_PIOCTL(PSetTokens)
1349 register struct unixuser *tu;
1350 struct ClearToken clear;
1351 register struct cell *tcell;
1354 struct vrequest treq;
1355 afs_int32 flag, set_parent_pag = 0;
1357 AFS_STATCNT(PSetTokens);
1358 if (!afs_resourceinit_flag) {
1361 memcpy((char *)&i, ain, sizeof(afs_int32));
1362 ain += sizeof(afs_int32);
1363 stp = ain; /* remember where the ticket is */
1364 if (i < 0 || i > 2000) return EINVAL; /* malloc may fail */
1366 ain += i; /* skip over ticket */
1367 memcpy((char *)&i, ain, sizeof(afs_int32));
1368 ain += sizeof(afs_int32);
1369 if (i != sizeof(struct ClearToken)) {
1372 memcpy((char *)&clear, ain, sizeof(struct ClearToken));
1373 if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */
1374 ain += sizeof(struct ClearToken);
1375 if (ainSize != 2*sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) {
1376 /* still stuff left? we've got primary flag and cell name. Set these */
1377 memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */
1378 ain += sizeof(afs_int32); /* skip id field */
1379 /* rest is cell name, look it up */
1380 /* some versions of gcc appear to need != 0 in order to get this right */
1381 if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */
1385 tcell = afs_GetCellByName(ain, READ_LOCK);
1386 if (!tcell) goto nocell;
1389 /* default to primary cell, primary id */
1390 flag = 1; /* primary id */
1391 tcell = afs_GetPrimaryCell(READ_LOCK);
1392 if (!tcell) goto nocell;
1395 afs_PutCell(tcell, READ_LOCK);
1396 if (set_parent_pag) {
1398 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1399 #if defined(AFS_DARWIN_ENV)
1400 struct proc *p=current_proc(); /* XXX */
1402 struct proc *p=curproc; /* XXX */
1404 uprintf("Process %d (%s) tried to change pags in PSetTokens\n",
1405 p->p_pid, p->p_comm);
1406 if (!setpag(p, acred, -1, &pag, 1)) {
1409 if (!setpag(u.u_procp, acred, -1, &pag, 1)) { /* XXX u.u_procp is a no-op XXX */
1411 if (!setpag(acred, -1, &pag, 1)) {
1414 afs_InitReq(&treq, *acred);
1418 /* now we just set the tokens */
1419 tu = afs_GetUser(areq->uid, i, WRITE_LOCK); /* i has the cell # */
1420 tu->vid = clear.ViceId;
1421 if (tu->stp != NULL) {
1422 afs_osi_Free(tu->stp, tu->stLen);
1424 tu->stp = (char *) afs_osi_Alloc(stLen);
1426 memcpy(tu->stp, stp, stLen);
1429 afs_stats_cmfullperf.authent.TicketUpdates++;
1430 afs_ComputePAGStats();
1431 #endif /* AFS_NOSTATS */
1432 tu->states |= UHasTokens;
1433 tu->states &= ~UTokensBad;
1434 afs_SetPrimary(tu, flag);
1435 tu->tokenTime =osi_Time();
1436 afs_ResetUserConns(tu);
1437 afs_PutUser(tu, WRITE_LOCK);
1452 DECL_PIOCTL(PGetVolumeStatus)
1455 char offLineMsg[256];
1457 register struct conn *tc;
1458 register afs_int32 code;
1459 struct VolumeStatus volstat;
1461 char *Name, *OfflineMsg, *MOTD;
1464 AFS_STATCNT(PGetVolumeStatus);
1465 if (!avc) return EINVAL;
1467 OfflineMsg = offLineMsg;
1470 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1472 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS);
1474 code = RXAFS_GetVolumeStatus(tc->id, avc->fid.Fid.Volume, &volstat,
1475 &Name, &OfflineMsg, &MOTD);
1481 (afs_Analyze(tc, code, &avc->fid, areq,
1482 AFS_STATS_FS_RPCIDX_GETVOLUMESTATUS,
1483 SHARED_LOCK, NULL));
1485 if (code) return code;
1486 /* Copy all this junk into msg->im_data, keeping track of the lengths. */
1488 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1489 cp += sizeof(VolumeStatus);
1490 strcpy(cp, volName);
1491 cp += strlen(volName)+1;
1492 strcpy(cp, offLineMsg);
1493 cp += strlen(offLineMsg)+1;
1495 cp += strlen(motd)+1;
1496 *aoutSize = (cp - aout);
1500 DECL_PIOCTL(PSetVolumeStatus)
1503 char offLineMsg[256];
1505 register struct conn *tc;
1506 register afs_int32 code;
1507 struct AFSFetchVolumeStatus volstat;
1508 struct AFSStoreVolumeStatus storeStat;
1509 register struct volume *tvp;
1513 AFS_STATCNT(PSetVolumeStatus);
1514 if (!avc) return EINVAL;
1516 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1518 if (tvp->states & (VRO | VBackup)) {
1519 afs_PutVolume(tvp, READ_LOCK);
1522 afs_PutVolume(tvp, READ_LOCK);
1525 /* Copy the junk out, using cp as a roving pointer. */
1527 memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
1528 cp += sizeof(AFSFetchVolumeStatus);
1529 if (strlen(cp) >= sizeof(volName))
1531 strcpy(volName, cp);
1532 cp += strlen(volName)+1;
1533 if (strlen(cp) >= sizeof(offLineMsg))
1535 strcpy(offLineMsg, cp);
1536 cp += strlen(offLineMsg)+1;
1537 if (strlen(cp) >= sizeof(motd))
1541 if (volstat.MinQuota != -1) {
1542 storeStat.MinQuota = volstat.MinQuota;
1543 storeStat.Mask |= AFS_SETMINQUOTA;
1545 if (volstat.MaxQuota != -1) {
1546 storeStat.MaxQuota = volstat.MaxQuota;
1547 storeStat.Mask |= AFS_SETMAXQUOTA;
1550 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
1552 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS);
1554 code = RXAFS_SetVolumeStatus(tc->id, avc->fid.Fid.Volume,
1555 &storeStat, volName, offLineMsg, motd);
1561 (afs_Analyze(tc, code, &avc->fid, areq,
1562 AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS,
1563 SHARED_LOCK, NULL));
1565 if (code) return code;
1566 /* we are sending parms back to make compat. with prev system. should
1567 change interface later to not ask for current status, just set new status */
1569 memcpy(cp, (char *)&volstat, sizeof(VolumeStatus));
1570 cp += sizeof(VolumeStatus);
1571 strcpy(cp, volName);
1572 cp += strlen(volName)+1;
1573 strcpy(cp, offLineMsg);
1574 cp += strlen(offLineMsg)+1;
1576 cp += strlen(motd)+1;
1577 *aoutSize = cp - aout;
1583 AFS_STATCNT(PFlush);
1584 if (!avc) return EINVAL;
1585 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1586 afs_BozonLock(&avc->pvnLock, avc); /* Since afs_TryToSmush will do a pvn_vptrunc */
1588 ObtainWriteLock(&avc->lock,225);
1589 ObtainWriteLock(&afs_xcbhash, 456);
1590 afs_DequeueCallback(avc);
1591 avc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
1592 ReleaseWriteLock(&afs_xcbhash);
1593 /* now find the disk cache entries */
1594 afs_TryToSmush(avc, *acred, 1);
1595 osi_dnlc_purgedp(avc);
1596 afs_symhint_inval(avc);
1597 if (avc->linkData && !(avc->states & CCore)) {
1598 afs_osi_Free(avc->linkData, strlen(avc->linkData)+1);
1599 avc->linkData = NULL;
1601 ReleaseWriteLock(&avc->lock);
1602 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
1603 afs_BozonUnlock(&avc->pvnLock, avc);
1608 DECL_PIOCTL(PNewStatMount)
1610 register afs_int32 code;
1611 register struct vcache *tvc;
1612 register struct dcache *tdc;
1613 struct VenusFid tfid;
1615 struct sysname_info sysState;
1616 afs_size_t offset, len;
1618 AFS_STATCNT(PNewStatMount);
1619 if (!avc) return EINVAL;
1620 code = afs_VerifyVCache(avc, areq);
1621 if (code) return code;
1622 if (vType(avc) != VDIR) {
1625 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
1626 if (!tdc) return ENOENT;
1627 Check_AtSys(avc, ain, &sysState, areq);
1628 ObtainReadLock(&tdc->lock);
1630 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
1631 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
1632 ReleaseReadLock(&tdc->lock);
1633 afs_PutDCache(tdc); /* we're done with the data */
1634 bufp = sysState.name;
1638 tfid.Cell = avc->fid.Cell;
1639 tfid.Fid.Volume = avc->fid.Fid.Volume;
1640 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
1641 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
1643 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
1649 if (tvc->mvstat != 1) {
1654 ObtainWriteLock(&tvc->lock,226);
1655 code = afs_HandleLink(tvc, areq);
1657 if (tvc->linkData) {
1658 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
1661 /* we have the data */
1662 strcpy(aout, tvc->linkData);
1663 *aoutSize = strlen(tvc->linkData)+1;
1668 ReleaseWriteLock(&tvc->lock);
1671 if (sysState.allocked) osi_FreeLargeSpace(bufp);
1675 DECL_PIOCTL(PGetTokens)
1677 register struct cell *tcell;
1678 register afs_int32 i;
1679 register struct unixuser *tu;
1684 AFS_STATCNT(PGetTokens);
1685 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1686 return EIO; /* Inappropriate ioctl for device */
1688 /* weird interface. If input parameter is present, it is an integer and
1689 we're supposed to return the parm'th tokens for this unix uid.
1690 If not present, we just return tokens for cell 1.
1691 If counter out of bounds, return EDOM.
1692 If no tokens for the particular cell, return ENOTCONN.
1693 Also, if this mysterious parm is present, we return, along with the
1694 tokens, the primary cell indicator (an afs_int32 0) and the cell name
1695 at the end, in that order.
1697 if ((newStyle = (ainSize > 0))) {
1698 memcpy((char *)&iterator, ain, sizeof(afs_int32));
1700 i = UHash(areq->uid);
1701 ObtainReadLock(&afs_xuser);
1702 for(tu = afs_users[i]; tu; tu=tu->next) {
1704 if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
1705 if (iterator-- == 0) break; /* are we done yet? */
1709 if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell)) break;
1714 * No need to hold a read lock on each user entry
1718 ReleaseReadLock(&afs_xuser);
1723 if (((tu->states & UHasTokens) == 0) || (tu->ct.EndTimestamp < osi_Time())) {
1724 tu->states |= (UTokensBad | UNeedsReset);
1725 afs_PutUser(tu, READ_LOCK);
1728 /* use iterator for temp */
1730 iterator = tu->stLen; /* for compat, we try to return 56 byte tix if they fit */
1731 if (iterator < 56) iterator = 56; /* # of bytes we're returning */
1732 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1733 cp += sizeof(afs_int32);
1734 memcpy(cp, tu->stp, tu->stLen); /* copy out st */
1736 iterator = sizeof(struct ClearToken);
1737 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1738 cp += sizeof(afs_int32);
1739 memcpy(cp, (char *)&tu->ct, sizeof(struct ClearToken));
1740 cp += sizeof(struct ClearToken);
1742 /* put out primary id and cell name, too */
1743 iterator = (tu->states & UPrimary ? 1 : 0);
1744 memcpy(cp, (char *)&iterator, sizeof(afs_int32));
1745 cp += sizeof(afs_int32);
1746 tcell = afs_GetCell(tu->cell, READ_LOCK);
1748 strcpy(cp, tcell->cellName);
1749 cp += strlen(tcell->cellName)+1;
1750 afs_PutCell(tcell, READ_LOCK);
1754 *aoutSize = cp - aout;
1755 afs_PutUser(tu, READ_LOCK);
1761 register afs_int32 i;
1762 register struct unixuser *tu;
1764 AFS_STATCNT(PUnlog);
1765 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1766 return EIO; /* Inappropriate ioctl for device */
1768 i = UHash(areq->uid);
1769 ObtainWriteLock(&afs_xuser,227);
1770 for(tu=afs_users[i]; tu; tu=tu->next) {
1771 if (tu->uid == areq->uid) {
1773 tu->states &= ~UHasTokens;
1774 /* security is not having to say you're sorry */
1775 memset((char *)&tu->ct, 0, sizeof(struct ClearToken));
1777 ReleaseWriteLock(&afs_xuser);
1778 /* We have to drop the lock over the call to afs_ResetUserConns, since
1779 * it obtains the afs_xvcache lock. We could also keep the lock, and
1780 * modify ResetUserConns to take parm saying we obtained the lock
1781 * already, but that is overkill. By keeping the "tu" pointer
1782 * held over the released lock, we guarantee that we won't lose our
1783 * place, and that we'll pass over every user conn that existed when
1784 * we began this call.
1786 afs_ResetUserConns(tu);
1788 ObtainWriteLock(&afs_xuser,228);
1790 /* set the expire times to 0, causes
1791 * afs_GCUserData to remove this entry
1793 tu->ct.EndTimestamp = 0;
1795 #endif /* UKERNEL */
1798 ReleaseWriteLock(&afs_xuser);
1802 DECL_PIOCTL(PMariner)
1804 afs_int32 newHostAddr;
1805 afs_int32 oldHostAddr;
1807 AFS_STATCNT(PMariner);
1809 memcpy((char *)&oldHostAddr, (char *)&afs_marinerHost, sizeof(afs_int32));
1811 oldHostAddr = 0xffffffff; /* disabled */
1813 memcpy((char *)&newHostAddr, ain, sizeof(afs_int32));
1814 if (newHostAddr == 0xffffffff) {
1815 /* disable mariner operations */
1818 else if (newHostAddr) {
1820 afs_marinerHost = newHostAddr;
1822 memcpy(aout, (char *)&oldHostAddr, sizeof(afs_int32));
1823 *aoutSize = sizeof(afs_int32);
1827 DECL_PIOCTL(PCheckServers)
1829 register char *cp = 0;
1831 register struct server *ts;
1832 afs_int32 temp, *lp = (afs_int32 *)ain, havecell=0;
1834 struct chservinfo *pcheck;
1836 AFS_STATCNT(PCheckServers);
1838 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1839 return EIO; /* Inappropriate ioctl for device */
1841 if (*lp == 0x12345678) { /* For afs3.3 version */
1842 pcheck=(struct chservinfo *)ain;
1843 if (pcheck->tinterval >= 0) {
1845 memcpy(cp, (char *)&PROBE_INTERVAL, sizeof(afs_int32));
1846 *aoutSize = sizeof(afs_int32);
1847 if (pcheck->tinterval > 0) {
1848 if (!afs_osi_suser(*acred))
1850 PROBE_INTERVAL=pcheck->tinterval;
1856 temp=pcheck->tflags;
1857 cp = pcheck->tbuffer;
1858 } else { /* For pre afs3.3 versions */
1859 memcpy((char *)&temp, ain, sizeof(afs_int32));
1860 cp = ain+sizeof(afs_int32);
1861 if (ainSize > sizeof(afs_int32))
1866 * 1: fast check, don't contact servers.
1867 * 2: local cell only.
1870 /* have cell name, too */
1871 cellp = afs_GetCellByName(cp, READ_LOCK);
1872 if (!cellp) return ENOENT;
1875 if (!cellp && (temp & 2)) {
1876 /* use local cell */
1877 cellp = afs_GetPrimaryCell(READ_LOCK);
1879 if (!(temp & 1)) { /* if not fast, call server checker routine */
1880 afs_CheckServers(1, cellp); /* check down servers */
1881 afs_CheckServers(0, cellp); /* check up servers */
1883 /* now return the current down server list */
1885 ObtainReadLock(&afs_xserver);
1886 for(i=0;i<NSERVERS;i++) {
1887 for(ts = afs_servers[i]; ts; ts=ts->next) {
1888 if (cellp && ts->cell != cellp) continue; /* cell spec'd and wrong */
1889 if ((ts->flags & SRVR_ISDOWN) && ts->addr->sa_portal != ts->cell->vlport) {
1890 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1891 cp += sizeof(afs_int32);
1895 ReleaseReadLock(&afs_xserver);
1896 if (cellp) afs_PutCell(cellp, READ_LOCK);
1897 *aoutSize = cp - aout;
1901 DECL_PIOCTL(PCheckVolNames)
1903 AFS_STATCNT(PCheckVolNames);
1904 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1905 return EIO; /* Inappropriate ioctl for device */
1907 afs_CheckRootVolume();
1908 afs_CheckVolumeNames(AFS_VOLCHECK_FORCE |
1909 AFS_VOLCHECK_EXPIRED |
1911 AFS_VOLCHECK_MTPTS);
1915 DECL_PIOCTL(PCheckAuth)
1920 struct unixuser *tu;
1923 AFS_STATCNT(PCheckAuth);
1924 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
1925 return EIO; /* Inappropriate ioctl for device */
1928 tu = afs_GetUser(areq->uid, 1, READ_LOCK); /* check local cell authentication */
1929 if (!tu) retValue = EACCES;
1931 /* we have a user */
1932 ObtainReadLock(&afs_xsrvAddr);
1933 ObtainReadLock(&afs_xconn);
1935 /* any tokens set? */
1936 if ((tu->states & UHasTokens) == 0) retValue = EACCES;
1937 /* all connections in cell 1 working? */
1938 for(i=0;i<NSERVERS;i++) {
1939 for(sa = afs_srvAddrs[i]; sa; sa=sa->next_bkt) {
1940 for (tc = sa->conns; tc; tc=tc->next) {
1941 if (tc->user == tu && (tu->states & UTokensBad))
1946 ReleaseReadLock(&afs_xsrvAddr);
1947 ReleaseReadLock(&afs_xconn);
1948 afs_PutUser(tu, READ_LOCK);
1950 memcpy(aout, (char *)&retValue, sizeof(afs_int32));
1951 *aoutSize = sizeof(afs_int32);
1955 static int Prefetch(char *apath, struct afs_ioctl *adata, int afollow, struct AFS_UCRED *acred)
1958 register afs_int32 code;
1959 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
1965 AFS_STATCNT(Prefetch);
1966 if (!apath) return EINVAL;
1967 tp = osi_AllocLargeSpace(1024);
1968 AFS_COPYINSTR(apath, tp, 1024, &bufferSize, code);
1970 osi_FreeLargeSpace(tp);
1973 if (afs_BBusy()) { /* do this as late as possible */
1974 osi_FreeLargeSpace(tp);
1975 return EWOULDBLOCK; /* pretty close */
1977 afs_BQueue(BOP_PATH, (struct vcache*)0, 0, 0, acred,
1978 (afs_size_t) 0, (afs_size_t) 0, tp);
1982 DECL_PIOCTL(PFindVolume)
1984 register struct volume *tvp;
1985 register struct server *ts;
1986 register afs_int32 i;
1989 AFS_STATCNT(PFindVolume);
1990 if (!avc) return EINVAL;
1991 tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
1994 for(i=0;i<MAXHOSTS;i++) {
1995 ts = tvp->serverHost[i];
1997 memcpy(cp, (char *)&ts->addr->sa_ip, sizeof(afs_int32));
1998 cp += sizeof(afs_int32);
2001 /* still room for terminating NULL, add it on */
2002 ainSize = 0; /* reuse vbl */
2003 memcpy(cp, (char *)&ainSize, sizeof(afs_int32));
2004 cp += sizeof(afs_int32);
2006 *aoutSize = cp - aout;
2007 afs_PutVolume(tvp, READ_LOCK);
2013 DECL_PIOCTL(PViceAccess)
2015 register afs_int32 code;
2018 AFS_STATCNT(PViceAccess);
2019 if (!avc) return EINVAL;
2020 code = afs_VerifyVCache(avc, areq);
2021 if (code) return code;
2022 memcpy((char *)&temp, ain, sizeof(afs_int32));
2023 code = afs_AccessOK(avc,temp, areq, CHECK_MODE_BITS);
2028 DECL_PIOCTL(PSetCacheSize)
2033 AFS_STATCNT(PSetCacheSize);
2034 if (!afs_osi_suser(*acred))
2036 /* too many things are setup initially in mem cache version */
2037 if (cacheDiskType == AFS_FCACHE_TYPE_MEM) return EROFS;
2038 memcpy((char *)&newValue, ain, sizeof(afs_int32));
2039 if (newValue == 0) afs_cacheBlocks = afs_stats_cmperf.cacheBlocksOrig;
2041 if (newValue < afs_min_cache)
2042 afs_cacheBlocks = afs_min_cache;
2044 afs_cacheBlocks = newValue;
2046 afs_stats_cmperf.cacheBlocksTotal = afs_cacheBlocks;
2047 afs_ComputeCacheParms(); /* recompute basic cache parameters */
2048 afs_MaybeWakeupTruncateDaemon();
2049 while (waitcnt++ < 100 && afs_cacheBlocks < afs_blocksUsed) {
2050 afs_osi_Wait(1000, 0, 0);
2051 afs_MaybeWakeupTruncateDaemon();
2056 #define MAXGCSTATS 16
2057 DECL_PIOCTL(PGetCacheSize)
2059 afs_int32 results[MAXGCSTATS];
2061 AFS_STATCNT(PGetCacheSize);
2062 memset((char *)results, 0, sizeof(results));
2063 results[0] = afs_cacheBlocks;
2064 results[1] = afs_blocksUsed;
2065 memcpy(aout, (char *)results, sizeof(results));
2066 *aoutSize = sizeof(results);
2070 DECL_PIOCTL(PRemoveCallBack)
2072 register struct conn *tc;
2073 register afs_int32 code;
2074 struct AFSCallBack CallBacks_Array[1];
2075 struct AFSCBFids theFids;
2076 struct AFSCBs theCBs;
2079 AFS_STATCNT(PRemoveCallBack);
2080 if (!avc) return EINVAL;
2081 if (avc->states & CRO) return 0; /* read-only-ness can't change */
2082 ObtainWriteLock(&avc->lock,229);
2083 theFids.AFSCBFids_len = 1;
2084 theCBs.AFSCBs_len = 1;
2085 theFids.AFSCBFids_val = (struct AFSFid *) &avc->fid.Fid;
2086 theCBs.AFSCBs_val = CallBacks_Array;
2087 CallBacks_Array[0].CallBackType = CB_DROPPED;
2088 if (avc->callback) {
2090 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2092 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS);
2094 code = RXAFS_GiveUpCallBacks(tc->id, &theFids, &theCBs);
2098 /* don't set code on failure since we wouldn't use it */
2100 (afs_Analyze(tc, code, &avc->fid, areq,
2101 AFS_STATS_FS_RPCIDX_GIVEUPCALLBACKS,
2102 SHARED_LOCK, NULL));
2104 ObtainWriteLock(&afs_xcbhash, 457);
2105 afs_DequeueCallback(avc);
2107 avc->states &= ~(CStatd | CUnique);
2108 ReleaseWriteLock(&afs_xcbhash);
2109 if (avc->fid.Fid.Vnode & 1 || (vType(avc) == VDIR))
2110 osi_dnlc_purgedp(avc);
2112 ReleaseWriteLock(&avc->lock);
2116 DECL_PIOCTL(PNewCell)
2118 /* create a new cell */
2119 afs_int32 cellHosts[MAXCELLHOSTS], *lp, magic=0;
2120 register struct cell *tcell;
2121 char *newcell=0, *linkedcell=0, *tp= ain;
2122 register afs_int32 code, linkedstate=0, ls;
2123 u_short fsport = 0, vlport = 0;
2126 AFS_STATCNT(PNewCell);
2127 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2128 return EIO; /* Inappropriate ioctl for device */
2130 if (!afs_osi_suser(*acred))
2133 memcpy((char *)&magic, tp, sizeof(afs_int32));
2134 tp += sizeof(afs_int32);
2135 if (magic != 0x12345678)
2138 /* A 3.4 fs newcell command will pass an array of MAXCELLHOSTS
2139 * server addresses while the 3.5 fs newcell command passes
2140 * MAXHOSTS. To figure out which is which, check if the cellname
2143 newcell = tp + (MAXCELLHOSTS+3)*sizeof(afs_int32);
2144 scount = ((newcell[0] != '\0') ? MAXCELLHOSTS : MAXHOSTS);
2146 /* MAXCELLHOSTS (=8) is less than MAXHOSTS (=13) */
2147 memcpy((char *)cellHosts, tp, MAXCELLHOSTS * sizeof(afs_int32));
2148 tp += (scount * sizeof(afs_int32));
2150 lp = (afs_int32 *)tp;
2153 if (fsport < 1024) fsport = 0; /* Privileged ports not allowed */
2154 if (vlport < 1024) vlport = 0; /* Privileged ports not allowed */
2155 tp += (3 * sizeof(afs_int32));
2157 if ((ls = *lp) & 1) {
2158 linkedcell = tp + strlen(newcell)+1;
2159 linkedstate |= CLinkedCell;
2162 linkedstate |= CNoSUID; /* setuid is disabled by default for fs newcell */
2163 code = afs_NewCell(newcell, cellHosts, linkedstate, linkedcell, fsport,
2168 DECL_PIOCTL(PNewAlias)
2170 /* create a new cell alias */
2172 register afs_int32 code;
2173 char *realName, *aliasName;
2175 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2176 return EIO; /* Inappropriate ioctl for device */
2178 if (!afs_osi_suser(*acred))
2182 tp += strlen(aliasName) + 1;
2185 code = afs_NewCellAlias(aliasName, realName);
2190 DECL_PIOCTL(PListCells)
2192 afs_int32 whichCell;
2193 register struct cell *tcell=0;
2194 register afs_int32 i;
2195 register char *cp, *tp = ain;
2197 AFS_STATCNT(PListCells);
2198 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2199 return EIO; /* Inappropriate ioctl for device */
2201 memcpy((char *)&whichCell, tp, sizeof(afs_int32));
2202 tp += sizeof(afs_int32);
2203 tcell = afs_GetCellByIndex(whichCell, READ_LOCK);
2206 memset(cp, 0, MAXCELLHOSTS * sizeof(afs_int32));
2207 for(i=0;i<MAXCELLHOSTS;i++) {
2208 if (tcell->cellHosts[i] == 0) break;
2209 memcpy(cp, (char *)&tcell->cellHosts[i]->addr->sa_ip, sizeof(afs_int32));
2210 cp += sizeof(afs_int32);
2212 cp = aout + MAXCELLHOSTS * sizeof(afs_int32);
2213 strcpy(cp, tcell->cellName);
2214 cp += strlen(tcell->cellName)+1;
2215 *aoutSize = cp - aout;
2216 afs_PutCell(tcell, READ_LOCK);
2218 if (tcell) return 0;
2222 DECL_PIOCTL(PListAliases)
2224 afs_int32 whichAlias;
2225 register struct cell_alias *tcalias=0;
2226 register char *cp, *tp = ain;
2228 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2229 return EIO; /* Inappropriate ioctl for device */
2230 if (ainSize < sizeof(afs_int32))
2233 memcpy((char *)&whichAlias, tp, sizeof(afs_int32));
2234 tp += sizeof(afs_int32);
2236 tcalias = afs_GetCellAlias(whichAlias);
2239 strcpy(cp, tcalias->alias);
2240 cp += strlen(tcalias->alias)+1;
2241 strcpy(cp, tcalias->cell);
2242 cp += strlen(tcalias->cell)+1;
2243 *aoutSize = cp - aout;
2244 afs_PutCellAlias(tcalias);
2246 if (tcalias) return 0;
2250 DECL_PIOCTL(PRemoveMount)
2252 register afs_int32 code;
2254 struct sysname_info sysState;
2255 afs_size_t offset, len;
2256 register struct conn *tc;
2257 register struct dcache *tdc;
2258 register struct vcache *tvc;
2259 struct AFSFetchStatus OutDirStatus;
2260 struct VenusFid tfid;
2261 struct AFSVolSync tsync;
2265 /* "ain" is the name of the file in this dir to remove */
2267 AFS_STATCNT(PRemoveMount);
2268 if (!avc) return EINVAL;
2269 code = afs_VerifyVCache(avc, areq);
2270 if (code) return code;
2271 if (vType(avc) != VDIR) return ENOTDIR;
2273 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1); /* test for error below */
2274 if (!tdc) return ENOENT;
2275 Check_AtSys(avc, ain, &sysState, areq);
2276 ObtainReadLock(&tdc->lock);
2278 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
2279 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
2280 ReleaseReadLock(&tdc->lock);
2281 bufp = sysState.name;
2286 tfid.Cell = avc->fid.Cell;
2287 tfid.Fid.Volume = avc->fid.Fid.Volume;
2288 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
2289 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
2291 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
2298 if (tvc->mvstat != 1) {
2304 ObtainWriteLock(&tvc->lock,230);
2305 code = afs_HandleLink(tvc, areq);
2307 if (tvc->linkData) {
2308 if ((tvc->linkData[0] != '#') && (tvc->linkData[0] != '%'))
2313 ReleaseWriteLock(&tvc->lock);
2314 osi_dnlc_purgedp(tvc);
2320 ObtainWriteLock(&avc->lock,231);
2321 osi_dnlc_remove(avc, bufp, tvc);
2323 tc = afs_Conn(&avc->fid, areq, SHARED_LOCK);
2325 XSTATS_START_TIME(AFS_STATS_FS_RPCIDX_REMOVEFILE);
2327 code = RXAFS_RemoveFile(tc->id, (struct AFSFid *) &avc->fid.Fid,
2328 bufp, &OutDirStatus, &tsync);
2334 (afs_Analyze(tc, code, &avc->fid, areq,
2335 AFS_STATS_FS_RPCIDX_REMOVEFILE,
2336 SHARED_LOCK, NULL));
2339 if (tdc) afs_PutDCache(tdc);
2340 ReleaseWriteLock(&avc->lock);
2344 /* we have the thing in the cache */
2345 ObtainWriteLock(&tdc->lock, 661);
2346 if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
2347 /* we can do it locally */
2348 code = afs_dir_Delete(&tdc->f.inode, bufp);
2350 ZapDCE(tdc); /* surprise error -- invalid value */
2351 DZap(&tdc->f.inode);
2354 ReleaseWriteLock(&tdc->lock);
2355 afs_PutDCache(tdc); /* drop ref count */
2357 avc->states &= ~CUnique; /* For the dfs xlator */
2358 ReleaseWriteLock(&avc->lock);
2361 if (sysState.allocked) osi_FreeLargeSpace(bufp);
2365 DECL_PIOCTL(PVenusLogging)
2367 return EINVAL; /* OBSOLETE */
2370 DECL_PIOCTL(PGetCellStatus)
2372 register struct cell *tcell;
2375 AFS_STATCNT(PGetCellStatus);
2376 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2377 return EIO; /* Inappropriate ioctl for device */
2379 tcell = afs_GetCellByName(ain, READ_LOCK);
2380 if (!tcell) return ENOENT;
2381 temp = tcell->states;
2382 afs_PutCell(tcell, READ_LOCK);
2383 memcpy(aout, (char *)&temp, sizeof(afs_int32));
2384 *aoutSize = sizeof(afs_int32);
2388 DECL_PIOCTL(PSetCellStatus)
2390 register struct cell *tcell;
2393 if (!afs_osi_suser(*acred))
2395 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2396 return EIO; /* Inappropriate ioctl for device */
2398 tcell = afs_GetCellByName(ain+2*sizeof(afs_int32), WRITE_LOCK);
2399 if (!tcell) return ENOENT;
2400 memcpy((char *)&temp, ain, sizeof(afs_int32));
2402 tcell->states |= CNoSUID;
2404 tcell->states &= ~CNoSUID;
2405 afs_PutCell(tcell, WRITE_LOCK);
2409 DECL_PIOCTL(PFlushVolumeData)
2411 register afs_int32 i;
2412 register struct dcache *tdc;
2413 register struct vcache *tvc;
2414 register struct volume *tv;
2415 afs_int32 cell, volume;
2417 AFS_STATCNT(PFlushVolumeData);
2420 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2421 return EIO; /* Inappropriate ioctl for device */
2423 volume = avc->fid.Fid.Volume; /* who to zap */
2424 cell = avc->fid.Cell;
2427 * Clear stat'd flag from all vnodes from this volume; this will invalidate all
2428 * the vcaches associated with the volume.
2430 ObtainReadLock(&afs_xvcache);
2431 for(i = 0; i < VCSIZE; i++) {
2432 for(tvc = afs_vhashT[i]; tvc; tvc=tvc->hnext) {
2433 if (tvc->fid.Fid.Volume == volume && tvc->fid.Cell == cell) {
2434 #if defined(AFS_SGI_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
2435 VN_HOLD(AFSTOV(tvc));
2437 #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV)
2443 ReleaseReadLock(&afs_xvcache);
2444 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2445 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
2447 ObtainWriteLock(&tvc->lock,232);
2449 ObtainWriteLock(&afs_xcbhash, 458);
2450 afs_DequeueCallback(tvc);
2451 tvc->states &= ~(CStatd | CDirty);
2452 ReleaseWriteLock(&afs_xcbhash);
2453 if (tvc->fid.Fid.Vnode & 1 || (vType(tvc) == VDIR))
2454 osi_dnlc_purgedp(tvc);
2455 afs_TryToSmush(tvc, *acred, 1);
2456 ReleaseWriteLock(&tvc->lock);
2457 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
2458 afs_BozonUnlock(&tvc->pvnLock, tvc);
2460 ObtainReadLock(&afs_xvcache);
2461 /* our tvc ptr is still good until now */
2466 ReleaseReadLock(&afs_xvcache);
2469 MObtainWriteLock(&afs_xdcache,328); /* needed if you're going to flush any stuff */
2470 for(i=0;i<afs_cacheFiles;i++) {
2471 if (!(afs_indexFlags[i] & IFEverUsed)) continue; /* never had any data */
2472 tdc = afs_GetDSlot(i, NULL);
2473 if (tdc->refCount <= 1) { /* too high, in use by running sys call */
2474 ReleaseReadLock(&tdc->tlock);
2475 if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
2476 if (! (afs_indexFlags[i] & IFDataMod)) {
2477 /* if the file is modified, but has a ref cnt of only 1, then
2478 someone probably has the file open and is writing into it.
2479 Better to skip flushing such a file, it will be brought back
2480 immediately on the next write anyway.
2482 If we *must* flush, then this code has to be rearranged to call
2483 afs_storeAllSegments() first */
2484 afs_FlushDCache(tdc);
2488 ReleaseReadLock(&tdc->tlock);
2490 afs_PutDCache(tdc); /* bumped by getdslot */
2492 MReleaseWriteLock(&afs_xdcache);
2494 ObtainReadLock(&afs_xvolume);
2495 for (i=0;i<NVOLS;i++) {
2496 for (tv = afs_volumes[i]; tv; tv=tv->next) {
2497 if (tv->volume == volume) {
2498 afs_ResetVolumeInfo(tv);
2503 ReleaseReadLock(&afs_xvolume);
2505 /* probably, a user is doing this, probably, because things are screwed up.
2506 * maybe it's the dnlc's fault? */
2513 DECL_PIOCTL(PGetVnodeXStatus)
2515 register afs_int32 code;
2516 struct vcxstat stat;
2519 /* AFS_STATCNT(PGetVnodeXStatus); */
2520 if (!avc) return EINVAL;
2521 code = afs_VerifyVCache(avc, areq);
2522 if (code) return code;
2523 if (vType(avc) == VDIR)
2524 mode = PRSFS_LOOKUP;
2527 if (!afs_AccessOK(avc, mode, areq, CHECK_MODE_BITS))
2529 stat.fid = avc->fid;
2530 hset32(stat.DataVersion, hgetlo(avc->m.DataVersion));
2531 stat.lock = avc->lock;
2532 stat.parentVnode = avc->parentVnode;
2533 stat.parentUnique = avc->parentUnique;
2534 hset(stat.flushDV, avc->flushDV);
2535 hset(stat.mapDV, avc->mapDV);
2536 stat.truncPos = avc->truncPos;
2537 { /* just grab the first two - won't break anything... */
2538 struct axscache *ac;
2540 for (i=0, ac=avc->Access; ac && i < CPSIZE; i++, ac=ac->next) {
2541 stat.randomUid[i] = ac->uid;
2542 stat.randomAccess[i] = ac->axess;
2545 stat.callback = afs_data_pointer_to_int32(avc->callback);
2546 stat.cbExpires = avc->cbExpires;
2547 stat.anyAccess = avc->anyAccess;
2548 stat.opens = avc->opens;
2549 stat.execsOrWriters = avc->execsOrWriters;
2550 stat.flockCount = avc->flockCount;
2551 stat.mvstat = avc->mvstat;
2552 stat.states = avc->states;
2553 memcpy(aout, (char *)&stat, sizeof(struct vcxstat));
2554 *aoutSize = sizeof(struct vcxstat);
2559 /* We require root for local sysname changes, but not for remote */
2560 /* (since we don't really believe remote uids anyway) */
2561 /* outname[] shouldn't really be needed- this is left as an excercise */
2562 /* for the reader. */
2563 DECL_PIOCTL(PSetSysName)
2565 char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
2566 int setsysname, foundname=0;
2567 register struct afs_exporter *exporter;
2568 register struct unixuser *au;
2569 register afs_int32 pag, error;
2573 AFS_STATCNT(PSetSysName);
2574 if (!afs_globalVFS) {
2575 /* Afsd is NOT running; disable it */
2576 #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)
2579 return (setuerror(EINVAL), EINVAL);
2582 memset(inname, 0, MAXSYSNAME);
2583 memcpy((char *)&setsysname, ain, sizeof(afs_int32));
2584 ain += sizeof(afs_int32);
2588 if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
2590 for(cp = ain,count = 0;count < setsysname;count++) {
2591 /* won't go past end of ain since maxsysname*num < ain length */
2593 if (t >= MAXSYSNAME || t <= 0)
2595 /* check for names that can shoot us in the foot */
2596 if (*cp == '.' && (cp[1] == 0 || (cp[1] == '.' && cp[2] == 0)))
2602 /* inname gets first entry in case we're being a translater */
2604 memcpy(inname, ain, t+1); /* include terminating null */
2607 if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
2608 pag = PagInCred(*acred);
2610 return EINVAL; /* Better than panicing */
2612 if (!(au = afs_FindUser(pag, -1, READ_LOCK))) {
2613 return EINVAL; /* Better than panicing */
2615 if (!(exporter = au->exporter)) {
2616 afs_PutUser(au, READ_LOCK);
2617 return EINVAL; /* Better than panicing */
2619 error = EXP_SYSNAME(exporter, (setsysname? inname : NULL), outname);
2621 if (error == ENODEV) foundname = 0; /* sysname not set yet! */
2623 afs_PutUser(au, READ_LOCK);
2628 afs_PutUser(au, READ_LOCK);
2631 /* Not xlating, so local case */
2632 if (!afs_sysname) osi_Panic("PSetSysName: !afs_sysname\n");
2633 if (!setsysname) { /* user just wants the info */
2634 strcpy(outname, afs_sysname);
2635 foundname = afs_sysnamecount;
2636 } else { /* Local guy; only root can change sysname */
2637 if (!afs_osi_suser(*acred))
2640 /* clear @sys entries from the dnlc, once afs_lookup can
2641 do lookups of @sys entries and thinks it can trust them */
2642 /* privs ok, store the entry, ... */
2643 strcpy(afs_sysname, inname);
2644 if (setsysname > 1) { /* ... or list */
2646 for(count=1; count < setsysname;++count) {
2647 if (!afs_sysnamelist[count])
2648 osi_Panic("PSetSysName: no afs_sysnamelist entry to write\n");
2650 memcpy(afs_sysnamelist[count], cp, t+1); /* include null */
2654 afs_sysnamecount = setsysname;
2658 cp = aout; /* not changing so report back the count and ... */
2659 memcpy(cp, (char *)&foundname, sizeof(afs_int32));
2660 cp += sizeof(afs_int32);
2662 strcpy(cp, outname); /* ... the entry, ... */
2663 cp += strlen(outname)+1;
2664 for(count=1; count < foundname; ++count) { /* ... or list. */
2665 /* Note: we don't support @sys lists for exporters */
2666 if (!afs_sysnamelist[count])
2667 osi_Panic("PSetSysName: no afs_sysnamelist entry to read\n");
2668 t = strlen(afs_sysnamelist[count]);
2669 if (t >= MAXSYSNAME)
2670 osi_Panic("PSetSysName: sysname entry garbled\n");
2671 strcpy(cp, afs_sysnamelist[count]);
2675 *aoutSize = cp - aout;
2680 /* sequential search through the list of touched cells is not a good
2681 * long-term solution here. For small n, though, it should be just
2682 * fine. Should consider special-casing the local cell for large n.
2683 * Likewise for PSetSPrefs.
2685 * s - number of ids in array l[] -- NOT index of last id
2686 * l - array of cell ids which have volumes that need to be sorted
2687 * vlonly - sort vl servers or file servers?
2689 static void *ReSortCells_cb(struct cell *cell, void *arg)
2691 afs_int32 *p = (afs_int32 *) arg;
2692 afs_int32 *l = p + 1;
2695 for (i=0; i<s; i++) {
2696 if (l[i] == cell->cellNum) {
2697 ObtainWriteLock(&cell->lock, 690);
2698 afs_SortServers(cell->cellHosts, MAXCELLHOSTS);
2699 ReleaseWriteLock(&cell->lock);
2704 static void ReSortCells(int s, afs_int32 *l, int vlonly)
2712 p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s+1));
2714 memcpy(p+1, l, s * sizeof(afs_int32));
2715 afs_TraverseCells(&ReSortCells_cb, p);
2716 afs_osi_Free(p, sizeof(afs_int32) * (s+1));
2720 ObtainReadLock(&afs_xvolume);
2721 for (i= 0; i< NVOLS; i++) {
2722 for (j=afs_volumes[i];j;j=j->next) {
2724 if (j->cell == l[k]) {
2725 ObtainWriteLock(&j->lock,233);
2726 afs_SortServers(j->serverHost, MAXHOSTS);
2727 ReleaseWriteLock(&j->lock);
2732 ReleaseReadLock(&afs_xvolume);
2736 static int debugsetsp = 0;
2737 static int afs_setsprefs(sp, num, vlonly)
2740 unsigned int vlonly;
2743 int i,j,k,matches,touchedSize;
2744 struct server *srvr = NULL;
2745 afs_int32 touched[34];
2749 for (k=0; k < num; sp++, k++) {
2751 printf ("sp host=%x, rank=%d\n",sp->host.s_addr, sp->rank);
2754 ObtainReadLock(&afs_xserver);
2756 i = SHash(sp->host.s_addr);
2757 for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
2758 if (sa->sa_ip == sp->host.s_addr) {
2760 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2761 || (sa->sa_portal == AFS_FSPORT);
2762 if ((!vlonly && isfs) || (vlonly && !isfs)) {
2769 if (sa && matches) { /* found one! */
2771 printf ("sa ip=%x, ip_rank=%d\n",sa->sa_ip, sa->sa_iprank);
2773 sa->sa_iprank = sp->rank + afs_randomMod15();
2774 afs_SortOneServer(sa->server);
2777 /* if we don't know yet what cell it's in, this is moot */
2778 for (j=touchedSize-1; j>=0 && touched[j] != srvr->cell->cellNum; j--)
2779 /* is it in our list of touched cells ? */ ;
2780 if (j < 0) { /* no, it's not */
2781 touched[touchedSize++] = srvr->cell->cellNum;
2782 if (touchedSize >= 32) { /* watch for ovrflow */
2783 ReleaseReadLock(&afs_xserver);
2784 ReSortCells(touchedSize, touched, vlonly);
2786 ObtainReadLock(&afs_xserver);
2792 ReleaseReadLock(&afs_xserver);
2793 /* if we didn't find one, start to create one. */
2794 /* Note that it doesn't have a cell yet... */
2796 afs_uint32 temp = sp->host.s_addr;
2797 srvr = afs_GetServer(&temp, 1, 0, (vlonly ? AFS_VLPORT : AFS_FSPORT),
2798 WRITE_LOCK, (afsUUID *)0,0);
2799 srvr->addr->sa_iprank = sp->rank + afs_randomMod15();
2800 afs_PutServer(srvr, WRITE_LOCK);
2802 } /* for all cited preferences */
2804 ReSortCells(touchedSize, touched, vlonly);
2808 /* Note that this may only be performed by the local root user.
2810 DECL_PIOCTL(PSetSPrefs)
2812 struct setspref *ssp;
2813 AFS_STATCNT(PSetSPrefs);
2815 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2816 return EIO; /* Inappropriate ioctl for device */
2818 if (!afs_osi_suser(*acred))
2821 if (ainSize < sizeof(struct setspref))
2824 ssp = (struct setspref *)ain;
2825 if (ainSize < sizeof(struct spref)*ssp->num_servers)
2828 afs_setsprefs(&(ssp->servers[0]), ssp->num_servers,
2829 (ssp->flags & DBservers));
2833 DECL_PIOCTL(PSetSPrefs33)
2836 AFS_STATCNT(PSetSPrefs);
2837 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2838 return EIO; /* Inappropriate ioctl for device */
2841 if (!afs_osi_suser(*acred))
2844 sp = (struct spref *)ain;
2845 afs_setsprefs(sp, ainSize/(sizeof(struct spref)), 0 /*!vlonly*/);
2849 /* some notes on the following code...
2850 * in the hash table of server structs, all servers with the same IP address
2851 * will be on the same overflow chain.
2852 * This could be sped slightly in some circumstances by having it cache the
2853 * immediately previous slot in the hash table and some supporting information
2854 * Only reports file servers now.
2856 DECL_PIOCTL(PGetSPrefs)
2858 struct sprefrequest *spin; /* input */
2859 struct sprefinfo *spout; /* output */
2860 struct spref *srvout; /* one output component */
2861 int i,j; /* counters for hash table traversal */
2862 struct server *srvr; /* one of CM's server structs */
2865 int vlonly; /* just return vlservers ? */
2868 AFS_STATCNT(PGetSPrefs);
2869 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
2870 return EIO; /* Inappropriate ioctl for device */
2873 if (ainSize < sizeof (struct sprefrequest_33)) {
2877 spin = ((struct sprefrequest *) ain);
2880 if (ainSize > sizeof (struct sprefrequest_33)) {
2881 vlonly = (spin->flags & DBservers);
2885 /* struct sprefinfo includes 1 server struct... that size gets added
2886 * in during the loop that follows.
2888 *aoutSize = sizeof(struct sprefinfo) - sizeof (struct spref);
2889 spout = (struct sprefinfo *) aout;
2890 spout->next_offset = spin->offset;
2891 spout->num_servers = 0;
2892 srvout = spout->servers;
2894 ObtainReadLock(&afs_xserver);
2895 for (i=0, j=0; j < NSERVERS; j++) { /* sift through hash table */
2896 for (sa = afs_srvAddrs[j]; sa; sa = sa->next_bkt, i++) {
2897 if (spin->offset > (unsigned short)i) {
2898 continue; /* catch up to where we left off */
2900 spout->next_offset++;
2903 isfs = (srvr->cell && (sa->sa_portal == srvr->cell->fsport))
2904 || (sa->sa_portal == AFS_FSPORT);
2906 if ((vlonly && isfs) || (!vlonly && !isfs)) {
2907 /* only report ranks for vl servers */
2911 srvout->host.s_addr = sa->sa_ip;
2912 srvout->rank = sa->sa_iprank;
2913 *aoutSize += sizeof(struct spref);
2914 spout->num_servers++;
2917 if (*aoutSize > (PIGGYSIZE - sizeof(struct spref))) {
2918 ReleaseReadLock(&afs_xserver); /* no more room! */
2923 ReleaseReadLock(&afs_xserver);
2925 spout->next_offset = 0; /* start over from the beginning next time */
2929 /* Enable/Disable the specified exporter. Must be root to disable an exporter */
2930 int afs_NFSRootOnly = 1;
2931 DECL_PIOCTL(PExportAfs)
2933 afs_int32 export, newint=0, type, changestate, handleValue, convmode, pwsync, smounts;
2934 register struct afs_exporter *exporter;
2936 AFS_STATCNT(PExportAfs);
2937 memcpy((char *)&handleValue, ain, sizeof(afs_int32));
2938 type = handleValue >> 24;
2943 exporter = exporter_find(type);
2945 export = handleValue & 3;
2946 changestate = handleValue & 0xff;
2947 smounts = (handleValue >> 2) & 3;
2948 pwsync = (handleValue >> 4) & 3;
2949 convmode = (handleValue >> 6) & 3;
2951 changestate = (handleValue >> 16) & 0x1;
2952 convmode = (handleValue >> 16) & 0x2;
2953 pwsync = (handleValue >> 16) & 0x4;
2954 smounts = (handleValue >> 16) & 0x8;
2955 export = handleValue & 0xff;
2958 /* Failed finding desired exporter; */
2962 handleValue = exporter->exp_states;
2963 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2964 *aoutSize = sizeof(afs_int32);
2966 if (!afs_osi_suser(*acred))
2967 return EACCES; /* Only superuser can do this */
2971 exporter->exp_states |= EXP_EXPORTED;
2973 exporter->exp_states &= ~EXP_EXPORTED;
2977 exporter->exp_states |= EXP_UNIXMODE;
2979 exporter->exp_states &= ~EXP_UNIXMODE;
2983 exporter->exp_states |= EXP_PWSYNC;
2985 exporter->exp_states &= ~EXP_PWSYNC;
2989 afs_NFSRootOnly = 0;
2990 exporter->exp_states |= EXP_SUBMOUNTS;
2992 afs_NFSRootOnly = 1;
2993 exporter->exp_states &= ~EXP_SUBMOUNTS;
2996 handleValue = exporter->exp_states;
2997 memcpy(aout, (char *)&handleValue, sizeof(afs_int32));
2998 *aoutSize = sizeof(afs_int32);
3001 exporter->exp_states |= EXP_EXPORTED;
3003 exporter->exp_states &= ~EXP_EXPORTED;
3005 exporter->exp_states |= EXP_UNIXMODE;
3007 exporter->exp_states &= ~EXP_UNIXMODE;
3009 exporter->exp_states |= EXP_PWSYNC;
3011 exporter->exp_states &= ~EXP_PWSYNC;
3013 afs_NFSRootOnly = 0;
3014 exporter->exp_states |= EXP_SUBMOUNTS;
3016 afs_NFSRootOnly = 1;
3017 exporter->exp_states &= ~EXP_SUBMOUNTS;
3027 struct gaginfo *gagflags;
3029 if (!afs_osi_suser(*acred))
3032 gagflags = (struct gaginfo *) ain;
3033 afs_showflags = gagflags->showflags;
3039 DECL_PIOCTL(PTwiddleRx)
3041 struct rxparams *rxp;
3043 if (!afs_osi_suser(*acred))
3046 rxp = (struct rxparams *) ain;
3048 if (rxp->rx_initReceiveWindow)
3049 rx_initReceiveWindow = rxp->rx_initReceiveWindow;
3050 if (rxp->rx_maxReceiveWindow)
3051 rx_maxReceiveWindow = rxp->rx_maxReceiveWindow;
3052 if (rxp->rx_initSendWindow)
3053 rx_initSendWindow = rxp->rx_initSendWindow;
3054 if (rxp->rx_maxSendWindow)
3055 rx_maxSendWindow = rxp->rx_maxSendWindow;
3056 if (rxp->rxi_nSendFrags)
3057 rxi_nSendFrags = rxp->rxi_nSendFrags;
3058 if (rxp->rxi_nRecvFrags)
3059 rxi_nRecvFrags = rxp->rxi_nRecvFrags;
3060 if (rxp->rxi_OrphanFragSize)
3061 rxi_OrphanFragSize = rxp->rxi_OrphanFragSize;
3062 if (rxp->rx_maxReceiveSize)
3064 rx_maxReceiveSize = rxp->rx_maxReceiveSize;
3065 rx_maxReceiveSizeUser = rxp->rx_maxReceiveSize;
3067 if (rxp->rx_MyMaxSendSize)
3068 rx_MyMaxSendSize = rxp->rx_MyMaxSendSize;
3073 DECL_PIOCTL(PGetInitParams)
3075 if (sizeof(struct cm_initparams) > PIGGYSIZE)
3078 memcpy(aout, (char*)&cm_initParams, sizeof(struct cm_initparams));
3079 *aoutSize = sizeof(struct cm_initparams);
3083 #ifdef AFS_SGI65_ENV
3084 /* They took crget() from us, so fake it. */
3085 static cred_t *crget(void)
3088 cr = crdup(get_current_cred());
3089 memset((char*)cr, 0, sizeof(cred_t));
3090 #if CELL || CELL_PREPARE
3097 DECL_PIOCTL(PGetRxkcrypt)
3099 memcpy(aout, (char *)&cryptall, sizeof(afs_int32));
3100 *aoutSize=sizeof(afs_int32);
3104 DECL_PIOCTL(PSetRxkcrypt)
3108 if (!afs_osi_suser(*acred))
3110 if (ainSize != sizeof(afs_int32) || ain == NULL)
3112 memcpy((char *)&tmpval, ain, sizeof(afs_int32));
3113 /* if new mappings added later this will need to be changed */
3114 if (tmpval != 0 && tmpval != 1)
3121 * Create new credentials to correspond to a remote user with given
3122 * <hostaddr, uid, g0, g1>. This allows a server running as root to
3123 * provide pioctl (and other) services to foreign clients (i.e. nfs
3124 * clients) by using this call to `become' the client.
3127 #define PIOCTL_HEADER 6
3128 static int HandleClientContext(struct afs_ioctl *ablob, int *com, struct AFS_UCRED **acred, struct AFS_UCRED *credp)
3130 #if defined(AFS_DEC_ENV) || (defined(AFS_NONFSTRANS) && !defined(AFS_AIX_IAUTH_ENV))
3131 return EINVAL; /* NFS trans not supported for Ultrix */
3134 afs_uint32 hostaddr;
3135 afs_int32 uid, g0, g1, i, code, pag, exporter_type;
3136 struct afs_exporter *exporter, *outexporter;
3137 struct AFS_UCRED *newcred;
3138 struct unixuser *au;
3140 #if defined(AFS_SGIMP_ENV)
3141 osi_Assert(ISAFS_GLOCK());
3143 AFS_STATCNT(HandleClientContext);
3144 if (ablob->in_size < PIOCTL_HEADER*sizeof(afs_int32)) {
3145 /* Must at least include the PIOCTL_HEADER header words required by the protocol */
3146 return EINVAL; /* Too small to be good */
3148 ain = inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
3149 AFS_COPYIN(ablob->in, ain, PIOCTL_HEADER*sizeof(afs_int32), code);
3151 osi_FreeLargeSpace(inData);
3155 /* Extract information for remote user */
3156 hostaddr = *((afs_uint32 *)ain);
3157 ain += sizeof(hostaddr);
3158 uid = *((afs_uint32 *)ain);
3160 g0 = *((afs_uint32 *)ain);
3162 g1 = *((afs_uint32 *)ain);
3164 *com = *((afs_uint32 *)ain);
3165 ain += sizeof(afs_int32);
3166 exporter_type = *((afs_uint32 *)ain); /* In case we support more than NFS */
3169 * Of course, one must be root for most of these functions, but
3170 * we'll allow (for knfs) you to set things if the pag is 0 and
3171 * you're setting tokens or unlogging.
3174 if (!afs_osi_suser(credp)) {
3176 #ifndef AFS_SGI64_ENV
3177 /* Since SGI's suser() returns explicit failure after the call.. */
3181 /* check for acceptable opcodes for normal folks, which are, so far,
3182 * set tokens and unlog.
3184 if (i != 9 && i != 3 && i != 38 && i != 8) {
3185 osi_FreeLargeSpace(inData);
3190 ablob->in_size -= PIOCTL_HEADER*sizeof(afs_int32);
3191 ablob->in += PIOCTL_HEADER*sizeof(afs_int32);
3192 osi_FreeLargeSpace(inData);
3195 * We map uid 0 to nobody to match the mapping that the nfs
3196 * server does and to ensure that the suser() calls in the afs
3197 * code fails for remote client roots.
3199 uid = afs_nobody; /* NFS_NOBODY == -2 */
3202 #ifdef AFS_AIX41_ENV
3205 newcred->cr_gid = RMTUSER_REQ;
3206 newcred->cr_groups[0] = g0;
3207 newcred->cr_groups[1] = g1;
3209 newcred->cr_ngrps = 2;
3211 #if defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)
3212 newcred->cr_ngroups = 2;
3214 for (i=2; i<NGROUPS; i++)
3215 newcred->cr_groups[i] = NOGROUP;
3218 #if !defined(AFS_OSF_ENV) && !defined(AFS_DEC_ENV)
3219 afs_nfsclient_init(); /* before looking for exporter, ensure one exists */
3221 if (!(exporter = exporter_find(exporter_type))) {
3222 /* Exporter wasn't initialized or an invalid exporter type */
3226 if (exporter->exp_states & EXP_PWSYNC) {
3227 if (uid != credp->cr_uid) {
3229 return ENOEXEC; /* XXX Find a better errno XXX */
3232 newcred->cr_uid = uid; /* Only temporary */
3233 code = EXP_REQHANDLER(exporter, &newcred, hostaddr, &pag, &outexporter);
3234 /* The client's pag is the only unique identifier for it */
3235 newcred->cr_uid = pag;
3237 if (!code && *com == PSETPAG) {
3238 /* Special case for 'setpag' */
3239 afs_uint32 pagvalue = genpag();
3241 au = afs_GetUser(pagvalue, -1, WRITE_LOCK); /* a new unixuser struct */
3243 * Note that we leave the 'outexporter' struct held so it won't
3246 au->exporter = outexporter;
3247 if (ablob->out_size >= 4) {
3248 AFS_COPYOUT((char *)&pagvalue, ablob->out, sizeof(afs_int32), code);
3250 afs_PutUser(au, WRITE_LOCK);
3251 if (code) return code;
3252 return PSETPAG; /* Special return for setpag */
3254 EXP_RELE(outexporter);
3257 #endif /*defined(AFS_DEC_ENV) || defined(AFS_NONFSTRANS)*/
3260 /* get all interface addresses of this client */
3262 DECL_PIOCTL(PGetCPrefs)
3264 struct sprefrequest *spin; /* input */
3265 struct sprefinfo *spout; /* output */
3266 struct spref *srvout; /* one output component */
3270 AFS_STATCNT(PGetCPrefs);
3271 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3272 return EIO; /* Inappropriate ioctl for device */
3274 if ( ainSize < sizeof (struct sprefrequest ))
3277 spin = (struct sprefrequest *) ain;
3278 spout = (struct sprefinfo *) aout;
3280 maxNumber = spin->num_servers; /* max addrs this time */
3281 srvout = spout->servers;
3283 ObtainReadLock(&afs_xinterface);
3285 /* copy out the client interface information from the
3286 ** kernel data structure "interface" to the output buffer
3288 for ( i=spin->offset, j=0; (i < afs_cb_interface.numberOfInterfaces)
3289 && ( j< maxNumber) ; i++, j++, srvout++)
3290 srvout->host.s_addr = afs_cb_interface.addr_in[i];
3292 spout->num_servers = j;
3293 *aoutSize = sizeof(struct sprefinfo) +(j-1)* sizeof (struct spref);
3295 if ( i >= afs_cb_interface.numberOfInterfaces )
3296 spout->next_offset = 0; /* start from beginning again */
3298 spout->next_offset = spin->offset + j;
3300 ReleaseReadLock(&afs_xinterface);
3304 DECL_PIOCTL(PSetCPrefs)
3306 struct setspref *sin;
3309 AFS_STATCNT(PSetCPrefs);
3310 if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
3311 return EIO; /* Inappropriate ioctl for device */
3313 sin = (struct setspref *)ain;
3315 if ( ainSize < sizeof(struct setspref) )
3317 #if 0 /* num_servers is unsigned */
3318 if ( sin->num_servers < 0 )
3321 if ( sin->num_servers > AFS_MAX_INTERFACE_ADDR)
3324 ObtainWriteLock(&afs_xinterface, 412);
3325 afs_cb_interface.numberOfInterfaces = sin->num_servers;
3326 for ( i=0; (unsigned short)i < sin->num_servers; i++)
3327 afs_cb_interface.addr_in[i] = sin->servers[i].host.s_addr;
3329 ReleaseWriteLock(&afs_xinterface);
3333 DECL_PIOCTL(PFlushMount)
3335 register afs_int32 code;
3336 register struct vcache *tvc;
3337 register struct dcache *tdc;
3338 struct VenusFid tfid;
3340 struct sysname_info sysState;
3341 afs_size_t offset, len;
3343 AFS_STATCNT(PFlushMount);
3344 if (!avc) return EINVAL;
3345 code = afs_VerifyVCache(avc, areq);
3346 if (code) return code;
3347 if (vType(avc) != VDIR) {
3350 tdc = afs_GetDCache(avc, (afs_size_t) 0, areq, &offset, &len, 1);
3351 if (!tdc) return ENOENT;
3352 Check_AtSys(avc, ain, &sysState, areq);
3353 ObtainReadLock(&tdc->lock);
3355 code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
3356 } while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
3357 ReleaseReadLock(&tdc->lock);
3358 afs_PutDCache(tdc); /* we're done with the data */
3359 bufp = sysState.name;
3363 tfid.Cell = avc->fid.Cell;
3364 tfid.Fid.Volume = avc->fid.Fid.Volume;
3365 if (!tfid.Fid.Unique && (avc->states & CForeign)) {
3366 tvc = afs_LookupVCache(&tfid, areq, NULL, avc, bufp);
3368 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3374 if (tvc->mvstat != 1) {
3379 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3380 afs_BozonLock(&tvc->pvnLock, tvc); /* Since afs_TryToSmush will do a pvn_vptrunc */
3382 ObtainWriteLock(&tvc->lock,649);
3383 ObtainWriteLock(&afs_xcbhash, 650);
3384 afs_DequeueCallback(tvc);
3385 tvc->states &= ~(CStatd | CDirty); /* next reference will re-stat cache entry */
3386 ReleaseWriteLock(&afs_xcbhash);
3387 /* now find the disk cache entries */
3388 afs_TryToSmush(tvc, *acred, 1);
3389 osi_dnlc_purgedp(tvc);
3390 afs_symhint_inval(tvc);
3391 if (tvc->linkData && !(tvc->states & CCore)) {
3392 afs_osi_Free(tvc->linkData, strlen(tvc->linkData)+1);
3393 tvc->linkData = NULL;
3395 ReleaseWriteLock(&tvc->lock);
3396 #if defined(AFS_SUN_ENV) || defined(AFS_ALPHA_ENV) || defined(AFS_SUN5_ENV)
3397 afs_BozonUnlock(&tvc->pvnLock, tvc);
3401 if (sysState.allocked) osi_FreeLargeSpace(bufp);
3405 DECL_PIOCTL(PRxStatProc)
3410 if (!afs_osi_suser(*acred)) {
3414 if (ainSize != sizeof(afs_int32)) {
3418 memcpy((char *)&flags, ain, sizeof(afs_int32));
3419 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3423 if (flags & AFSCALL_RXSTATS_ENABLE) {
3424 rx_enableProcessRPCStats();
3426 if (flags & AFSCALL_RXSTATS_DISABLE) {
3427 rx_disableProcessRPCStats();
3429 if (flags & AFSCALL_RXSTATS_CLEAR) {
3430 rx_clearProcessRPCStats(AFS_RX_STATS_CLEAR_ALL);
3438 DECL_PIOCTL(PRxStatPeer)
3443 if (!afs_osi_suser(*acred)) {
3447 if (ainSize != sizeof(afs_int32)) {
3451 memcpy((char *)&flags, ain, sizeof(afs_int32));
3452 if (!(flags & AFSCALL_RXSTATS_MASK) || (flags & ~AFSCALL_RXSTATS_MASK)) {
3456 if (flags & AFSCALL_RXSTATS_ENABLE) {
3457 rx_enablePeerRPCStats();
3459 if (flags & AFSCALL_RXSTATS_DISABLE) {
3460 rx_disablePeerRPCStats();
3462 if (flags & AFSCALL_RXSTATS_CLEAR) {
3463 rx_clearPeerRPCStats(AFS_RX_STATS_CLEAR_ALL);
3470 DECL_PIOCTL(PPrefetchFromTape)
3472 register afs_int32 code, code1;
3475 struct rx_call *tcall;
3476 struct AFSVolSync tsync;
3477 struct AFSFetchStatus OutStatus;
3478 struct AFSCallBack CallBack;
3479 struct VenusFid tfid;
3484 AFS_STATCNT(PSetAcl);
3488 if (ain && (ainSize == 3 * sizeof(afs_int32)))
3489 Fid = (struct AFSFid *) ain;
3491 Fid = &avc->fid.Fid;
3492 tfid.Cell = avc->fid.Cell;
3493 tfid.Fid.Volume = Fid->Volume;
3494 tfid.Fid.Vnode = Fid->Vnode;
3495 tfid.Fid.Unique = Fid->Unique;
3497 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3499 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3500 ICL_TYPE_POINTER, tvc,
3501 ICL_TYPE_FID, &tfid,
3502 ICL_TYPE_FID, &avc->fid);
3505 afs_Trace3(afs_iclSetp, CM_TRACE_PREFETCHCMD,
3506 ICL_TYPE_POINTER, tvc,
3507 ICL_TYPE_FID, &tfid,
3508 ICL_TYPE_FID, &tvc->fid);
3511 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3515 tcall = rx_NewCall(tc->id);
3516 code = StartRXAFS_FetchData(tcall,
3517 (struct AFSFid *) &tvc->fid.Fid, 0, 0);
3519 bytes = rx_Read(tcall, (char *) aout, sizeof(afs_int32));
3520 code = EndRXAFS_FetchData(tcall, &OutStatus, &CallBack, &tsync);
3522 code1 = rx_EndCall(tcall, code);
3527 (afs_Analyze(tc, code, &tvc->fid, areq,
3528 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3530 /* This call is done only to have the callback things handled correctly */
3531 afs_FetchStatus(tvc, &tfid, areq, &OutStatus);
3535 *aoutSize = sizeof(afs_int32);
3540 DECL_PIOCTL(PResidencyCmd)
3542 register afs_int32 code;
3545 struct ResidencyCmdInputs *Inputs;
3546 struct ResidencyCmdOutputs *Outputs;
3547 struct VenusFid tfid;
3550 Inputs = (struct ResidencyCmdInputs *) ain;
3551 Outputs = (struct ResidencyCmdOutputs *) aout;
3552 if (!avc) return EINVAL;
3553 if (!ain || ainSize != sizeof(struct ResidencyCmdInputs)) return EINVAL;
3557 Fid = &avc->fid.Fid;
3559 tfid.Cell = avc->fid.Cell;
3560 tfid.Fid.Volume = Fid->Volume;
3561 tfid.Fid.Vnode = Fid->Vnode;
3562 tfid.Fid.Unique = Fid->Unique;
3564 tvc = afs_GetVCache(&tfid, areq, NULL, NULL);
3565 afs_Trace3(afs_iclSetp, CM_TRACE_RESIDCMD,
3566 ICL_TYPE_POINTER, tvc,
3567 ICL_TYPE_INT32, Inputs->command,
3568 ICL_TYPE_FID, &tfid);
3572 if (Inputs->command) {
3574 tc = afs_Conn(&tvc->fid, areq, SHARED_LOCK);
3577 code = RXAFS_ResidencyCmd(tc->id, Fid,
3579 (struct ResidencyCmdOutputs *) aout);
3584 (afs_Analyze(tc, code, &tvc->fid, areq,
3585 AFS_STATS_FS_RPCIDX_RESIDENCYRPCS, SHARED_LOCK,
3587 /* This call is done to have the callback things handled correctly */
3588 afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3589 } else { /* just a status request, return also link data */
3591 Outputs->code = afs_FetchStatus(tvc, &tfid, areq, &Outputs->status);
3592 Outputs->chars[0] = 0;
3593 if (vType(tvc) == VLNK) {
3594 ObtainWriteLock(&tvc->lock,555);
3595 if (afs_HandleLink(tvc, areq) == 0)
3596 strncpy((char *) &Outputs->chars, tvc->linkData, MAXCMDCHARS);
3597 ReleaseWriteLock(&tvc->lock);
3604 *aoutSize = sizeof(struct ResidencyCmdOutputs);