1*34bdffbfSGarrett D'Amore /* 2*34bdffbfSGarrett D'Amore * This file and its contents are supplied under the terms of the 3*34bdffbfSGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 4*34bdffbfSGarrett D'Amore * You may only use this file in accordance with the terms of version 5*34bdffbfSGarrett D'Amore * 1.0 of the CDDL. 6*34bdffbfSGarrett D'Amore * 7*34bdffbfSGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 8*34bdffbfSGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 9*34bdffbfSGarrett D'Amore * http://www.illumos.org/license/CDDL. 10*34bdffbfSGarrett D'Amore */ 11*34bdffbfSGarrett D'Amore 12*34bdffbfSGarrett D'Amore /* 13*34bdffbfSGarrett D'Amore * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 14*34bdffbfSGarrett D'Amore */ 15*34bdffbfSGarrett D'Amore 16*34bdffbfSGarrett D'Amore #include <limits.h> 17*34bdffbfSGarrett D'Amore #include <stdio.h> 18*34bdffbfSGarrett D'Amore #include <errno.h> 19*34bdffbfSGarrett D'Amore #include <unistd.h> 20*34bdffbfSGarrett D'Amore #include <dirent.h> 21*34bdffbfSGarrett D'Amore #include <ctype.h> 22*34bdffbfSGarrett D'Amore #include <string.h> 23*34bdffbfSGarrett D'Amore #include <sys/mkdev.h> 24*34bdffbfSGarrett D'Amore 25*34bdffbfSGarrett D'Amore #include "libproc.h" 26*34bdffbfSGarrett D'Amore #include "Pcontrol.h" 27*34bdffbfSGarrett D'Amore 28*34bdffbfSGarrett D'Amore /* 29*34bdffbfSGarrett D'Amore * Pfdinfo.c - obtain open file information. 30*34bdffbfSGarrett D'Amore */ 31*34bdffbfSGarrett D'Amore 32*34bdffbfSGarrett D'Amore /* 33*34bdffbfSGarrett D'Amore * Allocate an fd_info structure and stick it on the list. 34*34bdffbfSGarrett D'Amore * (Unless one already exists.) The list is sorted in 35*34bdffbfSGarrett D'Amore * reverse order. We will traverse it in that order later. 36*34bdffbfSGarrett D'Amore * This makes the usual ordered insert *fast*. 37*34bdffbfSGarrett D'Amore */ 38*34bdffbfSGarrett D'Amore fd_info_t * 39*34bdffbfSGarrett D'Amore Pfd2info(struct ps_prochandle *P, int fd) 40*34bdffbfSGarrett D'Amore { 41*34bdffbfSGarrett D'Amore fd_info_t *fip = list_next(&P->fd_head); 42*34bdffbfSGarrett D'Amore fd_info_t *next; 43*34bdffbfSGarrett D'Amore int i; 44*34bdffbfSGarrett D'Amore 45*34bdffbfSGarrett D'Amore if (fip == NULL) { 46*34bdffbfSGarrett D'Amore list_link(&P->fd_head, NULL); 47*34bdffbfSGarrett D'Amore fip = list_next(&P->fd_head); 48*34bdffbfSGarrett D'Amore } 49*34bdffbfSGarrett D'Amore 50*34bdffbfSGarrett D'Amore for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) { 51*34bdffbfSGarrett D'Amore if (fip->fd_info.pr_fd == fd) { 52*34bdffbfSGarrett D'Amore return (fip); 53*34bdffbfSGarrett D'Amore } 54*34bdffbfSGarrett D'Amore if (fip->fd_info.pr_fd < fd) { 55*34bdffbfSGarrett D'Amore break; 56*34bdffbfSGarrett D'Amore } 57*34bdffbfSGarrett D'Amore } 58*34bdffbfSGarrett D'Amore 59*34bdffbfSGarrett D'Amore next = fip; 60*34bdffbfSGarrett D'Amore if ((fip = calloc(1, sizeof (*fip))) == NULL) 61*34bdffbfSGarrett D'Amore return (NULL); 62*34bdffbfSGarrett D'Amore 63*34bdffbfSGarrett D'Amore fip->fd_info.pr_fd = fd; 64*34bdffbfSGarrett D'Amore list_link(fip, next ? next : (void *)&(P->fd_head)); 65*34bdffbfSGarrett D'Amore P->num_fd++; 66*34bdffbfSGarrett D'Amore return (fip); 67*34bdffbfSGarrett D'Amore } 68*34bdffbfSGarrett D'Amore 69*34bdffbfSGarrett D'Amore /* 70*34bdffbfSGarrett D'Amore * Attempt to load the open file information from a live process. 71*34bdffbfSGarrett D'Amore */ 72*34bdffbfSGarrett D'Amore static void 73*34bdffbfSGarrett D'Amore load_fdinfo(struct ps_prochandle *P) 74*34bdffbfSGarrett D'Amore { 75*34bdffbfSGarrett D'Amore /* 76*34bdffbfSGarrett D'Amore * In the unlikely case there are *no* file descriptors open, 77*34bdffbfSGarrett D'Amore * we will keep rescanning the proc directory, which will be empty. 78*34bdffbfSGarrett D'Amore * This is an edge case it isn't worth adding additional state to 79*34bdffbfSGarrett D'Amore * to eliminate. 80*34bdffbfSGarrett D'Amore */ 81*34bdffbfSGarrett D'Amore if (P->num_fd > 0) { 82*34bdffbfSGarrett D'Amore return; 83*34bdffbfSGarrett D'Amore } 84*34bdffbfSGarrett D'Amore 85*34bdffbfSGarrett D'Amore if (P->state != PS_DEAD && P->state != PS_IDLE) { 86*34bdffbfSGarrett D'Amore char dir_name[PATH_MAX]; 87*34bdffbfSGarrett D'Amore char path[PATH_MAX]; 88*34bdffbfSGarrett D'Amore struct dirent *ent; 89*34bdffbfSGarrett D'Amore DIR *dirp; 90*34bdffbfSGarrett D'Amore int fd; 91*34bdffbfSGarrett D'Amore 92*34bdffbfSGarrett D'Amore /* 93*34bdffbfSGarrett D'Amore * Try to get the path information first. 94*34bdffbfSGarrett D'Amore */ 95*34bdffbfSGarrett D'Amore (void) snprintf(dir_name, sizeof (dir_name), 96*34bdffbfSGarrett D'Amore "%s/%d/path", procfs_path, (int)P->pid); 97*34bdffbfSGarrett D'Amore dirp = opendir(dir_name); 98*34bdffbfSGarrett D'Amore if (dirp == NULL) { 99*34bdffbfSGarrett D'Amore return; 100*34bdffbfSGarrett D'Amore } 101*34bdffbfSGarrett D'Amore ent = NULL; 102*34bdffbfSGarrett D'Amore while ((ent = readdir(dirp)) != NULL) { 103*34bdffbfSGarrett D'Amore fd_info_t *fip; 104*34bdffbfSGarrett D'Amore prfdinfo_t *info; 105*34bdffbfSGarrett D'Amore int len; 106*34bdffbfSGarrett D'Amore struct stat64 stat; 107*34bdffbfSGarrett D'Amore 108*34bdffbfSGarrett D'Amore if (!isdigit(ent->d_name[0])) 109*34bdffbfSGarrett D'Amore continue; 110*34bdffbfSGarrett D'Amore 111*34bdffbfSGarrett D'Amore fd = atoi(ent->d_name); 112*34bdffbfSGarrett D'Amore 113*34bdffbfSGarrett D'Amore fip = Pfd2info(P, fd); 114*34bdffbfSGarrett D'Amore info = &fip->fd_info; 115*34bdffbfSGarrett D'Amore info->pr_fd = fd; 116*34bdffbfSGarrett D'Amore 117*34bdffbfSGarrett D'Amore if (pr_fstat64(P, fd, &stat) == 0) { 118*34bdffbfSGarrett D'Amore info->pr_mode = stat.st_mode; 119*34bdffbfSGarrett D'Amore info->pr_uid = stat.st_uid; 120*34bdffbfSGarrett D'Amore info->pr_gid = stat.st_gid; 121*34bdffbfSGarrett D'Amore info->pr_major = major(stat.st_dev); 122*34bdffbfSGarrett D'Amore info->pr_minor = minor(stat.st_dev); 123*34bdffbfSGarrett D'Amore info->pr_rmajor = major(stat.st_rdev); 124*34bdffbfSGarrett D'Amore info->pr_rminor = minor(stat.st_rdev); 125*34bdffbfSGarrett D'Amore info->pr_size = stat.st_size; 126*34bdffbfSGarrett D'Amore info->pr_ino = stat.st_ino; 127*34bdffbfSGarrett D'Amore } 128*34bdffbfSGarrett D'Amore 129*34bdffbfSGarrett D'Amore info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0); 130*34bdffbfSGarrett D'Amore info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0); 131*34bdffbfSGarrett D'Amore info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR); 132*34bdffbfSGarrett D'Amore 133*34bdffbfSGarrett D'Amore /* attempt to determine the path to it */ 134*34bdffbfSGarrett D'Amore (void) snprintf(path, sizeof (path), 135*34bdffbfSGarrett D'Amore "%s/%d/path/%d", procfs_path, (int)P->pid, fd); 136*34bdffbfSGarrett D'Amore len = readlink(path, info->pr_path, 137*34bdffbfSGarrett D'Amore sizeof (info->pr_path) - 1); 138*34bdffbfSGarrett D'Amore 139*34bdffbfSGarrett D'Amore if (len < 0) { 140*34bdffbfSGarrett D'Amore info->pr_path[0] = 0; 141*34bdffbfSGarrett D'Amore } else { 142*34bdffbfSGarrett D'Amore info->pr_path[len] = 0; 143*34bdffbfSGarrett D'Amore } 144*34bdffbfSGarrett D'Amore } 145*34bdffbfSGarrett D'Amore (void) closedir(dirp); 146*34bdffbfSGarrett D'Amore 147*34bdffbfSGarrett D'Amore } 148*34bdffbfSGarrett D'Amore } 149*34bdffbfSGarrett D'Amore 150*34bdffbfSGarrett D'Amore int 151*34bdffbfSGarrett D'Amore Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd) 152*34bdffbfSGarrett D'Amore { 153*34bdffbfSGarrett D'Amore fd_info_t *fip; 154*34bdffbfSGarrett D'Amore int rv; 155*34bdffbfSGarrett D'Amore 156*34bdffbfSGarrett D'Amore /* Make sure we have live data, if appropriate */ 157*34bdffbfSGarrett D'Amore load_fdinfo(P); 158*34bdffbfSGarrett D'Amore 159*34bdffbfSGarrett D'Amore /* NB: We walk the list backwards. */ 160*34bdffbfSGarrett D'Amore 161*34bdffbfSGarrett D'Amore for (fip = list_prev(&P->fd_head); 162*34bdffbfSGarrett D'Amore fip != (void *)&P->fd_head; 163*34bdffbfSGarrett D'Amore fip = list_prev(fip)) { 164*34bdffbfSGarrett D'Amore if ((rv = func(cd, &fip->fd_info)) != 0) 165*34bdffbfSGarrett D'Amore return (rv); 166*34bdffbfSGarrett D'Amore } 167*34bdffbfSGarrett D'Amore return (0); 168*34bdffbfSGarrett D'Amore } 169