lsof.c revision 8b9b105bc7bf6428591d55462b3e727ba7504b29
18b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root/* 28b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * Copyright (c) 2010, The Android Open Source Project 38b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * All rights reserved. 48b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * 58b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * Redistribution and use in source and binary forms, with or without 68b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * modification, are permitted provided that the following conditions 78b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * are met: 88b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * * Redistributions of source code must retain the above copyright 98b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * notice, this list of conditions and the following disclaimer. 108b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * * Redistributions in binary form must reproduce the above copyright 118b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * notice, this list of conditions and the following disclaimer in 128b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * the documentation and/or other materials provided with the 138b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * distribution. 148b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * * Neither the name of Google, Inc. nor the names of its contributors 158b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * may be used to endorse or promote products derived from this 168b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * software without specific prior written permission. 178b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * 188b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 198b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 208b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 218b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 228b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 238b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 248b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 258b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 268b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 278b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 288b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 298b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root * SUCH DAMAGE. 308b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root */ 318b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 328b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <dirent.h> 338b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <errno.h> 348b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <fcntl.h> 358b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <libgen.h> 368b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <stdio.h> 378b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <stdlib.h> 388b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#include <unistd.h> 398b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 408b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#define BUF_MAX 1024 418b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root#define CMD_DISPLAY_MAX 10 428b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 438b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootstruct pid_info_t { 448b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root pid_t pid; 458b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 468b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char cmdline[CMD_DISPLAY_MAX]; 478b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 488b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char path[PATH_MAX]; 498b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root ssize_t parent_length; 508b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root}; 518b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 528b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootvoid print_header() 538b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 548b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root printf("%-9s %5s %10s %4s %9s %18s %9s %10s %s\n", 558b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "COMMAND", 568b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "PID", 578b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "USER", 588b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "FD", 598b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "TYPE", 608b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "DEVICE", 618b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "SIZE/OFF", 628b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "NODE", 638b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "NAME"); 648b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 658b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 668b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootvoid print_type(char *type, struct pid_info_t* info) 678b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 688b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root static ssize_t link_dest_size; 698b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root static char link_dest[PATH_MAX]; 708b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 718b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root strncat(info->path, type, sizeof(info->path)); 728b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if ((link_dest_size = readlink(info->path, link_dest, sizeof(link_dest)-1)) < 0) { 738b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (errno == ENOENT) 748b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root goto out; 758b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 768b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root snprintf(link_dest, sizeof(link_dest), "%s (readlink: %s)", info->path, strerror(errno)); 778b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } else { 788b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root link_dest[link_dest_size] = '\0'; 798b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 808b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 818b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // Things that are just the root filesystem are uninteresting (we already know) 828b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (!strcmp(link_dest, "/")) 838b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root goto out; 848b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 858b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n", info->cmdline, info->pid, "???", type, 868b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "???", "???", "???", "???", link_dest); 878b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 888b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootout: 898b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info->path[info->parent_length] = '\0'; 908b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 918b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 928b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root// Prints out all file that have been memory mapped 938b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootvoid print_maps(struct pid_info_t* info) 948b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 958b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root FILE *maps; 968b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char buffer[PATH_MAX + 100]; 978b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 988b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root size_t offset; 998b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root int major, minor; 1008b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char device[10]; 1018b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root long int inode; 1028b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char file[PATH_MAX]; 1038b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1048b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root strncat(info->path, "maps", sizeof(info->path)); 1058b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1068b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root maps = fopen(info->path, "r"); 1078b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (!maps) 1088b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root goto out; 1098b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1108b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root while (fscanf(maps, "%*x-%*x %*s %zx %5s %ld %s\n", &offset, device, &inode, 1118b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root file) == 4) { 1128b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // We don't care about non-file maps 1138b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (inode == 0 || !strcmp(device, "00:00")) 1148b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root continue; 1158b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1168b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root printf("%-9s %5d %10s %4s %9s %18s %9zd %10ld %s\n", info->cmdline, info->pid, "???", "mem", 1178b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "???", device, offset, inode, file); 1188b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 1198b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1208b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root fclose(maps); 1218b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1228b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootout: 1238b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info->path[info->parent_length] = '\0'; 1248b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 1258b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1268b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root// Prints out all open file descriptors 1278b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootvoid print_fds(struct pid_info_t* info) 1288b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 1298b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root static char* fd_path = "fd/"; 1308b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root strncat(info->path, fd_path, sizeof(info->path)); 1318b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1328b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root int previous_length = info->parent_length; 1338b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info->parent_length += strlen(fd_path); 1348b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1358b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root DIR *dir = opendir(info->path); 1368b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (dir == NULL) { 1378b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char msg[BUF_MAX]; 1388b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root snprintf(msg, sizeof(msg), "%s (opendir: %s)", info->path, strerror(errno)); 1398b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root printf("%-9s %5d %10s %4s %9s %18s %9s %10s %s\n", info->cmdline, info->pid, "???", "FDS", 1408b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root "", "", "", "", msg); 1418b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root goto out; 1428b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 1438b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1448b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root struct dirent* de; 1458b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root while ((de = readdir(dir))) { 1468b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 1478b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root continue; 1488b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1498b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_type(de->d_name, info); 1508b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 1518b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root closedir(dir); 1528b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1538b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootout: 1548b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info->parent_length = previous_length; 1558b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info->path[info->parent_length] = '\0'; 1568b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 1578b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1588b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootvoid lsof_dumpinfo(pid_t pid) 1598b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 1608b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root int fd; 1618b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root struct pid_info_t info; 1628b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info.pid = pid; 1638b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1648b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root snprintf(info.path, sizeof(info.path), "/proc/%d/", pid); 1658b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1668b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info.parent_length = strlen(info.path); 1678b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1688b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // Read the command line information; each argument is terminated with NULL. 1698b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root strncat(info.path, "cmdline", sizeof(info.path)); 1708b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root fd = open(info.path, O_RDONLY); 1718b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (fd < 0) { 1728b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root fprintf(stderr, "Couldn't read %s\n", info.path); 1738b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root return; 1748b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 1758b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char cmdline[PATH_MAX]; 1768b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (read(fd, cmdline, sizeof(cmdline)) < 0) { 1778b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root fprintf(stderr, "Error reading cmdline: %s: %s\n", info.path, strerror(errno)); 1788b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root close(fd); 1798b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root return; 1808b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 1818b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root close(fd); 1828b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info.path[info.parent_length] = '\0'; 1838b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1848b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // We only want the basename of the cmdline 1858b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root strncpy(info.cmdline, basename(cmdline), sizeof(info.cmdline)); 1868b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root info.cmdline[sizeof(info.cmdline)-1] = '\0'; 1878b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1888b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // Read each of these symlinks 1898b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_type("cwd", &info); 1908b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_type("exe", &info); 1918b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_type("root", &info); 1928b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1938b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_fds(&info); 1948b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_maps(&info); 1958b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 1968b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 1978b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Rootint lsof_main(int argc, char *argv[]) 1988b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root{ 1998b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root DIR *dir = opendir("/proc"); 2008b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (dir == NULL) { 2018b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root fprintf(stderr, "Couldn't open /proc\n"); 2028b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root return -1; 2038b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 2048b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 2058b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root print_header(); 2068b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 2078b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root struct dirent* de; 2088b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root while ((de = readdir(dir))) { 2098b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 2108b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root continue; 2118b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 2128b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root // Only inspect directories that are PID numbers 2138b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root char* endptr; 2148b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root long int pid = strtol(de->d_name, &endptr, 10); 2158b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root if (*endptr != '\0') 2168b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root continue; 2178b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 2188b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root lsof_dumpinfo(pid); 2198b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root } 2208b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root closedir(dir); 2218b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root 2228b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root return 0; 2238b9b105bc7bf6428591d55462b3e727ba7504b29Kenny Root} 224