Deleted Added
full compact
libprocstat.c (247602) libprocstat.c (249666)
1/*-
2 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 19 unchanged lines hidden (view full) ---

28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
3 * Copyright (c) 1988, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 19 unchanged lines hidden (view full) ---

28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/lib/libprocstat/libprocstat.c 247602 2013-03-02 00:53:12Z pjd $");
36__FBSDID("$FreeBSD: head/lib/libprocstat/libprocstat.c 249666 2013-04-20 07:47:26Z trociny $");
37
38#include <sys/param.h>
39#include <sys/time.h>
40#include <sys/proc.h>
41#include <sys/user.h>
42#include <sys/stat.h>
43#include <sys/vnode.h>
44#include <sys/socket.h>

--- 46 unchanged lines hidden (view full) ---

91#include <stddef.h>
92#include <string.h>
93#include <unistd.h>
94#include <netdb.h>
95
96#include <libprocstat.h>
97#include "libprocstat_internal.h"
98#include "common_kvm.h"
37
38#include <sys/param.h>
39#include <sys/time.h>
40#include <sys/proc.h>
41#include <sys/user.h>
42#include <sys/stat.h>
43#include <sys/vnode.h>
44#include <sys/socket.h>

--- 46 unchanged lines hidden (view full) ---

91#include <stddef.h>
92#include <string.h>
93#include <unistd.h>
94#include <netdb.h>
95
96#include <libprocstat.h>
97#include "libprocstat_internal.h"
98#include "common_kvm.h"
99#include "core.h"
99
100int statfs(const char *, struct statfs *); /* XXX */
101
102#define PROCSTAT_KVM 1
103#define PROCSTAT_SYSCTL 2
100
101int statfs(const char *, struct statfs *); /* XXX */
102
103#define PROCSTAT_KVM 1
104#define PROCSTAT_SYSCTL 2
105#define PROCSTAT_CORE 3
104
105static char *getmnton(kvm_t *kd, struct mount *m);
106static struct filestat_list *procstat_getfiles_kvm(
107 struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
108static struct filestat_list *procstat_getfiles_sysctl(
109 struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
110static int procstat_get_pipe_info_sysctl(struct filestat *fst,
111 struct pipestat *pipe, char *errbuf);

--- 20 unchanged lines hidden (view full) ---

132
133void
134procstat_close(struct procstat *procstat)
135{
136
137 assert(procstat);
138 if (procstat->type == PROCSTAT_KVM)
139 kvm_close(procstat->kd);
106
107static char *getmnton(kvm_t *kd, struct mount *m);
108static struct filestat_list *procstat_getfiles_kvm(
109 struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
110static struct filestat_list *procstat_getfiles_sysctl(
111 struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
112static int procstat_get_pipe_info_sysctl(struct filestat *fst,
113 struct pipestat *pipe, char *errbuf);

--- 20 unchanged lines hidden (view full) ---

134
135void
136procstat_close(struct procstat *procstat)
137{
138
139 assert(procstat);
140 if (procstat->type == PROCSTAT_KVM)
141 kvm_close(procstat->kd);
142 else if (procstat->type == PROCSTAT_CORE)
143 procstat_core_close(procstat->core);
140 free(procstat);
141}
142
143struct procstat *
144procstat_open_sysctl(void)
145{
146 struct procstat *procstat;
147

--- 24 unchanged lines hidden (view full) ---

172 free(procstat);
173 return (NULL);
174 }
175 procstat->type = PROCSTAT_KVM;
176 procstat->kd = kd;
177 return (procstat);
178}
179
144 free(procstat);
145}
146
147struct procstat *
148procstat_open_sysctl(void)
149{
150 struct procstat *procstat;
151

--- 24 unchanged lines hidden (view full) ---

176 free(procstat);
177 return (NULL);
178 }
179 procstat->type = PROCSTAT_KVM;
180 procstat->kd = kd;
181 return (procstat);
182}
183
184struct procstat *
185procstat_open_core(const char *filename)
186{
187 struct procstat *procstat;
188 struct procstat_core *core;
189
190 procstat = calloc(1, sizeof(*procstat));
191 if (procstat == NULL) {
192 warn("malloc()");
193 return (NULL);
194 }
195 core = procstat_core_open(filename);
196 if (core == NULL) {
197 free(procstat);
198 return (NULL);
199 }
200 procstat->type = PROCSTAT_CORE;
201 procstat->core = core;
202 return (procstat);
203}
204
180struct kinfo_proc *
181procstat_getprocs(struct procstat *procstat, int what, int arg,
182 unsigned int *count)
183{
184 struct kinfo_proc *p0, *p;
185 size_t len;
186 int name[4];
187 int cnt;

--- 38 unchanged lines hidden (view full) ---

226 }
227 error = sysctl(name, 4, p, &len, NULL, 0);
228 if (error < 0 && errno != EPERM) {
229 warn("sysctl(kern.proc)");
230 goto fail;
231 }
232 /* Perform simple consistency checks. */
233 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
205struct kinfo_proc *
206procstat_getprocs(struct procstat *procstat, int what, int arg,
207 unsigned int *count)
208{
209 struct kinfo_proc *p0, *p;
210 size_t len;
211 int name[4];
212 int cnt;

--- 38 unchanged lines hidden (view full) ---

251 }
252 error = sysctl(name, 4, p, &len, NULL, 0);
253 if (error < 0 && errno != EPERM) {
254 warn("sysctl(kern.proc)");
255 goto fail;
256 }
257 /* Perform simple consistency checks. */
258 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
259 warnx("kinfo_proc structure size mismatch (len = %zu)", len);
260 goto fail;
261 }
262 *count = len / sizeof(*p);
263 return (p);
264 } else if (procstat->type == PROCSTAT_CORE) {
265 p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL,
266 &len);
267 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
234 warnx("kinfo_proc structure size mismatch");
235 goto fail;
236 }
237 *count = len / sizeof(*p);
238 return (p);
239 } else {
240 warnx("unknown access method: %d", procstat->type);
241 return (NULL);

--- 11 unchanged lines hidden (view full) ---

253 if (p != NULL)
254 free(p);
255 p = NULL;
256}
257
258struct filestat_list *
259procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
260{
268 warnx("kinfo_proc structure size mismatch");
269 goto fail;
270 }
271 *count = len / sizeof(*p);
272 return (p);
273 } else {
274 warnx("unknown access method: %d", procstat->type);
275 return (NULL);

--- 11 unchanged lines hidden (view full) ---

287 if (p != NULL)
288 free(p);
289 p = NULL;
290}
291
292struct filestat_list *
293procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
294{
261
262 if (procstat->type == PROCSTAT_SYSCTL)
263 return (procstat_getfiles_sysctl(procstat, kp, mmapped));
264 else if (procstat->type == PROCSTAT_KVM)
295
296 switch(procstat->type) {
297 case PROCSTAT_KVM:
265 return (procstat_getfiles_kvm(procstat, kp, mmapped));
298 return (procstat_getfiles_kvm(procstat, kp, mmapped));
266 else
299 case PROCSTAT_SYSCTL:
300 case PROCSTAT_CORE:
301 return (procstat_getfiles_sysctl(procstat, kp, mmapped));
302 default:
303 warnx("unknown access method: %d", procstat->type);
267 return (NULL);
304 return (NULL);
305 }
268}
269
270void
271procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
272{
273 struct filestat *fst, *tmp;
274
275 STAILQ_FOREACH_SAFE(fst, head, next, tmp) {

--- 365 unchanged lines hidden (view full) ---

641 case KF_FD_TYPE_TRACE:
642 return (PS_FST_UFLAG_TRACE);
643 case KF_FD_TYPE_ROOT:
644 return (PS_FST_UFLAG_RDIR);
645 }
646 return (0);
647}
648
306}
307
308void
309procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
310{
311 struct filestat *fst, *tmp;
312
313 STAILQ_FOREACH_SAFE(fst, head, next, tmp) {

--- 365 unchanged lines hidden (view full) ---

679 case KF_FD_TYPE_TRACE:
680 return (PS_FST_UFLAG_TRACE);
681 case KF_FD_TYPE_ROOT:
682 return (PS_FST_UFLAG_RDIR);
683 }
684 return (0);
685}
686
687static struct kinfo_file *
688kinfo_getfile_core(struct procstat_core *core, int *cntp)
689{
690 int cnt;
691 size_t len;
692 char *buf, *bp, *eb;
693 struct kinfo_file *kif, *kp, *kf;
694
695 buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len);
696 if (buf == NULL)
697 return (NULL);
698 /*
699 * XXXMG: The code below is just copy&past from libutil.
700 * The code duplication can be avoided if libutil
701 * is extended to provide something like:
702 * struct kinfo_file *kinfo_getfile_from_buf(const char *buf,
703 * size_t len, int *cntp);
704 */
705
706 /* Pass 1: count items */
707 cnt = 0;
708 bp = buf;
709 eb = buf + len;
710 while (bp < eb) {
711 kf = (struct kinfo_file *)(uintptr_t)bp;
712 bp += kf->kf_structsize;
713 cnt++;
714 }
715
716 kif = calloc(cnt, sizeof(*kif));
717 if (kif == NULL) {
718 free(buf);
719 return (NULL);
720 }
721 bp = buf;
722 eb = buf + len;
723 kp = kif;
724 /* Pass 2: unpack */
725 while (bp < eb) {
726 kf = (struct kinfo_file *)(uintptr_t)bp;
727 /* Copy/expand into pre-zeroed buffer */
728 memcpy(kp, kf, kf->kf_structsize);
729 /* Advance to next packed record */
730 bp += kf->kf_structsize;
731 /* Set field size to fixed length, advance */
732 kp->kf_structsize = sizeof(*kp);
733 kp++;
734 }
735 free(buf);
736 *cntp = cnt;
737 return (kif); /* Caller must free() return value */
738}
739
649static struct filestat_list *
740static struct filestat_list *
650procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
741procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
742 int mmapped)
651{
652 struct kinfo_file *kif, *files;
653 struct kinfo_vmentry *kve, *vmentries;
654 struct filestat_list *head;
655 struct filestat *entry;
656 char *path;
657 off_t offset;
658 int cnt, fd, fflags;
659 int i, type, uflags;
660 int refcount;
661 cap_rights_t cap_rights;
662
663 assert(kp);
664 if (kp->ki_fd == NULL)
665 return (NULL);
743{
744 struct kinfo_file *kif, *files;
745 struct kinfo_vmentry *kve, *vmentries;
746 struct filestat_list *head;
747 struct filestat *entry;
748 char *path;
749 off_t offset;
750 int cnt, fd, fflags;
751 int i, type, uflags;
752 int refcount;
753 cap_rights_t cap_rights;
754
755 assert(kp);
756 if (kp->ki_fd == NULL)
757 return (NULL);
666
667 files = kinfo_getfile(kp->ki_pid, &cnt);
758 switch(procstat->type) {
759 case PROCSTAT_SYSCTL:
760 files = kinfo_getfile(kp->ki_pid, &cnt);
761 break;
762 case PROCSTAT_CORE:
763 files = kinfo_getfile_core(procstat->core, &cnt);
764 break;
765 default:
766 assert(!"invalid type");
767 }
668 if (files == NULL && errno != EPERM) {
669 warn("kinfo_getfile()");
670 return (NULL);
671 }
672 procstat->files = files;
673
674 /*
675 * Allocate list head.

--- 61 unchanged lines hidden (view full) ---

737procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
738 struct pipestat *ps, char *errbuf)
739{
740
741 assert(ps);
742 if (procstat->type == PROCSTAT_KVM) {
743 return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
744 errbuf));
768 if (files == NULL && errno != EPERM) {
769 warn("kinfo_getfile()");
770 return (NULL);
771 }
772 procstat->files = files;
773
774 /*
775 * Allocate list head.

--- 61 unchanged lines hidden (view full) ---

837procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
838 struct pipestat *ps, char *errbuf)
839{
840
841 assert(ps);
842 if (procstat->type == PROCSTAT_KVM) {
843 return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
844 errbuf));
745 } else if (procstat->type == PROCSTAT_SYSCTL) {
845 } else if (procstat->type == PROCSTAT_SYSCTL ||
846 procstat->type == PROCSTAT_CORE) {
746 return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
747 } else {
748 warnx("unknown access method: %d", procstat->type);
749 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
750 return (1);
751 }
752}
753

--- 47 unchanged lines hidden (view full) ---

801procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
802 struct ptsstat *pts, char *errbuf)
803{
804
805 assert(pts);
806 if (procstat->type == PROCSTAT_KVM) {
807 return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
808 errbuf));
847 return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
848 } else {
849 warnx("unknown access method: %d", procstat->type);
850 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
851 return (1);
852 }
853}
854

--- 47 unchanged lines hidden (view full) ---

902procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
903 struct ptsstat *pts, char *errbuf)
904{
905
906 assert(pts);
907 if (procstat->type == PROCSTAT_KVM) {
908 return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
909 errbuf));
809 } else if (procstat->type == PROCSTAT_SYSCTL) {
910 } else if (procstat->type == PROCSTAT_SYSCTL ||
911 procstat->type == PROCSTAT_CORE) {
810 return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
811 } else {
812 warnx("unknown access method: %d", procstat->type);
813 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
814 return (1);
815 }
816}
817

--- 45 unchanged lines hidden (view full) ---

863procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
864 struct shmstat *shm, char *errbuf)
865{
866
867 assert(shm);
868 if (procstat->type == PROCSTAT_KVM) {
869 return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
870 errbuf));
912 return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
913 } else {
914 warnx("unknown access method: %d", procstat->type);
915 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
916 return (1);
917 }
918}
919

--- 45 unchanged lines hidden (view full) ---

965procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
966 struct shmstat *shm, char *errbuf)
967{
968
969 assert(shm);
970 if (procstat->type == PROCSTAT_KVM) {
971 return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
972 errbuf));
871 } else if (procstat->type == PROCSTAT_SYSCTL) {
973 } else if (procstat->type == PROCSTAT_SYSCTL ||
974 procstat->type == PROCSTAT_CORE) {
872 return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
873 } else {
874 warnx("unknown access method: %d", procstat->type);
875 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
876 return (1);
877 }
878}
879

--- 63 unchanged lines hidden (view full) ---

943procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
944 struct vnstat *vn, char *errbuf)
945{
946
947 assert(vn);
948 if (procstat->type == PROCSTAT_KVM) {
949 return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
950 errbuf));
975 return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
976 } else {
977 warnx("unknown access method: %d", procstat->type);
978 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
979 return (1);
980 }
981}
982

--- 63 unchanged lines hidden (view full) ---

1046procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
1047 struct vnstat *vn, char *errbuf)
1048{
1049
1050 assert(vn);
1051 if (procstat->type == PROCSTAT_KVM) {
1052 return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
1053 errbuf));
951 } else if (procstat->type == PROCSTAT_SYSCTL) {
1054 } else if (procstat->type == PROCSTAT_SYSCTL ||
1055 procstat->type == PROCSTAT_CORE) {
952 return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
953 } else {
954 warnx("unknown access method: %d", procstat->type);
955 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
956 return (1);
957 }
958}
959

--- 185 unchanged lines hidden (view full) ---

1145procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
1146 struct sockstat *sock, char *errbuf)
1147{
1148
1149 assert(sock);
1150 if (procstat->type == PROCSTAT_KVM) {
1151 return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
1152 errbuf));
1056 return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
1057 } else {
1058 warnx("unknown access method: %d", procstat->type);
1059 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1060 return (1);
1061 }
1062}
1063

--- 185 unchanged lines hidden (view full) ---

1249procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
1250 struct sockstat *sock, char *errbuf)
1251{
1252
1253 assert(sock);
1254 if (procstat->type == PROCSTAT_KVM) {
1255 return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
1256 errbuf));
1153 } else if (procstat->type == PROCSTAT_SYSCTL) {
1257 } else if (procstat->type == PROCSTAT_SYSCTL ||
1258 procstat->type == PROCSTAT_CORE) {
1154 return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
1155 } else {
1156 warnx("unknown access method: %d", procstat->type);
1157 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1158 return (1);
1159 }
1160}
1161

--- 234 unchanged lines hidden (view full) ---

1396 err(1, NULL);
1397 mt->m = m;
1398 bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
1399 mt->mntonname[MNAMELEN] = '\0';
1400 mt->next = mhead;
1401 mhead = mt;
1402 return (mt->mntonname);
1403}
1259 return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
1260 } else {
1261 warnx("unknown access method: %d", procstat->type);
1262 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1263 return (1);
1264 }
1265}
1266

--- 234 unchanged lines hidden (view full) ---

1501 err(1, NULL);
1502 mt->m = m;
1503 bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
1504 mt->mntonname[MNAMELEN] = '\0';
1505 mt->next = mhead;
1506 mhead = mt;
1507 return (mt->mntonname);
1508}
1509