1 /* 2 * Copyright 2006, 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 * 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 47 print_fds(team_info &teamInfo) 48 { 49 printf("Team: (%ld) %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 %ld:%Ld\n", info.number, open_mode_to_string(info.open_mode), 56 info.device, info.node); 57 } 58 } 59 60 61 void 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("%5ld %s\n", teamInfo.team, teamInfo.args); 73 break; 74 } 75 76 printf("%5ld %3d %3s %ld:%Ld %s\n", teamInfo.team, info.number, 77 open_mode_to_string(info.open_mode), info.device, info.node, 78 teamInfo.args); 79 } 80 } 81 82 83 void 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("%5ld %s\n", teamInfo.team, teamInfo.args); 95 break; 96 } 97 98 printf("%5ld %3d %3s %s\n", teamInfo.team, info.number, 99 open_mode_to_string(info.open_mode), teamInfo.args); 100 } 101 } 102 103 104 void 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 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