xref: /titanic_54/usr/src/lib/libproc/common/Pfdinfo.c (revision 34bdffbf3e3c188027e767e631f717b10159316d)
1*34bdffbfSGarrett D'Amore /*
2*34bdffbfSGarrett D'Amore  * This file and its contents are supplied under the terms of the
3*34bdffbfSGarrett D'Amore  * Common Development and Distribution License ("CDDL"), version 1.0.
4*34bdffbfSGarrett D'Amore  * You may only use this file in accordance with the terms of version
5*34bdffbfSGarrett D'Amore  * 1.0 of the CDDL.
6*34bdffbfSGarrett D'Amore  *
7*34bdffbfSGarrett D'Amore  * A full copy of the text of the CDDL should have accompanied this
8*34bdffbfSGarrett D'Amore  * source.  A copy of the CDDL is also available via the Internet at
9*34bdffbfSGarrett D'Amore  * http://www.illumos.org/license/CDDL.
10*34bdffbfSGarrett D'Amore  */
11*34bdffbfSGarrett D'Amore 
12*34bdffbfSGarrett D'Amore /*
13*34bdffbfSGarrett D'Amore  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
14*34bdffbfSGarrett D'Amore  */
15*34bdffbfSGarrett D'Amore 
16*34bdffbfSGarrett D'Amore #include <limits.h>
17*34bdffbfSGarrett D'Amore #include <stdio.h>
18*34bdffbfSGarrett D'Amore #include <errno.h>
19*34bdffbfSGarrett D'Amore #include <unistd.h>
20*34bdffbfSGarrett D'Amore #include <dirent.h>
21*34bdffbfSGarrett D'Amore #include <ctype.h>
22*34bdffbfSGarrett D'Amore #include <string.h>
23*34bdffbfSGarrett D'Amore #include <sys/mkdev.h>
24*34bdffbfSGarrett D'Amore 
25*34bdffbfSGarrett D'Amore #include "libproc.h"
26*34bdffbfSGarrett D'Amore #include "Pcontrol.h"
27*34bdffbfSGarrett D'Amore 
28*34bdffbfSGarrett D'Amore /*
29*34bdffbfSGarrett D'Amore  * Pfdinfo.c - obtain open file information.
30*34bdffbfSGarrett D'Amore  */
31*34bdffbfSGarrett D'Amore 
32*34bdffbfSGarrett D'Amore /*
33*34bdffbfSGarrett D'Amore  * Allocate an fd_info structure and stick it on the list.
34*34bdffbfSGarrett D'Amore  * (Unless one already exists.)  The list is sorted in
35*34bdffbfSGarrett D'Amore  * reverse order.  We will traverse it in that order later.
36*34bdffbfSGarrett D'Amore  * This makes the usual ordered insert *fast*.
37*34bdffbfSGarrett D'Amore  */
38*34bdffbfSGarrett D'Amore fd_info_t *
39*34bdffbfSGarrett D'Amore Pfd2info(struct ps_prochandle *P, int fd)
40*34bdffbfSGarrett D'Amore {
41*34bdffbfSGarrett D'Amore 	fd_info_t	*fip = list_next(&P->fd_head);
42*34bdffbfSGarrett D'Amore 	fd_info_t	*next;
43*34bdffbfSGarrett D'Amore 	int i;
44*34bdffbfSGarrett D'Amore 
45*34bdffbfSGarrett D'Amore 	if (fip == NULL) {
46*34bdffbfSGarrett D'Amore 		list_link(&P->fd_head, NULL);
47*34bdffbfSGarrett D'Amore 		fip = list_next(&P->fd_head);
48*34bdffbfSGarrett D'Amore 	}
49*34bdffbfSGarrett D'Amore 
50*34bdffbfSGarrett D'Amore 	for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) {
51*34bdffbfSGarrett D'Amore 		if (fip->fd_info.pr_fd == fd) {
52*34bdffbfSGarrett D'Amore 			return (fip);
53*34bdffbfSGarrett D'Amore 		}
54*34bdffbfSGarrett D'Amore 		if (fip->fd_info.pr_fd < fd) {
55*34bdffbfSGarrett D'Amore 			break;
56*34bdffbfSGarrett D'Amore 		}
57*34bdffbfSGarrett D'Amore 	}
58*34bdffbfSGarrett D'Amore 
59*34bdffbfSGarrett D'Amore 	next = fip;
60*34bdffbfSGarrett D'Amore 	if ((fip = calloc(1, sizeof (*fip))) == NULL)
61*34bdffbfSGarrett D'Amore 		return (NULL);
62*34bdffbfSGarrett D'Amore 
63*34bdffbfSGarrett D'Amore 	fip->fd_info.pr_fd = fd;
64*34bdffbfSGarrett D'Amore 	list_link(fip, next ? next : (void *)&(P->fd_head));
65*34bdffbfSGarrett D'Amore 	P->num_fd++;
66*34bdffbfSGarrett D'Amore 	return (fip);
67*34bdffbfSGarrett D'Amore }
68*34bdffbfSGarrett D'Amore 
69*34bdffbfSGarrett D'Amore /*
70*34bdffbfSGarrett D'Amore  * Attempt to load the open file information from a live process.
71*34bdffbfSGarrett D'Amore  */
72*34bdffbfSGarrett D'Amore static void
73*34bdffbfSGarrett D'Amore load_fdinfo(struct ps_prochandle *P)
74*34bdffbfSGarrett D'Amore {
75*34bdffbfSGarrett D'Amore 	/*
76*34bdffbfSGarrett D'Amore 	 * In the unlikely case there are *no* file descriptors open,
77*34bdffbfSGarrett D'Amore 	 * we will keep rescanning the proc directory, which will be empty.
78*34bdffbfSGarrett D'Amore 	 * This is an edge case it isn't worth adding additional state to
79*34bdffbfSGarrett D'Amore 	 * to eliminate.
80*34bdffbfSGarrett D'Amore 	 */
81*34bdffbfSGarrett D'Amore 	if (P->num_fd > 0) {
82*34bdffbfSGarrett D'Amore 		return;
83*34bdffbfSGarrett D'Amore 	}
84*34bdffbfSGarrett D'Amore 
85*34bdffbfSGarrett D'Amore 	if (P->state != PS_DEAD && P->state != PS_IDLE) {
86*34bdffbfSGarrett D'Amore 		char dir_name[PATH_MAX];
87*34bdffbfSGarrett D'Amore 		char path[PATH_MAX];
88*34bdffbfSGarrett D'Amore 		struct dirent *ent;
89*34bdffbfSGarrett D'Amore 		DIR	*dirp;
90*34bdffbfSGarrett D'Amore 		int	fd;
91*34bdffbfSGarrett D'Amore 
92*34bdffbfSGarrett D'Amore 		/*
93*34bdffbfSGarrett D'Amore 		 * Try to get the path information first.
94*34bdffbfSGarrett D'Amore 		 */
95*34bdffbfSGarrett D'Amore 		(void) snprintf(dir_name, sizeof (dir_name),
96*34bdffbfSGarrett D'Amore 		    "%s/%d/path", procfs_path, (int)P->pid);
97*34bdffbfSGarrett D'Amore 		dirp = opendir(dir_name);
98*34bdffbfSGarrett D'Amore 		if (dirp == NULL) {
99*34bdffbfSGarrett D'Amore 			return;
100*34bdffbfSGarrett D'Amore 		}
101*34bdffbfSGarrett D'Amore 		ent = NULL;
102*34bdffbfSGarrett D'Amore 		while ((ent = readdir(dirp)) != NULL) {
103*34bdffbfSGarrett D'Amore 			fd_info_t	*fip;
104*34bdffbfSGarrett D'Amore 			prfdinfo_t	*info;
105*34bdffbfSGarrett D'Amore 			int		len;
106*34bdffbfSGarrett D'Amore 			struct stat64	stat;
107*34bdffbfSGarrett D'Amore 
108*34bdffbfSGarrett D'Amore 			if (!isdigit(ent->d_name[0]))
109*34bdffbfSGarrett D'Amore 				continue;
110*34bdffbfSGarrett D'Amore 
111*34bdffbfSGarrett D'Amore 			fd = atoi(ent->d_name);
112*34bdffbfSGarrett D'Amore 
113*34bdffbfSGarrett D'Amore 			fip = Pfd2info(P, fd);
114*34bdffbfSGarrett D'Amore 			info = &fip->fd_info;
115*34bdffbfSGarrett D'Amore 			info->pr_fd = fd;
116*34bdffbfSGarrett D'Amore 
117*34bdffbfSGarrett D'Amore 			if (pr_fstat64(P, fd, &stat) == 0) {
118*34bdffbfSGarrett D'Amore 				info->pr_mode = stat.st_mode;
119*34bdffbfSGarrett D'Amore 				info->pr_uid = stat.st_uid;
120*34bdffbfSGarrett D'Amore 				info->pr_gid = stat.st_gid;
121*34bdffbfSGarrett D'Amore 				info->pr_major = major(stat.st_dev);
122*34bdffbfSGarrett D'Amore 				info->pr_minor = minor(stat.st_dev);
123*34bdffbfSGarrett D'Amore 				info->pr_rmajor = major(stat.st_rdev);
124*34bdffbfSGarrett D'Amore 				info->pr_rminor = minor(stat.st_rdev);
125*34bdffbfSGarrett D'Amore 				info->pr_size = stat.st_size;
126*34bdffbfSGarrett D'Amore 				info->pr_ino = stat.st_ino;
127*34bdffbfSGarrett D'Amore 			}
128*34bdffbfSGarrett D'Amore 
129*34bdffbfSGarrett D'Amore 			info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0);
130*34bdffbfSGarrett D'Amore 			info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0);
131*34bdffbfSGarrett D'Amore 			info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR);
132*34bdffbfSGarrett D'Amore 
133*34bdffbfSGarrett D'Amore 			/* attempt to determine the path to it */
134*34bdffbfSGarrett D'Amore 			(void) snprintf(path, sizeof (path),
135*34bdffbfSGarrett D'Amore 			    "%s/%d/path/%d", procfs_path, (int)P->pid, fd);
136*34bdffbfSGarrett D'Amore 			len = readlink(path, info->pr_path,
137*34bdffbfSGarrett D'Amore 			    sizeof (info->pr_path) - 1);
138*34bdffbfSGarrett D'Amore 
139*34bdffbfSGarrett D'Amore 			if (len < 0) {
140*34bdffbfSGarrett D'Amore 				info->pr_path[0] = 0;
141*34bdffbfSGarrett D'Amore 			} else {
142*34bdffbfSGarrett D'Amore 				info->pr_path[len] = 0;
143*34bdffbfSGarrett D'Amore 			}
144*34bdffbfSGarrett D'Amore 		}
145*34bdffbfSGarrett D'Amore 		(void) closedir(dirp);
146*34bdffbfSGarrett D'Amore 
147*34bdffbfSGarrett D'Amore 	}
148*34bdffbfSGarrett D'Amore }
149*34bdffbfSGarrett D'Amore 
150*34bdffbfSGarrett D'Amore int
151*34bdffbfSGarrett D'Amore Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd)
152*34bdffbfSGarrett D'Amore {
153*34bdffbfSGarrett D'Amore 	fd_info_t *fip;
154*34bdffbfSGarrett D'Amore 	int rv;
155*34bdffbfSGarrett D'Amore 
156*34bdffbfSGarrett D'Amore 	/* Make sure we have live data, if appropriate */
157*34bdffbfSGarrett D'Amore 	load_fdinfo(P);
158*34bdffbfSGarrett D'Amore 
159*34bdffbfSGarrett D'Amore 	/* NB: We walk the list backwards. */
160*34bdffbfSGarrett D'Amore 
161*34bdffbfSGarrett D'Amore 	for (fip = list_prev(&P->fd_head);
162*34bdffbfSGarrett D'Amore 	    fip != (void *)&P->fd_head;
163*34bdffbfSGarrett D'Amore 	    fip = list_prev(fip)) {
164*34bdffbfSGarrett D'Amore 		if ((rv = func(cd, &fip->fd_info)) != 0)
165*34bdffbfSGarrett D'Amore 			return (rv);
166*34bdffbfSGarrett D'Amore 	}
167*34bdffbfSGarrett D'Amore 	return (0);
168*34bdffbfSGarrett D'Amore }
169