1 /*- 2 * Copyright (c) 1989, 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #if defined(LIBC_SCCS) && !defined(lint) 9 static char sccsid[] = "@(#)kvm_file.c 5.2 (Berkeley) 05/26/92"; 10 #endif /* LIBC_SCCS and not lint */ 11 12 /* 13 * File list interface for kvm. pstat, fstat and netstat are 14 * users of this code, so we've factored it out into a separate module. 15 * Thus, we keep this grunge out of the other kvm applications (i.e., 16 * most other applications are interested only in open/close/read/nlist). 17 */ 18 19 #include <sys/param.h> 20 #include <sys/user.h> 21 #include <sys/proc.h> 22 #include <sys/exec.h> 23 #define KERNEL 24 #include <sys/file.h> 25 #undef KERNEL 26 #include <sys/stat.h> 27 #include <sys/ioctl.h> 28 #include <sys/tty.h> 29 #include <nlist.h> 30 #include <kvm.h> 31 32 #include <vm/vm.h> 33 #include <vm/vm_param.h> 34 #include <vm/swap_pager.h> 35 36 #include <sys/kinfo.h> 37 38 #include <limits.h> 39 #include <ndbm.h> 40 #include <paths.h> 41 42 #include "kvm_private.h" 43 44 #define KREAD(kd, addr, obj) \ 45 (kvm_read(kd, addr, (char *)(obj), sizeof(*obj)) != sizeof(*obj)) 46 47 /* 48 * Get file structures. 49 */ 50 static 51 kvm_deadfiles(kd, op, arg, filehead_o, nfiles) 52 kvm_t *kd; 53 int op, arg, nfiles; 54 off_t filehead_o; 55 { 56 int buflen = kd->arglen, needed = buflen, error, n = 0; 57 struct file *fp, file, *filehead; 58 register char *where = kd->argspc; 59 char *start = where; 60 61 /* 62 * first copyout filehead 63 */ 64 if (buflen > sizeof (filehead)) { 65 if (KREAD(kd, filehead_o, &filehead)) { 66 _kvm_err(kd, kd->program, "can't read filehead"); 67 return (0); 68 } 69 buflen -= sizeof (filehead); 70 where += sizeof (filehead); 71 *(struct file **)kd->argspc = filehead; 72 } 73 /* 74 * followed by an array of file structures 75 */ 76 for (fp = filehead; fp != NULL; fp = fp->f_filef) { 77 if (buflen > sizeof (struct file)) { 78 if (KREAD(kd, (off_t)fp, ((struct file *)where))) { 79 _kvm_err(kd, kd->program, "can't read kfp"); 80 return (0); 81 } 82 buflen -= sizeof (struct file); 83 where += sizeof (struct file); 84 n++; 85 } 86 } 87 if (n != nfiles) { 88 _kvm_err(kd, kd->program, "inconsistant nfiles"); 89 return (0); 90 } 91 return (nfiles); 92 } 93 94 char * 95 kvm_getfiles(kd, op, arg, cnt) 96 kvm_t *kd; 97 int op, arg; 98 int *cnt; 99 { 100 int size, st, nfiles; 101 struct file *filehead, *fp, *fplim; 102 103 if (ISALIVE(kd)) { 104 size = 0; 105 st = getkerninfo(op, NULL, &size, arg); 106 if (st <= 0) { 107 _kvm_syserr(kd, kd->program, "kvm_getprocs"); 108 return (0); 109 } 110 if (kd->argspc == 0) 111 kd->argspc = (char *)_kvm_malloc(kd, st); 112 else if (kd->arglen < st) 113 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, st); 114 if (kd->argspc == 0) 115 return (0); 116 size = kd->arglen = st; 117 st = getkerninfo(op, kd->argspc, &size, arg); 118 if (st < sizeof(filehead)) { 119 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 120 return (0); 121 } 122 filehead = *(struct file **)kd->argspc; 123 fp = (struct file *)(kd->argspc + sizeof (filehead)); 124 fplim = (struct file *)(kd->argspc + size); 125 for (nfiles = 0; filehead && (fp < fplim); nfiles++, fp++) 126 filehead = fp->f_filef; 127 } else { 128 struct nlist nl[3], *p; 129 130 nl[0].n_name = "_filehead"; 131 nl[1].n_name = "_nfiles"; 132 nl[2].n_name = 0; 133 134 if (kvm_nlist(kd, nl) != 0) { 135 for (p = nl; p->n_type != 0; ++p) 136 ; 137 _kvm_err(kd, kd->program, 138 "%s: no such symbol", p->n_name); 139 return (0); 140 } 141 if (KREAD(kd, nl[0].n_value, &nfiles)) { 142 _kvm_err(kd, kd->program, "can't read nfiles"); 143 return (0); 144 } 145 size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 146 if (kd->argspc == 0) 147 kd->argspc = (char *)_kvm_malloc(kd, st); 148 else if (kd->arglen < st) 149 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, st); 150 if (kd->argspc == 0) 151 return (0); 152 size = kd->arglen = st; 153 nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); 154 if (nfiles == 0) 155 return (0); 156 } 157 *cnt = nfiles; 158 return (kd->argspc); 159 } 160