diff options
Diffstat (limited to 'dialects/darwin/libproc/dfile.c')
-rw-r--r-- | dialects/darwin/libproc/dfile.c | 682 |
1 files changed, 682 insertions, 0 deletions
diff --git a/dialects/darwin/libproc/dfile.c b/dialects/darwin/libproc/dfile.c new file mode 100644 index 0000000..bd8d81a --- /dev/null +++ b/dialects/darwin/libproc/dfile.c @@ -0,0 +1,682 @@ +/* + * dfile.c -- Darwin file processing functions for libproc-based lsof + */ + + +/* + * Portions Copyright 2005-2007 Apple Inc. All rights reserved. + * + * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana + * 47907. All rights reserved. + * + * Written by Allan Nathanson, Apple Inc., and Victor A. Abell, Purdue + * University. + * + * 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 Apple Inc. 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, Apple + * Inc. 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 2005-2007 Apple Inc. and Purdue Research Foundation.\nAll rights reserved.\n"; +static char *rcsid = "$Id: dfile.c,v 1.8 2012/04/10 16:41:04 abe Exp $"; +#endif + + +#include "lsof.h" + + +/* + * enter_file_info() -- enter file information + */ + +void +enter_file_info(pfi) + struct proc_fileinfo *pfi; /* pointer to process file info */ +{ + int f; +/* + * Construct access code + */ + f = pfi->fi_openflags & (FREAD | FWRITE); + if (f == FREAD) + Lf->access = 'r'; + else if (f == FWRITE) + Lf->access = 'w'; + else if (f == (FREAD | FWRITE)) + Lf->access = 'u'; +/* + * Save the offset / size + */ + Lf->off = (SZOFFTYPE)pfi->fi_offset; + if (Foffset) + Lf->off_def = 1; +/* + * Save file structure information as requested. + */ + if (Fsv & FSV_FG) { + Lf->ffg = (long)pfi->fi_openflags; + Lf->fsv |= FSV_FG; + } +} + + +/* + * enter_vnode_info() -- enter vnode information + */ + +void +enter_vnode_info(vip) + struct vnode_info_path *vip; /* pointer to vnode info with path */ +{ + char buf[32], *cp; + dev_t dev = 0; + int devs = 0; + struct mounts *mp; +/* + * Derive file type. + */ + switch ((int)(vip->vip_vi.vi_stat.vst_mode & S_IFMT)) { + case S_IFIFO: + cp = "FIFO"; + Ntype = N_FIFO; + break; + case S_IFCHR: + cp = "CHR"; + Ntype = N_CHR; + break; + case S_IFDIR: + cp = "DIR"; + Ntype = N_REGLR; + break; + case S_IFBLK: + cp = "BLK"; + Ntype = N_BLK; + break; + case S_IFREG: + cp = "REG"; + Ntype = N_REGLR; + break; + default: + (void) snpf(buf, sizeof(buf), "%04o", + (((vip->vip_vi.vi_stat.vst_mode & S_IFMT) >> 12) & 0xfff)); + cp = buf; + Ntype = N_REGLR; + } + if (!Lf->type[0]) + (void) snpf(Lf->type, sizeof(Lf->type), "%s", cp); + Lf->ntype = Ntype; +/* + * Save device number and path + */ + switch (Ntype) { + case N_FIFO: + break; + case N_CHR: + case N_BLK: + Lf->rdev = vip->vip_vi.vi_stat.vst_rdev; + Lf->rdev_def = 1; + /* fall through */ + default: + Lf->dev = dev = vip->vip_vi.vi_stat.vst_dev; + Lf->dev_def = devs = 1; + } +/* + * Save path name. + */ + vip->vip_path[sizeof(vip->vip_path) - 1] = '\0'; + if (vip->vip_path[0] != '\0') { + Lf->V_path = mkstrcpy(vip->vip_path, (MALLOC_S *)NULL); + } +/* + * Save node number. + */ + Lf->inode = (INODETYPE)vip->vip_vi.vi_stat.vst_ino; + Lf->inp_ty = 1; +/* + * Save link count, as requested. + */ + if (Fnlink) { + Lf->nlink = vip->vip_vi.vi_stat.vst_nlink; + Lf->nlink_def = 1; + if (Nlink && (Lf->nlink < Nlink)) + Lf->sf |= SELNLINK; + } +/* + * If a device number is defined, locate file system and save its identity. + */ + if (devs) { + for (mp = readmnt(); mp; mp = mp->next) { + if (dev == mp->dev) { + Lf->fsdir = mp->dir; + Lf->fsdev = mp->fsname; + if (mp->is_nfs && Fnfs) + Lf->sf |= SELNFS; + break; + } + } + } +/* + * Save the file size. + */ + switch (Ntype) { + case N_CHR: + case N_FIFO: + Lf->off_def = 1; + break; + default: + Lf->sz = (SZOFFTYPE)vip->vip_vi.vi_stat.vst_size; + Lf->sz_def = 1; + } +/* + * Test for specified file. + */ + if (Sfile && is_file_named(NULL, + ((Ntype == N_CHR) || (Ntype == N_BLK) ? 1 + : 0))) + { + Lf->sf |= SELNM; + } +/* + * Enter name characters. + */ + if (!Lf->nm && Namech[0]) + enter_nm(Namech); +} + + +/* + * err2nm() -- convert errno to a message in Namech + */ + +void +err2nm(pfx) + char *pfx; /* Namech message prefix */ +{ + char *sfx; + + switch (errno) { + case EBADF: + + /* + * The file descriptor is no longer available. + */ + sfx = "FD unavailable"; + break; + case ESRCH: + + /* + * The process is no longer available. + */ + sfx = "process unavailable"; + break; + default: + + /* + * All other errors are reported with strerror() information. + */ + sfx = strerror(errno); + } + (void) snpf(Namech, Namechl, "%s: %s", pfx, sfx); + enter_nm(Namech); +} + + +/* + * print_nm() -- print Name column + */ +void +print_nm(lf) + struct lfile *lf; +{ + printname(0); +#ifdef PROC_PIDLISTFILEPORTS + if (lf->fileport) { + (void) printf(" (fileport=0x%04x)", lf->fileport); + } +#endif /* PROC_PIDLISTFILEPORTS */ + putchar('\n'); +} + + +/* + * print_v_path() -- print vnode's path + */ + +int +print_v_path(lf) + struct lfile *lf; +{ + if (lf->V_path) { + safestrprt(lf->V_path, stdout, 0); + return(1); + } + return(0); +} + + +/* + * process_atalk() -- process an Apple Talk file + */ + +void +process_atalk(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + (void) snpf(Lf->type, sizeof(Lf->type), "ATALK"); + return; +} + + +/* + * process_fsevents() -- process a file system events file + */ + +void +process_fsevents(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + (void) snpf(Lf->type, sizeof(Lf->type), "FSEVENTS"); +} + + +/* + * process_kqueue() -- process a kernel queue file + */ + +void +process_kqueue(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + struct kqueue_fdinfo kq; + int nb; +/* + * Get the kernel queue file information. + */ + (void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE"); + nb = proc_pidfdinfo(pid, fd, PROC_PIDFDKQUEUEINFO, &kq, sizeof(kq)); + if (nb <= 0) { + (void) err2nm("kqueue"); + return; + } else if (nb < sizeof(kq)) { + (void) fprintf(stderr, + "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDKQUEUEINFO);\n", + Pn, pid, fd); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(kq), nb); + Exit(1); + } +/* + * Enter the kernel queue file information. + */ + enter_file_info(&kq.pfi); +/* + * Enter queue counts as NAME column information. + */ + (void) snpf(Namech, Namechl, + "count=%" SZOFFPSPEC "u, state=%#x", + (SZOFFTYPE)kq.kqueueinfo.kq_stat.vst_size, + kq.kqueueinfo.kq_state); + enter_nm(Namech); +} + + +/* + * process_pipe() -- process pipe file + */ + +static void +process_pipe_common(pi) + struct pipe_fdinfo *pi; +{ + char dev_ch[32], *ep; + size_t sz; + + (void) snpf(Lf->type, sizeof(Lf->type), "PIPE"); +/* + * Enter the pipe handle as the device. + */ + (void) snpf(dev_ch, sizeof(dev_ch), "%s", + print_kptr((KA_T)pi->pipeinfo.pipe_handle, (char *)NULL, 0)); + enter_dev_ch(dev_ch); +/* + * Enable offset or size reporting. + */ + if (Foffset) + Lf->off_def = 1; + else { + Lf->sz = (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_blksize; + Lf->sz_def = 1; + } +/* + * If there is a peer handle, enter it in as NAME column information. + */ + if (pi->pipeinfo.pipe_peerhandle) { + (void) snpf(Namech, Namechl, "->%s", + print_kptr((KA_T)pi->pipeinfo.pipe_peerhandle, (char *)NULL, 0)); + enter_nm(Namech); + } else + Namech[0] = '\0'; +/* + * If the pipe has a count, add it to the NAME column. + */ + if (pi->pipeinfo.pipe_stat.vst_size) { + ep = endnm(&sz); + (void) snpf(ep, sz, ", cnt=%" SZOFFPSPEC "u", + (SZOFFTYPE)pi->pipeinfo.pipe_stat.vst_size); + } +} + + +void +process_pipe(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + int nb; + struct pipe_fdinfo pi; +/* + * Get pipe file information. + */ + nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPIPEINFO, &pi, sizeof(pi)); + if (nb <= 0) { + (void) err2nm("pipe"); + return; + } else if (nb < sizeof(pi)) { + (void) fprintf(stderr, + "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPIPEINFO);\n", + Pn, pid, fd); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(pi), nb); + Exit(1); + } + + process_pipe_common(&pi); +} + + +#ifdef PROC_PIDLISTFILEPORTS +void +process_fileport_pipe(pid, fp) + int pid; /* PID */ + uint32_t fp; /* FILEPORT */ +{ + int nb; + struct pipe_fdinfo pi; +/* + * Get pipe file information. + */ + nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPIPEINFO, &pi, sizeof(pi)); + if (nb <= 0) { + (void) err2nm("pipe"); + return; + } else if (nb < sizeof(pi)) { + (void) fprintf(stderr, + "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPIPEINFO);\n", + Pn, pid, fp); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(pi), nb); + Exit(1); + } + + process_pipe_common(&pi); +} +#endif /* PROC_PIDLISTFILEPORTS */ + + +/* + * process_psem() -- process a POSIX semaphore file + */ + +void +process_psem(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + int nb; + struct psem_fdinfo ps; +/* + * Get the sempaphore file information. + */ + (void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM"); + nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSEMINFO, &ps, sizeof(ps)); + if (nb <= 0) { + (void) err2nm("semaphore"); + return; + } else if (nb < sizeof(ps)) { + (void) fprintf(stderr, + "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSEMINFO);\n", + Pn, pid, fd); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(ps), nb); + Exit(1); + } +/* + * Enter the semaphore file information. + */ + enter_file_info(&ps.pfi); +/* + * If there is a semaphore file name, enter it. + */ + if (ps.pseminfo.psem_name[0]) { + ps.pseminfo.psem_name[sizeof(ps.pseminfo.psem_name) - 1] = '\0'; + (void) snpf(Namech, Namechl, "%s", ps.pseminfo.psem_name); + enter_nm(Namech); + } +/* + * Unless file size has been specifically requested, enable the printing of + * file offset. + */ + if (!Fsize) + Lf->off_def = 1; +} + + +/* + * process_pshm() -- process POSIX shared memory file + */ + +static void +process_pshm_common(ps) + struct pshm_fdinfo *ps; +{ + (void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM"); +/* + * Enter the POSIX shared memory file information. + */ + enter_file_info(&ps->pfi); +/* + * If the POSIX shared memory file has a path name, enter it; otherwise, if it + * has a mapping address, enter that. + */ + if (ps->pshminfo.pshm_name[0]) { + ps->pshminfo.pshm_name[sizeof(ps->pshminfo.pshm_name) - 1] = '\0'; + (void) snpf(Namech, Namechl, "%s", ps->pshminfo.pshm_name); + enter_nm(Namech); + } else if (ps->pshminfo.pshm_mappaddr) { + (void) snpf(Namech, Namechl, "obj=%s", + print_kptr((KA_T)ps->pshminfo.pshm_mappaddr, (char *)NULL, 0)); + enter_nm(Namech); + } +/* + * Enable offset or size reporting. + */ + if (Foffset) + Lf->off_def = 1; + else { + Lf->sz = (SZOFFTYPE)ps->pshminfo.pshm_stat.vst_size; + Lf->sz_def = 1; + } +} + + +void +process_pshm(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + int nb; + struct pshm_fdinfo ps; +/* + * Get the POSIX shared memory file information. + */ + nb = proc_pidfdinfo(pid, fd, PROC_PIDFDPSHMINFO, &ps, sizeof(ps)); + if (nb <= 0) { + (void) err2nm("POSIX shared memory"); + return; + } else if (nb < sizeof(ps)) { + (void) fprintf(stderr, + "%s: PID %d, FD %d; proc_pidfdinfo(PROC_PIDFDPSHMINFO);\n", + Pn, pid, fd); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(ps), nb); + Exit(1); + } + + process_pshm_common(&ps); +} + + +#ifdef PROC_PIDLISTFILEPORTS +void +process_fileport_pshm(pid, fp) + int pid; /* PID */ + uint32_t fp; /* FILEPORT */ +{ + int nb; + struct pshm_fdinfo ps; +/* + * Get the POSIX shared memory file information. + */ + nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTPSHMINFO, &ps, sizeof(ps)); + if (nb <= 0) { + (void) err2nm("POSIX shared memory"); + return; + } else if (nb < sizeof(ps)) { + (void) fprintf(stderr, + "%s: PID %d, FILEPORT %u; proc_pidfileportinfo(PROC_PIDFILEPORTPSHMINFO);\n", + Pn, pid, fp); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(ps), nb); + Exit(1); + } + + process_pshm_common(&ps); +} +#endif /* PROC_PIDLISTFILEPORTS */ + + +/* + * process_vnode() -- process a vnode file + */ + +static void +process_vnode_common(vi) + struct vnode_fdinfowithpath *vi; +{ +/* + * Enter the file and vnode information. + */ + enter_file_info(&vi->pfi); + enter_vnode_info(&vi->pvip); +} + + +void +process_vnode(pid, fd) + int pid; /* PID */ + int32_t fd; /* FD */ +{ + int nb; + struct vnode_fdinfowithpath vi; + + nb = proc_pidfdinfo(pid, fd, PROC_PIDFDVNODEPATHINFO, &vi, sizeof(vi)); + if (nb <= 0) { + if (errno == ENOENT) { + + /* + * The file descriptor's vnode may have been revoked. This is a + * bit of a hack, since an ENOENT error might not always mean the + * descriptor's vnode has been revoked. As the libproc API + * matures, this code may need to be revisited. + */ + enter_nm("(revoked)"); + } else + (void) err2nm("vnode"); + return; + } else if (nb < sizeof(vi)) { + (void) fprintf(stderr, + "%s: PID %d, FD %d: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n", + Pn, pid, fd); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(vi), nb); + Exit(1); + } + + process_vnode_common(&vi); +} + + +#ifdef PROC_PIDLISTFILEPORTS +void +process_fileport_vnode(pid, fp) + int pid; /* PID */ + uint32_t fp; /* FILEPORT */ +{ + int nb; + struct vnode_fdinfowithpath vi; + + nb = proc_pidfileportinfo(pid, fp, PROC_PIDFILEPORTVNODEPATHINFO, &vi, sizeof(vi)); + if (nb <= 0) { + if (errno == ENOENT) { + + /* + * The file descriptor's vnode may have been revoked. This is a + * bit of a hack, since an ENOENT error might not always mean the + * descriptor's vnode has been revoked. As the libproc API + * matures, this code may need to be revisited. + */ + enter_nm("(revoked)"); + } else + (void) err2nm("vnode"); + return; + } else if (nb < sizeof(vi)) { + (void) fprintf(stderr, + "%s: PID %d, FILEPORT %u: proc_pidfdinfo(PROC_PIDFDVNODEPATHINFO);\n", + Pn, pid, fp); + (void) fprintf(stderr, + " too few bytes; expected %ld, got %d\n", + sizeof(vi), nb); + Exit(1); + } + + process_vnode_common(&vi); +} +#endif /* PROC_PIDLISTFILEPORTS */ |