#include #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "interfere.h" const char *progname="pfiles"; struct private { struct stat statbuf; char procfd[256]; DIR *dir; struct dirent *dirent; int fd; }; void modecvt(char *txt, int mode, int setuid, char *chrs) { if (mode & 4) txt[0]='r'; if (mode & 2) txt[1]='w'; if (mode & 1) txt[2]='x'; if (setuid) txt[2]=chrs[(mode & 1)]; } int pfiles(struct process *proc, struct private *priv) { PROC_BEGIN(proc); sprintf(priv->procfd, "/proc/%li/fd", (long)proc->pid); if (!(priv->dir=opendir(priv->procfd))) { warn("opendir %s: %s\n", priv->procfd, strerror(errno)); goto out; } while (errno=0, priv->dirent=readdir(priv->dir)) { char procfdfile[256]; char filename[PATH_MAX]; int bytes; if (priv->dirent->d_name[0]=='.') continue; priv->fd=str_to_fd(priv->dirent->d_name); sprintf(procfdfile, "%s/%i", priv->procfd, priv->fd); bytes=readlink(procfdfile, filename, sizeof(filename)); if (bytes==-1) warn("readlink(%s): %s\n", procfdfile, strerror(errno)); else printf("pid:%li fd:%i name:%.*s\n", (long)proc->pid, priv->fd, bytes, filename); proc_fstat(proc, priv->fd, &priv->statbuf); if (proc->last_error) warn("fstat(pid %li, fd %i): %s\n", (long)proc->pid, priv->fd, strerror(proc->last_error)); else { const struct { int flag; char letter; } flags[]={ {S_IFSOCK, 's'}, {S_IFLNK, 'l'}, {S_IFREG, '-'}, {S_IFBLK, 'b'}, {S_IFDIR, 'd'}, {S_IFCHR, 'c'}, {S_IFIFO, 'p'}, {0,'?'} }; int i; int type = priv->statbuf.st_mode & S_IFMT; int mode = priv->statbuf.st_mode; char modetxt[10]="----------"; printf("pid:%li fd:%i dev:%li,%li ino:%li nlink:%li uid:%li gid:%li rdev:%li,%li size:%li blksize:%li blocks:%li\n", (long)proc->pid, priv->fd, (long)MAJOR(priv->statbuf.st_dev), (long)MINOR(priv->statbuf.st_dev), (long)priv->statbuf.st_ino, (long)priv->statbuf.st_nlink, (long)priv->statbuf.st_uid, (long)priv->statbuf.st_gid, (long)MAJOR(priv->statbuf.st_rdev), (long)MINOR(priv->statbuf.st_rdev), (long)priv->statbuf.st_size, (long)priv->statbuf.st_blksize, (long)priv->statbuf.st_blocks); for (i=0; flags[i].flag; i++) if (type == flags[i].flag) break; modetxt[0]=flags[i].letter; mode &= ~flags[i].flag; modecvt(modetxt+1, (mode & 0700) >> 6, mode & 04000, "Ss"); modecvt(modetxt+4, (mode & 0070) >> 3, mode & 02000, "Ss"); modecvt(modetxt+7, (mode & 0007) >> 0, mode & 01000, "Tt"); mode &= ~07777; printf("pid:%li fd:%i mode:%s", (long)proc->pid, priv->fd, modetxt); if (mode) printf("|0x%x\n", mode); printf("\n"); printf("pid:%li fd:%i atime:%s", (long)proc->pid, priv->fd, ctime(&priv->statbuf.st_atime)); printf("pid:%li fd:%i mtime:%s", (long)proc->pid, priv->fd, ctime(&priv->statbuf.st_mtime)); printf("pid:%li fd:%i ctime:%s", (long)proc->pid, priv->fd, ctime(&priv->statbuf.st_ctime)); } proc_fcntl(proc, priv->fd, F_GETFL, 0); if (proc->last_error) warn("fcntl(pid %li, fd %i F_GETFL): %s\n", (long)proc->pid, priv->fd, strerror(proc->last_error)); else { #define ENTRY(flag) {flag, #flag} const struct { int flag; const char *desc; } flags[]={ ENTRY(O_APPEND), ENTRY(O_NONBLOCK), ENTRY(O_SYNC), ENTRY(O_DIRECT), ENTRY(O_DIRECTORY), ENTRY(O_NOFOLLOW), ENTRY(O_LARGEFILE), {0,NULL} }; const char *accmodes[]= { "O_RDONLY", "O_WRONLY", "O_RDWR", "INVALID_ACCMODE" }; int f=proc->retval; int accmode; int i; accmode=f & O_ACCMODE; f &= ~O_ACCMODE; printf("pid:%li fd:%i flags:0x%x=%s", (long)proc->pid, priv->fd, f, accmodes[accmode]); for (i=0; flags[i].flag; i++) { if (f & flags[i].flag) { f &= ~flags[i].flag; printf("|%s", flags[i].desc); } } if (f) printf("|0x%x", f); printf("\n"); } proc_fcntl(proc, priv->fd, F_GETFD, 0); if (proc->last_error) warn("fcntl(pid %li, fd %i, F_GETFD): %s\n", (long)proc->pid, priv->fd, strerror(proc->last_error)); else { const struct { int flag; const char *desc; } flags[]={ ENTRY(FD_CLOEXEC), {0,NULL} }; int f=proc->retval; int i; const char *sep="="; printf("pid:%li fd:%i fdflags:0x%x", (long)proc->pid, priv->fd, f); for (i=0; flags[i].flag; i++) { if (f & flags[i].flag) { f &= ~flags[i].flag; printf("%s%s", sep, flags[i].desc); sep="|"; } } if (f) printf("|0x%x", f); printf("\n"); } proc_lseek(proc, priv->fd, 0, SEEK_CUR); if (proc->last_error) { if (proc->last_error != ESPIPE) warn("lseek(pid %li, fd %i SEEK_CUR): %s\n", (long)proc->pid, priv->fd, strerror(proc->last_error)); } else { printf("pid:%li fd:%i filepos:%li\n", (long)proc->pid, priv->fd, proc->retval); } } out: PROC_END(proc); } int main(int argc, char *argv[]) { pid_t pid; int i, status, nprocs=argc-1; struct process *procs; struct private *privs; if (argc>0) setprogname(argv[0]); if (nprocs<1) die("Usage: %s pid...\n", progname); /* First pass - just check arguments */ for (i=1; i