2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
16 * Copyright (c) 2013 Joyent, Inc. All Rights reserved.
26 #include <sys/mkdev.h>
32 * Pfdinfo.c - obtain open file information.
36 * Allocate an fd_info structure and stick it on the list.
37 * (Unless one already exists.) The list is sorted in
38 * reverse order. We will traverse it in that order later.
39 * This makes the usual ordered insert *fast*.
42 Pfd2info(struct ps_prochandle
*P
, int fd
)
44 fd_info_t
*fip
= list_next(&P
->fd_head
);
49 list_link(&P
->fd_head
, NULL
);
50 fip
= list_next(&P
->fd_head
);
53 for (i
= 0; i
< P
->num_fd
; i
++, fip
= list_next(fip
)) {
54 if (fip
->fd_info
.pr_fd
== fd
) {
57 if (fip
->fd_info
.pr_fd
< fd
) {
63 if ((fip
= calloc(1, sizeof (*fip
))) == NULL
)
66 fip
->fd_info
.pr_fd
= fd
;
67 list_link(fip
, next
? next
: (void *)&(P
->fd_head
));
73 * Attempt to load the open file information from a live process.
76 load_fdinfo(struct ps_prochandle
*P
)
79 * In the unlikely case there are *no* file descriptors open,
80 * we will keep rescanning the proc directory, which will be empty.
81 * This is an edge case it isn't worth adding additional state to
88 if (P
->state
!= PS_DEAD
&& P
->state
!= PS_IDLE
) {
89 char dir_name
[PATH_MAX
];
96 * Try to get the path information first.
98 (void) snprintf(dir_name
, sizeof (dir_name
),
99 "%s/%d/path", procfs_path
, (int)P
->pid
);
100 dirp
= opendir(dir_name
);
105 while ((ent
= readdir(dirp
)) != NULL
) {
111 if (!isdigit(ent
->d_name
[0]))
114 fd
= atoi(ent
->d_name
);
116 fip
= Pfd2info(P
, fd
);
117 info
= &fip
->fd_info
;
120 if (pr_fstat64(P
, fd
, &stat
) == 0) {
121 info
->pr_mode
= stat
.st_mode
;
122 info
->pr_uid
= stat
.st_uid
;
123 info
->pr_gid
= stat
.st_gid
;
124 info
->pr_major
= major(stat
.st_dev
);
125 info
->pr_minor
= minor(stat
.st_dev
);
126 info
->pr_rmajor
= major(stat
.st_rdev
);
127 info
->pr_rminor
= minor(stat
.st_rdev
);
128 info
->pr_size
= stat
.st_size
;
129 info
->pr_ino
= stat
.st_ino
;
132 info
->pr_fileflags
= pr_fcntl(P
, fd
, F_GETXFL
, 0);
133 info
->pr_fdflags
= pr_fcntl(P
, fd
, F_GETFD
, 0);
134 info
->pr_offset
= pr_llseek(P
, fd
, 0, SEEK_CUR
);
136 /* attempt to determine the path to it */
137 switch (info
->pr_mode
& S_IFMT
) {
144 (void) snprintf(path
, sizeof (path
),
145 "%s/%d/path/%d", procfs_path
, (int)P
->pid
,
147 len
= readlink(path
, info
->pr_path
,
148 sizeof (info
->pr_path
) - 1);
153 info
->pr_path
[0] = 0;
155 info
->pr_path
[len
] = 0;
158 (void) closedir(dirp
);
164 Pfdinfo_iter(struct ps_prochandle
*P
, proc_fdinfo_f
*func
, void *cd
)
169 /* Make sure we have live data, if appropriate */
172 /* NB: We walk the list backwards. */
174 for (fip
= list_prev(&P
->fd_head
);
175 fip
!= (void *)&P
->fd_head
&& fip
!= NULL
;
176 fip
= list_prev(fip
)) {
177 if ((rv
= func(cd
, &fip
->fd_info
)) != 0)