134bdffbfSGarrett D'Amore /* 234bdffbfSGarrett D'Amore * This file and its contents are supplied under the terms of the 334bdffbfSGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 434bdffbfSGarrett D'Amore * You may only use this file in accordance with the terms of version 534bdffbfSGarrett D'Amore * 1.0 of the CDDL. 634bdffbfSGarrett D'Amore * 734bdffbfSGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 834bdffbfSGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 934bdffbfSGarrett D'Amore * http://www.illumos.org/license/CDDL. 1034bdffbfSGarrett D'Amore */ 1134bdffbfSGarrett D'Amore 1234bdffbfSGarrett D'Amore /* 1334bdffbfSGarrett D'Amore * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 1434bdffbfSGarrett D'Amore */ 15*dfc0fed8SRobert Mustacchi /* 16*dfc0fed8SRobert Mustacchi * Copyright (c) 2013 Joyent, Inc. All Rights reserved. 17*dfc0fed8SRobert Mustacchi */ 1834bdffbfSGarrett D'Amore 1934bdffbfSGarrett D'Amore #include <limits.h> 2034bdffbfSGarrett D'Amore #include <stdio.h> 2134bdffbfSGarrett D'Amore #include <errno.h> 2234bdffbfSGarrett D'Amore #include <unistd.h> 2334bdffbfSGarrett D'Amore #include <dirent.h> 2434bdffbfSGarrett D'Amore #include <ctype.h> 2534bdffbfSGarrett D'Amore #include <string.h> 2634bdffbfSGarrett D'Amore #include <sys/mkdev.h> 2734bdffbfSGarrett D'Amore 2834bdffbfSGarrett D'Amore #include "libproc.h" 2934bdffbfSGarrett D'Amore #include "Pcontrol.h" 3034bdffbfSGarrett D'Amore 3134bdffbfSGarrett D'Amore /* 3234bdffbfSGarrett D'Amore * Pfdinfo.c - obtain open file information. 3334bdffbfSGarrett D'Amore */ 3434bdffbfSGarrett D'Amore 3534bdffbfSGarrett D'Amore /* 3634bdffbfSGarrett D'Amore * Allocate an fd_info structure and stick it on the list. 3734bdffbfSGarrett D'Amore * (Unless one already exists.) The list is sorted in 3834bdffbfSGarrett D'Amore * reverse order. We will traverse it in that order later. 3934bdffbfSGarrett D'Amore * This makes the usual ordered insert *fast*. 4034bdffbfSGarrett D'Amore */ 4134bdffbfSGarrett D'Amore fd_info_t * 4234bdffbfSGarrett D'Amore Pfd2info(struct ps_prochandle *P, int fd) 4334bdffbfSGarrett D'Amore { 4434bdffbfSGarrett D'Amore fd_info_t *fip = list_next(&P->fd_head); 4534bdffbfSGarrett D'Amore fd_info_t *next; 4634bdffbfSGarrett D'Amore int i; 4734bdffbfSGarrett D'Amore 4834bdffbfSGarrett D'Amore if (fip == NULL) { 4934bdffbfSGarrett D'Amore list_link(&P->fd_head, NULL); 5034bdffbfSGarrett D'Amore fip = list_next(&P->fd_head); 5134bdffbfSGarrett D'Amore } 5234bdffbfSGarrett D'Amore 5334bdffbfSGarrett D'Amore for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) { 5434bdffbfSGarrett D'Amore if (fip->fd_info.pr_fd == fd) { 5534bdffbfSGarrett D'Amore return (fip); 5634bdffbfSGarrett D'Amore } 5734bdffbfSGarrett D'Amore if (fip->fd_info.pr_fd < fd) { 5834bdffbfSGarrett D'Amore break; 5934bdffbfSGarrett D'Amore } 6034bdffbfSGarrett D'Amore } 6134bdffbfSGarrett D'Amore 6234bdffbfSGarrett D'Amore next = fip; 6334bdffbfSGarrett D'Amore if ((fip = calloc(1, sizeof (*fip))) == NULL) 6434bdffbfSGarrett D'Amore return (NULL); 6534bdffbfSGarrett D'Amore 6634bdffbfSGarrett D'Amore fip->fd_info.pr_fd = fd; 6734bdffbfSGarrett D'Amore list_link(fip, next ? next : (void *)&(P->fd_head)); 6834bdffbfSGarrett D'Amore P->num_fd++; 6934bdffbfSGarrett D'Amore return (fip); 7034bdffbfSGarrett D'Amore } 7134bdffbfSGarrett D'Amore 7234bdffbfSGarrett D'Amore /* 7334bdffbfSGarrett D'Amore * Attempt to load the open file information from a live process. 7434bdffbfSGarrett D'Amore */ 7534bdffbfSGarrett D'Amore static void 7634bdffbfSGarrett D'Amore load_fdinfo(struct ps_prochandle *P) 7734bdffbfSGarrett D'Amore { 7834bdffbfSGarrett D'Amore /* 7934bdffbfSGarrett D'Amore * In the unlikely case there are *no* file descriptors open, 8034bdffbfSGarrett D'Amore * we will keep rescanning the proc directory, which will be empty. 8134bdffbfSGarrett D'Amore * This is an edge case it isn't worth adding additional state to 8234bdffbfSGarrett D'Amore * to eliminate. 8334bdffbfSGarrett D'Amore */ 8434bdffbfSGarrett D'Amore if (P->num_fd > 0) { 8534bdffbfSGarrett D'Amore return; 8634bdffbfSGarrett D'Amore } 8734bdffbfSGarrett D'Amore 8834bdffbfSGarrett D'Amore if (P->state != PS_DEAD && P->state != PS_IDLE) { 8934bdffbfSGarrett D'Amore char dir_name[PATH_MAX]; 9034bdffbfSGarrett D'Amore char path[PATH_MAX]; 9134bdffbfSGarrett D'Amore struct dirent *ent; 9234bdffbfSGarrett D'Amore DIR *dirp; 9334bdffbfSGarrett D'Amore int fd; 9434bdffbfSGarrett D'Amore 9534bdffbfSGarrett D'Amore /* 9634bdffbfSGarrett D'Amore * Try to get the path information first. 9734bdffbfSGarrett D'Amore */ 9834bdffbfSGarrett D'Amore (void) snprintf(dir_name, sizeof (dir_name), 9934bdffbfSGarrett D'Amore "%s/%d/path", procfs_path, (int)P->pid); 10034bdffbfSGarrett D'Amore dirp = opendir(dir_name); 10134bdffbfSGarrett D'Amore if (dirp == NULL) { 10234bdffbfSGarrett D'Amore return; 10334bdffbfSGarrett D'Amore } 10434bdffbfSGarrett D'Amore ent = NULL; 10534bdffbfSGarrett D'Amore while ((ent = readdir(dirp)) != NULL) { 10634bdffbfSGarrett D'Amore fd_info_t *fip; 10734bdffbfSGarrett D'Amore prfdinfo_t *info; 10834bdffbfSGarrett D'Amore int len; 10934bdffbfSGarrett D'Amore struct stat64 stat; 11034bdffbfSGarrett D'Amore 11134bdffbfSGarrett D'Amore if (!isdigit(ent->d_name[0])) 11234bdffbfSGarrett D'Amore continue; 11334bdffbfSGarrett D'Amore 11434bdffbfSGarrett D'Amore fd = atoi(ent->d_name); 11534bdffbfSGarrett D'Amore 11634bdffbfSGarrett D'Amore fip = Pfd2info(P, fd); 11734bdffbfSGarrett D'Amore info = &fip->fd_info; 11834bdffbfSGarrett D'Amore info->pr_fd = fd; 11934bdffbfSGarrett D'Amore 12034bdffbfSGarrett D'Amore if (pr_fstat64(P, fd, &stat) == 0) { 12134bdffbfSGarrett D'Amore info->pr_mode = stat.st_mode; 12234bdffbfSGarrett D'Amore info->pr_uid = stat.st_uid; 12334bdffbfSGarrett D'Amore info->pr_gid = stat.st_gid; 12434bdffbfSGarrett D'Amore info->pr_major = major(stat.st_dev); 12534bdffbfSGarrett D'Amore info->pr_minor = minor(stat.st_dev); 12634bdffbfSGarrett D'Amore info->pr_rmajor = major(stat.st_rdev); 12734bdffbfSGarrett D'Amore info->pr_rminor = minor(stat.st_rdev); 12834bdffbfSGarrett D'Amore info->pr_size = stat.st_size; 12934bdffbfSGarrett D'Amore info->pr_ino = stat.st_ino; 13034bdffbfSGarrett D'Amore } 13134bdffbfSGarrett D'Amore 13234bdffbfSGarrett D'Amore info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0); 13334bdffbfSGarrett D'Amore info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0); 13434bdffbfSGarrett D'Amore info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR); 13534bdffbfSGarrett D'Amore 13634bdffbfSGarrett D'Amore /* attempt to determine the path to it */ 13734bdffbfSGarrett D'Amore (void) snprintf(path, sizeof (path), 13834bdffbfSGarrett D'Amore "%s/%d/path/%d", procfs_path, (int)P->pid, fd); 13934bdffbfSGarrett D'Amore len = readlink(path, info->pr_path, 14034bdffbfSGarrett D'Amore sizeof (info->pr_path) - 1); 14134bdffbfSGarrett D'Amore 14234bdffbfSGarrett D'Amore if (len < 0) { 14334bdffbfSGarrett D'Amore info->pr_path[0] = 0; 14434bdffbfSGarrett D'Amore } else { 14534bdffbfSGarrett D'Amore info->pr_path[len] = 0; 14634bdffbfSGarrett D'Amore } 14734bdffbfSGarrett D'Amore } 14834bdffbfSGarrett D'Amore (void) closedir(dirp); 14934bdffbfSGarrett D'Amore 15034bdffbfSGarrett D'Amore } 15134bdffbfSGarrett D'Amore } 15234bdffbfSGarrett D'Amore 15334bdffbfSGarrett D'Amore int 15434bdffbfSGarrett D'Amore Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd) 15534bdffbfSGarrett D'Amore { 15634bdffbfSGarrett D'Amore fd_info_t *fip; 15734bdffbfSGarrett D'Amore int rv; 15834bdffbfSGarrett D'Amore 15934bdffbfSGarrett D'Amore /* Make sure we have live data, if appropriate */ 16034bdffbfSGarrett D'Amore load_fdinfo(P); 16134bdffbfSGarrett D'Amore 16234bdffbfSGarrett D'Amore /* NB: We walk the list backwards. */ 16334bdffbfSGarrett D'Amore 16434bdffbfSGarrett D'Amore for (fip = list_prev(&P->fd_head); 165*dfc0fed8SRobert Mustacchi fip != (void *)&P->fd_head && fip != NULL; 16634bdffbfSGarrett D'Amore fip = list_prev(fip)) { 16734bdffbfSGarrett D'Amore if ((rv = func(cd, &fip->fd_info)) != 0) 16834bdffbfSGarrett D'Amore return (rv); 16934bdffbfSGarrett D'Amore } 17034bdffbfSGarrett D'Amore return (0); 17134bdffbfSGarrett D'Amore } 172