1 /*
2 * Copyright 2006-2015, Haiku, Inc.
3 * Distributed under the terms of the MIT license.
4 *
5 * Author:
6 * Axel Dörfler, axeld@pinc-software.de
7 */
8
9
10 #include <OS.h>
11 #include <fs_info.h>
12
13 #include <syscalls.h>
14 #include <vfs_defs.h>
15
16 #include <ctype.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21
22
23 enum info_mode {
24 kList,
25 kFilterDevice,
26 kFilterFile,
27 };
28
29 extern const char *__progname;
30
31
32 const char *
open_mode_to_string(int openMode)33 open_mode_to_string(int openMode)
34 {
35 switch (openMode & O_RWMASK) {
36 case O_RDONLY:
37 return "R ";
38 case O_WRONLY:
39 return " W";
40 default:
41 return "R/W";
42 }
43 }
44
45
46 void
print_fds(team_info & teamInfo)47 print_fds(team_info &teamInfo)
48 {
49 printf("Team: (%" B_PRId32 ") %s\n", teamInfo.team, teamInfo.args);
50
51 uint32 cookie = 0;
52 fd_info info;
53
54 while (_kern_get_next_fd_info(teamInfo.team, &cookie, &info, sizeof(fd_info)) == B_OK) {
55 printf("%5d %s %" B_PRIdDEV ":%" B_PRIdINO "\n", info.number,
56 open_mode_to_string(info.open_mode), info.device, info.node);
57 }
58 }
59
60
61 void
filter_device(team_info & teamInfo,dev_t device,bool brief)62 filter_device(team_info &teamInfo, dev_t device, bool brief)
63 {
64 uint32 cookie = 0;
65 fd_info info;
66
67 while (_kern_get_next_fd_info(teamInfo.team, &cookie, &info, sizeof(fd_info)) == B_OK) {
68 if (info.device != device)
69 continue;
70
71 if (brief) {
72 printf("%5" B_PRId32 " %s\n", teamInfo.team, teamInfo.args);
73 break;
74 }
75
76 printf("%5" B_PRId32 " %3d %3s %" B_PRIdDEV ":%" B_PRIdINO " %s\n",
77 teamInfo.team, info.number, open_mode_to_string(info.open_mode),
78 info.device, info.node, teamInfo.args);
79 }
80 }
81
82
83 void
filter_file(team_info & teamInfo,dev_t device,ino_t node,bool brief)84 filter_file(team_info &teamInfo, dev_t device, ino_t node, bool brief)
85 {
86 uint32 cookie = 0;
87 fd_info info;
88
89 while (_kern_get_next_fd_info(teamInfo.team, &cookie, &info, sizeof(fd_info)) == B_OK) {
90 if (info.device != device || info.node != node)
91 continue;
92
93 if (brief) {
94 printf("%5" B_PRId32 " %s\n", teamInfo.team, teamInfo.args);
95 break;
96 }
97
98 printf("%5" B_PRId32 " %3d %3s %s\n", teamInfo.team, info.number,
99 open_mode_to_string(info.open_mode), teamInfo.args);
100 }
101 }
102
103
104 void
usage(bool failure)105 usage(bool failure)
106 {
107 printf("Usage: %s <id/pattern> or -[dD] <path-to-device> or -[fF] <file>\n"
108 " Shows info about the used file descriptors in the system.\n\n"
109 " -d\tOnly shows accesses to the given device\n"
110 " -D\tLikewise, but only shows the teams that access it\n"
111 " -f\tOnly shows accesses to the given file\n"
112 " -F\tLikewise, but only shows the teams that access it\n",
113 __progname);
114
115 exit(failure ? 1 : 0);
116 }
117
118
119 int
main(int argc,char ** argv)120 main(int argc, char **argv)
121 {
122 const char *pattern = NULL;
123 dev_t device = -1;
124 ino_t node = -1;
125 int32 id = -1;
126 info_mode mode = kList;
127 bool brief = false;
128
129 // parse arguments
130
131 if (argc == 2) {
132 // filter output
133 if (isdigit(argv[1][0]))
134 id = atol(argv[1]);
135 else if (argv[1][0] == '-')
136 usage(!strcmp(argv[1], "--help"));
137 else
138 pattern = argv[1];
139 } else if (argc > 2) {
140 if (!strcmp(argv[1], "-d") || !strcmp(argv[1], "-D")) {
141 // filter by device usage
142 device = dev_for_path(argv[2]);
143 if (device < 0) {
144 fprintf(stderr, "%s: could not find device: %s\n", __progname,
145 strerror(errno));
146 return 1;
147 }
148 mode = kFilterDevice;
149 if (argv[1][1] == 'D')
150 brief = true;
151 } else if (!strcmp(argv[1], "-f") || !strcmp(argv[1], "-F")) {
152 // filter by file usage
153 struct stat stat;
154 if (::stat(argv[2], &stat) < 0) {
155 fprintf(stderr, "%s: could not open file: %s\n", __progname,
156 strerror(errno));
157 return 1;
158 }
159 device = stat.st_dev;
160 node = stat.st_ino;
161 mode = kFilterFile;
162 if (argv[1][1] == 'F')
163 brief = true;
164 } else
165 usage(true);
166 }
167
168 // do the job!
169
170 team_info info;
171 int32 cookie = 0;
172
173 while (get_next_team_info(&cookie, &info) == B_OK) {
174 switch (mode) {
175 case kList:
176 if ((id != -1 && id != info.team)
177 || (pattern != NULL && !strstr(info.args, pattern)))
178 continue;
179 print_fds(info);
180 break;
181
182 case kFilterDevice:
183 filter_device(info, device, brief);
184 break;
185 case kFilterFile:
186 filter_file(info, device, node, brief);
187 break;
188 }
189 }
190
191 return 0;
192 }
193
194