| /* |
| * dnode.c - Solaris node reading functions for lsof |
| */ |
| |
| |
| /* |
| * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana |
| * 47907. All rights reserved. |
| * |
| * Written by Victor A. Abell |
| * |
| * This software is not subject to any license of the American Telephone |
| * and Telegraph Company or the Regents of the University of California. |
| * |
| * Permission is granted to anyone to use this software for any purpose on |
| * any computer system, and to alter it and redistribute it freely, subject |
| * to the following restrictions: |
| * |
| * 1. Neither the authors nor Purdue University are responsible for any |
| * consequences of the use of this software. |
| * |
| * 2. The origin of this software must not be misrepresented, either by |
| * explicit claim or by omission. Credit to the authors and Purdue |
| * University must appear in documentation and sources. |
| * |
| * 3. Altered versions must be plainly marked as such, and must not be |
| * misrepresented as being the original software. |
| * |
| * 4. This notice may not be removed or altered. |
| */ |
| |
| #ifndef lint |
| static char copyright[] = |
| "@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; |
| static char *rcsid = "$Id: dnode.c,v 1.58 2011/08/07 22:53:42 abe Exp $"; |
| #endif |
| |
| |
| #include "lsof.h" |
| |
| #if solaris>=110000 |
| #include <sys/fs/sdev_impl.h> |
| #endif /* solaris>=110000 */ |
| |
| #undef fs_bsize |
| #include <sys/fs/ufs_inode.h> |
| |
| |
| #if solaris>=110000 && defined(HAS_LIBCTF) |
| /* |
| * Sockfs support for Solaris 11 via libctf |
| */ |
| |
| |
| /* |
| * Sockfs internal structure definitions |
| * |
| * The structure definitions may look like kernel structures, but they are |
| * not. They have been defined to have member names that duplicate those |
| * used by the kernel that are of interest to lsof. Member values are |
| * obtained via the CTF library, libctf. |
| * |
| * Robert Byrnes developed the CTF library access code and contributed it |
| * to lsof. |
| */ |
| |
| struct soaddr { /* sadly, CTF doesn't grok this |
| * structure */ |
| struct sockaddr *soa_sa; /* address */ |
| t_uscalar_t soa_len; /* length in bytes */ |
| t_uscalar_t soa_maxlen; /* maximum length */ |
| }; |
| |
| typedef struct sotpi_info { |
| dev_t sti_dev; /* sonode device */ |
| struct soaddr sti_laddr; /* local address */ |
| struct soaddr sti_faddr; /* peer address */ |
| struct so_ux_addr sti_ux_laddr; /* bound local address */ |
| struct so_ux_addr sti_ux_faddr; /* bound peer address */ |
| t_scalar_t sti_serv_type; /* service type */ |
| } sotpi_info_t; |
| |
| |
| /* |
| * CTF definitions for sockfs |
| */ |
| |
| static int Sockfs_ctfs = 0; /* CTF initialization status for |
| * sockfs */ |
| |
| # if defined(_LP64) |
| #define SOCKFS_MOD_FORMAT "/kernel/fs/%s/sockfs" |
| # else /* !defined(_LP64) */ |
| #define SOCKFS_MOD_FORMAT "/kernel/fs/sockfs" |
| # endif /* defined(_LP64) */ |
| |
| /* sockfs module pathname template to |
| * which the kernel's instruction type |
| * set is added for CTF access */ |
| |
| |
| /* |
| * Sockfs access definitions and structures |
| */ |
| |
| #define SOADDR_TYPE_NAME "soaddr" |
| |
| static CTF_member_t soaddr_members[] = { |
| CTF_MEMBER(soa_sa), |
| #define MX_soa_sa 0 |
| |
| CTF_MEMBER(soa_len), |
| #define MX_soa_len 1 |
| |
| CTF_MEMBER(soa_maxlen), |
| #define MX_soa_maxlen 2 |
| |
| { NULL, 0 } |
| }; |
| |
| |
| #define SOTPI_INFO_TYPE_NAME "sotpi_info_t" |
| |
| static CTF_member_t sotpi_info_members[] = { |
| CTF_MEMBER(sti_dev), |
| #define MX_sti_dev 0 |
| |
| CTF_MEMBER(sti_laddr), |
| #define MX_sti_laddr 1 |
| |
| CTF_MEMBER(sti_faddr), |
| #define MX_sti_faddr 2 |
| |
| CTF_MEMBER(sti_ux_laddr), |
| #define MX_sti_ux_laddr 3 |
| |
| CTF_MEMBER(sti_ux_faddr), |
| #define MX_sti_ux_faddr 4 |
| |
| CTF_MEMBER(sti_serv_type), |
| #define MX_sti_serv_type 5 |
| |
| { NULL, 0 } |
| }; |
| |
| |
| /* |
| * CTF sockfs request table |
| */ |
| |
| static CTF_request_t Sockfs_requests[] = { |
| { SOTPI_INFO_TYPE_NAME, sotpi_info_members }, |
| { NULL, NULL } |
| }; |
| |
| |
| /* |
| * Sockfs function prototypes |
| */ |
| |
| _PROTOTYPE(static int read_nsti,(struct sonode *so, sotpi_info_t *stpi)); |
| #endif /* solaris>=110000 && defined(HAS_LIBCTF) */ |
| |
| |
| #if defined(HAS_ZFS) && defined(HAS_LIBCTF) |
| /* |
| * ZFS support via libctf |
| */ |
| |
| |
| /* |
| * ZFS internal structure definitions |
| * |
| * The structure definitions may look like kernel structures, but they are |
| * not. They have been defined to have member names that duplicate those |
| * used by the kernel that are of interest to lsof. Member values are |
| * obtained via the CTF library, libctf. |
| * |
| * Robert Byrnes developed the CTF library access code and contributed it |
| * to lsof. |
| */ |
| |
| typedef struct zfsvfs { |
| vfs_t *z_vfs; /* pointer to VFS */ |
| } zfsvfs_t; |
| |
| typedef struct znode_phys { |
| uint64_t zp_size; /* file size (ZFS below 5) */ |
| uint64_t zp_links; /* links (ZFS below 5) */ |
| } znode_phys_t; |
| |
| typedef struct znode { |
| zfsvfs_t *z_zfsvfs; /* pointer to associated vfs */ |
| vnode_t *z_vnode; /* pointer to associated vnode */ |
| uint64_t z_id; /* node ID */ |
| znode_phys_t *z_phys; /* pointer to persistent znode (ZFS |
| * below 5) */ |
| uint64_t z_links; /* links (ZFS 5 and above) */ |
| uint64_t z_size; /* file size (ZFS 5 and above) */ |
| } znode_t; |
| |
| |
| /* |
| * CTF definitions for ZFS |
| */ |
| |
| static int ZFS_ctfs = 0; /* CTF initialization status for ZFS */ |
| |
| # if defined(_LP64) |
| #define ZFS_MOD_FORMAT "/kernel/fs/%s/zfs" |
| # else /* !defined(_LP64) */ |
| #define ZFS_MOD_FORMAT "/kernel/fs/zfs" |
| # endif /* defined(_LP64) */ |
| |
| /* ZFS module pathname template to |
| * which the kernel's instruction type |
| * set is added for CTF access */ |
| |
| /* |
| * ZFS access definitions and structures |
| */ |
| |
| #define ZNODE_TYPE_NAME "znode_t" |
| |
| static CTF_member_t znode_members[] = { |
| CTF_MEMBER(z_zfsvfs), |
| #define MX_z_zfsvfs 0 |
| |
| CTF_MEMBER(z_vnode), |
| #define MX_z_vnode 1 |
| |
| CTF_MEMBER(z_id), |
| #define MX_z_id 2 |
| |
| CTF_MEMBER(z_link_node), |
| #define MX_z_link_node 3 |
| |
| CTF_MEMBER(z_phys), |
| #define MX_z_phys 4 |
| |
| CTF_MEMBER(z_links), |
| #define MX_z_links 5 |
| |
| CTF_MEMBER(z_size), |
| #define MX_z_size 6 |
| |
| { NULL, 0 } |
| }; |
| |
| |
| #define ZNODE_PHYS_TYPE_NAME "znode_phys_t" |
| |
| static CTF_member_t znode_phys_members[] = { |
| CTF_MEMBER(zp_size), |
| #define MX_zp_size 0 |
| |
| CTF_MEMBER(zp_links), |
| #define MX_zp_links 1 |
| |
| { NULL, 0 } |
| }; |
| |
| |
| #define ZFSVFS_TYPE_NAME "zfsvfs_t" |
| |
| static CTF_member_t zfsvfs_members[] = { |
| CTF_MEMBER(z_vfs), |
| #define MX_z_vfs 0 |
| |
| { NULL, 0 } |
| }; |
| |
| |
| /* |
| * CTF ZFS request table |
| */ |
| |
| static CTF_request_t ZFS_requests[] = { |
| { ZNODE_TYPE_NAME, znode_members }, |
| { ZNODE_PHYS_TYPE_NAME, znode_phys_members }, |
| { ZFSVFS_TYPE_NAME, zfsvfs_members }, |
| { NULL, NULL } |
| }; |
| |
| |
| /* |
| * Missing members exceptions -- i.e., CTF_getmem won't consider it |
| * an error if any of these members are undefined. |
| */ |
| |
| typedef struct CTF_exception { |
| char *tynm; /* type name */ |
| char *memnm; /* member name */ |
| } CTF_exception_t; |
| |
| static CTF_exception_t CTF_exceptions[] = { |
| { ZNODE_TYPE_NAME, "z_phys" }, |
| { ZNODE_TYPE_NAME, "z_links" }, |
| { ZNODE_TYPE_NAME, "z_size" }, |
| { NULL, NULL } |
| }; |
| |
| |
| /* |
| * ZFS function prototypes |
| */ |
| |
| _PROTOTYPE(static int read_nzn,(KA_T na, KA_T nza, znode_t *z)); |
| _PROTOTYPE(static int read_nznp,(KA_T nza, KA_T nzpa, znode_phys_t *zp)); |
| _PROTOTYPE(static int read_nzvfs,(KA_T nza, KA_T nzva, zfsvfs_t *zv)); |
| #endif /* defined(HAS_ZFS) && defined(HAS_LIBCTF) */ |
| |
| |
| _PROTOTYPE(static struct l_dev *finddev,(dev_t *dev, dev_t *rdev, int flags)); |
| |
| |
| /* |
| * Finddev() "look-in " flags |
| */ |
| |
| #define LOOKDEV_TAB 0x01 /* look in device table */ |
| #define LOOKDEV_CLONE 0x02 /* look in Clone table */ |
| #define LOOKDEV_PSEUDO 0x04 /* look in Pseudo table */ |
| #define LOOKDEV_ALL (LOOKDEV_TAB | LOOKDEV_CLONE | LOOKDEV_PSEUDO) |
| /* look all places */ |
| |
| |
| /* |
| * SAM-FS definitions |
| */ |
| |
| #define SAMFS_NMA_MSG "(limited SAM-FS info)" |
| |
| |
| /* |
| * Voptab definitions |
| */ |
| |
| typedef struct build_v_optab { |
| char *dnm; /* drive_NL name */ |
| char *fsys; /* file system type name */ |
| int nty; /* node type index (i.e., N_*) */ |
| } build_v_optab_t; |
| |
| static build_v_optab_t Build_v_optab[] = { |
| { "auvops", "autofs", N_AUTO }, |
| { "avops", "afs", N_AFS }, |
| { "afsops", "afs", N_AFS }, |
| { "ctfsadir", NULL, N_CTFSADIR }, |
| { "ctfsbund", NULL, N_CTFSBUND }, |
| { "ctfscdir", NULL, N_CTFSCDIR }, |
| { "ctfsctl", NULL, N_CTFSCTL }, |
| { "ctfsevt", NULL, N_CTFSEVT }, |
| { "ctfslate", NULL, N_CTFSLATE }, |
| { "ctfsroot", NULL, N_CTFSROOT }, |
| { "ctfsstat", NULL, N_CTFSSTAT }, |
| { "ctfssym", NULL, N_CTFSSYM }, |
| { "ctfstdir", NULL, N_CTFSTDIR }, |
| { "ctfstmpl", NULL, N_CTFSTMPL }, |
| { "cvops", NULL, N_CACHE }, |
| { "devops", "devfs", N_DEV }, |
| { "doorops", NULL, N_DOOR }, |
| { "fdops", "fd", N_FD }, |
| { "fd_ops", "fd", N_FD }, |
| { "fvops", "fifofs", N_FIFO }, |
| { "hvops", "hsfs", N_HSFS }, |
| { "lvops", "lofs", N_LOFS }, |
| { "mntops", "mntfs", N_MNT }, |
| { "mvops", "mvfs", N_MVFS }, |
| { "n3vops", NULL, N_NFS }, |
| |
| #if solaris>=100000 |
| { "n4vops", NULL, N_NFS4 }, |
| #else /* solaris<100000 */ |
| { "n4vops", NULL, N_NFS }, |
| #endif /* solaris>=100000 */ |
| |
| { "nmvops", "namefs", N_NM }, |
| { "nvops", NULL, N_NFS }, |
| { "pdvops", "pcfs", N_PCFS }, |
| { "pfvops", "pcfs", N_PCFS }, |
| { "portvops", NULL, N_PORT }, |
| { "prvops", "proc", N_PROC }, |
| { "sam1vops", NULL, N_SAMFS }, |
| { "sam2vops", NULL, N_SAMFS }, |
| { "sam3vops", NULL, N_SAMFS }, |
| { "sam4vops", NULL, N_SAMFS }, |
| { "sckvops", "sockfs", N_SOCK }, |
| { "devipnetops", "sdevfs", N_SDEV }, |
| { "devnetops", "sdevfs", N_SDEV }, |
| { "devptsops", "sdevfs", N_SDEV }, |
| { "devvtops", "sdevfs", N_SDEV }, |
| { "socketvops", "sockfs", N_SOCK }, |
| { "sdevops", "sdevfs", N_SDEV }, |
| { "shvops", "sharedfs", N_SHARED }, |
| { "sncavops", "sockfs", N_SOCK }, |
| { "stpivops", "sockfs", N_SOCK }, |
| { "spvops", "specfs", N_REGLR }, |
| { "tvops", "tmpfs", N_TMP }, |
| { "uvops", "ufs", N_REGLR }, |
| { "vvfclops", "vxfs", N_VXFS }, |
| { "vvfops", "vxfs", N_VXFS }, |
| { "vvfcops", "vxfs", N_VXFS }, |
| { "vvops", "vxfs", N_VXFS }, |
| { "vvops_p", "vxfs", N_VXFS }, |
| { "zfsdops", "zfs", N_ZFS }, |
| { "zfseops", "zfs", N_ZFS }, |
| { "zfsfops", "zfs", N_ZFS }, |
| { "zfsshops", "zfs", N_ZFS }, |
| { "zfssymops", "zfs", N_ZFS }, |
| { "zfsxdops", "zfs", N_ZFS }, |
| { NULL, NULL, 0 } /* table end */ |
| }; |
| |
| typedef struct v_optab { |
| char *fsys; /* file system type name */ |
| int fx; /* Fsinfo[] index (-1 if none) */ |
| int nty; /* node type index (i.e., N_*) */ |
| KA_T v_op; /* vnodeops address */ |
| struct v_optab *next; /* next entry */ |
| } v_optab_t; |
| |
| static v_optab_t **FxToVoptab = (v_optab_t **)NULL; |
| /* table to convert file system index |
| * to Voptab address[] -- built by |
| * build_Voptab() */ |
| static v_optab_t **Voptab = (v_optab_t **)NULL; |
| /* table to convert vnode v_op |
| * addresses to file system name and |
| * node type -- built by build_Voptab() |
| * and addressed through the HASHVOP() |
| * macro */ |
| |
| #define VOPHASHBINS 256 /* number of Voptab[] hash bins -- |
| * MUST BE A POWER OF TWO! */ |
| |
| |
| /* |
| * Local function prototypes |
| */ |
| |
| _PROTOTYPE(static void build_Voptab,(void)); |
| _PROTOTYPE(static char isvlocked,(struct vnode *va)); |
| _PROTOTYPE(static int readinode,(KA_T ia, struct inode *i)); |
| _PROTOTYPE(static void read_mi,(KA_T s, dev_t *dev, caddr_t so, int *so_st, KA_T *so_ad, struct l_dev **sdp)); |
| |
| |
| #if solaris>=20500 |
| # if solaris>=20600 |
| _PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct fnnode *rn)); |
| _PROTOTYPE(static int read_nson,(KA_T na, KA_T sa, struct sonode *sn)); |
| _PROTOTYPE(static int read_nusa,(struct soaddr *so, struct sockaddr_un *ua)); |
| # else /* solaris<20600 */ |
| _PROTOTYPE(static int read_nan,(KA_T na, KA_T aa, struct autonode *a)); |
| # endif /* solaris>=20600 */ |
| _PROTOTYPE(static int idoorkeep,(struct door_node *d)); |
| _PROTOTYPE(static int read_ndn,(KA_T na, KA_T da, struct door_node *d)); |
| #endif /* solaris>=20500 */ |
| |
| #if solaris>=110000 |
| _PROTOTYPE(static int read_nsdn,(KA_T na, KA_T sa, struct sdev_node *sdn, struct vattr *sdva)); |
| #endif /* solaris>=110000 */ |
| |
| _PROTOTYPE(static int read_nfn,(KA_T na, KA_T fa, struct fifonode *f)); |
| _PROTOTYPE(static int read_nhn,(KA_T na, KA_T ha, struct hsnode *h)); |
| _PROTOTYPE(static int read_nin,(KA_T na, KA_T ia, struct inode *i)); |
| _PROTOTYPE(static int read_nmn,(KA_T na, KA_T ia, struct mvfsnode *m)); |
| _PROTOTYPE(static int read_npn,(KA_T na, KA_T pa, struct pcnode *p)); |
| _PROTOTYPE(static int read_nrn,(KA_T na, KA_T ra, struct rnode *r)); |
| |
| #if solaris>=100000 |
| _PROTOTYPE(static int read_nctfsn,(int ty, KA_T na, KA_T ca, char *cn)); |
| _PROTOTYPE(static int read_nprtn,(KA_T na, KA_T ra, port_t *p)); |
| _PROTOTYPE(static int read_nrn4,(KA_T na, KA_T ra, struct rnode4 *r)); |
| #endif /* solaris>=100000 */ |
| |
| _PROTOTYPE(static int read_nsn,(KA_T na, KA_T sa, struct snode *s)); |
| _PROTOTYPE(static int read_ntn,(KA_T na, KA_T ta, struct tmpnode *t)); |
| _PROTOTYPE(static int read_nvn,(KA_T na, KA_T va, struct vnode *v)); |
| |
| #if defined(HASPROCFS) |
| _PROTOTYPE(static int read_npi,(KA_T na, struct vnode *v, struct pid *pids)); |
| #endif /* defined(HASPROCFS) */ |
| |
| _PROTOTYPE(static char *ent_fa,(KA_T *a1, KA_T *a2, char *d, int *len)); |
| _PROTOTYPE(static int is_socket,(struct vnode *v)); |
| _PROTOTYPE(static int read_cni,(struct snode *s, struct vnode *rv, |
| struct vnode *v, struct snode *rs, struct dev_info *di, char *din, |
| int dinl)); |
| _PROTOTYPE(static int read_ncn,(KA_T na, KA_T ca, struct cnode *cn)); |
| _PROTOTYPE(static int read_nln,(KA_T na, KA_T la, struct lnode *ln)); |
| _PROTOTYPE(static int read_nnn,(KA_T na, KA_T nna, struct namenode *n)); |
| |
| #if solaris<100000 |
| _PROTOTYPE(static void savesockmod,(struct so_so *so, struct so_so *sop, int *so_st)); |
| #else /* solaris>=100000 */ |
| _PROTOTYPE(static int read_ndvn,(KA_T na, KA_T da, struct dv_node *dv, |
| dev_t *dev, unsigned char *devs)); |
| #endif /* solaris<100000 */ |
| |
| |
| /* |
| * Local static values |
| */ |
| |
| static KA_T Spvops = (KA_T)0; /* specfs vnodeops address -- saved |
| * by build_Voptab() */ |
| static KA_T Vvops[VXVOP_NUM]; /* addresses of: |
| * vx_fcl_dnodeops_p (VXVOP_FCL) |
| * fdd_vnops (VXVOP_FDD) |
| * fdd_chain_vnops (VXVOP_FDDCH), |
| * vx_vnodeops (VXVOP_REG) |
| * vx_vnodeops_p (VXVOP_REG_P) |
| * -- saved by build_Voptab() */ |
| |
| /* |
| * Local macros |
| * |
| * GETVOPS() -- get direct or indirect *vnodeops address |
| * |
| * HASHVOP() -- hash the vnode's v_op address |
| */ |
| |
| #if defined(VOPNAME_OPEN) && solaris>=100000 |
| #define GETVOPS(name, nl, ops) \ |
| if (get_Nl_value(name, nl, &ops) < 0) \ |
| ops = (KA_T)0; \ |
| else if (kread(ops, (char *)&ops, sizeof(ops))) \ |
| ops = (KA_T)0 |
| #else /* !defined(VOPNAME_OPEN) || solaris<100000 */ |
| #define GETVOPS(name, nl, ops) \ |
| if (get_Nl_value(name, nl, &ops) < 0) \ |
| ops = (KA_T)0 |
| #endif /* defined(VOPNAME_OPEN) && solaris>=100000 */ |
| |
| #define HASHVOP(ka) ((int)((((ka &0x1fffffff) * 31415) >> 3) & \ |
| (VOPHASHBINS - 1))) |
| |
| |
| /* |
| * build_Voptab() -- build Voptab[] |
| */ |
| |
| static void |
| build_Voptab() |
| { |
| build_v_optab_t *bp; /* Build_v_optab[] pointer */ |
| int fx; /* temporary file system type index */ |
| int h; /* hash index */ |
| int i, j; /* temporary indexes */ |
| KA_T ka; /* temporary kernel address */ |
| v_optab_t *nv, *vp, *vpp; /* Voptab[] working pointers */ |
| int vv = 0; /* number of Vvops[] addresses that |
| * have been located */ |
| /* |
| * If Voptab[] is allocated, return; otherwise allocate space for Voptab[] |
| * and FxToVoptab[] amd fill them. |
| */ |
| if (Voptab) |
| return; |
| /* |
| * During first call, allocate space for Voptab[] and FxToVoptab[]. |
| */ |
| |
| if (!(Voptab = (v_optab_t **)calloc((MALLOC_S)VOPHASHBINS, |
| sizeof(v_optab_t))) |
| ) { |
| (void) fprintf(stderr, "%s: no space for Voptab\n", Pn); |
| Exit(1); |
| } |
| if (!(FxToVoptab = (v_optab_t **)calloc((MALLOC_S)Fsinfomax, |
| sizeof(v_optab_t *))) |
| ) { |
| (void) fprintf(stderr, "%s: no space for FxToVoptab\n", Pn); |
| Exit(1); |
| } |
| for (i = 0; i < VXVOP_NUM; i++) { |
| Vvops[i] = (KA_T)NULL; |
| } |
| /* |
| * Use Build_v_optab[] to build Voptab[]. |
| */ |
| for (bp = Build_v_optab; bp->dnm; bp++) { |
| |
| /* |
| * Get the kernel address for the symbol. Do nothing if it can't |
| * be determined. |
| */ |
| GETVOPS(bp->dnm, Drive_Nl, ka); |
| if (!ka) |
| continue; |
| /* |
| * Check the Voptab[] for the address. |
| */ |
| h = HASHVOP(ka); |
| for (vp = Voptab[h], vpp = (v_optab_t *)NULL; vp; vp = vp->next) { |
| if (vp->v_op == ka) |
| break; |
| vpp = vp; |
| } |
| if (vp) { |
| |
| /* |
| * Ignore duplicates. |
| */ |
| continue; |
| } |
| /* |
| * No Voptab[] entry was found, so allocate space for a new |
| * v_optab_t structure, determine its file system type index, |
| * fill it and link it to the Voptab[]. |
| */ |
| if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) { |
| (void) fprintf(stderr, "%s: out of Voptab space at: %s\n", |
| Pn, bp->dnm); |
| Exit(1); |
| } |
| nv->fsys = bp->fsys; |
| nv->fx = -1; |
| nv->nty = bp->nty; |
| nv->next = (v_optab_t *)NULL; |
| nv->v_op = ka; |
| if (bp->fsys) { |
| for (i = 0; i < Fsinfomax; i++) { |
| if (!strcmp(bp->fsys, Fsinfo[i])) { |
| nv->fx = i; |
| break; |
| } |
| } |
| } |
| if (!Voptab[h]) |
| Voptab[h] = nv; |
| else |
| vpp->next = nv; |
| /* |
| * Handle special v_op addresses: |
| * |
| * special vnode ops; |
| * VxFS ops. |
| */ |
| if (!Spvops) { |
| if (!strcmp(bp->dnm, "spvops")) |
| Spvops = ka; |
| } |
| for (i = 0; (i < VXVOP_NUM) && (vv < VXVOP_NUM); i++) { |
| if (Vvops[i]) |
| continue; |
| switch (i) { |
| case VXVOP_FCL: |
| if (!strcmp(bp->dnm, "vvfclops")) { |
| Vvops[i] = ka; |
| vv++; |
| } |
| break; |
| case VXVOP_FDD: |
| if (!strcmp(bp->dnm, "vvfops")) { |
| Vvops[i] = ka; |
| vv++; |
| } |
| break; |
| case VXVOP_FDDCH: |
| if (!strcmp(bp->dnm, "vvfcops")) { |
| Vvops[i] = ka; |
| vv++; |
| } |
| break; |
| case VXVOP_REG: |
| if (!strcmp(bp->dnm, "vvops")) { |
| Vvops[i] = ka; |
| vv++; |
| } |
| break; |
| case VXVOP_REG_P: |
| if (!strcmp(bp->dnm, "vvops_p")) { |
| Vvops[i] = ka; |
| vv++; |
| } |
| break; |
| } |
| } |
| } |
| /* |
| * Link Voptab[] entries to FxToVoptab[] entries. |
| */ |
| for (h = 0; h < VOPHASHBINS; h++) { |
| for (vp = Voptab[h]; vp; vp = vp->next) { |
| if (!vp->fsys) |
| continue; |
| if (((fx = vp->fx) >= 0) && (fx < Fsinfomax)) { |
| if (!FxToVoptab[fx]) |
| FxToVoptab[fx] = vp; |
| continue; |
| } |
| for (i = 0; i < Fsinfomax; i++) { |
| if (!strcmp(Fsinfo[i], vp->fsys)) { |
| vp->fx = i; |
| if (!FxToVoptab[i]) |
| FxToVoptab[i] = vp; |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| |
| #if defined(HAS_LIBCTF) |
| /* |
| * CTF_getmem() -- get CTF members |
| */ |
| |
| int |
| CTF_getmem(f, mod, ty, mem) |
| ctf_file_t *f; /* CTF file handle */ |
| const char *mod; /* module name */ |
| const char *ty; /* type */ |
| CTF_member_t *mem; /* member table */ |
| { |
| int err; /* error flag */ |
| ctf_id_t id; /* CTF ID */ |
| CTF_member_t *mp; /* member pointer */ |
| CTF_exception_t *xp; /* exception table pointer */ |
| int xs; /* exception status */ |
| /* |
| * Look up the type. |
| */ |
| if ((id = ctf_lookup_by_name(f, ty)) == CTF_ERR) { |
| (void) fprintf(stderr, "%s: ctf_lookup_by_name: %s: %s: %s\n", |
| Pn, mod, ty, ctf_errmsg(ctf_errno(f))); |
| return(1); |
| } |
| /* |
| * Get member offsets. |
| */ |
| if (ctf_member_iter(f, id, CTF_memCB, mem) == CTF_ERR) { |
| (void) fprintf(stderr, "%s: ctf_member_iter: %s: %s: %s\n", |
| Pn, mod, ty, ctf_errmsg(ctf_errno(f))); |
| return(1); |
| } |
| /* |
| * Examine members. |
| */ |
| for (err = 0, mp = mem; mp->m_name; mp++) { |
| if (mp->m_offset == CTF_MEMBER_UNDEF) { |
| |
| /* |
| * Check for an undefined member exception. Report an error if |
| * no exception is found. |
| */ |
| for (xp = CTF_exceptions, xs = 0; xp->tynm; xp++) { |
| if (!strcmp(xp->tynm, ty) && !strcmp(xp->memnm, mp->m_name)) { |
| xs = 1; |
| break; |
| } |
| } |
| if (!xs) { |
| (void) fprintf(stderr, |
| "%s: getmembers: %s: %s: %s: struct member undefined\n", |
| Pn, mod, ty, mp->m_name); |
| err = 1; |
| } |
| } else { |
| |
| /* |
| * Convert bit offsets to byte offsets. |
| */ |
| if ((mp->m_offset % NBBY) != 0) { |
| (void) fprintf(stderr, |
| "%s: getmembers: %s: %s: %s: struct member is bit field\n", |
| Pn, mod, ty, mp->m_name); |
| err = 1; |
| } else |
| mp->m_offset /= NBBY; |
| } |
| } |
| return(err); |
| } |
| |
| |
| /* |
| * CTF_init - initialize CTF library access |
| */ |
| |
| void |
| CTF_init(i, t, r) |
| int *i; /* initialization status */ |
| char *t; /* kernel module template */ |
| CTF_request_t *r; /* CTF requests */ |
| { |
| int err; /* error status */ |
| ctf_file_t *f; /* CTF file info handle */ |
| |
| # if defined(_LP64) |
| static char isa[256+1]; /* kernel instruction set name */ |
| static int isas = 0; /* isa[] status */ |
| # endif /* defined(_LP64) */ |
| |
| char kernmod[MAXPATHLEN]; /* kernel module pathname */ |
| char *kmp; /* kernel module path name pointer */ |
| static char pfn[256+1]; /* system platform name */ |
| static int pfns = 0; /* pfn[] status: -1 = request failed |
| * 0 = none requested |
| * >0 = available */ |
| char pfxkernmod[MAXPATHLEN]; /* prefixed kernel module name */ |
| struct stat sb; /* stat(2) buffer */ |
| |
| if (*i) |
| return; |
| |
| # if defined(_LP64) |
| /* |
| * If CTF access hasn't been initialized and a 64 bit kernel is in use, |
| * determine the name of the kernel's instruction set, and construct the |
| * pathname of the kernel module, using the supplied template. |
| */ |
| if (!isas) { |
| if (sysinfo(SI_ARCHITECTURE_K, isa, sizeof(isa) - 1) == -1) { |
| (void) fprintf(stderr, "%s: sysinfo: %s\n", Pn, strerror(errno)); |
| Exit(1); |
| } |
| isas = 1; |
| isa[sizeof(isa) - 1] = '\0'; |
| } |
| (void) snprintf(kernmod, sizeof(kernmod) - 1, t, isa); |
| kernmod[sizeof(kernmod) - 1] = '\0'; |
| # else /* !defined(_LP64) */ |
| /* |
| * If CTF access hasn't been initialized and a 32 bit kernel is in use, the |
| * supplied template is the module path name. |
| */ |
| (void) strncpy(kernmod, t, sizeof(kernmod) - 1); |
| # endif /* defined(_LP64) */ |
| |
| kernmod[sizeof(kernmod) - 1] = '\0'; |
| kmp = kernmod; |
| if (statsafely(kmp, &sb)) { |
| |
| /* |
| * The module at the specified path does not exist or is inaccessible. |
| * |
| * Get the platform name and construct a prefix from it for module path |
| * name and see if that exists and is accessible. |
| * |
| * If it is, let CTF_init() use it; otherwise let CTF_init() fail on |
| * the specified path. |
| */ |
| if (pfns >= 0) { |
| if (!pfns) |
| pfns = sysinfo(SI_MACHINE, pfn, sizeof(pfn) - 1); |
| if (pfns > 0) { |
| pfn[sizeof(pfn) - 1] = '\0'; |
| (void) snprintf(pfxkernmod, sizeof(pfxkernmod) - 1, |
| "/platform/%s/%s", pfn, |
| (kernmod[0] == '/') ? &kernmod[1] : kernmod); |
| pfxkernmod[sizeof(pfxkernmod) - 1] = '\0'; |
| if (!stat(pfxkernmod, &sb)) |
| kmp = pfxkernmod; |
| } |
| } |
| } |
| /* |
| * Open the module file and read its CTF info. |
| */ |
| if ((f = ctf_open(kmp, &err)) == NULL) { |
| (void) fprintf(stderr, "%s: ctf_open: %s: %s\n", |
| Pn, kmp, ctf_errmsg(err)); |
| Exit(1); |
| } |
| for (err = 0; r->name; r++) { |
| if (CTF_getmem(f, kmp, r->name, r->mem)) |
| err = 1; |
| } |
| (void) ctf_close(f); |
| if (err) |
| Exit(1); |
| *i = 1; |
| } |
| |
| |
| /* |
| * CTF_memCB() - Callback function for ctf_member_iter() |
| */ |
| |
| int |
| CTF_memCB(name, id, offset, arg) |
| const char *name; /* structure member name */ |
| ctf_id_t id; /* CTF ID */ |
| ulong_t offset; /* member offset */ |
| void *arg; /* member table */ |
| { |
| CTF_member_t *mp; |
| /* |
| * Check for members of interest and record their offsets. |
| */ |
| for (mp = (CTF_member_t *)arg; mp->m_name; mp++) { |
| if (!strcmp(name, mp->m_name)) { |
| mp->m_offset = offset; |
| break; |
| } |
| } |
| return(0); |
| } |
| #endif /* defined(HAS_LIBCTF) */ |
| |
| |
| /* |
| * ent_fa() - enter fattach addresses in NAME column addition |
| */ |
| |
| static char * |
| ent_fa(a1, a2, d, len) |
| KA_T *a1; /* first fattach address (NULL OK) */ |
| KA_T *a2; /* second fattach address */ |
| char *d; /* direction ("->" or "<-") */ |
| int *len; /* returned description length */ |
| { |
| static char buf[1024]; |
| size_t bufl = sizeof(buf); |
| char tbuf[32]; |
| /* |
| * Form the fattach description. |
| */ |
| if (!a1) |
| |
| #if solaris<20600 |
| (void) snpf(buf, bufl, "(FA:%s%s)", d, |
| print_kptr(*a2, (char *)NULL, 0)); |
| #else /* solaris>=20600 */ |
| (void) snpf(buf, bufl, "(FA:%s%s)", d, |
| print_kptr(*a2, (char *)NULL, 0)); |
| #endif /* solaris<20600 */ |
| |
| else |
| |
| #if solaris<20600 |
| (void) snpf(buf, bufl, "(FA:%s%s%s)", |
| print_kptr(*a1, tbuf, sizeof(tbuf)), d, |
| print_kptr(*a2, (char *)NULL, 0)); |
| #else /* solaris>=20600 */ |
| (void) snpf(buf, bufl, "(FA:%s%s%s)", |
| print_kptr(*a1, tbuf, sizeof(tbuf)), d, |
| print_kptr(*a2, (char *)NULL, 0)); |
| #endif /* solaris<20600 */ |
| |
| *len = (int)strlen(buf); |
| return(buf); |
| } |
| |
| |
| /* |
| * is_socket() - is the stream a socket? |
| */ |
| |
| static int |
| is_socket(v) |
| struct vnode *v; /* vnode pointer */ |
| { |
| char *cp, *ep, *pf; |
| int i, j, len, n, pfl; |
| major_t maj; |
| minor_t min; |
| static struct tcpudp { |
| int ds; |
| major_t maj; |
| minor_t min; |
| char *proto; |
| } tcpudp[] = { |
| { 0, 0, 0, "tcp" }, |
| { 0, 0, 0, "udp" }, |
| |
| #if defined(HASIPv6) |
| { 0, 0, 0, "tcp6" }, |
| { 0, 0, 0, "udp6" }, |
| #endif /* defined(HASIPv6) */ |
| |
| }; |
| #define NTCPUDP (sizeof(tcpudp) / sizeof(struct tcpudp)) |
| |
| static int tcpudps = 0; |
| |
| if (!v->v_stream) |
| return(0); |
| maj = (major_t) GET_MAJ_DEV(v->v_rdev); |
| min = (minor_t) GET_MIN_DEV(v->v_rdev); |
| /* |
| * Fill in tcpudp[], as required. |
| */ |
| if (!tcpudps) { |
| |
| #if solaris<80000 |
| pf = "/devices/pseudo/clone"; |
| #else /* solaris>=80000 */ |
| pf = "/devices/pseudo/"; |
| #endif /* solaris<80000 */ |
| |
| for (i = n = 0, pfl = (int)strlen(pf); (i < Ndev) && (n < NTCPUDP); i++) |
| { |
| if (strncmp(Devtp[i].name, pf, pfl) |
| || !(ep = strrchr((cp = &Devtp[i].name[pfl]), ':')) |
| || (strncmp(++ep, "tcp", 3) && strncmp(ep, "udp", 3))) |
| continue; |
| |
| #if solaris<80000 |
| if (*(ep + 3)) |
| #else /* solaris>=80000 */ |
| len = (*(ep + 3) == '6') ? 4 : 3; |
| if (*(ep + len) || ((cp + len) >= ep) || strncmp(cp, ep, len)) |
| #endif /* solaris<80000 */ |
| |
| continue; |
| for (j = 0; j < NTCPUDP; j++) { |
| if (!tcpudp[j].ds && !strcmp(ep, tcpudp[j].proto)) { |
| tcpudp[j].ds = 1; |
| tcpudp[j].maj = (major_t) GET_MAJ_DEV(Devtp[i].rdev); |
| tcpudp[j].min = (minor_t) GET_MIN_DEV(Devtp[i].rdev); |
| n++; |
| break; |
| } |
| } |
| } |
| tcpudps = n ? 1 : -1; |
| } |
| /* |
| * Check for known IPv[46] TCP or UDP device. |
| */ |
| for (i = 0; (i < NTCPUDP) && (tcpudps > 0); i++) { |
| if (tcpudp[i].ds |
| |
| #if solaris<80000 |
| && (maj == tcpudp[i].min) |
| #else /* solaris>=80000 */ |
| && (maj == tcpudp[i].maj) |
| #endif /* solaris<80000 */ |
| |
| ) { |
| process_socket((KA_T)v->v_stream, tcpudp[i].proto); |
| return(1); |
| } |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * isvlocked() - is Solaris vnode locked? |
| */ |
| |
| static char |
| isvlocked(va) |
| struct vnode *va; /* local vnode address */ |
| { |
| |
| #if solaris<20500 |
| struct filock f; |
| KA_T ff; |
| KA_T fp; |
| #endif /* solaris<20500 */ |
| |
| int i, l; |
| |
| #if solaris>=20300 |
| struct lock_descriptor ld; |
| KA_T lf; |
| KA_T lp; |
| # if solaris<20500 |
| #define LOCK_END ld.info.li_sleep.sli_flock.l_len |
| #define LOCK_FLAGS ld.flags |
| #define LOCK_NEXT ld.next |
| #define LOCK_OWNER ld.owner.pid |
| #define LOCK_START ld.start |
| #define LOCK_TYPE ld.type |
| # else /* solaris>=20500 */ |
| #define LOCK_END ld.l_flock.l_len |
| #define LOCK_FLAGS ld.l_state |
| #define LOCK_NEXT ld.l_next |
| #define LOCK_OWNER ld.l_flock.l_pid |
| #define LOCK_START ld.l_start |
| #define LOCK_TYPE ld.l_type |
| # endif /* solaris<20500 */ |
| #endif /* solaris>=20300 */ |
| |
| if (va->v_filocks == NULL) |
| return(' '); |
| |
| #if solaris<20500 |
| # if solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45) |
| if (Ntype == N_NFS) |
| # endif /* solaris>20300 || (solaris==20300 && defined(P101318) && P101318>=45) */ |
| |
| { |
| ff = fp = (KA_T)va->v_filocks; |
| i = 0; |
| do { |
| if (kread(fp, (char *)&f, sizeof(f))) |
| return(' '); |
| i++; |
| if (f.set.l_pid != (pid_t)Lp->pid) |
| continue; |
| if (f.set.l_whence == 0 && f.set.l_start == 0 |
| && f.set.l_len == MAXEND) |
| l = 1; |
| else |
| l = 0; |
| switch (f.set.l_type & (F_RDLCK | F_WRLCK)) { |
| case F_RDLCK: |
| return(l ? 'R' : 'r'); |
| case F_WRLCK: |
| return(l ? 'W' : 'w'); |
| case F_RDLCK|F_WRLCK: |
| return('u'); |
| default: |
| return('N'); |
| } |
| } while ((fp = (KA_T)f.next) && (fp != ff) && (i < 10000)); |
| } |
| #endif /* solaris<20500 */ |
| |
| #if solaris>=20300 |
| lf = lp = (KA_T)va->v_filocks; |
| i = 0; |
| do { |
| if (kread(lp, (char *)&ld, sizeof(ld))) |
| return(' '); |
| i++; |
| if (!(LOCK_FLAGS & ACTIVE_LOCK) || LOCK_OWNER != (pid_t)Lp->pid) |
| continue; |
| if (LOCK_START == 0 |
| && (LOCK_END == 0 |
| |
| # if solaris<20500 |
| || LOCK_END == MAXEND |
| # else /* solaris>=20500 */ |
| || LOCK_END == MAXEND |
| # endif /* solaris<20500 */ |
| |
| )) |
| l = 1; |
| else |
| l = 0; |
| switch (LOCK_TYPE) { |
| case F_RDLCK: |
| return(l ? 'R' : 'r'); |
| case F_WRLCK: |
| return(l ? 'W' : 'w'); |
| case (F_RDLCK | F_WRLCK): |
| return('u'); |
| default: |
| return('L'); |
| } |
| } while ((lp = (KA_T)LOCK_NEXT) && (lp != lf) && (i < 10000)); |
| return(' '); |
| #endif /* solaris>=20300 */ |
| |
| } |
| |
| |
| /* |
| * finddev() - look up device by device number |
| */ |
| |
| static struct l_dev * |
| finddev(dev, rdev, flags) |
| dev_t *dev; /* device */ |
| dev_t *rdev; /* raw device */ |
| int flags; /* look flags -- see LOOKDEV_* symbol |
| * definitions */ |
| { |
| struct clone *c; |
| struct l_dev *dp; |
| struct pseudo *p; |
| |
| if (!Sdev) |
| readdev(0); |
| /* |
| * Search device table for match. |
| */ |
| |
| #if defined(HASDCACHE) |
| |
| finddev_again: |
| |
| #endif /* defined(HASDCACHE) */ |
| |
| if (flags & LOOKDEV_TAB) { |
| if ((dp = lkupdev(dev, rdev, 0, 0))) |
| return(dp); |
| } |
| /* |
| * Search for clone. |
| */ |
| if ((flags & LOOKDEV_CLONE) && Clone) { |
| for (c = Clone; c; c = c->next) { |
| if (GET_MAJ_DEV(*rdev) == GET_MIN_DEV(c->cd.rdev)) { |
| |
| #if defined(HASDCACHE) |
| if (DCunsafe && !c->cd.v && !vfy_dev(&c->cd)) |
| goto finddev_again; |
| #endif /* defined(HASDCACHE) */ |
| |
| return(&c->cd); |
| } |
| } |
| } |
| /* |
| * Search for pseudo device match on major device only. |
| */ |
| if ((flags & LOOKDEV_PSEUDO) && Pseudo) { |
| for (p = Pseudo; p; p = p->next) { |
| if (GET_MAJ_DEV(*rdev) == GET_MAJ_DEV(p->pd.rdev)) { |
| |
| #if defined(HASDCACHE) |
| if (DCunsafe && !p->pd.v && !vfy_dev(&p->pd)) |
| goto finddev_again; |
| #endif /* defined(HASDCACHE) */ |
| |
| return(&p->pd); |
| } |
| } |
| } |
| return((struct l_dev *)NULL); |
| } |
| |
| |
| #if solaris>=20500 |
| /* |
| * idoorkeep() -- identify door keeper process |
| */ |
| |
| static int |
| idoorkeep(d) |
| struct door_node *d; /* door's node */ |
| { |
| char buf[1024]; |
| size_t bufl = sizeof(buf); |
| struct proc dp; |
| struct pid dpid; |
| /* |
| * Get the proc structure and its pid structure for the door target. |
| */ |
| if (!d->door_target |
| || kread((KA_T)d->door_target, (char *)&dp, sizeof(dp))) |
| return(0); |
| if (!dp.p_pidp |
| || kread((KA_T)dp.p_pidp, (char *)&dpid, sizeof(dpid))) |
| return(0); |
| /* |
| * Form a description of the door. |
| * |
| * Put the description in the NAME column addition field. If there's already |
| * something there, allocate more space and add the door description to it. |
| */ |
| if (Lp->pid == (int)dpid.pid_id) |
| (void) snpf(buf, bufl, "(this PID's door)"); |
| else { |
| (void) snpf(buf, bufl, "(door to %.64s[%ld])", dp.p_user.u_comm, |
| (long)dpid.pid_id); |
| } |
| (void) add_nma(buf, (int)strlen(buf)); |
| return(1); |
| } |
| #endif /* solaris>=20500 */ |
| |
| |
| /* |
| * process_node() - process vnode |
| */ |
| |
| void |
| process_node(va) |
| KA_T va; /* vnode kernel space address */ |
| { |
| struct cnode cn; |
| dev_t dev, rdev, trdev; |
| unsigned char devs = 0; |
| unsigned char fxs = 0; |
| unsigned char ins = 0; |
| unsigned char kvs = 0; |
| unsigned char nns = 0; |
| unsigned char pnl = 0; |
| unsigned char rdevs = 0; |
| unsigned char rvs = 0; |
| unsigned char rfxs = 0; |
| unsigned char sdns = 0; |
| unsigned char tdef; |
| unsigned char trdevs = 0; |
| unsigned char unix_sock = 0; |
| struct dev_info di; |
| char din[DINAMEL]; |
| char *ep; |
| struct fifonode f; |
| char *fa = (char *)NULL; |
| int fal; |
| static int ft = 1; |
| struct vnode fv, rv; |
| int fx, rfx; |
| struct hsnode h; |
| struct inode i; |
| int j; |
| KA_T ka, vka; |
| struct lnode lo; |
| struct vfs kv, rkv; |
| int len, llc, nl, snl, sepl; |
| struct mvfsnode m; |
| struct namenode nn; |
| struct l_vfs *nvfs, *vfs; |
| struct pcnode pc; |
| struct pcfs pcfs; |
| struct rnode r; |
| KA_T realvp = (KA_T)NULL; |
| struct snode rs; |
| struct snode s; |
| |
| #if solaris>=110000 |
| char *nm, *sep; |
| size_t nmrl, tl; |
| struct sdev_node sdn; |
| struct vattr sdva; |
| sotpi_info_t sti; |
| int stis = 0; |
| #endif /* solaris>=110000 */ |
| |
| struct l_dev *sdp = (struct l_dev *)NULL; |
| size_t sz; |
| struct tmpnode t; |
| char tbuf[128], *ty, ubuf[128]; |
| int tbufx; |
| enum vtype type; |
| struct sockaddr_un ua; |
| static struct vnode *v = (struct vnode *)NULL; |
| KA_T vs; |
| int vty = 0; |
| int vty_tmp; |
| |
| #if solaris>=20500 |
| # if solaris>=20600 |
| struct fnnode fnn; |
| struct pairaddr { |
| short f; |
| unsigned short p; |
| } *pa; |
| KA_T peer; |
| struct sonode so; |
| KA_T soa, sona; |
| # else /* solaris<20600 */ |
| struct autonode au; |
| # endif /* solaris>=20600 */ |
| |
| struct door_node dn; |
| int dns = 0; |
| #endif /* solaris >=20500 */ |
| |
| #if solaris<100000 |
| KA_T so_ad[2]; |
| struct so_so soso; |
| int so_st = 0; |
| #else /* solaris>=100000 */ |
| union { |
| ctfs_adirnode_t adir; |
| ctfs_bunode_t bun; |
| ctfs_cdirnode_t cdir; |
| ctfs_ctlnode_t ctl; |
| ctfs_evnode_t ev; |
| ctfs_latenode_t late; |
| ctfs_rootnode_t root; |
| ctfs_symnode_t sym; |
| ctfs_tdirnode_t tdir; |
| ctfs_tmplnode_t tmpl; |
| } ctfs; |
| dev_t dv_dev; |
| struct dv_node dv; |
| unsigned char dv_devs = 0; |
| unsigned char dvs = 0; |
| port_t pn; |
| struct rnode4 r4; |
| #endif /* solaris<100000 */ |
| |
| |
| #if defined(HASPROCFS) |
| struct procfsid *pfi; |
| struct pid pids; |
| #endif /* defined(HASPROCFS) */ |
| |
| #if defined(HAS_AFS) |
| struct afsnode an; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if defined(HASVXFS) |
| struct l_ino vx; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| vfs_t zgvfs; |
| unsigned char zns = 0; |
| znode_t zn; |
| zfsvfs_t zvfs; |
| #endif /* defined(HAS_ZFS) */ |
| |
| /* |
| * Do first-time only operations. |
| */ |
| |
| #if solaris<100000 |
| so_ad[0] = so_ad[1] = (KA_T)0; |
| #endif /* solaris<100000 */ |
| |
| if (ft) { |
| (void) build_Voptab(); |
| ft = 0; |
| } |
| /* |
| * Read the vnode. |
| */ |
| if (!va) { |
| enter_nm("no vnode address"); |
| return; |
| } |
| if (!v) { |
| |
| /* |
| * Allocate space for the vnode or AFS vcache structure. |
| */ |
| |
| #if defined(HAS_AFS) |
| v = alloc_vcache(); |
| #else /* !defined(HAS_AFS) */ |
| v = (struct vnode *) malloc(sizeof(struct vnode)); |
| #endif /* defined(HAS_AFS) */ |
| |
| if (!v) { |
| (void) fprintf(stderr, "%s: can't allocate %s space\n", Pn, |
| |
| #if defined(HAS_AFS) |
| "vcache" |
| #else /* !defined(HAS_AFS) */ |
| "vnode" |
| #endif /* defined(HAS_AFS) */ |
| |
| ); |
| Exit(1); |
| } |
| } |
| if (readvnode(va, v)) { |
| enter_nm(Namech); |
| return; |
| } |
| |
| #if defined(HASNCACHE) |
| Lf->na = va; |
| #endif /* defined(HASNCACHE) */ |
| |
| #if defined(HASFSTRUCT) |
| Lf->fna = va; |
| Lf->fsv |= FSV_NI; |
| #endif /* defined(HASFSTRUCT) */ |
| |
| #if defined(HASLFILEADD) && defined(HAS_V_PATH) |
| Lf->V_path = (KA_T)v->v_path; |
| #endif /* defined(HASLFILEADD) && defined(HAS_V_PATH) */ |
| |
| vs = (KA_T)v->v_stream; |
| /* |
| * Check for a Solaris socket. |
| */ |
| if (is_socket(v)) |
| return; |
| /* |
| * Obtain the Solaris virtual file system structure. |
| */ |
| if ((ka = (KA_T)v->v_vfsp)) { |
| if (kread(ka, (char *)&kv, sizeof(kv))) { |
| vka = va; |
| |
| vfs_read_error: |
| |
| (void) snpf(Namech, Namechl - 1, |
| "vnode at %s: can't read vfs: %s", |
| print_kptr(vka, tbuf, sizeof(tbuf)), |
| print_kptr(ka, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return; |
| } |
| kvs = 1; |
| } else |
| kvs = 0; |
| /* |
| * Derive the virtual file system structure's device number from |
| * its file system ID for NFS and High Sierra file systems. |
| */ |
| if (kvs && ((fx = kv.vfs_fstype - 1) >= 0) && (fx < Fsinfomax)) { |
| fxs = 1; |
| if (strcmp(Fsinfo[fx], "nfs") == 0 |
| || strcmp(Fsinfo[fx], "nfs3") == 0 |
| || strcmp(Fsinfo[fx], "hsfs") == 0) |
| kv.vfs_dev = (dev_t)kv.vfs_fsid.val[0]; |
| } else { |
| fx = -1; |
| fxs = 0; |
| } |
| /* |
| * Determine the Solaris vnode type. |
| */ |
| if ((Ntype = vop2ty(v, fx)) < 0) { |
| if (v->v_type == VFIFO) { |
| vty = N_REGLR; |
| Ntype = N_FIFO; |
| } else if (vs) { |
| Ntype = vty = N_STREAM; |
| Lf->is_stream = 1; |
| } |
| if (Ntype < 0) { |
| (void) snpf(Namech, Namechl - 1, |
| "unknown file system type%s%s%s, v_op: %s", |
| fxs ? " (" : "", |
| fxs ? Fsinfo[fx] : "", |
| fxs ? ")" : "", |
| print_kptr((KA_T)v->v_op, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return; |
| } |
| } else { |
| vty = Ntype; |
| if (v->v_type == VFIFO) |
| Ntype = N_FIFO; |
| else if (vs && Ntype != N_SOCK) { |
| Ntype = vty = N_STREAM; |
| Lf->is_stream = 1; |
| } |
| } |
| /* |
| * See if this Solaris node has been fattach'ed to another node. |
| * If it has, read the namenode, and enter the node addresses in |
| * the NAME column addition. |
| * |
| * See if it's covering a socket as well and process accordingly. |
| */ |
| if (vty == N_NM) { |
| if (read_nnn(va, (KA_T)v->v_data, &nn)) |
| return; |
| nns = 1; |
| if (nn.nm_mountpt) |
| |
| #if solaris>=20500 |
| fa = ent_fa((KA_T *)((Ntype == N_FIFO || v->v_type == VDOOR) |
| ? NULL : &va), |
| (KA_T *)&nn.nm_mountpt, "->", &fal); |
| #else /* solaris<20500 */ |
| fa = ent_fa((KA_T *)((Ntype == N_FIFO) |
| ? NULL : &va), |
| (KA_T *)&nn.nm_mountpt, "->", &fal); |
| #endif /* solaris>=20500 */ |
| |
| if (Ntype != N_FIFO |
| && nn.nm_filevp |
| && !kread((KA_T)nn.nm_filevp, (char *)&rv, sizeof(rv))) { |
| rvs = 1; |
| if ((ka = (KA_T)rv.v_vfsp) |
| && !kread(ka, (char *)&rkv, sizeof(rkv)) |
| && ((rfx = rkv.vfs_fstype - 1) >= 0) |
| && (rfx < Fsinfomax) |
| ) { |
| rfxs = 1; |
| } else { |
| rfx = fx; |
| rfxs = fxs; |
| } |
| |
| #if defined(HASNCACHE) |
| Lf->na = (KA_T)nn.nm_filevp; |
| #endif /* defined(HASNCACHE) */ |
| |
| if (is_socket(&rv)) |
| return; |
| } |
| } |
| if (Selinet && Ntype != N_SOCK) |
| return; |
| /* |
| * See if this Solaris node is served by spec_vnodeops. |
| */ |
| if (Spvops && Spvops == (KA_T)v->v_op) |
| Ntype = N_SPEC; |
| /* |
| * Determine the Solaris lock state. |
| */ |
| Lf->lock = isvlocked(v); |
| /* |
| * Establish the Solaris local virtual file system structure. |
| */ |
| if (!(ka = (KA_T)v->v_vfsp) || !kvs) |
| vfs = (struct l_vfs *)NULL; |
| else if (!(vfs = readvfs(ka, &kv, v))) { |
| vka = va; |
| goto vfs_read_error; |
| } |
| /* |
| * Read the afsnode, autonode, cnode, door_node, fifonode, fnnode, lnode, |
| * inode, pcnode, rnode, snode, tmpnode, znode, etc. |
| */ |
| switch (Ntype) { |
| case N_SPEC: |
| |
| /* |
| * A N_SPEC node is a node that resides in in an underlying file system |
| * type -- e.g. NFS, HSFS. Its vnode points to an snode. Subsequent |
| * node structures are implied by the underlying node type. |
| */ |
| if (read_nsn(va, (KA_T)v->v_data, &s)) |
| return; |
| realvp = (KA_T)s.s_realvp; |
| if (!realvp && s.s_commonvp) { |
| if (read_cni(&s, &rv, v, &rs, &di, din, sizeof(din)) == 1) |
| return; |
| if (!rv.v_stream) { |
| if (din[0]) { |
| (void) snpf(Namech, Namechl, "COMMON: %s", din); |
| Namech[Namechl - 1] = '\0'; |
| Lf->is_com = 1; |
| } |
| break; |
| } |
| } |
| if (!realvp) { |
| |
| /* |
| * If the snode lacks a real vnode (and also lacks a common vnode), |
| * it's original type is N_STREAM or N_REGLR, and it has a stream |
| * pointer, get the module names. |
| */ |
| if ((vty == N_STREAM || vty == N_REGLR) && vs) { |
| Lf->is_stream = 1; |
| vty = N_STREAM; |
| |
| #if solaris<100000 |
| read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, |
| so_ad, &sdp); |
| #else /* solaris>=100000 */ |
| read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); |
| #endif /* solaris<100000 */ |
| |
| vs = (KA_T)NULL; |
| } |
| } |
| break; |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| if (readafsnode(va, v, &an)) |
| return; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| |
| # if solaris<20600 |
| if (read_nan(va, (KA_T)v->v_data, &au)) |
| # else /* solaris>=20600 */ |
| if (read_nan(va, (KA_T)v->v_data, &fnn)) |
| # endif /* solaris<20600 */ |
| |
| return; |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs)) |
| return; |
| dvs = 1; |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| if (read_ndn(va, (KA_T)v->v_data, &dn)) |
| return; |
| dns = 1; |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case N_CACHE: |
| if (read_ncn(va, (KA_T)v->v_data, &cn)) |
| return; |
| break; |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| if (read_nctfsn(Ntype, va, (KA_T)v->v_data, (char *)&ctfs)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| #if solaris>=20600 |
| case N_SOCK: |
| sona = (KA_T)v->v_data; |
| if (read_nson(va, sona, &so)) |
| return; |
| break; |
| #endif /* solaris>=20600 */ |
| |
| case N_MNT: |
| /* Information comes from the l_vfs structure. */ |
| break; |
| case N_MVFS: |
| if (read_nmn(va, (KA_T)v->v_data, &m)) |
| return; |
| break; |
| case N_NFS: |
| if (read_nrn(va, (KA_T)v->v_data, &r)) |
| return; |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| if (read_nrn4(va, (KA_T)v->v_data, &r4)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_NM: |
| if (nns) |
| realvp = (KA_T)nn.nm_filevp; |
| |
| #if defined(HASNCACHE) |
| Lf->na = (KA_T)nn.nm_filevp; |
| #endif /* defined(HASNCACHE) */ |
| |
| break; |
| case N_FD: |
| break; /* no successor node */ |
| case N_FIFO: |
| |
| /* |
| * Solaris FIFO vnodes are usually linked to a fifonode. One |
| * exception is a FIFO vnode served by nm_vnodeops; it is linked |
| * to a namenode, and the namenode points to the fifonode. |
| * |
| * Non-pipe fifonodes are linked to a vnode thorough fn_realvp. |
| */ |
| if (vty == N_NM && nns) { |
| if (nn.nm_filevp) { |
| if (read_nfn(va, (KA_T)nn.nm_filevp, &f)) |
| return; |
| realvp = (KA_T)NULL; |
| vty = N_FIFO; |
| } else { |
| (void) snpf(Namech, Namechl - 1, |
| "FIFO namenode at %s: no fifonode pointer", |
| print_kptr((KA_T)v->v_data, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| return; |
| } |
| } else { |
| if (read_nfn(va, (KA_T)v->v_data, &f)) |
| return; |
| realvp = (KA_T)f.fn_realvp; |
| } |
| if (!realvp) { |
| Lf->inode = (INODETYPE)(nns ? nn.nm_vattr.va_nodeid : f.fn_ino); |
| |
| #if solaris>=80000 /* Solaris 8 and above hack! */ |
| # if defined(_LP64) |
| if (Lf->inode >= (unsigned long)0xbaddcafebaddcafe) |
| # else /* !defined(_LP64) */ |
| if (Lf->inode >= (unsigned long)0xbaddcafe) |
| # endif /* defined(_LP64) */ |
| |
| Lf->inp_ty = 0; |
| else |
| #endif /* solaris>=80000 Solaris 8 and above hack! */ |
| |
| Lf->inp_ty = 1; |
| enter_dev_ch(print_kptr((KA_T)v->v_data, (char *)NULL, 0)); |
| if (f.fn_flag & ISPIPE) { |
| (void) snpf(tbuf, sizeof(tbuf), "PIPE"); |
| tbufx = (int)strlen(tbuf); |
| } else |
| tbufx = 0; |
| |
| #if solaris<20500 |
| if (f.fn_mate) { |
| (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s", |
| print_kptr((KA_T)f.fn_mate, (char *)NULL, 0)); |
| tbufx = (int)strlen(tbuf); |
| } |
| #else /* solaris>=20500 */ |
| if (f.fn_dest) { |
| (void) snpf(&tbuf[tbufx], sizeof(tbuf) - tbufx, "->%s", |
| print_kptr((KA_T)f.fn_dest, (char *)NULL, 0)); |
| tbufx = (int)strlen(tbuf); |
| } |
| #endif /* solaris<20500 */ |
| |
| if (tbufx) |
| (void) add_nma(tbuf, tbufx); |
| break; |
| } |
| break; |
| |
| case N_HSFS: |
| if (read_nhn(va, (KA_T)v->v_data, &h)) |
| return; |
| break; |
| case N_LOFS: |
| llc = 0; |
| do { |
| rvs = 0; |
| if (read_nln(va, |
| llc ? (KA_T)rv.v_data : (KA_T)v->v_data, |
| &lo)) |
| { |
| return; |
| } |
| if (!(realvp = (KA_T)lo.lo_vp)) { |
| (void) snpf(Namech, Namechl - 1, |
| "lnode at %s: no real vnode", |
| print_kptr((KA_T)v->v_data, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return; |
| } |
| if (read_nvn((KA_T)v->v_data, (KA_T)realvp, &rv)) |
| return; |
| rvs = 1; |
| llc++; |
| if ((ka = (KA_T)rv.v_vfsp) |
| && !kread(ka, (char *)&rkv, sizeof(rkv)) |
| && ((rfx = rkv.vfs_fstype - 1) >= 0) |
| && (rfx < Fsinfomax) |
| ) { |
| rfxs = 1; |
| } else { |
| rfx = fx; |
| rfxs = fxs; |
| } |
| if (((vty_tmp = vop2ty(&rv, rfx)) == N_LOFS) && (llc > 1000)) { |
| (void) snpf(Namech, Namechl - 1, |
| "lnode at %s: loop > 1000", |
| print_kptr((KA_T)v->v_data, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return; |
| } |
| } while (vty_tmp == N_LOFS); |
| break; |
| case N_PCFS: |
| if (read_npn(va, (KA_T)v->v_data, &pc)) |
| return; |
| break; |
| |
| #if solaris>=100000 |
| case N_PORT: |
| if (read_nprtn(va, (KA_T)v->v_data, &pn)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| #if defined(HASPROCFS) |
| case N_PROC: |
| if (read_npi(va, v, &pids)) |
| return; |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva)) |
| return; |
| sdns = 1; |
| break; |
| #endif /* solaris>=110000 */ |
| |
| case N_SAMFS: |
| (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG)); |
| break; |
| case N_SHARED: |
| break; /* No more sharedfs information is available. */ |
| case N_STREAM: |
| if (read_nsn(va, (KA_T)v->v_data, &s)) |
| return; |
| if (vs) { |
| Lf->is_stream = 1; |
| |
| #if solaris<100000 |
| read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, |
| &sdp); |
| #else /* solaris>=100000 */ |
| read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); |
| #endif /* solaris<100000 */ |
| |
| vs = (KA_T)NULL; |
| } |
| break; |
| case N_TMP: |
| if (read_ntn(va, (KA_T)v->v_data, &t)) |
| return; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| if (read_vxnode(va, v, vfs, fx, &vx, Vvops)) |
| return; |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (read_nzn(va, (KA_T)v->v_data, &zn)) |
| return; |
| zns = 1; |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| case N_REGLR: |
| default: |
| if (read_nin(va, (KA_T)v->v_data, &i)) |
| return; |
| ins = 1; |
| } |
| /* |
| * If the node has a real vnode pointer, follow it. |
| */ |
| if (realvp) { |
| if (rvs) { |
| *v = rv; |
| fx = rfx; |
| fxs = rfxs; |
| } |
| else { |
| if (read_nvn((KA_T)v->v_data, (KA_T)realvp, v)) |
| return; |
| else { |
| |
| #if defined(HASNCACHE) |
| Lf->na = (KA_T)realvp; |
| #endif /* defined(HASNCACHE) */ |
| |
| if ((ka = (KA_T)v->v_vfsp) |
| && !kread(ka, (char *)&kv, sizeof(kv))) |
| { |
| kvs = 1; |
| } |
| if (kvs |
| && ((fx = kv.vfs_fstype - 1) >= 0) |
| && (fx < Fsinfomax) |
| ) { |
| fxs = 1; |
| } |
| } |
| } |
| /* |
| * If the original vnode type is N_STREAM, if there is a stream |
| * pointer and if there is no sdev_node, get the module names. |
| */ |
| if (vty == N_STREAM && vs && !sdns) { |
| Lf->is_stream = 1; |
| |
| #if solaris<100000 |
| read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, |
| &sdp); |
| #else /* solaris>=100000 */ |
| read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); |
| #endif /* solaris<100000 */ |
| |
| vs = (KA_T)NULL; |
| } |
| /* |
| * Get the real vnode's type. |
| */ |
| if ((vty = vop2ty(v, fx)) < 0) { |
| if (Ntype != N_FIFO && vs) |
| vty = N_STREAM; |
| else { |
| |
| #if solaris<100000 |
| (void) snpf(Namech, Namechl - 1, |
| "unknown file system type, v_op: %s", |
| print_kptr((KA_T)v->v_op, (char *)NULL, 0)); |
| #else /* solaris>=100000 */ |
| (void) snpf(Namech, Namechl - 1, |
| "unknown file system type (%s), v_op: %s", |
| fxs ? Fsinfo[fx] : "unknown", |
| print_kptr((KA_T)v->v_op, (char *)NULL, 0)); |
| #endif /* solaris<100000 */ |
| |
| Namech[Namechl - 1] = '\0'; |
| } |
| } |
| if (Ntype == N_NM || Ntype == N_AFS) |
| Ntype = vty; |
| /* |
| * Base further processing on the "real" vnode. |
| */ |
| Lf->lock = isvlocked(v); |
| switch (vty) { |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| if (readafsnode(va, v, &an)) |
| return; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| |
| # if solaris<20600 |
| if (read_nan(va, (KA_T)v->v_data, &au)) |
| # else /* solaris>=20600 */ |
| if (read_nan(va, (KA_T)v->v_data, &fnn)) |
| # endif /* solaris<20600 */ |
| |
| return; |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (read_ndvn(va, (KA_T)v->v_data, &dv, &dv_dev, &dv_devs)) |
| return; |
| dvs = 1; |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| |
| # if solaris<20600 |
| if (read_ndn(realvp, (KA_T)v->v_data, &dn)) |
| # else /* solaris>=20600 */ |
| if (read_ndn(va, (KA_T)v->v_data, &dn)) |
| # endif /* solaris<20500 */ |
| |
| return; |
| dns = 1; |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case N_CACHE: |
| if (read_ncn(va, (KA_T)v->v_data, &cn)) |
| return; |
| break; |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| if (read_nctfsn(vty, va, (KA_T)v->v_data, (char *)&ctfs)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_HSFS: |
| if (read_nhn(va, (KA_T)v->v_data, &h)) |
| return; |
| break; |
| case N_MNT: |
| /* Information comes from the l_vfs structure. */ |
| break; |
| case N_MVFS: |
| if (read_nmn(va, (KA_T)v->v_data, &m)) |
| return; |
| break; |
| case N_NFS: |
| if (read_nrn(va, (KA_T)v->v_data, &r)) |
| return; |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| if (read_nrn4(va, (KA_T)v->v_data, &r4)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_NM: |
| if (read_nnn(va, (KA_T)v->v_data, &nn)) |
| return; |
| nns = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_PORT: |
| if (read_nprtn(va, (KA_T)v->v_data, &pn)) |
| return; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_PCFS: |
| if (read_npn(va, (KA_T)v->v_data, &pc)) |
| return; |
| break; |
| case N_SAMFS: |
| (void) add_nma(SAMFS_NMA_MSG, (int)strlen(SAMFS_NMA_MSG)); |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (read_nsdn(va, (KA_T)v->v_data, &sdn, &sdva)) |
| return; |
| if (Lf->is_stream) { |
| |
| /* |
| * This stream's real node is an sdev_node, so it's not really |
| * a stream. Reverse prior stream settings. |
| */ |
| Lf->is_stream = 0; |
| Namech[0] = '\0'; |
| } |
| sdns = 1; |
| break; |
| #endif /* solaris>=110000 */ |
| |
| break; |
| |
| #if solaris>=20600 |
| case N_SOCK: |
| sona = (KA_T)v->v_data; |
| if (read_nson(va, sona, &so)) |
| return; |
| break; |
| #endif /* solaris>=20600 */ |
| |
| case N_STREAM: |
| if (vs) { |
| Lf->is_stream = 1; |
| |
| #if solaris<100000 |
| read_mi(vs, (dev_t *)&s.s_dev, (caddr_t)&soso, &so_st, so_ad, |
| &sdp); |
| #else /* solaris>=100000 */ |
| read_mi(vs, (dev_t *)&s.s_dev, NULL, NULL, NULL, &sdp); |
| #endif /* solaris<100000 */ |
| |
| vs = (KA_T)NULL; |
| } |
| break; |
| case N_TMP: |
| if (read_ntn(va, (KA_T)v->v_data, &t)) |
| return; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| if (read_vxnode(va, v, vfs, fx, &vx, Vvops)) |
| return; |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (read_nzn(va, (KA_T)v->v_data, &zn)) |
| return; |
| zns = 1; |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| case N_REGLR: |
| default: |
| if (read_nin(va, (KA_T)v->v_data, &i)) |
| return; |
| ins = 1; |
| } |
| /* |
| * If this is a Solaris loopback node, use the "real" node type. |
| */ |
| if (Ntype == N_LOFS) |
| Ntype = vty; |
| } |
| /* |
| * Get device and type for printing. |
| */ |
| switch (((Ntype == N_FIFO) || (vty == N_SDEV)) ? vty : Ntype) { |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| dev = an.dev; |
| devs = 1; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| if (kvs) { |
| dev = (dev_t)kv.vfs_fsid.val[0]; |
| devs = 1; |
| } |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (dv_devs) { |
| dev = dv_dev; |
| devs = 1; |
| } else if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| rdev = v->v_rdev; |
| rdevs = 1; |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| |
| # if solaris<20600 |
| if (kvs) { |
| dev = (dev_t)kv.vfs_fsid.val[0]; |
| devs = 1; |
| } |
| # else /* solaris>=20600 */ |
| if (nns) { |
| dev = (dev_t)nn.nm_vattr.va_fsid; |
| devs = 1; |
| } else if (dns) { |
| dev = (dev_t)dn.door_index; |
| devs = 1; |
| } |
| # endif /* solaris<20600 */ |
| |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case N_CACHE: |
| case N_HSFS: |
| case N_PCFS: |
| if (kvs) { |
| dev = kv.vfs_dev; |
| devs = 1; |
| } |
| break; |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| if (kvs) { |
| dev = kv.vfs_dev; |
| devs = 1; |
| } |
| break; |
| #endif /* solaris>=100000 */ |
| |
| |
| case N_FD: |
| if (kvs) { |
| dev = kv.vfs_dev; |
| devs = 1; |
| } |
| if ((v->v_type == VCHR) || (v->v_type == VBLK)) { |
| rdev = v->v_rdev; |
| rdevs = 1; |
| } |
| break; |
| |
| case N_MNT: |
| |
| #if defined(CVFS_DEVSAVE) |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| #endif /* defined(CVFS_DEVSAVE) */ |
| |
| break; |
| case N_MVFS: |
| |
| #if defined(CVFS_DEVSAVE) |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| #endif /* defined(CVFS_DEVSAVE) */ |
| |
| break; |
| case N_NFS: |
| dev = r.r_attr.va_fsid; |
| devs = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| dev = r4.r_attr.va_fsid; |
| devs = 1; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_NM: |
| if (nns) { |
| dev = (dev_t)nn.nm_vattr.va_fsid; |
| devs = 1; |
| } else |
| enter_dev_ch(" NMFS"); |
| break; |
| |
| #if solaris>=100000 |
| case N_PORT: |
| if (kvs) { |
| dev = kv.vfs_dev; |
| devs = 1; |
| } |
| break; |
| #endif /* solaris>=100000 */ |
| |
| |
| #if defined(HASPROCFS) |
| case N_PROC: |
| if (kvs) { |
| dev = kv.vfs_dev; |
| devs = 1; |
| } |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| case N_SAMFS: |
| if ((v->v_type == VCHR) || (v->v_type == VBLK)) { |
| rdev = v->v_rdev; |
| rdevs = 1; |
| } else if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| break; |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (sdns) { |
| dev = sdva.va_fsid; |
| rdev = sdva.va_rdev; |
| devs = rdevs = 1; |
| } |
| break; |
| #endif /* solaris>=110000 */ |
| |
| case N_SHARED: |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| break; |
| |
| #if solaris>=20600 |
| case N_SOCK: |
| if (so.so_family == AF_UNIX) |
| |
| /* |
| * Process an AF_UNIX socket node. |
| */ |
| |
| # if solaris>=110000 |
| { |
| |
| /* |
| * Process a Solaris >= 11 AF_UNIX socket node: |
| * |
| * Get its sotpi_info_t structure; |
| */ |
| if (read_nsti(&so, &sti)) |
| return; |
| /* |
| * Get its device numbers. If they are located, start the NAME |
| * column with the device name, followed by "->". |
| */ |
| nm = Namech; |
| nmrl = Namechl - 1; |
| Namech[Namechl - 1] = '\0'; |
| if (!sdp) |
| sdp = finddev(&DevDev, &sti.sti_dev, LOOKDEV_ALL); |
| if (sdp) { |
| dev = DevDev; |
| rdev = v->v_rdev; |
| trdev = sdp->rdev; |
| devs = rdevs = trdevs = 1; |
| Lf->inode = (INODETYPE)sdp->inode; |
| Lf->inp_ty = 1; |
| (void) snpf(nm, nmrl, "%s", sdp->name); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| sep = "->"; |
| } else { |
| devs = rdevs = trdevs = 0; |
| sep = ""; |
| } |
| /* |
| * Add the socket node's address to the NAME column. |
| */ |
| sepl = strlen(sep); |
| if (sona && ((nmrl - sepl) > 0)) { |
| (void) snpf(nm, nmrl, "%s%s", sep, |
| print_kptr(sona, (char *)NULL, 0)); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| /* |
| * Add the service type to the NAME column. |
| */ |
| switch (sti.sti_serv_type) { |
| case T_CLTS: |
| ty = "dgram"; |
| break; |
| case T_COTS: |
| ty = "stream"; |
| break; |
| case T_COTS_ORD: |
| ty = "stream-ord"; |
| break; |
| default: |
| ty = (char *)NULL; |
| } |
| if (ty && (nmrl > 1)) { |
| (void) snpf(nm, nmrl, " %s", ty); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| /* |
| * Add the vnode and connected addresses to the NAME column, |
| * as indicated by the socket node state. |
| */ |
| if ((so.so_state & SS_ISBOUND) |
| && (nmrl > 36) |
| && (sti.sti_ux_laddr.soua_magic == SOU_MAGIC_EXPLICIT) |
| ) { |
| (void) snpf(nm, nmrl, " Vn=%s", |
| print_kptr((KA_T)sti.sti_ux_laddr.soua_vp, |
| (char *)NULL, 0) |
| ); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| if ((so.so_state & SS_ISCONNECTED) |
| && (nmrl > 38) |
| && (sti.sti_ux_faddr.soua_magic == SOU_MAGIC_EXPLICIT) |
| ) { |
| (void) snpf(nm, nmrl, " Conn=%s ", |
| print_kptr((KA_T)sti.sti_ux_faddr.soua_vp, |
| (char *)NULL, 0) |
| ); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| /* |
| * Put local and connected UNIX addresses in the NAME column, if |
| * they exist and as indicated by the socket node's state. |
| */ |
| if ((so.so_state & SS_ISBOUND) |
| && ((len = read_nusa(&sti.sti_laddr, &ua)) > 0) |
| && (nmrl > (len + 5)) |
| ) { |
| if (Sfile |
| && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) |
| Lf->sf |= SELNM; |
| if (len > nmrl) |
| len = nmrl; |
| if (len > 0) { |
| ua.sun_path[len] = '\0'; |
| (void) snpf(nm, nmrl, " Lcl=%s", ua.sun_path); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| } |
| if ((so.so_state & SS_ISCONNECTED) |
| && ((len = read_nusa(&sti.sti_faddr, &ua)) > 0) |
| && (nmrl > (len + 5)) |
| ) { |
| if (Sfile |
| && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) |
| Lf->sf |= SELNM; |
| if (len > nmrl) |
| len = nmrl; |
| if (len > 0) { |
| ua.sun_path[len] = '\0'; |
| (void) snpf(nm, nmrl, " Rem=%s", ua.sun_path); |
| tl = strlen(nm); |
| nm += tl; |
| nmrl -= tl; |
| } |
| } |
| } else { |
| |
| /* |
| * Process Solaris >= 11 AF_INET, AF_INET6 and AF_ROUTE VSOCK |
| * nodes. |
| */ |
| switch (so.so_family) { |
| case AF_INET: |
| case AF_INET6: |
| case AF_ROUTE: |
| if (process_VSOCK((KA_T)va, v, &so)) |
| return; |
| } |
| } |
| # else /* solaris<110000 */ |
| { |
| |
| /* |
| * Process an AF_UNIX socket node for Solaris < 11: |
| * Locate its device numbers; |
| * Enter the sonode address as the device (netstat's local |
| * address); |
| * Get a non-NULL local sockaddr_un and enter it in Namech; |
| * Get a non-NULL foreign sockaddr_un and enter it in Namech; |
| * Check for matches on sockaddr_un.sun_path names. |
| */ |
| |
| if (!sdp) |
| sdp = finddev(&DevDev, |
| |
| # if solaris<100000 |
| &so.so_vnode.v_rdev, |
| # else /* solaris>=100000 */ |
| &so.so_dev, |
| # endif /* solaris<100000 */ |
| |
| LOOKDEV_ALL); |
| |
| if (sdp) { |
| dev = DevDev; |
| |
| # if solaris<100000 |
| rdev = so.so_vnode.v_rdev; |
| # else /* solaris>=100000 */ |
| rdev = so.so_dev; |
| # endif /* solaris<100000 */ |
| |
| trdev = sdp->rdev; |
| devs = rdevs = trdevs = 1; |
| Lf->inode = (INODETYPE)sdp->inode; |
| Lf->inp_ty = 1; |
| (void) snpf(Namech, Namechl - 1, "%s", sdp->name); |
| Namech[Namechl - 1] = '\0'; |
| } else |
| devs = 0; |
| nl = snl = (int)strlen(Namech); |
| |
| if ((len = read_nusa(&so.so_laddr, &ua))) |
| { |
| if (Sfile |
| && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) |
| Lf->sf |= SELNM; |
| sepl = Namech[0] ? 2 : 0; |
| if (len > (Namechl - nl - sepl - 1)) |
| len = Namechl - nl - sepl - 1; |
| if (len > 0) { |
| ua.sun_path[len] = '\0'; |
| (void) snpf(&Namech[nl], Namechl - nl, "%s%s", |
| sepl ? "->" : "", ua.sun_path); |
| nl += (len + sepl); |
| } |
| } |
| if ((len = read_nusa(&so.so_faddr, &ua))) |
| { |
| if (Sfile |
| && is_file_named(ua.sun_path, Ntype, VSOCK, 0)) |
| Lf->sf |= SELNM; |
| sepl = Namech[0] ? 2 : 0; |
| if (len > (Namechl - nl - sepl - 1)) |
| len = Namechl - nl - sepl - 1; |
| if (len > 0) { |
| ua.sun_path[len] = 0; |
| (void) snpf(&Namech[nl], Namechl - nl, "%s%s", |
| sepl ? "->" : "", ua.sun_path); |
| nl += (len + sepl); |
| } |
| } |
| if ((nl == snl) |
| |
| # if defined(HASSOUXSOUA) |
| && so.so_ux_laddr.soua_magic == SOU_MAGIC_IMPLICIT |
| # else /* !defined(HASSOUXSOUA) */ |
| && so.so_ux_laddr.sou_magic == SOU_MAGIC_IMPLICIT |
| # endif /* defined(HASSOUXSOUA) */ |
| |
| ) { |
| |
| /* |
| * There are no addresses; this must be a socket pair. |
| * Print its identity. |
| */ |
| pa = (struct pairaddr *)&ua; |
| if (!(peer = (KA_T)((int)pa->p))) |
| |
| # if defined(HASSOUXSOUA) |
| peer = (KA_T)so.so_ux_laddr.soua_vp; |
| # else /* !defined(HASSOUXSOUA) */ |
| peer = (KA_T)so.so_ux_laddr.sou_vp; |
| # endif /* defined(HASSOUXSOUA) */ |
| |
| if (peer) |
| (void) snpf(ubuf, sizeof(ubuf), "(socketpair: %s)", |
| print_kptr(peer, (char *)NULL, 0)); |
| else |
| (void) snpf(ubuf, sizeof(ubuf), "(socketpair)"); |
| len = (int)strlen(ubuf); |
| sepl = Namech[0] ? 2 : 0; |
| if (len > (Namechl - nl - sepl - 1)) |
| len = Namechl - nl - sepl - 1; |
| if (len > 0) { |
| (void) snpf(&Namech[nl], Namechl - nl, "%s%s", |
| sepl ? "->" : "", ubuf); |
| nl += (len + sepl); |
| } |
| } |
| /* |
| * Add the local and foreign addresses, ala `netstat -f unix` to |
| * the name. |
| */ |
| |
| # if defined(HASSOUXSOUA) |
| soa = (KA_T)so.so_ux_faddr.soua_vp; |
| # else /* !defined(HASSOUXSOUA) */ |
| soa = (KA_T)so.so_ux_faddr.sou_vp; |
| # endif /* defined(HASSOUXSOUA) */ |
| |
| (void) snpf(ubuf, sizeof(ubuf), "%s(%s%s%s)", |
| Namech[0] ? " " : "", |
| print_kptr((KA_T)v->v_data, (char *)NULL, 0), |
| soa ? "->" : "", |
| soa ? print_kptr(soa, tbuf, sizeof(tbuf)) : ""); |
| len = (int)strlen(ubuf); |
| if (len <= (Namechl - nl - 1)) { |
| (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf); |
| nl += len; |
| } |
| /* |
| * If there is a bound vnode, add its address to the name. |
| */ |
| |
| if (so.so_ux_bound_vp) { |
| (void) snpf(ubuf, sizeof(ubuf), "%s(Vnode=%s)", |
| Namech[0] ? " " : "", |
| print_kptr((KA_T)so.so_ux_bound_vp, (char *)NULL, 0)); |
| len = (int)strlen(ubuf); |
| if (len <= (Namechl - nl - 1)) { |
| (void) snpf(&Namech[nl], Namechl - nl, "%s", ubuf); |
| nl += len; |
| } |
| } |
| } |
| # endif /* solaris>=110000 */ |
| |
| break; |
| |
| #endif /* solaris>=20600 */ |
| |
| case N_SPEC: |
| |
| #if solaris<100000 |
| if (((Ntype = vty) == N_STREAM) && so_st) { |
| if (Funix) |
| Lf->sf |= SELUNX; |
| unix_sock = 1; |
| if (so_ad[0]) { |
| if (sdp) { |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| rdev = sdp->rdev; |
| rdevs = 1; |
| Lf->inode = (INODETYPE)sdp->inode; |
| Lf->inp_ty = 1; |
| (void) snpf(ubuf, sizeof(ubuf), "(%s%s%s)", |
| print_kptr(so_ad[0], (char *)NULL, 0), |
| so_ad[1] ? "->" : "", |
| so_ad[1] ? print_kptr(so_ad[1], tbuf, sizeof(tbuf)) |
| : ""); |
| } else { |
| enter_dev_ch(print_kptr(so_ad[0], (char *)NULL, 0)); |
| if (so_ad[1]) |
| (void) snpf(ubuf, sizeof(ubuf), "(->%s)", |
| print_kptr(so_ad[1], (char *)NULL, 0)); |
| } |
| if (!Lf->nma && (Lf->nma = (char *) |
| malloc((int)strlen(ubuf) + 1))) |
| { |
| (void) snpf(Lf->nma, (int)strlen(ubuf) + 1, "%s", ubuf); |
| } |
| } else if (soso.lux_dev.addr.tu_addr.ino) { |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| rdev = soso.lux_dev.addr.tu_addr.dev; |
| rdevs = 1; |
| } else { |
| int dc, dl, dr; |
| |
| #if solaris<20400 |
| dl = (soso.lux_dev.addr.tu_addr.dev >> 16) & 0xffff; |
| dr = (soso.rux_dev.addr.tu_addr.dev >> 16) & 0xffff; |
| #else /* solaris>=20400 */ |
| dl = soso.lux_dev.addr.tu_addr.dev & 0xffff; |
| dr = soso.rux_dev.addr.tu_addr.dev & 0xffff; |
| #endif /* solaris<20400 */ |
| |
| dc = (dl << 16) | dr; |
| enter_dev_ch(print_kptr((KA_T)dc, (char *)NULL, 0)); |
| devs = 0; |
| } |
| if (soso.laddr.buf && soso.laddr.len == sizeof(ua)) { |
| if (kread((KA_T)soso.laddr.buf, (char *)&ua, sizeof(ua)) |
| == 0) { |
| ua.sun_path[sizeof(ua.sun_path) - 1] = '\0'; |
| if (ua.sun_path[0]) { |
| if (Sfile |
| && is_file_named(ua.sun_path, Ntype, type, 0)) |
| Lf->sf |= SELNM; |
| len = (int)strlen(ua.sun_path); |
| nl = (int)strlen(Namech); |
| sepl = Namech[0] ? 2 : 0; |
| if (len > (Namechl - nl - sepl - 1)) |
| len = Namechl - nl - sepl - 1; |
| if (len > 0) { |
| ua.sun_path[len] = '\0'; |
| (void) snpf(&Namech[nl], Namechl - nl, "%s%s", |
| sepl ? "->" : "", ua.sun_path); |
| } |
| } |
| } |
| } |
| } else |
| #endif /* solaris<100000 */ |
| |
| { |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| rdev = s.s_dev; |
| rdevs = 1; |
| } |
| break; |
| case N_STREAM: |
| if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| rdev = s.s_dev; |
| rdevs = 1; |
| break; |
| case N_TMP: |
| dev = t.tn_attr.va_fsid; |
| devs = 1; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| dev = vx.dev; |
| devs = vx.dev_def; |
| if ((v->v_type == VCHR) || (v->v_type == VBLK)) { |
| rdev = vx.rdev; |
| rdevs = vx.rdev_def; |
| } |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (zns) { |
| if (!read_nzvfs((KA_T)v->v_data, (KA_T)zn.z_zfsvfs, &zvfs) |
| && zvfs.z_vfs |
| && !kread((KA_T)zvfs.z_vfs, (char *)&zgvfs, sizeof(zgvfs)) |
| ) { |
| dev = zgvfs.vfs_dev; |
| devs = 1; |
| } |
| } |
| if ((v->v_type == VCHR) || (v->v_type == VBLK)) { |
| rdev = v->v_rdev; |
| rdevs = 1; |
| } |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| default: |
| if (ins) { |
| dev = i.i_dev; |
| devs = 1; |
| } else if (nns) { |
| dev = nn.nm_vattr.va_fsid; |
| devs = 1; |
| } else if (vfs) { |
| dev = vfs->dev; |
| devs = 1; |
| } |
| if ((v->v_type == VCHR) || (v->v_type == VBLK)) { |
| rdev = v->v_rdev; |
| rdevs = 1; |
| } |
| } |
| type = v->v_type; |
| if (devs && vfs && !vfs->dir) { |
| (void) completevfs(vfs, &dev); |
| |
| #if defined(HAS_AFS) |
| if (vfs->dir && (Ntype == N_AFS || vty == N_AFS) && !AFSVfsp) |
| AFSVfsp = (KA_T)v->v_vfsp; |
| #endif /* defined(HAS_AFS) */ |
| |
| } |
| /* |
| * Obtain the inode number. |
| */ |
| switch (vty) { |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| if (an.ino_st) { |
| Lf->inode = (INODETYPE)an.inode; |
| Lf->inp_ty = 1; |
| } |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| |
| # if solaris<20600 |
| Lf->inode = (INODETYPE)au.an_nodeid; |
| # else /* solaris>=20600 */ |
| Lf->inode = (INODETYPE)fnn.fn_nodeid; |
| # endif /* solaris<20600 */ |
| |
| Lf->inp_ty = 1; |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (dvs) { |
| Lf->inode = (INODETYPE)dv.dv_ino; |
| Lf->inp_ty = 1; |
| } |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| if (nns && (Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid)) { |
| Lf->inp_ty = 1; |
| break; |
| } |
| if (dns) { |
| if ((Lf->inode = (INODETYPE)dn.door_index)) |
| Lf->inp_ty = 1; |
| } |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case N_CACHE: |
| Lf->inode = (INODETYPE)cn.c_fileno; |
| Lf->inp_ty = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| /* Method of computing CTFS inode not known. */ |
| break; |
| #endif /* solaris>=10000 */ |
| |
| case N_FD: |
| if (v->v_type == VDIR) |
| Lf->inode = (INODETYPE)2; |
| else |
| Lf->inode = (INODETYPE)(GET_MIN_DEV(v->v_rdev) * 100); |
| Lf->inp_ty = 1; |
| break; |
| case N_HSFS: |
| Lf->inode = (INODETYPE)h.hs_nodeid; |
| Lf->inp_ty = 1; |
| break; |
| |
| case N_MNT: |
| |
| #if defined(HASFSINO) |
| if (vfs) { |
| Lf->inode = vfs->fs_ino; |
| Lf->inp_ty = 1; |
| } |
| #endif /* defined(HASFSINO) */ |
| |
| break; |
| case N_MVFS: |
| Lf->inode = (INODETYPE)m.m_ino; |
| Lf->inp_ty = 1; |
| break; |
| case N_NFS: |
| Lf->inode = (INODETYPE)r.r_attr.va_nodeid; |
| Lf->inp_ty = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| Lf->inode = (INODETYPE)r4.r_attr.va_nodeid; |
| Lf->inp_ty = 1; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_NM: |
| Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid; |
| Lf->inp_ty = 1; |
| break; |
| |
| #if defined(HASPROCFS) |
| case N_PROC: |
| |
| /* |
| * The proc file system inode number is defined when the |
| * prnode is read. |
| */ |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| case N_PCFS: |
| if (kvs && kv.vfs_data |
| && !kread((KA_T)kv.vfs_data, (char *)&pcfs, sizeof(pcfs))) { |
| |
| #if solaris>=70000 |
| # if defined(HAS_PC_DIRENTPERSEC) |
| Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, |
| pc.pc_eoffset, |
| pc.pc_entry.pcd_attr, |
| IS_FAT32(&pcfs) |
| ? ltohs(pc.pc_entry.pcd_scluster_lo) | |
| (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16) |
| : ltohs(pc.pc_entry.pcd_scluster_lo), |
| pc_direntpersec(&pcfs)); |
| # else /* !defined(HAS_PC_DIRENTPERSEC) */ |
| Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, |
| pc.pc_eoffset, |
| pc.pc_entry.pcd_attr, |
| IS_FAT32(&pcfs) |
| ? ltohs(pc.pc_entry.pcd_scluster_lo) | |
| (ltohs(pc.pc_entry.un.pcd_scluster_hi) << 16) |
| : ltohs(pc.pc_entry.pcd_scluster_lo), |
| pcfs.pcfs_entps); |
| # endif /* defined(HAS_PC_DIRENTPERSEC) */ |
| #else /* solaris<70000 */ |
| Lf->inode = (INODETYPE)pc_makenodeid(pc.pc_eblkno, |
| pc.pc_eoffset, |
| &pc.pc_entry, |
| pcfs.pcfs_entps); |
| #endif /* solaris>=70000 */ |
| |
| Lf->inp_ty = 1; |
| } |
| break; |
| |
| case N_REGLR: |
| if (nns) { |
| if ((Lf->inode = (INODETYPE)nn.nm_vattr.va_nodeid)) |
| Lf->inp_ty = 1; |
| } else if (ins) { |
| if ((Lf->inode = (INODETYPE)i.i_number)) |
| Lf->inp_ty = 1; |
| } |
| break; |
| case N_SAMFS: |
| break; /* No more SAM-FS information is available. */ |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (sdns) { |
| Lf->inode = (INODETYPE)sdva.va_nodeid; |
| Lf->inp_ty = 1; |
| } |
| break; |
| #endif /* solaris>=110000 */ |
| |
| case N_SHARED: |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "SHARED"); |
| Lf->inp_ty = 2; |
| break; |
| case N_STREAM: |
| |
| #if solaris<100000 |
| if (so_st && soso.lux_dev.addr.tu_addr.ino) { |
| if (Lf->inp_ty) { |
| nl = Lf->nma ? (int)strlen(Lf->nma) : 0; |
| (void) snpf(ubuf, sizeof(ubuf), |
| "%s(Inode=%lu)", nl ? " " : "", |
| (unsigned long)soso.lux_dev.addr.tu_addr.ino); |
| len = nl + (int)strlen(ubuf) + 1; |
| if (Lf->nma) |
| Lf->nma = (char *) realloc(Lf->nma, len); |
| else |
| Lf->nma = (char *) malloc(len); |
| if (Lf->nma) |
| (void) snpf(&Lf->nma[nl], len - nl, "%s", ubuf); |
| } else { |
| Lf->inode = (INODETYPE)soso.lux_dev.addr.tu_addr.ino; |
| Lf->inp_ty = 1; |
| } |
| } |
| #endif /* solaris<100000 */ |
| |
| break; |
| case N_TMP: |
| Lf->inode = (INODETYPE)t.tn_attr.va_nodeid; |
| Lf->inp_ty = 1; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| if (vx.ino_def) { |
| Lf->inode = (INODETYPE)vx.ino; |
| Lf->inp_ty = 1; |
| } else if (type == VCHR) |
| pnl = 1; |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (zns) { |
| Lf->inode = (INODETYPE)zn.z_id; |
| Lf->inp_ty = 1; |
| } |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| } |
| /* |
| * Obtain the file size. |
| */ |
| if (Foffset) |
| Lf->off_def = 1; |
| else { |
| switch (Ntype) { |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| Lf->sz = (SZOFFTYPE)an.size; |
| Lf->sz_def = 1; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| |
| # if solaris<20600 |
| Lf->sz = (SZOFFTYPE)au.an_size; |
| # else /* solaris >=20600 */ |
| Lf->sz = (SZOFFTYPE)fnn.fn_size; |
| # endif /* solaris < 20600 */ |
| |
| Lf->sz_def = 1; |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case N_CACHE: |
| Lf->sz = (SZOFFTYPE)cn.c_size; |
| Lf->sz_def = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| /* Method of computing CTFS size not known. */ |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_FD: |
| if (v->v_type == VDIR) |
| Lf->sz = (Unof + 2) * 16; |
| else |
| Lf->sz = (unsigned long)0; |
| Lf->sz_def = 1; |
| break; |
| |
| #if solaris>=20600 |
| case N_SOCK: |
| Lf->off_def = 1; |
| break; |
| #endif /* solaris>=20600 */ |
| |
| case N_HSFS: |
| Lf->sz = (SZOFFTYPE)h.hs_dirent.ext_size; |
| Lf->sz_def = 1; |
| break; |
| case N_NM: |
| Lf->sz = (SZOFFTYPE)nn.nm_vattr.va_size; |
| Lf->sz_def = 1; |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (!Fsize) |
| Lf->off_def = 1; |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| case N_FIFO: |
| if (!Fsize) |
| Lf->off_def = 1; |
| break; |
| case N_MNT: |
| |
| #if defined(CVFS_SZSAVE) |
| if (vfs) { |
| Lf->sz = (SZOFFTYPE)vfs->size; |
| Lf->sz_def = 1; |
| } else |
| #endif /* defined(CVFS_SZSAVE) */ |
| |
| Lf->off_def = 1; |
| break; |
| case N_MVFS: |
| /* The location of file size isn't known. */ |
| break; |
| case N_NFS: |
| if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| else { |
| Lf->sz = (SZOFFTYPE)r.r_size; |
| Lf->sz_def = 1; |
| } |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| else { |
| Lf->sz = (SZOFFTYPE)r4.r_size; |
| Lf->sz_def = 1; |
| } |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_PCFS: |
| Lf->sz = (SZOFFTYPE)pc.pc_size; |
| Lf->sz_def = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_PORT: |
| Lf->sz = (SZOFFTYPE)pn.port_curr; |
| Lf->sz_def = 1; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| |
| #if defined(HASPROCFS) |
| case N_PROC: |
| |
| /* |
| * The proc file system size is defined when the |
| * prnode is read. |
| */ |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| case N_REGLR: |
| if (type == VREG || type == VDIR) { |
| if (ins | nns) { |
| Lf->sz = (SZOFFTYPE)(nns ? nn.nm_vattr.va_size |
| : i.i_size); |
| Lf->sz_def = 1; |
| } |
| } else if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| break; |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (sdns) { |
| if (type == VREG || type == VDIR) { |
| Lf->sz = (SZOFFTYPE)sdva.va_size; |
| Lf->sz_def = 1; |
| } else if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| } |
| break; |
| #endif /* solaris>=110000 */ |
| |
| case N_SAMFS: |
| break; /* No more SAM-FS information is available. */ |
| case N_SHARED: |
| break; /* No more sharedfs information is available. */ |
| case N_STREAM: |
| if (!Fsize) |
| Lf->off_def = 1; |
| break; |
| case N_TMP: |
| Lf->sz = (SZOFFTYPE)t.tn_attr.va_size; |
| Lf->sz_def = 1; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| if (type == VREG || type == VDIR) { |
| Lf->sz = (SZOFFTYPE)vx.sz; |
| Lf->sz_def = vx.sz_def; |
| } else if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (zns) { |
| if (type == VREG || type == VDIR) { |
| Lf->sz = (SZOFFTYPE)zn.z_size; |
| Lf->sz_def = 1; |
| } else if ((type == VCHR || type == VBLK) && !Fsize) |
| Lf->off_def = 1; |
| } |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| } |
| } |
| /* |
| * Record link count. |
| */ |
| |
| #if !defined(HASXOPT) |
| if (Fnlink) |
| #endif /* !defined(HASXOPT) */ |
| |
| { |
| switch (Ntype) { |
| |
| #if defined(HAS_AFS) |
| case N_AFS: |
| Lf->nlink = an.nlink; |
| Lf->nlink_def = an.nlink_st; |
| break; |
| #endif /* defined(HAS_AFS) */ |
| |
| #if solaris>=20500 |
| case N_AUTO: |
| break; |
| case N_CACHE: |
| Lf->nlink = (long)cn.c_attr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| #endif /* solaris>=20500 */ |
| |
| #if solaris>=100000 |
| case N_CTFSADIR: |
| case N_CTFSBUND: |
| case N_CTFSCDIR: |
| case N_CTFSCTL: |
| case N_CTFSEVT: |
| case N_CTFSLATE: |
| case N_CTFSROOT: |
| case N_CTFSSTAT: |
| case N_CTFSSYM: |
| case N_CTFSTDIR: |
| case N_CTFSTMPL: |
| /* Method of computing CTFS link count not known. */ |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_FD: |
| Lf->nlink = (v->v_type == VDIR) ? 2 : 1; |
| Lf->nlink_def = 1; |
| break; |
| |
| #if solaris>=20600 |
| case N_SOCK: /* no link count */ |
| break; |
| #endif /* solaris>=20600 */ |
| |
| case N_HSFS: |
| Lf->nlink = (long)h.hs_dirent.nlink; |
| Lf->nlink_def = 1; |
| break; |
| case N_NM: |
| Lf->nlink = (long)nn.nm_vattr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| |
| # if solaris>=100000 |
| case N_DEV: |
| if (dvs) { |
| Lf->nlink = (long)dv.dv_nlink; |
| Lf->nlink_def = 1; |
| } |
| break; |
| # endif /* solaris>=100000 */ |
| |
| case N_DOOR: |
| Lf->nlink = (long)v->v_count; |
| Lf->nlink_def = 1; |
| break; |
| case N_FIFO: |
| break; |
| case N_MNT: |
| |
| #if defined(CVFS_NLKSAVE) |
| if (vfs) { |
| Lf->nlink = (long)vfs->nlink; |
| Lf->nlink_def = 1; |
| } |
| #endif /* defined(CVFS_NLKSAVE) */ |
| |
| break; |
| case N_MVFS: /* no link count */ |
| break; |
| case N_NFS: |
| Lf->nlink = (long)r.r_attr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| |
| #if solaris>=100000 |
| case N_NFS4: |
| Lf->nlink = (long)r4.r_attr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| case N_PCFS: |
| break; |
| |
| #if defined(HASPROCFS) |
| case N_PROC: |
| break; |
| #endif /* defined(HASPROCFS) */ |
| |
| case N_REGLR: |
| if (ins) { |
| Lf->nlink = (long)i.i_nlink; |
| Lf->nlink_def = 1; |
| } |
| break; |
| case N_SAMFS: |
| break; /* No more SAM-FS information is available. */ |
| |
| #if solaris>=110000 |
| case N_SDEV: |
| if (sdns) { |
| Lf->nlink = (long)sdva.va_nlink; |
| Lf->nlink_def = 1; |
| } |
| break; |
| #endif /* solaris>=110000 */ |
| |
| case N_SHARED: |
| break; /* No more sharedfs information is available. */ |
| case N_STREAM: |
| break; |
| case N_TMP: |
| Lf->nlink = (long)t.tn_attr.va_nlink; |
| Lf->nlink_def = 1; |
| break; |
| |
| #if defined(HASVXFS) |
| case N_VXFS: |
| Lf->nlink = vx.nl; |
| Lf->nlink_def = vx.nl_def; |
| break; |
| #endif /* defined(HASVXFS) */ |
| |
| #if defined(HAS_ZFS) |
| case N_ZFS: |
| if (zns) { |
| Lf->nlink = (long)MIN(zn.z_links, UINT32_MAX); |
| Lf->nlink_def = 1; |
| } |
| break; |
| #endif /* defined(HAS_ZFS) */ |
| |
| } |
| if (Nlink && Lf->nlink_def && (Lf->nlink < Nlink)) |
| Lf->sf |= SELNLINK; |
| } |
| |
| #if defined(HASVXFS) |
| /* |
| * Record a VxFS file. |
| */ |
| |
| # if defined(HASVXFSDNLC) |
| Lf->is_vxfs = (Ntype == N_VXFS) ? 1 : 0; |
| # endif /* defined(HASVXFSDNLC) */ |
| #endif /* defined(HASVXFS) */ |
| |
| /* |
| * Record an NFS selection. |
| */ |
| if (Fnfs) { |
| if ((Ntype == N_NFS) || (Ntype == N_NFS4)) |
| Lf->sf |= SELNFS; |
| } |
| |
| #if solaris>=20500 |
| /* |
| * If this is a Solaris 2.5 and greater autofs entry, save the autonode name |
| * (less than Solaris 2.6) or fnnode name (Solaris 2.6 and greater). |
| */ |
| if (Ntype == N_AUTO && !Namech[0]) { |
| |
| # if solaris<20600 |
| if (au.an_name[0]) |
| (void) snpf(Namech, Namechl - 1, "%s", au.an_name); |
| Namech[Namechl - 1] = '\0'; |
| # else /* solaris>=20600 */ |
| if (fnn.fn_name |
| && (len = fnn.fn_namelen) > 0 |
| && len < (Namechl - 1)) |
| { |
| if (kread((KA_T)fnn.fn_name, Namech, len)) |
| Namech[0] = '\0'; |
| else |
| Namech[len] = '\0'; |
| } |
| # endif /* solaris<20600 */ |
| |
| } |
| /* |
| * If there is no local virtual file system pointer, or if its directory and |
| * file system names are NULL, and if there is a namenode, and if we're using |
| * the device number from it, see if its nm_mountpt vnode pointer leads to a |
| * local virtual file system structure with non-NULL directory and file system |
| * names. If it does, switch to that local virtual file system pointer. |
| */ |
| if (nns && (!vfs || (!vfs->dir && !vfs->fsname)) |
| && devs && (dev == nn.nm_vattr.va_fsid) |
| && nn.nm_mountpt) |
| { |
| if (!readvnode((KA_T)nn.nm_mountpt, &fv) && fv.v_vfsp) { |
| if ((nvfs = readvfs((KA_T)fv.v_vfsp, (struct vfs *)NULL, |
| nn.nm_filevp)) |
| && !nvfs->dir) |
| { |
| (void) completevfs(nvfs, &dev); |
| } |
| |
| # if defined(HASNCACHE) |
| if (nvfs && nvfs->dir && nvfs->fsname) { |
| fa = (char *)NULL; |
| vfs = nvfs; |
| } |
| # endif /* defined(HASNCACHE) */ |
| |
| } |
| } |
| |
| # if defined(HASNCACHE) |
| /* |
| * If there's a namenode and its device and node number match this one, |
| * use the nm_mountpt's address for name cache lookups. |
| */ |
| if (nns && devs && (dev == nn.nm_vattr.va_fsid) && (Lf->inp_ty == 1) |
| && (Lf->inode == (INODETYPE)nn.nm_vattr.va_nodeid)) |
| Lf->na = (KA_T)nn.nm_mountpt; |
| # endif /* defined(HASNCACHE) */ |
| #endif /* solaris>=20500 */ |
| |
| /* |
| * Save the file system names. |
| */ |
| if (vfs) { |
| Lf->fsdir = vfs->dir; |
| Lf->fsdev = vfs->fsname; |
| |
| #if defined(HASMNTSTAT) |
| Lf->mnt_stat = vfs->mnt_stat; |
| #endif /* defined(HASMNTSTAT) */ |
| |
| if (!Lf->fsdir && !Lf->fsdev && kvs && fxs) { |
| |
| /* |
| * The file system names are unknown. |
| * |
| * Set the file system device to the file system type and clear |
| * the doubtful device numbers. |
| */ |
| Lf->fsdev = Fsinfo[fx]; |
| devs = 0; |
| rdevs = 0; |
| } |
| |
| #if defined(HASFSINO) |
| else |
| Lf->fs_ino = vfs->fs_ino; |
| #endif /* defined(HASFSINO) */ |
| |
| } |
| /* |
| * Save the device numbers, and their states. |
| * |
| * Format the vnode type, and possibly the device name. |
| */ |
| switch (type) { |
| |
| case VNON: |
| ty ="VNON"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| case VREG: |
| case VDIR: |
| ty = (type == VREG) ? "VREG" : "VDIR"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| case VBLK: |
| ty = "VBLK"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| Ntype = N_BLK; |
| break; |
| case VCHR: |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| if (unix_sock) { |
| ty = "unix"; |
| break; |
| } |
| ty = "VCHR"; |
| if (Lf->is_stream == 0 && Lf->is_com == 0) |
| Ntype = N_CHR; |
| break; |
| |
| #if solaris>=20500 |
| case VDOOR: |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| ty = "DOOR"; |
| if (dns) |
| (void) idoorkeep(&dn); |
| break; |
| #endif /* solaris>=20500 */ |
| |
| case VLNK: |
| ty = "VLNK"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| |
| #if solaris>=100000 |
| case VPORT: |
| ty = "PORT"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| #endif /* solaris>=100000 */ |
| |
| #if solaris>=20600 |
| case VPROC: |
| |
| /* |
| * The proc file system type is defined when the prnode is read. |
| */ |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| ty = (char *)NULL; |
| break; |
| #endif /* solaris>=20600 */ |
| |
| #if defined(HAS_VSOCK) |
| case VSOCK: |
| |
| # if solaris>=20600 |
| if (so.so_family == AF_UNIX) { |
| ty = "unix"; |
| if (Funix) |
| Lf->sf |= SELUNX; |
| } else { |
| if (so.so_family == AF_INET) { |
| |
| # if defined(HASIPv6) |
| ty = "IPv4"; |
| # else /* !defined(HASIPv6) */ |
| ty = "inet"; |
| # endif /* defined(HASIPv6) */ |
| |
| (void) snpf(Namech, Namechl - 1, printsockty(so.so_type)); |
| Namech[Namechl - 1] = '\0'; |
| if (TcpStIn || UdpStIn || TcpStXn || UdpStXn) |
| Lf->sf |= SELEXCLF; |
| else if (Fnet && (FnetTy != 6)) |
| Lf->sf |= SELNET; |
| } |
| |
| # if defined(HASIPv6) |
| else if (so.so_family == AF_INET6) { |
| ty = "IPv6"; |
| (void) snpf(Namech, Namechl - 1, printsockty(so.so_type)); |
| Namech[Namechl - 1] = '\0'; |
| if (TcpStIn || UdpStIn || TcpStXn || UdpStXn) |
| Lf->sf |= SELEXCLF; |
| else if (Fnet && (FnetTy != 4)) |
| Lf->sf |= SELNET; |
| } |
| # endif /* defined(HASIPv6) */ |
| |
| else { |
| ty = "sock"; |
| (void) printunkaf(so.so_family, 0); |
| ep = endnm(&sz); |
| (void) snpf(ep, sz, ", %s", printsockty(so.so_type)); |
| } |
| } |
| # endif /* solaris>=20600 */ |
| |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| #endif /* defined(HAS_VSOCK) */ |
| |
| case VBAD: |
| ty = "VBAD"; |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| break; |
| case VFIFO: |
| ty = "FIFO"; |
| if (!Lf->dev_ch || Lf->dev_ch[0] == '\0') { |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| } |
| break; |
| default: |
| Lf->dev = dev; |
| Lf->dev_def = devs; |
| Lf->rdev = rdev; |
| Lf->rdev_def = rdevs; |
| (void) snpf(Lf->type, sizeof(Lf->type), "%04o", (type & 0xfff)); |
| ty = (char *)NULL; |
| } |
| if (ty) |
| (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); |
| Lf->ntype = Ntype; |
| /* |
| * If this a Solaris common vnode/snode void some information. |
| */ |
| if (Lf->is_com) |
| Lf->sz_def = Lf->inp_ty = 0; |
| /* |
| * If a file attach description remains, put it in the NAME column addition. |
| */ |
| if (fa) |
| (void) add_nma(fa, fal); |
| |
| #if defined(HASBLKDEV) |
| /* |
| * If this is a VBLK file and it's missing an inode number, try to |
| * supply one. |
| */ |
| if ((Lf->inp_ty == 0) && (type == VBLK)) |
| find_bl_ino(); |
| #endif /* defined(HASBLKDEV) */ |
| |
| /* |
| * If this is a VCHR file and it's missing an inode number, try to |
| * supply one. |
| */ |
| if ((Lf->inp_ty == 0) && (type == VCHR)) { |
| find_ch_ino(); |
| /* |
| * If the VCHR inode number still isn't known and this is a COMMON |
| * vnode file or a stream, or if a pseudo node ID lookup has been |
| * requested, see if an inode number can be derived from a pseudo |
| * or clone device node. |
| * |
| * If it can, save the pseudo or clone device for temporary |
| * use when searching for a match with a named file argument. |
| */ |
| if ((Lf->inp_ty == 0) && (Lf->is_com || Lf->is_stream || pnl) |
| && (Clone || Pseudo)) |
| { |
| if (!sdp) { |
| if (rdevs || devs) { |
| if (Lf->is_stream && !pnl) |
| sdp = finddev(devs ? &dev : &DevDev, |
| rdevs ? &rdev : &Lf->dev, |
| LOOKDEV_CLONE); |
| else |
| sdp = finddev(devs ? &dev : &DevDev, |
| rdevs ? &rdev : &Lf->dev, |
| LOOKDEV_PSEUDO); |
| if (!sdp) |
| sdp = finddev(devs ? &dev : &DevDev, |
| rdevs ? &rdev : &Lf->dev, |
| LOOKDEV_ALL); |
| if (sdp) { |
| if (!rdevs) { |
| Lf->rdev = Lf->dev; |
| Lf->rdev_def = rdevs = 1; |
| } |
| if (!devs) { |
| Lf->dev = DevDev; |
| devs = Lf->dev_def = 1; |
| } |
| } |
| } |
| } else { |
| |
| /* |
| * A local device structure has been located. Make sure |
| * that it's accompanied by device settings. |
| */ |
| if (!devs && vfs) { |
| dev = Lf->dev = vfs->dev; |
| devs = Lf->dev_def = 1; |
| } |
| if (!rdevs) { |
| Lf->rdev = rdev = sdp->rdev; |
| Lf->rdev_def = rdevs = 1; |
| } |
| } |
| if (sdp) { |
| |
| /* |
| * Process the local device information. |
| */ |
| trdev = sdp->rdev; |
| Lf->inode = sdp->inode; |
| Lf->inp_ty = trdevs = 1; |
| if (!Namech[0] || Lf->is_com) { |
| (void) snpf(Namech, Namechl - 1, "%s", sdp->name); |
| Namech[Namechl - 1] = '\0'; |
| } |
| if (Lf->is_com && !Lf->nma) { |
| len = (int)strlen("(COMMON)") + 1; |
| if (!(Lf->nma = (char *) malloc(len))) { |
| (void) fprintf(stderr, |
| "%s: no space for (COMMON): PID %d; FD %s\n", |
| Pn, Lp->pid, Lf->fd); |
| Exit(1); |
| } |
| (void) snpf(Lf->nma, len, "(COMMON)"); |
| } |
| } |
| } |
| } |
| /* |
| * Record stream status. |
| */ |
| if (Lf->inp_ty == 0 && Lf->is_stream && strcmp(Lf->iproto, "STR") == 0) |
| Lf->inp_ty = 2; |
| /* |
| * Test for specified file. |
| */ |
| |
| #if defined(HASPROCFS) |
| if (Ntype == N_PROC) { |
| if (Procsrch) { |
| Procfind = 1; |
| Lf->sf |= SELNM; |
| } else { |
| for (pfi = Procfsid; pfi; pfi = pfi->next) { |
| if ((pfi->pid && pfi->pid == pids.pid_id) |
| |
| # if defined(HASPINODEN) |
| || (Lf->inp_ty == 1 && Lf->inode == pfi->inode) |
| # endif /* defined(HASPINODEN) */ |
| |
| ) { |
| pfi->f = 1; |
| if (!Namech[0]) { |
| (void) snpf(Namech, Namechl - 1, "%s", pfi->nm); |
| Namech[Namechl - 1] = '\0'; |
| } |
| Lf->sf |= SELNM; |
| break; |
| } |
| } |
| } |
| } else |
| #endif /* defined(HASPROCFS) */ |
| |
| { |
| if (Sfile) { |
| if (trdevs) { |
| rdev = Lf->rdev; |
| Lf->rdev = trdev; |
| tdef = Lf->rdev_def; |
| Lf->rdev_def = 1; |
| } |
| if (is_file_named(NULL, Ntype, type, 1)) |
| Lf->sf |= SELNM; |
| if (trdevs) { |
| Lf->rdev = rdev; |
| Lf->rdev_def = tdef; |
| } |
| } |
| } |
| /* |
| * Enter name characters. |
| */ |
| if (Namech[0]) |
| enter_nm(Namech); |
| } |
| |
| |
| /* |
| * read_cni() - read common snode information |
| */ |
| |
| static int |
| read_cni(s, rv, v, rs, di, din, dinl) |
| struct snode *s; /* starting snode */ |
| struct vnode *rv; /* "real" vnode receiver */ |
| struct vnode *v; /* starting vnode */ |
| struct snode *rs; /* "real" snode receiver */ |
| struct dev_info *di; /* dev_info structure receiver */ |
| char *din; /* device info name receiver */ |
| int dinl; /* sizeof(*din) */ |
| { |
| char tbuf[32]; |
| |
| if (read_nvn((KA_T)v->v_data, (KA_T)s->s_commonvp, rv)) |
| return(1); |
| if (read_nsn((KA_T)s->s_commonvp, (KA_T)rv->v_data, rs)) |
| return(1); |
| *din = '\0'; |
| if (rs->s_dip) { |
| if (kread((KA_T)rs->s_dip, (char *)di, sizeof(struct dev_info))) { |
| (void) snpf(Namech, Namechl - 1, |
| "common snode at %s: no dev info: %s", |
| print_kptr((KA_T)rv->v_data, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)rs->s_dip, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| if (di->devi_name |
| && kread((KA_T)di->devi_name, din, dinl-1) == 0) |
| din[dinl-1] = '\0'; |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * readinode() - read inode |
| */ |
| |
| static int |
| readinode(ia, i) |
| KA_T ia; /* inode kernel address */ |
| struct inode *i; /* inode buffer */ |
| { |
| if (kread((KA_T)ia, (char *)i, sizeof(struct inode))) { |
| (void) snpf(Namech, Namechl - 1, "can't read inode at %s", |
| print_kptr((KA_T)ia, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=20500 |
| /* |
| * read_ndn() - read node's door node |
| */ |
| |
| static int |
| read_ndn(na, da, dn) |
| KA_T na; /* containing vnode's address */ |
| KA_T da; /* door node's address */ |
| struct door_node *dn; /* door node receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!da || kread((KA_T)da, (char *)dn, sizeof(struct door_node))) { |
| (void) snpf(Namech, Namechl - 1, |
| "vnode at %s: can't read door_node: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(da, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=20500 */ |
| |
| |
| |
| /* |
| * read_mi() - read stream's module information |
| */ |
| |
| static void |
| read_mi(s, rdev, so, so_st, so_ad, sdp) |
| KA_T s; /* kernel stream pointer address */ |
| dev_t *rdev; /* raw device pointer */ |
| caddr_t so; /* so_so return (Solaris) */ |
| int *so_st; /* so_so status */ |
| KA_T *so_ad; /* so_so addresses */ |
| struct l_dev **sdp; /* returned device pointer */ |
| { |
| struct l_dev *dp; |
| int i, j, k, nl; |
| KA_T ka; |
| struct module_info mi; |
| char mn[STRNML]; |
| struct stdata sd; |
| struct queue q; |
| struct qinit qi; |
| KA_T qp; |
| /* |
| * If there is no stream pointer, or we can't read the stream head, |
| * return. |
| */ |
| if (!s) |
| return; |
| if (kread((KA_T)s, (char *)&sd, sizeof(sd))) { |
| (void) snpf(Namech, Namechl - 1, "can't read stream head: %s", |
| print_kptr(s, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return; |
| } |
| /* |
| * Follow the stream head to each of its queue structures, retrieving the |
| * module names from each queue's q_info->qi_minfo->mi_idname chain of |
| * structures. Separate each additional name from the previous one with |
| * "->". |
| * |
| * Ignore failures to read all but queue structure chain entries. |
| * |
| * Ignore module names that end in "head". |
| */ |
| k = 0; |
| Namech[0] = '\0'; |
| if (!(dp = finddev(&DevDev, rdev, LOOKDEV_CLONE))) |
| dp = finddev(&DevDev, rdev, LOOKDEV_ALL); |
| if (dp) { |
| (void) snpf(Namech, Namechl - 1, "%s", dp->name); |
| Namech[Namechl - 1] = '\0'; |
| k = (int)strlen(Namech); |
| *sdp = dp; |
| } else |
| (void) snpf(Lf->iproto, sizeof(Lf->iproto), "STR"); |
| nl = sizeof(mn) - 1; |
| mn[nl] = '\0'; |
| qp = (KA_T)sd.sd_wrq; |
| for (i = 0; qp && i < 20; i++, qp = (KA_T)q.q_next) { |
| if (!qp || kread(qp, (char *)&q, sizeof(q))) |
| break; |
| if ((ka = (KA_T)q.q_qinfo) == (KA_T)NULL |
| || kread(ka, (char *)&qi, sizeof(qi))) |
| continue; |
| if ((ka = (KA_T)qi.qi_minfo) == (KA_T)NULL |
| || kread(ka, (char *)&mi, sizeof(mi))) |
| continue; |
| if ((ka = (KA_T)mi.mi_idname) == (KA_T)NULL |
| || kread(ka, mn, nl)) |
| continue; |
| if ((j = (int)strlen(mn)) < 1) |
| continue; |
| if (j >= 4 && strcmp(&mn[j - 4], "head") == 0) |
| continue; |
| |
| #if solaris<100000 |
| if (strcmp(mn, "sockmod") == 0) { |
| |
| /* |
| * Save the Solaris sockmod device and inode numbers. |
| */ |
| if (so) { |
| |
| struct so_so s; |
| |
| if (!kread((KA_T)q.q_ptr, (char *)&s, sizeof(s))) { |
| if (!(*so_st)) |
| so_ad[0] = (KA_T)q.q_ptr; |
| else |
| so_ad[1] = (KA_T)q.q_ptr; |
| (void) savesockmod(&s, (struct so_so *)so, so_st); |
| } |
| } |
| } |
| #endif /* solaris<100000 */ |
| |
| if (k) { |
| if ((k + 2) > (Namechl - 1)) |
| break; |
| (void) snpf(&Namech[k], Namechl - k, "->"); |
| k += 2; |
| } |
| if ((k + j) > (Namechl - 1)) |
| break; |
| (void) snpf(&Namech[k], Namechl - k, "%s", mn); |
| k += j; |
| } |
| } |
| |
| |
| #if solaris>=20500 |
| |
| /* |
| * read_nan(na, ca, cn) - read node's autofs node |
| */ |
| |
| static int |
| read_nan(na, aa, rn) |
| KA_T na; /* containing node's address */ |
| KA_T aa; /* autofs node address */ |
| |
| # if solaris<20600 |
| struct autonode *rn; /* autofs node receiver */ |
| # else /* solaris>=20600 */ |
| struct fnnode *rn; /* autofs node receiver */ |
| # endif /* solaris<20600 */ |
| |
| { |
| char tbuf[32]; |
| |
| # if solaris<20600 |
| if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct autonode))) |
| # else /* solaris>=20600 */ |
| if (!aa || kread((KA_T)aa, (char *)rn, sizeof(struct fnnode))) |
| # endif /* solaris<20600 */ |
| |
| { |
| (void) snpf(Namech, Namechl - 1, |
| |
| # if solaris<20600 |
| "node at %s: can't read autonode: %s", |
| # else /* solaris>=20600 */ |
| "node at %s: can't read fnnode: %s", |
| # endif /* solaris<20600 */ |
| |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(aa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=20500 */ |
| |
| |
| /* |
| * read_ncn(na, ca, cn) - read node's cache node |
| */ |
| |
| static int |
| read_ncn(na, ca, cn) |
| KA_T na; /* containing node's address */ |
| KA_T ca; /* cache node address */ |
| struct cnode *cn; /* cache node receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ca || kread((KA_T)ca, (char *)cn, sizeof(struct cnode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read cnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ca, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=100000 |
| /* |
| * read_nctfsn(ty, na, ca, cn) - read node's cache node |
| */ |
| |
| static int |
| read_nctfsn(ty, na, ca, cn) |
| int ty; /* node type -- i.e., N_CTFS* */ |
| KA_T na; /* containing node's address */ |
| KA_T ca; /* cache node address */ |
| char *cn; /* CTFS node receiver */ |
| { |
| char *cp, *nm, tbuf[32]; |
| READLEN_T sz; |
| |
| switch (ty) { |
| case N_CTFSADIR: |
| nm = "ADIR"; |
| sz = (READLEN_T)sizeof(ctfs_adirnode_t); |
| break; |
| case N_CTFSBUND: |
| nm = "BUND"; |
| sz = (READLEN_T)sizeof(ctfs_bunode_t); |
| break; |
| case N_CTFSCDIR: |
| nm = "CDIR"; |
| sz = (READLEN_T)sizeof(ctfs_cdirnode_t); |
| break; |
| case N_CTFSCTL: |
| nm = "CTL"; |
| sz = (READLEN_T)sizeof(ctfs_ctlnode_t); |
| break; |
| case N_CTFSEVT: |
| nm = "EVT"; |
| sz = (READLEN_T)sizeof(ctfs_evnode_t); |
| break; |
| case N_CTFSLATE: |
| nm = "LATE"; |
| sz = (READLEN_T)sizeof(ctfs_latenode_t); |
| break; |
| case N_CTFSROOT: |
| nm = "ROOT"; |
| sz = (READLEN_T)sizeof(ctfs_rootnode_t); |
| break; |
| case N_CTFSSTAT: |
| nm = "STAT"; |
| sz = (READLEN_T)sizeof(ctfs_ctlnode_t); |
| break; |
| case N_CTFSSYM: |
| nm = "SYM"; |
| sz = (READLEN_T)sizeof(ctfs_symnode_t); |
| break; |
| case N_CTFSTDIR: |
| nm = "TDIR"; |
| sz = (READLEN_T)sizeof(ctfs_tdirnode_t); |
| break; |
| case N_CTFSTMPL: |
| nm = "TMPL"; |
| sz = (READLEN_T)sizeof(ctfs_tmplnode_t); |
| break; |
| default: |
| (void) snpf(Namech, Namechl - 1, "unknown CTFS node type: %d", ty); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| if (!ca || kread((KA_T)ca, cn, sz)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read CTFS %s node: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| nm, |
| print_kptr(ca, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=100000 */ |
| |
| |
| /* |
| * read_nfn() - read node's fifonode |
| */ |
| |
| static int |
| read_nfn(na, fa, f) |
| KA_T na; /* containing node's address */ |
| KA_T fa; /* fifonode address */ |
| struct fifonode *f; /* fifonode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!fa || readfifonode(fa, f)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read fifonode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(fa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nhn() - read node's High Sierra node |
| */ |
| |
| static int |
| read_nhn(na, ha, h) |
| KA_T na; /* containing node's address */ |
| KA_T ha; /* hsnode address */ |
| struct hsnode *h; /* hsnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ha || readhsnode(ha, h)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read hsnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ha, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nin() - read node's inode |
| */ |
| |
| static int |
| read_nin(na, ia, i) |
| KA_T na; /* containing node's address */ |
| KA_T ia; /* kernel inode address */ |
| struct inode *i; /* inode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ia || readinode(ia, i)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read inode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ia, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nln(na, la, ln) - read node's loopback node |
| */ |
| |
| static int |
| read_nln(na, la, ln) |
| KA_T na; /* containing node's address */ |
| KA_T la; /* loopback node address */ |
| struct lnode *ln; /* loopback node receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!la || kread((KA_T)la, (char *)ln, sizeof(struct lnode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read lnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(la, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nnn() - read node's namenode |
| */ |
| |
| static int |
| read_nnn(na, nna, nn) |
| KA_T na; /* containing node's address */ |
| KA_T nna; /* namenode address */ |
| struct namenode *nn; /* namenode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!nna || kread((KA_T)nna, (char *)nn, sizeof(struct namenode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read namenode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(nna, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nmn() - read node's mvfsnode |
| */ |
| |
| static int |
| read_nmn(na, ma, m) |
| KA_T na; /* containing node's address */ |
| KA_T ma; /* kernel mvfsnode address */ |
| struct mvfsnode *m; /* mvfsnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ma || kread((KA_T)ma, (char *)m, sizeof(struct mvfsnode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read mvfsnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ma, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if defined(HASPROCFS) |
| /* |
| * read_npi() - read node's /proc file system information |
| */ |
| |
| static int |
| read_npi(na, v, pids) |
| KA_T na; /* containing node's address */ |
| struct vnode *v; /* containing vnode */ |
| struct pid *pids; /* pid structure receiver */ |
| { |
| struct as as; |
| struct proc p; |
| struct prnode pr; |
| char tbuf[32]; |
| |
| #if solaris>=20600 |
| prcommon_t pc, ppc; |
| int pcs, ppcs, prpcs, prppcs; |
| struct proc pp; |
| pid_t prpid; |
| id_t prtid; |
| char *ty = (char *)NULL; |
| #endif /* solaris>=20600 */ |
| |
| if (!v->v_data || kread((KA_T)v->v_data, (char *)&pr, sizeof(pr))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read prnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)v->v_data, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| |
| #if solaris<20600 |
| /* |
| * For Solaris < 2.6: |
| * * Read the proc structure, get the process size and PID; |
| * * Return the PID; |
| * * Enter a name, constructed from the file system and PID; |
| * * Enter an inode number, constructed from the PID. |
| */ |
| if (!pr.pr_proc) { |
| if (v->v_type == VDIR) { |
| (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| Lf->inode = (INODETYPE)PR_ROOTINO; |
| Lf->inp_ty = 1; |
| } else { |
| (void) snpf(Namech, Namechl - 1, "/%s/", HASPROCFS); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| Lf->inp_ty = 0; |
| } |
| return(0); |
| } |
| if (kread((KA_T)pr.pr_proc, (char *)&p, sizeof(p))) { |
| (void) snpf(Namech, Namechl - 1, |
| "prnode at %s: can't read proc: %s", |
| print_kptr((KA_T)v->v_data, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)pr.pr_proc, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| if (p.p_as && !kread((KA_T)p.p_as, (char *)&as, sizeof(as))) { |
| Lf->sz = (SZOFFTYPE)as.a_size; |
| Lf->sz_def = 1; |
| } |
| if (!p.p_pidp |
| || kread((KA_T)p.p_pidp, (char *)pids, sizeof(struct pid))) { |
| (void) snpf(Namech, Namechl - 1, |
| "proc struct at %s: can't read pid: %s", |
| print_kptr((KA_T)pr.pr_proc, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)p.p_pidp, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| (void) snpf(Namech, Namechl, "/%s/%d", HASPROCFS, (int)pids->pid_id); |
| Namech[Namechl - 1] = '\0'; |
| Lf->inode = (INODETYPE)ptoi(pids->pid_id); |
| Lf->inp_ty = 1; |
| #else /* solaris>=20600 */ |
| /* |
| * Enter the >= Solaris 2.6 inode number. |
| */ |
| Lf->inode = (INODETYPE)pr.pr_ino; |
| Lf->inp_ty = 1; |
| /* |
| * Read the >= Solaris 2.6 prnode common structures. |
| * |
| * Return the PID number. |
| * |
| * Identify the lwp PID (the thread ID). |
| */ |
| if (pr.pr_common |
| && kread((KA_T)pr.pr_common, (char *)&pc, sizeof(pc)) == 0) { |
| pcs = 1; |
| if (pc.prc_proc |
| && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0) |
| prpcs = 1; |
| else |
| prpcs = 0; |
| } else |
| pcs = prpcs = 0; |
| if (pr.pr_pcommon |
| && kread((KA_T)pr.pr_pcommon, (char *)&ppc, sizeof(ppc)) == 0) { |
| ppcs = 1; |
| if (ppc.prc_proc |
| && kread((KA_T)ppc.prc_proc, (char *)&pp, sizeof(pp)) == 0) |
| prppcs = 1; |
| else |
| prppcs = 0; |
| } else |
| ppcs = prppcs = 0; |
| if (pcs && pc.prc_pid) |
| pids->pid_id = prpid = pc.prc_pid; |
| else if (ppcs && ppc.prc_pid) |
| pids->pid_id = prpid = ppc.prc_pid; |
| else |
| pids->pid_id = prpid = (pid_t)0; |
| if (pcs && pc.prc_tid) |
| prtid = pc.prc_tid; |
| else if (ppcs && ppc.prc_tid) |
| prtid = ppc.prc_tid; |
| else |
| prtid = (id_t)0; |
| /* |
| * Identify the Solaris 2.6 /proc file system name, file size, and file type. |
| */ |
| switch (pr.pr_type) { |
| case PR_PROCDIR: |
| (void) snpf(Namech, Namechl - 1, "/%s", HASPROCFS); |
| ty = "PDIR"; |
| break; |
| case PR_PIDDIR: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); |
| ty = "PDIR"; |
| break; |
| case PR_AS: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/as", HASPROCFS, (int)prpid); |
| ty = "PAS"; |
| if (prpcs |
| && kread((KA_T)pc.prc_proc, (char *)&p, sizeof(p)) == 0 |
| && p.p_as |
| && kread((KA_T)p.p_as, (char *)&as, sizeof(as)) == 0) { |
| Lf->sz = (SZOFFTYPE)as.a_size; |
| Lf->sz_def = 1; |
| } |
| break; |
| case PR_CTL: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/ctl", HASPROCFS, (int)prpid); |
| ty = "PCTL"; |
| break; |
| case PR_STATUS: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/status", HASPROCFS, (int)prpid); |
| ty = "PSTA"; |
| break; |
| case PR_LSTATUS: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lstatus", HASPROCFS, (int)prpid); |
| ty = "PLST"; |
| break; |
| case PR_PSINFO: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/psinfo", HASPROCFS, (int)prpid); |
| ty = "PSIN"; |
| break; |
| case PR_LPSINFO: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lpsinfo", HASPROCFS, (int)prpid); |
| ty = "PLPI"; |
| break; |
| case PR_MAP: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/map", HASPROCFS, (int)prpid); |
| ty = "PMAP"; |
| break; |
| case PR_RMAP: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/rmap", HASPROCFS, (int)prpid); |
| ty = "PRMP"; |
| break; |
| case PR_XMAP: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/xmap", HASPROCFS, (int)prpid); |
| ty = "PXMP"; |
| break; |
| case PR_CRED: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/cred", HASPROCFS, (int)prpid); |
| ty = "PCRE"; |
| break; |
| case PR_SIGACT: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/sigact", HASPROCFS, (int)prpid); |
| ty = "PSGA"; |
| break; |
| case PR_AUXV: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/auxv", HASPROCFS, (int)prpid); |
| ty = "PAXV"; |
| break; |
| |
| # if defined(HASPR_LDT) |
| case PR_LDT: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/ldt", HASPROCFS, (int)prpid); |
| ty = "PLDT"; |
| break; |
| # endif /* defined(HASPR_LDT) */ |
| |
| case PR_USAGE: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/usage", HASPROCFS, (int)prpid); |
| ty = "PUSG"; |
| break; |
| case PR_LUSAGE: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lusage", HASPROCFS, (int)prpid); |
| ty = "PLU"; |
| break; |
| case PR_PAGEDATA: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/pagedata", HASPROCFS, (int)prpid); |
| ty = "PGD"; |
| break; |
| case PR_WATCH: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/watch", HASPROCFS, (int)prpid); |
| ty = "PW"; |
| break; |
| case PR_CURDIR: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/cwd", HASPROCFS, (int)prpid); |
| ty = "PCWD"; |
| break; |
| case PR_ROOTDIR: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/root", HASPROCFS, (int)prpid); |
| ty = "PRTD"; |
| break; |
| case PR_FDDIR: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/fd", HASPROCFS, (int)prpid); |
| ty = "PFDR"; |
| break; |
| case PR_FD: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/fd/%d", HASPROCFS, (int)prpid, |
| pr.pr_index); |
| ty = "PFD"; |
| break; |
| case PR_OBJECTDIR: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/object", HASPROCFS, (int)prpid); |
| ty = "PODR"; |
| break; |
| case PR_OBJECT: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/object/", HASPROCFS, (int)prpid); |
| ty = "POBJ"; |
| break; |
| case PR_LWPDIR: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lpw", HASPROCFS, (int)prpid); |
| ty = "PLDR"; |
| break; |
| case PR_LWPIDDIR: |
| (void) snpf(Namech, Namechl, |
| "/%s/%d/lwp/%d", HASPROCFS, (int)prpid, (int)prtid); |
| ty = "PLDR"; |
| break; |
| case PR_LWPCTL: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/lwpctl", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLC"; |
| break; |
| case PR_LWPSTATUS: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lwp/%d/lwpstatus", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLWS"; |
| break; |
| case PR_LWPSINFO: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lwp/%d/lwpsinfo", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLWI"; |
| break; |
| case PR_LWPUSAGE: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lwp/%d/lwpusage", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLWU"; |
| break; |
| case PR_XREGS: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d/lwp/%d/xregs", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLWX"; |
| break; |
| |
| # if defined(HASPR_GWINDOWS) |
| case PR_GWINDOWS: |
| (void) snpf(Namech, Namechl - 1, |
| "/%s/%d/lwp/%d/gwindows", HASPROCFS, |
| (int)prpid, (int)prtid); |
| ty = "PLWG"; |
| break; |
| # endif /* defined(HASPR_GWINDOWS) */ |
| |
| case PR_PIDFILE: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); |
| ty = "POPF"; |
| break; |
| case PR_LWPIDFILE: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); |
| ty = "POLP"; |
| break; |
| case PR_OPAGEDATA: |
| (void) snpf(Namech, Namechl - 1, "/%s/%d", HASPROCFS, (int)prpid); |
| ty = "POPG"; |
| break; |
| default: |
| ty = (char *)NULL; |
| } |
| if (ty) |
| (void) snpf(Lf->type, sizeof(Lf->type), "%s", ty); |
| else |
| (void) snpf(Lf->type, sizeof(Lf->type), "%04o", |
| (pr.pr_type & 0xfff)); |
| /* |
| * Record the Solaris 2.6 /proc file system inode number. |
| */ |
| Lf->inode = (INODETYPE)pr.pr_ino; |
| Lf->inp_ty = 1; |
| # endif /* solaris<20600 */ |
| |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(0); |
| } |
| #endif /* defined(HASPROCFS) */ |
| |
| |
| /* |
| * read_npn() - read node's pcnode |
| */ |
| |
| static int |
| read_npn(na, pa, p) |
| KA_T na; /* containing node's address */ |
| KA_T pa; /* pcnode address */ |
| struct pcnode *p; /* pcnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!pa || kread(pa, (char *)p, sizeof(struct pcnode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read pcnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(pa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=100000 |
| /* |
| * read_nprtn() - read node's port node |
| */ |
| |
| static int |
| read_nprtn(na, pa, p) |
| KA_T na; /* containing node's address */ |
| KA_T pa; /* port node address */ |
| port_t *p; /* port node receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!pa || kread(pa, (char *)p, sizeof(port_t))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read port node: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(pa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=100000 */ |
| |
| |
| /* |
| * read_nrn() - read node's rnode |
| */ |
| |
| static int |
| read_nrn(na, ra, r) |
| KA_T na; /* containing node's address */ |
| KA_T ra; /* rnode address */ |
| struct rnode *r; /* rnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ra || readrnode(ra, r)) { |
| (void) snpf(Namech, Namechl - 1, "node at %s: can't read rnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ra, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=100000 |
| /* |
| * read_nrn4() - read node's rnode4 |
| */ |
| |
| static int |
| read_nrn4(na, ra, r) |
| KA_T na; /* containing node's address */ |
| KA_T ra; /* rnode address */ |
| struct rnode4 *r; /* rnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ra || |
| kread((KA_T)ra, (char *)r, sizeof(struct rnode4)) |
| ) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read rnode4: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ra, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=100000 */ |
| |
| |
| #if solaris>=110000 |
| /* |
| * read_nsdn() - read node's sdev_node |
| */ |
| |
| static int |
| read_nsdn(na, sa, sdn, sdva) |
| KA_T na; /* containing node's adress */ |
| KA_T sa; /* sdev_node address */ |
| struct sdev_node *sdn; /* sdev_node receiver */ |
| struct vattr *sdva; /* sdev_node's vattr receiver */ |
| { |
| KA_T va; |
| char tbuf[32], tbuf1[32]; |
| |
| if (!sa || kread((KA_T)sa, (char *)sdn, sizeof(struct sdev_node))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read sdev_node: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(sa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| if (!(va = (KA_T)sdn->sdev_attr) |
| || kread(va, (char *)sdva, sizeof(struct vattr)) |
| ) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s; sdev_node at %s: can't read vattr: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(sa, tbuf1, sizeof(tbuf1)), |
| print_kptr(va, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=110000 */ |
| |
| |
| #if solaris>=20600 |
| /* |
| * read_nson() - read node's sonode |
| */ |
| |
| static int |
| read_nson(na, sa, sn) |
| KA_T na; /* containing node's address */ |
| KA_T sa; /* sonode address */ |
| struct sonode *sn; /* sonode receiver */ |
| |
| { |
| char tbuf[32]; |
| |
| if (!sa || kread((KA_T)sa, (char *)sn, sizeof(struct sonode))) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read sonode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(sa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=20600 */ |
| |
| |
| /* |
| * read_nsn() - read node's snode |
| */ |
| |
| static int |
| read_nsn(na, sa, s) |
| KA_T na; /* containing node's address */ |
| KA_T sa; /* snode address */ |
| struct snode *s; /* snode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!sa || readsnode(sa, s)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read snode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(sa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=110000 |
| /* |
| * read_nsti() - read socket node's info |
| */ |
| |
| static int |
| read_nsti(so, stpi) |
| struct sonode *so; /* socket's sonode */ |
| sotpi_info_t *stpi; /* local socket info receiver */ |
| { |
| char tbuf[32]; |
| |
| (void) CTF_init(&Sockfs_ctfs, SOCKFS_MOD_FORMAT, Sockfs_requests); |
| if (!so |
| || !so->so_priv |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_dev) |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_laddr) |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_faddr) |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_laddr) |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_ux_faddr) |
| || CTF_MEMBER_READ(so->so_priv,stpi,sotpi_info_members, sti_serv_type) |
| ) { |
| (void) snpf(Namech, Namechl - 1, |
| "sonode at %s: can't read so_priv: %s", |
| print_kptr((KA_T)so, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)so->so_priv, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* solaris>=110000 */ |
| |
| |
| /* |
| * read_ntn() - read node's tmpnode |
| */ |
| |
| static int |
| read_ntn(na, ta, t) |
| KA_T na; /* containing node's address */ |
| KA_T ta; /* tmpnode address */ |
| struct tmpnode *t; /* tmpnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (!ta || readtnode(ta, t)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read tnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(ta, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if solaris>=20600 |
| /* |
| * read_nusa() - read sondode's UNIX socket address |
| */ |
| |
| static int |
| read_nusa(so, ua) |
| struct soaddr *so; /* kernel socket info structure */ |
| struct sockaddr_un *ua; /* local sockaddr_un address */ |
| { |
| KA_T a; |
| int len; |
| int min = offsetof(struct sockaddr_un, sun_path); |
| |
| ua->sun_path[0] = '\0'; |
| |
| if (!(a = (KA_T)so->soa_sa) |
| || (len = so->soa_len) < (min + 2) |
| || len > (int)sizeof(struct sockaddr_un) |
| || kread(a, (char *)ua, len) |
| || ua->sun_family != AF_UNIX) |
| return(0); |
| len -= min; |
| if (len >= sizeof(ua->sun_path)) |
| len = sizeof(ua->sun_path) - 1; |
| ua->sun_path[len] = '\0'; |
| return((int)strlen(ua->sun_path)); |
| } |
| #endif /* solaris>=20600 */ |
| |
| |
| /* |
| * read_nvn() - read node's vnode |
| */ |
| |
| static int |
| read_nvn(na, va, v) |
| KA_T na; /* node's address */ |
| KA_T va; /* vnode address */ |
| struct vnode *v; /* vnode receiver */ |
| { |
| char tbuf[32]; |
| |
| if (readvnode(va, v)) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read real vnode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(va, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| #if defined(HAS_ZFS) |
| /* |
| * read_nzn() - read node's ZFS node |
| */ |
| |
| static int |
| read_nzn(na, nza, zn) |
| KA_T na; /* containing node's address */ |
| KA_T nza; /* znode address */ |
| znode_t *zn; /* znode receiver */ |
| { |
| int err = 0; /* error flag */ |
| CTF_member_t *mp; /* member pointer */ |
| char tbuf[32]; /* temporary buffer */ |
| znode_phys_t zp; /* physical znode */ |
| |
| (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); |
| if (!nza |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_zfsvfs) |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_vnode) |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_id) |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_phys) |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_links) |
| || CTF_MEMBER_READ(nza, zn, znode_members, z_size) |
| ) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read znode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(nza, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * If the physical znode pointer is defined, read the physizal znode |
| * and propagate its values to the znode. |
| */ |
| if (znode_members[MX_z_phys].m_offset != CTF_MEMBER_UNDEF) { |
| err = read_nznp(nza, (KA_T)zn->z_phys, &zp); |
| if (!err) { |
| zn->z_links = zp.zp_links; |
| zn->z_size = zp.zp_size; |
| } |
| } else { |
| |
| /* |
| * Make sure z_link and z_size are defined when z_phys isn't. |
| */ |
| if (znode_members[MX_z_links].m_offset == CTF_MEMBER_UNDEF) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read z_links: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(nza, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| err = 1; |
| } |
| if (znode_members[MX_z_size].m_offset == CTF_MEMBER_UNDEF) { |
| (void) snpf(Namech, Namechl - 1, |
| "node at %s: can't read z_size: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(nza, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| err = 1; |
| } |
| } |
| return(err); |
| } |
| |
| |
| /* |
| * read_nznp() - read znode's persistent znode |
| */ |
| |
| static int |
| read_nznp(nza, nzpa, zp) |
| KA_T nza; /* containing znode's address */ |
| KA_T nzpa; /* persistent znode address */ |
| znode_phys_t *zp; /* persistent znode receiver */ |
| { |
| char tbuf[32]; |
| |
| (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); |
| if (!nzpa |
| || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_size) |
| || CTF_MEMBER_READ(nzpa, zp, znode_phys_members, zp_links) |
| ) { |
| (void) snpf(Namech, Namechl - 1, "znode at %s: " |
| "can't read znode_phys: %s", |
| print_kptr(nza, tbuf, sizeof(tbuf)), |
| print_kptr(nzpa, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| |
| |
| /* |
| * read_nzvfs() - read znode's associated vfs |
| */ |
| |
| static int |
| read_nzvfs(nza, nzva, zv) |
| KA_T nza; /* containing znode's address */ |
| KA_T nzva; /* associated vfs address */ |
| zfsvfs_t *zv; /* associated vfs receiver */ |
| { |
| char tbuf[32]; |
| |
| (void) CTF_init(&ZFS_ctfs, ZFS_MOD_FORMAT, ZFS_requests); |
| if (!nzva |
| || CTF_MEMBER_READ(nzva, zv, zfsvfs_members, z_vfs) |
| ) { |
| (void) snpf(Namech, Namechl - 1, |
| "znode at %s: can't read zfsvfs: %s", |
| print_kptr(nza, tbuf, sizeof(tbuf)), |
| print_kptr(nzva, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| return(0); |
| } |
| #endif /* defined(HAS_ZFS) */ |
| |
| |
| #if solaris<100000 |
| /* |
| * savesockmod() - save addresses from sockmod so_so structure |
| */ |
| |
| static void |
| savesockmod(so, sop, so_st) |
| struct so_so *so; /* new so_so structure pointer */ |
| struct so_so *sop; /* previous so_so structure pointer */ |
| int *so_st; /* status of *sop (0 if not loaded) */ |
| { |
| |
| #if solaris<20500 |
| dev_t d1, d2, d3; |
| #endif /* solaris<20500 */ |
| |
| #define luxadr lux_dev.addr.tu_addr |
| #define luxdev lux_dev.addr.tu_addr.dev |
| #define luxino lux_dev.addr.tu_addr.ino |
| #define ruxadr rux_dev.addr.tu_addr |
| #define ruxdev rux_dev.addr.tu_addr.dev |
| #define ruxino rux_dev.addr.tu_addr.ino |
| |
| #if solaris<20500 |
| /* |
| * If either address in the new structure is missing a device number, clear |
| * its corresponding inode number. Then sort the inode-less device numbers. |
| */ |
| if (!so->luxdev) |
| so->luxino = (ino_t)0; |
| if (!so->ruxdev) |
| so->ruxino = (ino_t)0; |
| if (!so->luxino && !so->ruxino) { |
| if (so->luxdev > so->ruxdev) { |
| d2 = so->luxdev; |
| d1 = so->luxdev = so->ruxdev; |
| so->ruxdev = d2; |
| } else { |
| d1 = so->luxdev; |
| d2 = so->ruxdev; |
| } |
| } else |
| d1 = d2 = (dev_t)0; |
| /* |
| * If the previous structure hasn't been loaded, save the new one in it with |
| * adjusted or sorted addresses. |
| */ |
| if (!*so_st) { |
| if (so->luxdev && so->luxino) { |
| *sop = *so; |
| sop->ruxdev = (dev_t)0; |
| sop->ruxino = (ino_t)0; |
| *so_st = 1; |
| return; |
| } |
| if (so->ruxdev && so->ruxino) { |
| *sop = *so; |
| sop->luxadr = sop->ruxadr; |
| sop->ruxdev = (dev_t)0; |
| sop->ruxino = (ino_t)0; |
| *so_st = 1; |
| return; |
| } |
| *sop = *so; |
| *so_st = 1; |
| return; |
| } |
| /* |
| * See if the new sockmod addresses need to be merged with the previous |
| * ones: |
| * |
| * * Don't merge if the previous so_so structure's lux_dev has a non- |
| * zero device and a non-zero inode number. |
| * |
| * * If either of the device/inode pairs in the new structure is non- |
| * zero, propagate them to the previous so_so structure. |
| * |
| * * Don't merge if the both device numbers in the new structure are |
| * zero. |
| */ |
| if (sop->luxdev && sop->luxino) |
| return; |
| if (so->luxdev && so->luxino) { |
| sop->luxadr = so->luxadr; |
| sop->ruxdev = (dev_t)0; |
| sop->ruxino = (ino_t)0; |
| return; |
| } |
| if (so->ruxdev && so->ruxino) { |
| sop->luxadr = so->ruxadr; |
| sop->ruxdev = (dev_t)0; |
| sop->ruxino = (ino_t)0; |
| return; |
| } |
| if (!so->luxdev && !so->ruxdev) |
| return; |
| /* |
| * Check the previous structure's device numbers: |
| * |
| * * If both are zero, replace the previous structure with the new one. |
| * |
| * * Choose the minimum and maximum non-zero device numbers contained in |
| * either structure. |
| */ |
| if (!sop->luxdev && !sop->ruxdev) { |
| *sop = *so; |
| return; |
| } |
| if (!sop->luxdev && (d1 || d2)) { |
| if (d1) { |
| sop->luxdev = d1; |
| d1 = (dev_t)0; |
| } else { |
| sop->luxdev = d2; |
| d2 = (dev_t)0; |
| } |
| if (sop->luxdev > sop->ruxdev) { |
| d3 = sop->luxdev; |
| sop->luxdev = sop->ruxdev; |
| sop->ruxdev = d3; |
| } |
| } |
| if (!sop->ruxdev && (d1 || d2)) { |
| if (d1) { |
| sop->ruxdev = d1; |
| d1 = (dev_t)0; |
| } else { |
| sop->ruxdev = d2; |
| d2 = (dev_t)0; |
| } |
| if (sop->luxdev > sop->ruxdev) { |
| d3 = sop->luxdev; |
| sop->luxdev = sop->ruxdev; |
| sop->ruxdev = d3; |
| } |
| } |
| if (sop->luxdev && sop->ruxdev) { |
| if (d1) { |
| if (d1 < sop->luxdev) |
| sop->luxdev = d1; |
| else if (d1 > sop->ruxdev) |
| sop->ruxdev = d1; |
| } |
| if (d2) { |
| if (d2 < sop->luxdev) |
| sop->luxdev = d2; |
| else if (d2 > sop->ruxdev) |
| sop->ruxdev = d2; |
| } |
| } |
| #else /* solaris>=20500 */ |
| /* |
| * Save the first sockmod structure. |
| */ |
| if (!*so_st) { |
| *so_st = 1; |
| *sop = *so; |
| } |
| #endif /* solaris<20500 */ |
| |
| } |
| #endif /* solaris<100000 */ |
| |
| |
| |
| /* |
| * vop2ty() - convert vnode operation switch address to internal type |
| */ |
| |
| int |
| vop2ty(vp, fx) |
| struct vnode *vp; /* local vnode pointer */ |
| int fx; /* file system index (-1 if none) */ |
| { |
| int h; |
| register int i; |
| KA_T ka; |
| int nty; |
| v_optab_t *nv, *v, *vt; |
| |
| #if defined(HAS_AFS) |
| static int afs = 0; /* afs test status: -1 = no AFS |
| * 0 = not tested |
| * 1 = AFS */ |
| #endif /* defined(HAS_AFS) */ |
| |
| /* |
| * Locate the node type by hashing the vnode's v_op address into the Voptab[]. |
| */ |
| if (!(ka = (KA_T)vp->v_op)) |
| return(-1); |
| h = HASHVOP(ka); |
| for (v = Voptab[h]; v; v = v->next) { |
| if (ka == v->v_op) |
| break; |
| } |
| if (!v) { |
| |
| /* |
| * If there's no entry in the Voptab[] for the v_op address, see if |
| * an entry can be found via the file system type and FxToVoptab[]. |
| */ |
| if ((fx >= 0) && (fx < Fsinfomax) && (v = FxToVoptab[fx])) { |
| |
| /* |
| * There's an FxToVoptab[] mapping, so add an entry to Voptab[] |
| * for the v_op address. |
| */ |
| if (!(nv = (v_optab_t *)malloc((MALLOC_S)sizeof(v_optab_t)))) { |
| (void) fprintf(stderr, "%s: can't add \"%s\" to Voptab\n", |
| Pn, Fsinfo[fx]); |
| Exit(1); |
| } |
| *nv = *v; |
| nv->v_op = ka; |
| h = HASHVOP(ka); |
| nv->next = Voptab[h]; |
| Voptab[h] = v = nv; |
| } |
| } |
| if (!v) |
| return(-1); |
| |
| #if defined(HAS_AFS) |
| /* |
| * Do special AFS checks. |
| */ |
| if (v->nty == N_AFS) { |
| if (vp->v_data || !vp->v_vfsp) |
| return(-1); |
| switch (afs) { |
| case -1: |
| return(-1); |
| case 0: |
| if (!hasAFS(vp)) { |
| afs = -1; |
| return(-1); |
| } |
| afs = 1; |
| return(N_AFS); |
| case 1: |
| if ((KA_T)vp->v_vfsp == AFSVfsp) |
| return(N_AFS); |
| } |
| return(-1); |
| } |
| #endif /* defined(HAS_AFS) */ |
| |
| return(v->nty); |
| } |
| |
| |
| #if solaris>=100000 |
| /* |
| * read_ndvn() -- read node's dv_node |
| */ |
| |
| static int |
| read_ndvn(na, da, dv, dev, devs) |
| KA_T na; /* containing vnode's address */ |
| KA_T da; /* containing vnode's v_data */ |
| struct dv_node *dv; /* dv_node receiver */ |
| dev_t *dev; /* underlying file system device |
| * number receptor */ |
| unsigned char *devs; /* status of *dev */ |
| { |
| struct vnode rv; |
| struct snode s; |
| char tbuf[32]; |
| struct vfs v; |
| /* |
| * Read the snode. |
| */ |
| if (!da || kread((KA_T)da, (char *)&s, sizeof(s))) { |
| (void) snpf(Namech, Namechl - 1, |
| "dv_node vnode at %s: can't read snode: %s", |
| print_kptr(na, tbuf, sizeof(tbuf)), |
| print_kptr(da, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * Read the snode's real vnode. |
| */ |
| if (!s.s_realvp |
| || kread((KA_T)s.s_realvp, (char *)&rv, sizeof(struct dv_node))) |
| { |
| (void) snpf(Namech, Namechl - 1, |
| "dv_node snode at %s: can't read real vnode: %s", |
| print_kptr(da, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)s.s_realvp, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * Read the real vnode's dv_node. |
| */ |
| if (!rv.v_data || kread((KA_T)rv.v_data, (char *)dv, sizeof(rv))) { |
| (void) snpf(Namech, Namechl - 1, |
| "dv_node real vnode at %s: can't read dv_node: %s", |
| print_kptr((KA_T)s.s_realvp, tbuf, sizeof(tbuf)), |
| print_kptr((KA_T)rv.v_data, (char *)NULL, 0)); |
| Namech[Namechl - 1] = '\0'; |
| enter_nm(Namech); |
| return(1); |
| } |
| /* |
| * Return the device number of the underlying file system, if possible. |
| */ |
| if (rv.v_vfsp && !kread((KA_T)rv.v_vfsp, (char *)&v, sizeof(v))) { |
| *dev = v.vfs_dev; |
| *devs = 1; |
| } |
| return(0); |
| } |
| #endif /* solaris<100000 */ |