From 65357c8c46154de4e4eca14075bfe5523bb5fc14 Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Mon, 7 Dec 2020 10:26:01 +0100 Subject: New upstream version 3.0.3 --- OpenFilesScreen.c | 194 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 142 insertions(+), 52 deletions(-) (limited to 'OpenFilesScreen.c') diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c index 3e45bf8..b1137c7 100644 --- a/OpenFilesScreen.c +++ b/OpenFilesScreen.c @@ -1,93 +1,143 @@ /* htop - OpenFilesScreen.c (C) 2005-2006 Hisham H. Muhammad -Released under the GNU GPL, see the COPYING file +Released under the GNU GPLv2, see the COPYING file in the source distribution for its full text. */ -#include "OpenFilesScreen.h" +#include "config.h" // IWYU pragma: keep -#include "CRT.h" -#include "ProcessList.h" -#include "IncSet.h" -#include "StringUtils.h" -#include "FunctionBar.h" +#include "OpenFilesScreen.h" -#include +#include #include -#include -#include -#include #include -#include +#include +#include #include #include +#include "Macros.h" +#include "Panel.h" +#include "ProvideCurses.h" +#include "Vector.h" +#include "XUtils.h" -InfoScreenClass OpenFilesScreen_class = { - .super = { - .extends = Class(Object), - .delete = OpenFilesScreen_delete - }, - .scan = OpenFilesScreen_scan, - .draw = OpenFilesScreen_draw -}; -OpenFilesScreen* OpenFilesScreen_new(Process* process) { +typedef struct OpenFiles_Data_ { + char* data[7]; +} OpenFiles_Data; + +typedef struct OpenFiles_ProcessData_ { + OpenFiles_Data data; + int error; + struct OpenFiles_FileData_* files; +} OpenFiles_ProcessData; + +typedef struct OpenFiles_FileData_ { + OpenFiles_Data data; + struct OpenFiles_FileData_* next; +} OpenFiles_FileData; + +static size_t getIndexForType(char type) { + switch (type) { + case 'f': + return 0; + case 'a': + return 1; + case 'D': + return 2; + case 'i': + return 3; + case 'n': + return 4; + case 's': + return 5; + case 't': + return 6; + } + + /* should never reach here */ + abort(); +} + +static const char* getDataForType(const OpenFiles_Data* data, char type) { + size_t index = getIndexForType(type); + return data->data[index] ? data->data[index] : ""; +} + +OpenFilesScreen* OpenFilesScreen_new(const Process* process) { OpenFilesScreen* this = xMalloc(sizeof(OpenFilesScreen)); Object_setClass(this, Class(OpenFilesScreen)); - if (Process_isThread(process)) + if (Process_isThread(process)) { this->pid = process->tgid; - else + } else { this->pid = process->pid; - return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES-3, " FD TYPE DEVICE SIZE NODE NAME"); + } + return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 3, " FD TYPE MODE DEVICE SIZE NODE NAME"); } void OpenFilesScreen_delete(Object* this) { free(InfoScreen_done((InfoScreen*)this)); } -void OpenFilesScreen_draw(InfoScreen* this) { - InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm); +static void OpenFilesScreen_draw(InfoScreen* this) { + InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, Process_getCommand(this->process)); } static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { - char buffer[1025]; - xSnprintf(buffer, 1024, "%d", pid); OpenFiles_ProcessData* pdata = xCalloc(1, sizeof(OpenFiles_ProcessData)); - OpenFiles_FileData* fdata = NULL; - OpenFiles_Data* item = &(pdata->data); - int fdpair[2]; + + int fdpair[2] = {0, 0}; if (pipe(fdpair) == -1) { pdata->error = 1; return pdata; } + pid_t child = fork(); if (child == -1) { + close(fdpair[1]); + close(fdpair[0]); pdata->error = 1; return pdata; } + if (child == 0) { close(fdpair[0]); dup2(fdpair[1], STDOUT_FILENO); close(fdpair[1]); int fdnull = open("/dev/null", O_WRONLY); - if (fdnull < 0) + if (fdnull < 0) { exit(1); + } + dup2(fdnull, STDERR_FILENO); close(fdnull); + char buffer[32] = {0}; + xSnprintf(buffer, sizeof(buffer), "%d", pid); execlp("lsof", "lsof", "-P", "-p", buffer, "-F", NULL); exit(127); } close(fdpair[1]); + + OpenFiles_Data* item = &(pdata->data); + OpenFiles_FileData* fdata = NULL; + FILE* fd = fdopen(fdpair[0], "r"); + if (!fd) { + pdata->error = 1; + return pdata; + } for (;;) { char* line = String_readLine(fd); if (!line) { break; } + unsigned char cmd = line[0]; - if (cmd == 'f') { + switch (cmd) { + case 'f': /* file descriptor */ + { OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData)); if (fdata == NULL) { pdata->files = nextFile; @@ -96,30 +146,60 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { } fdata = nextFile; item = &(fdata->data); + } /* FALLTHRU */ + case 'a': /* file access mode */ + case 'D': /* file's major/minor device number */ + case 'i': /* file's inode number */ + case 'n': /* file name, comment, Internet address */ + case 's': /* file's size */ + case 't': /* file's type */ + { + size_t index = getIndexForType(cmd); + free(item->data[index]); + item->data[index] = xStrdup(line + 1); + break; + } + case 'c': /* process command name */ + case 'd': /* file's device character code */ + case 'g': /* process group ID */ + case 'G': /* file flags */ + case 'k': /* link count */ + case 'l': /* file's lock status */ + case 'L': /* process login name */ + case 'o': /* file's offset */ + case 'p': /* process ID */ + case 'P': /* protocol name */ + case 'R': /* parent process ID */ + case 'T': /* TCP/TPI information, identified by prefixes */ + case 'u': /* process user ID */ + /* ignore */ + break; } - item->data[cmd] = xStrdup(line + 1); free(line); } fclose(fd); + int wstatus; if (waitpid(child, &wstatus, 0) == -1) { pdata->error = 1; return pdata; } - if (!WIFEXITED(wstatus)) + + if (!WIFEXITED(wstatus)) { pdata->error = 1; - else + } else { pdata->error = WEXITSTATUS(wstatus); + } + return pdata; } -static inline void OpenFiles_Data_clear(OpenFiles_Data* data) { - for (int i = 0; i < 255; i++) - if (data->data[i]) - free(data->data[i]); +static void OpenFiles_Data_clear(OpenFiles_Data* data) { + for (size_t i = 0; i < ARRAYSIZE(data->data); i++) + free(data->data[i]); } -void OpenFilesScreen_scan(InfoScreen* this) { +static void OpenFilesScreen_scan(InfoScreen* this) { Panel* panel = this->display; int idx = Panel_getSelectedIndex(panel); Panel_prune(panel); @@ -131,19 +211,20 @@ void OpenFilesScreen_scan(InfoScreen* this) { } else { OpenFiles_FileData* fdata = pdata->files; while (fdata) { - char** data = fdata->data.data; - int lenN = data['n'] ? strlen(data['n']) : 0; - int sizeEntry = 5 + 7 + 10 + 10 + 10 + lenN + 5 /*spaces*/ + 1 /*null*/; + OpenFiles_Data* data = &fdata->data; + size_t lenN = strlen(getDataForType(data, 'n')); + size_t sizeEntry = 5 + 7 + 4 + 10 + 10 + 10 + lenN + 7 /*spaces*/ + 1 /*null*/; char entry[sizeEntry]; - xSnprintf(entry, sizeEntry, "%5.5s %7.7s %10.10s %10.10s %10.10s %s", - data['f'] ? data['f'] : "", - data['t'] ? data['t'] : "", - data['D'] ? data['D'] : "", - data['s'] ? data['s'] : "", - data['i'] ? data['i'] : "", - data['n'] ? data['n'] : ""); + xSnprintf(entry, sizeof(entry), "%5.5s %-7.7s %-4.4s %-10.10s %10.10s %10.10s %s", + getDataForType(data, 'f'), + getDataForType(data, 't'), + getDataForType(data, 'a'), + getDataForType(data, 'D'), + getDataForType(data, 's'), + getDataForType(data, 'i'), + getDataForType(data, 'n')); InfoScreen_addLine(this, entry); - OpenFiles_Data_clear(&fdata->data); + OpenFiles_Data_clear(data); OpenFiles_FileData* old = fdata; fdata = fdata->next; free(old); @@ -155,3 +236,12 @@ void OpenFilesScreen_scan(InfoScreen* this) { Vector_insertionSort(panel->items); Panel_setSelected(panel, idx); } + +const InfoScreenClass OpenFilesScreen_class = { + .super = { + .extends = Class(Object), + .delete = OpenFilesScreen_delete + }, + .scan = OpenFilesScreen_scan, + .draw = OpenFilesScreen_draw +}; -- cgit v1.2.3