1 /*- 2 * Copyright (c) 1989, 1992, 1993 3 * The Regents of the University of California. 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 8.1 (Berkeley) 06/04/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, 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 long 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, (long)fp, ((struct file *)where))) { 79 _kvm_err(kd, kd->program, "can't read kfp"); 80 return (0); 81 } 82 buflen -= sizeof (struct file); 83 fp = (struct file *)where; 84 where += sizeof (struct file); 85 n++; 86 } 87 } 88 if (n != nfiles) { 89 _kvm_err(kd, kd->program, "inconsistant nfiles"); 90 return (0); 91 } 92 return (nfiles); 93 } 94 95 char * 96 kvm_getfiles(kd, op, arg, cnt) 97 kvm_t *kd; 98 int op, arg; 99 int *cnt; 100 { 101 int mib[2], size, st, nfiles; 102 struct file *filehead, *fp, *fplim; 103 104 if (ISALIVE(kd)) { 105 size = 0; 106 mib[0] = CTL_KERN; 107 mib[1] = KERN_FILE; 108 st = sysctl(mib, 2, NULL, &size, NULL, 0); 109 if (st == -1) { 110 _kvm_syserr(kd, kd->program, "kvm_getprocs"); 111 return (0); 112 } 113 if (kd->argspc == 0) 114 kd->argspc = (char *)_kvm_malloc(kd, size); 115 else if (kd->arglen < size) 116 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 117 if (kd->argspc == 0) 118 return (0); 119 kd->arglen = size; 120 st = sysctl(mib, 2, kd->argspc, &size, NULL, 0); 121 if (st == -1 || size < sizeof(filehead)) { 122 _kvm_syserr(kd, kd->program, "kvm_getfiles"); 123 return (0); 124 } 125 filehead = *(struct file **)kd->argspc; 126 fp = (struct file *)(kd->argspc + sizeof (filehead)); 127 fplim = (struct file *)(kd->argspc + size); 128 for (nfiles = 0; filehead && (fp < fplim); nfiles++, fp++) 129 filehead = fp->f_filef; 130 } else { 131 struct nlist nl[3], *p; 132 133 nl[0].n_name = "_filehead"; 134 nl[1].n_name = "_nfiles"; 135 nl[2].n_name = 0; 136 137 if (kvm_nlist(kd, nl) != 0) { 138 for (p = nl; p->n_type != 0; ++p) 139 ; 140 _kvm_err(kd, kd->program, 141 "%s: no such symbol", p->n_name); 142 return (0); 143 } 144 if (KREAD(kd, nl[0].n_value, &nfiles)) { 145 _kvm_err(kd, kd->program, "can't read nfiles"); 146 return (0); 147 } 148 size = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 149 if (kd->argspc == 0) 150 kd->argspc = (char *)_kvm_malloc(kd, size); 151 else if (kd->arglen < size) 152 kd->argspc = (char *)_kvm_realloc(kd, kd->argspc, size); 153 if (kd->argspc == 0) 154 return (0); 155 kd->arglen = size; 156 nfiles = kvm_deadfiles(kd, op, arg, nl[1].n_value, nfiles); 157 if (nfiles == 0) 158 return (0); 159 } 160 *cnt = nfiles; 161 return (kd->argspc); 162 } 163