1/*
2 * dfile.c - Darwin file processing functions for /dev/kmem-based lsof
3 */
4
5
6/*
7 * Copyright 2005 Purdue Research Foundation, West Lafayette, Indiana
8 * 47907.  All rights reserved.
9 *
10 * Written by Victor A. Abell
11 *
12 * This software is not subject to any license of the American Telephone
13 * and Telegraph Company or the Regents of the University of California.
14 *
15 * Permission is granted to anyone to use this software for any purpose on
16 * any computer system, and to alter it and redistribute it freely, subject
17 * to the following restrictions:
18 *
19 * 1. Neither the authors nor Purdue University are responsible for any
20 *    consequences of the use of this software.
21 *
22 * 2. The origin of this software must not be misrepresented, either by
23 *    explicit claim or by omission.  Credit to the authors and Purdue
24 *    University must appear in documentation and sources.
25 *
26 * 3. Altered versions must be plainly marked as such, and must not be
27 *    misrepresented as being the original software.
28 *
29 * 4. This notice may not be removed or altered.
30 */
31
32#ifndef lint
33static char copyright[] =
34"@(#) Copyright 2005 Purdue Research Foundation.\nAll rights reserved.\n";
35static char *rcsid = "$Id$";
36#endif
37
38
39#include "lsof.h"
40
41
42/*
43 * Local definitions
44 */
45
46#if	DARWINV>=800
47#define	file		fileglob
48#define	f_flag		fg_flag
49#define	f_type		fg_type
50#define	f_count		fg_count
51#define	f_ops		fg_ops
52#define	f_offset	fg_offset
53#define	f_data		fg_data
54#endif	/* DARWINV>=800 */
55
56#if	defined(HASPSXSEM)
57#define	PSEMNAMLEN	31		/* from kern/posix_sem.c */
58#endif	/* defined(HASPSXSEM) */
59
60#if	defined(HASPSXSHM)
61#define	PSHMNAMLEN	31		/* from kern/posix_shm.c */
62#endif	/* defined(HASPSXSHM) */
63
64
65/*
66 * Local structure definitions
67 */
68
69#if	defined(HASPSXSEM)
70struct pseminfo {			/* from kern/posix_sem.c */
71    unsigned int psem_flags;
72    unsigned int psem_usecount;
73    mode_t psem_mode;
74    uid_t psem_uid;
75    gid_t psem_gid;
76    char psem_name[PSEMNAMLEN + 1];
77    void *psem_semobject;
78    struct proc *sem_proc;
79};
80
81struct psemnode {
82    struct pseminfo *pinfo;
83};
84#endif	/* defined(HASPSXSEM) */
85
86#if	defined(HASPSXSHM)		/* from kern/posix_shm.c */
87struct pshminfo {
88    unsigned int pshm_flags;
89    unsigned int pshm_usecount;
90    off_t pshm_length;
91    mode_t pshm_mode;
92    uid_t pshm_uid;
93    gid_t pshm_gid;
94    char pshm_name[PSHMNAMLEN + 1];
95    void *pshm_memobject;
96};
97
98struct pshmnode {
99    off_t mapp_addr;
100
101# if	DARWINV<800
102    size_t map_size;
103# else	/* DARWINV>=800 */
104    user_size_t map_size;
105# endif	/* DARWINV>=800 */
106
107    struct pshminfo *pinfo;
108};
109#endif	/* defined(HASPSXSHM) */
110
111
112#if	DARWINV>=800
113/*
114 * print_v_path() - print vnode's path
115 */
116
117int
118print_v_path(lf)
119	struct lfile *lf;
120{
121	if (lf->V_path) {
122	    safestrprt(lf->V_path, stdout, 0);
123	    return(1);
124	}
125	return(0);
126}
127#endif	/* DARWINV>=800 */
128
129
130#if	defined(HASKQUEUE)
131/*
132 * process_kqueue() -- process kqueue file
133 */
134
135void
136process_kqueue(ka)
137	KA_T ka;			/* kqueue file structure address */
138{
139	struct kqueue kq;		/* kqueue structure */
140
141	(void) snpf(Lf->type, sizeof(Lf->type), "KQUEUE");
142	enter_dev_ch(print_kptr(ka, (char *)NULL, 0));
143	if (!ka || kread(ka, (char *)&kq, sizeof(kq)))
144	    return;
145	(void) snpf(Namech, Namechl, "count=%d, state=%#x", kq.kq_count,
146	    kq.kq_state);
147	enter_nm(Namech);
148}
149#endif	/* defined(HASKQUEUE) */
150
151
152#if	DARWINV>=800
153/*
154 * process_pipe() - process a file structure whose type is DTYPE_PIPE
155 */
156
157void
158process_pipe(pa)
159	KA_T pa;			/* pipe structure address */
160{
161	(void) snpf(Lf->type, sizeof(Lf->type), "PIPE");
162	enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
163	Namech[0] = '\0';
164}
165#endif	/* DARWINV>=800 */
166
167
168#if	defined(HASPSXSEM)
169/*
170 * process_psxsem() -- process POSIX semaphore file
171 */
172
173void
174process_psxsem(pa)
175	KA_T pa;			/* psxsem file structure address */
176{
177	struct pseminfo pi;
178 	struct psemnode pn;
179
180	(void) snpf(Lf->type, sizeof(Lf->type), "PSXSEM");
181	enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
182	if (!Fsize)
183	    Lf->off_def = 1;
184	if (pa && !kread(pa, (char *)&pn, sizeof(pn))) {
185	    if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) {
186		if (pi.psem_name[0]) {
187		    pi.psem_name[PSEMNAMLEN] = '\0';
188		    (void) snpf(Namech, Namechl, "%s", pi.psem_name);
189		    enter_nm(Namech);
190		}
191	    }
192	}
193}
194#endif	/* defined(HASPSXSEM) */
195
196
197#if	defined(HASPSXSHM)
198/*
199 * process_psxshm() -- process POSIX shared memory file
200 */
201
202void
203process_psxshm(pa)
204	KA_T pa;			/* psxshm file structure address */
205{
206	struct pshminfo pi;
207	struct pshmnode pn;
208	int pns = 0;
209
210	(void) snpf(Lf->type, sizeof(Lf->type), "PSXSHM");
211	enter_dev_ch(print_kptr(pa, (char *)NULL, 0));
212	if (pa && !kread(pa, (char *)&pn, sizeof(pn))) {
213	    pns = 1;
214	    if (pn.pinfo && !kread((KA_T)pn.pinfo, (char *)&pi, sizeof(pi))) {
215		if (pi.pshm_name[0]) {
216		    pi.pshm_name[PSEMNAMLEN] = '\0';
217		    (void) snpf(Namech, Namechl, "%s", pi.pshm_name);
218		    enter_nm(Namech);
219		} else if (pi.pshm_memobject) {
220		    (void) snpf(Namech, Namechl, "obj=%s",
221			print_kptr((KA_T)pi.pshm_memobject, (char *)NULL, 0));
222		    enter_nm(Namech);
223		}
224	    }
225	}
226	if (Foffset)
227	    Lf->off_def = 1;
228	else if (pns) {
229	    Lf->sz = (SZOFFTYPE)pn.map_size;
230	    Lf->sz_def = 1;
231	}
232}
233#endif	/* defined(HASPSXSHM) */
234
235
236/*
237 * process_file() - process file
238 */
239
240/*
241 * The caller may define:
242 *
243 *	FILEPTR	as the name of the location to store a pointer
244 *			to the current file struct -- e.g.,
245 *
246 *			struct file *foobar;
247 *			#define FILEPTR	foobar
248 */
249
250void
251process_file(fp)
252	KA_T fp;			/* kernel file structure address */
253{
254
255#if	DARWINV<800
256	struct file f;
257#else	/* DARWINV>=800 */
258	struct fileglob f;
259	struct fileproc fileproc;
260#endif	/* DARWINV>=800 */
261
262	int flag;
263
264#if	defined(FILEPTR)
265/*
266 * Save file structure address for process_node().
267 */
268	FILEPTR = &f;
269#endif	/* defined(FILEPTR) */
270
271/*
272 * Read file structure.
273 */
274
275#if	DARWINV<800
276	if (kread((KA_T)fp, (char *)&f, sizeof(f))) {
277	    (void) snpf(Namech, Namechl, "can't read file struct from %s",
278		print_kptr(fp, (char *)NULL, 0));
279	    enter_nm(Namech);
280	    return;
281	}
282#else	/* DARWINV>=800 */
283	if (kread((KA_T)fp, (char *)&fileproc, sizeof(fileproc))) {
284	    (void) snpf(Namech, Namechl, "can't read fileproc struct from %s",
285		print_kptr(fp, (char *)NULL, 0));
286	    enter_nm(Namech);
287	    return;
288	}
289	if (kread((KA_T)fileproc.f_fglob, (char *)&f, sizeof(f))) {
290	    (void) snpf(Namech, Namechl, "can't read fileglob struct from %s",
291		print_kptr((KA_T)fileproc.f_fglob, (char *)NULL, 0));
292	    enter_nm(Namech);
293	    return;
294	}
295#endif	/* DARWINV>=800 */
296
297	Lf->off = (SZOFFTYPE)f.f_offset;
298	if (f.f_count) {
299
300	/*
301	 * Construct access code.
302	 */
303	    if ((flag = (f.f_flag & (FREAD | FWRITE))) == FREAD)
304		Lf->access = 'r';
305	    else if (flag == FWRITE)
306		Lf->access = 'w';
307	    else if (flag == (FREAD | FWRITE))
308		Lf->access = 'u';
309
310#if	defined(HASFSTRUCT)
311	/*
312	 * Save file structure values.
313	 */
314	    if (Fsv & FSV_CT) {
315		Lf->fct = (long)f.f_count;
316		Lf->fsv |= FSV_CT;
317	    }
318	    if (Fsv & FSV_FA) {
319		Lf->fsa = fp;
320		Lf->fsv |= FSV_FA;
321	    }
322	    if (Fsv & FSV_FG) {
323		Lf->ffg = (long)f.f_flag;
324		Lf->fsv |= FSV_FG;
325	    }
326	    if (Fsv & FSV_NI) {
327		Lf->fna = (KA_T)f.f_data;
328		Lf->fsv |= FSV_NI;
329	    }
330#endif	/* defined(HASFSTRUCT) */
331
332	/*
333	 * Process structure by its type.
334	 */
335	    switch (f.f_type) {
336
337
338#if	defined(DTYPE_PIPE)
339	    case DTYPE_PIPE:
340# if	defined(HASPIPEFN)
341		if (!Selinet)
342		    HASPIPEFN((KA_T)f.f_data);
343# endif	/* defined(HASPIPEFN) */
344		return;
345#endif	/* defined(DTYPE_PIPE) */
346
347	    case DTYPE_VNODE:
348		if (!Selinet)
349		    process_node((KA_T)f.f_data);
350		return;
351	    case DTYPE_SOCKET:
352		process_socket((KA_T)f.f_data);
353		return;
354
355#if	defined(HASKQUEUE)
356	    case DTYPE_KQUEUE:
357		process_kqueue((KA_T)f.f_data);
358		return;
359#endif	/* defined(HASKQUEUE) */
360
361#if	defined(HASPSXSEM)
362	    case DTYPE_PSXSEM:
363		process_psxsem((KA_T)f.f_data);
364		return;
365#endif	/* defined(HASPSXSEM) */
366
367#if	defined(HASPSXSHM)
368	    case DTYPE_PSXSHM:
369		process_psxshm((KA_T)f.f_data);
370		return;
371#endif	/* defined(HASPSXSHM) */
372
373#if	defined(HASPRIVFILETYPE)
374	    case PRIVFILETYPE:
375		HASPRIVFILETYPE((KA_T)f.f_data);
376		return;
377#endif	/* defined(HASPRIVFILETYPE) */
378
379	    default:
380		if (f.f_type || f.f_ops) {
381		    (void) snpf(Namech, Namechl,
382			"%s file struct, ty=%#x, op=%p",
383			print_kptr(fp, (char *)NULL, 0), f.f_type, f.f_ops);
384		    enter_nm(Namech);
385		    return;
386		}
387	    }
388	}
389	enter_nm("no more information");
390}
391