From f8b9ced93f258f1b4b6071f08a54c6f0f9233b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Wed, 7 Oct 2020 19:02:23 +0200 Subject: [PATCH] OpenFilesScreen update - Remove local types and function from header file - Reduce OpenFiles_Data to neccessary size - Print file access mode (r/w/u) - Fix memory leak on consecutive items without an intermediate file item: ==15257==ERROR: LeakSanitizer: detected memory leaks Direct leak of 120 byte(s) in 12 object(s) allocated from: #0 0x48c864 in strdup (htop/htop+0x48c864) #1 0x542f68 in xStrdup htop/XAlloc.c:71:17 #2 0x50e225 in OpenFilesScreen_getProcessData htop/OpenFilesScreen.c:112:25 #3 0x50cd17 in OpenFilesScreen_scan htop/OpenFilesScreen.c:141:35 #4 0x4fd3eb in InfoScreen_run htop/InfoScreen.c:81:35 #5 0x4d58bb in actionLsof htop/Action.c:361:4 #6 0x501766 in MainPanel_eventHandler htop/MainPanel.c:80:19 #7 0x5289fa in ScreenManager_run htop/ScreenManager.c:227:19 #8 0x4f748e in main htop/htop.c:300:4 #9 0x7ff73e0d8cc9 in __libc_start_main csu/../csu/libc-start.c:308:16 SUMMARY: AddressSanitizer: 120 byte(s) leaked in 12 allocation(s). --- OpenFilesScreen.c | 129 +++++++++++++++++++++++++++++++++++----------- OpenFilesScreen.h | 21 +------- 2 files changed, 101 insertions(+), 49 deletions(-) diff --git a/OpenFilesScreen.c b/OpenFilesScreen.c index 7c0acebe..1973cc45 100644 --- a/OpenFilesScreen.c +++ b/OpenFilesScreen.c @@ -24,30 +24,63 @@ in the source distribution for its full text. #include -const InfoScreenClass OpenFilesScreen_class = { - .super = { - .extends = Class(Object), - .delete = OpenFilesScreen_delete - }, - .scan = OpenFilesScreen_scan, - .draw = OpenFilesScreen_draw -}; +typedef struct OpenFiles_Data_ { + char* data[7]; +} OpenFiles_Data; -OpenFilesScreen* OpenFilesScreen_new(Process* process) { +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)) this->pid = process->tgid; 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) { +static void OpenFilesScreen_draw(InfoScreen* this) { InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, this->process->comm); } @@ -99,7 +132,9 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { } 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; @@ -108,8 +143,35 @@ 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); @@ -128,13 +190,12 @@ static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { 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); @@ -146,19 +207,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); @@ -170,3 +232,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 +}; diff --git a/OpenFilesScreen.h b/OpenFilesScreen.h index 9a12dcd0..04a8e395 100644 --- a/OpenFilesScreen.h +++ b/OpenFilesScreen.h @@ -9,21 +9,6 @@ in the source distribution for its full text. #include "InfoScreen.h" -typedef struct OpenFiles_Data_ { - char* data[256]; -} 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; - typedef struct OpenFilesScreen_ { InfoScreen super; pid_t pid; @@ -31,12 +16,8 @@ typedef struct OpenFilesScreen_ { extern const InfoScreenClass OpenFilesScreen_class; -OpenFilesScreen* OpenFilesScreen_new(Process* process); +OpenFilesScreen* OpenFilesScreen_new(const Process* process); void OpenFilesScreen_delete(Object* this); -void OpenFilesScreen_draw(InfoScreen* this); - -void OpenFilesScreen_scan(InfoScreen* this); - #endif