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.3 (Berkeley) 03/31/93"; 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/sysctl.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 mib[2], size, st, nfiles; 101 struct file *filehead, *fp, *fplim; 102 103 if (ISALIVE(kd)) { 104 size = 0; 105 mib[0] = CTL_KERN; 106 mib[1] = KERN_FILE; 107 st = sysctl(mib, 2, NULL, &size, NULL, 0); 108 if (st == -1) { 109 _kvm_syserr(kd, kd->program, "kvm_getprocs"); 110 return (0); 111 } 112 if (kd->argspc == 0) 113 kd->argspc = (char *)_kvm_malloc(kd, size); 114 else if (kd->arglen < size) 115 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 116 if (kd->argspc == 0) 117 return (0); 118 kd->arglen = size; 119 st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 120 if (st == -1 || size < sizeof(filehead)) { 121 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 122 return (0); 123 } 124 filehead = *(struct file **)kd->argspc; 125 fp = (struct file *)(kd->argspc + sizeof (filehead)); 126 fplim = (struct file *)(kd->argspc + size); 127 for (nfiles = 0; filehead && (fp < fplim); nfiles++, fp++) 128 filehead = fp->f_filef; 129 } else { 130 struct nlist nl[3], *p; 131 132 nl[0].n_name = "_filehead"; 133 nl[1].n_name = "_nfiles"; 134 nl[2].n_name = 0; 135 136 if (kvm_nlist(kd, nl) != 0) { 137 for (p = nl; p->n_type != 0; ++p) 138 ; 139 _kvm_err(kd, kd->program, 140 "%s: no such symbol", p->n_name); 141 return (0); 142 } 143 if (KREAD(kd, nl[0].n_value, &nfiles)) { 144 _kvm_err(kd, kd->program, "can't read nfiles"); 145 return (0); 146 } 147 size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 148 if (kd->argspc == 0) 149 kd->argspc = (char *)_kvm_malloc(kd, size); 150 else if (kd->arglen < size) 151 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 152 if (kd->argspc == 0) 153 return (0); 154 kd->arglen = size; 155 nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); 156 if (nfiles == 0) 157 return (0); 158 } 159 *cnt = nfiles; 160 return (kd->argspc); 161 } 162