| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 1 | /* |
| 2 | htop - OpenFilesScreen.c |
| 3 | (C) 2005-2006 Hisham H. Muhammad |
| Daniel Lange | 94ad111 | 2021-09-22 11:33:00 +0200 | [diff] [blame] | 4 | Released under the GNU GPLv2+, see the COPYING file |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 5 | in the source distribution for its full text. |
| 6 | */ |
| 7 | |
| Benny Baumann | 0f52629 | 2020-09-19 13:55:23 +0200 | [diff] [blame] | 8 | #include "config.h" // IWYU pragma: keep |
| 9 | |
| Hisham Muhammad | 84281bd | 2011-12-26 21:35:57 +0000 | [diff] [blame] | 10 | #include "OpenFilesScreen.h" |
| 11 | |
| Tobias Stoeckmann | d0d9f20 | 2022-01-11 22:25:29 +0100 | [diff] [blame] | 12 | #include <errno.h> |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 13 | #include <fcntl.h> |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 14 | #include <inttypes.h> |
| Benny Baumann | e56089e | 2023-11-28 15:15:03 +0100 | [diff] [blame] | 15 | #include <stdbool.h> |
| Benny Baumann | 0f52629 | 2020-09-19 13:55:23 +0200 | [diff] [blame] | 16 | #include <stdio.h> |
| 17 | #include <stdlib.h> |
| Benny Baumann | 0f52629 | 2020-09-19 13:55:23 +0200 | [diff] [blame] | 18 | #include <unistd.h> |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 19 | #include <sys/types.h> |
| 20 | #include <sys/wait.h> |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 21 | #include <sys/stat.h> |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 22 | |
| Benny Baumann | 0f52629 | 2020-09-19 13:55:23 +0200 | [diff] [blame] | 23 | #include "Macros.h" |
| 24 | #include "Panel.h" |
| 25 | #include "ProvideCurses.h" |
| 26 | #include "Vector.h" |
| 27 | #include "XUtils.h" |
| 28 | |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 29 | |
| Benny Baumann | c845b79 | 2023-12-29 14:01:10 +0100 | [diff] [blame] | 30 | // cf. getIndexForType; must be larger than the maximum value returned. |
| 31 | #define LSOF_DATACOL_COUNT 8 |
| 32 | |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 33 | typedef struct OpenFiles_Data_ { |
| Benny Baumann | c845b79 | 2023-12-29 14:01:10 +0100 | [diff] [blame] | 34 | char* data[LSOF_DATACOL_COUNT]; |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 35 | } OpenFiles_Data; |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 36 | |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 37 | typedef struct OpenFiles_ProcessData_ { |
| 38 | OpenFiles_Data data; |
| 39 | int error; |
| Benny Baumann | c845b79 | 2023-12-29 14:01:10 +0100 | [diff] [blame] | 40 | int cols[LSOF_DATACOL_COUNT]; |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 41 | struct OpenFiles_FileData_* files; |
| 42 | } OpenFiles_ProcessData; |
| 43 | |
| 44 | typedef struct OpenFiles_FileData_ { |
| 45 | OpenFiles_Data data; |
| 46 | struct OpenFiles_FileData_* next; |
| 47 | } OpenFiles_FileData; |
| 48 | |
| 49 | static size_t getIndexForType(char type) { |
| 50 | switch (type) { |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 51 | case 'f': |
| 52 | return 0; |
| 53 | case 'a': |
| 54 | return 1; |
| 55 | case 'D': |
| 56 | return 2; |
| 57 | case 'i': |
| 58 | return 3; |
| 59 | case 'n': |
| 60 | return 4; |
| 61 | case 's': |
| 62 | return 5; |
| 63 | case 't': |
| 64 | return 6; |
| 65 | case 'o': |
| 66 | return 7; |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | /* should never reach here */ |
| 70 | abort(); |
| 71 | } |
| 72 | |
| 73 | static const char* getDataForType(const OpenFiles_Data* data, char type) { |
| 74 | size_t index = getIndexForType(type); |
| 75 | return data->data[index] ? data->data[index] : ""; |
| 76 | } |
| 77 | |
| 78 | OpenFilesScreen* OpenFilesScreen_new(const Process* process) { |
| Nathan Scott | 0f751e9 | 2023-08-22 16:11:05 +1000 | [diff] [blame] | 79 | OpenFilesScreen* this = xCalloc(1, sizeof(OpenFilesScreen)); |
| Hisham Muhammad | 466d4da | 2016-01-12 06:00:58 -0200 | [diff] [blame] | 80 | Object_setClass(this, Class(OpenFilesScreen)); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 81 | if (Process_isThread(process)) { |
| Nathan Scott | 0f751e9 | 2023-08-22 16:11:05 +1000 | [diff] [blame] | 82 | this->pid = Process_getThreadGroup(process); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 83 | } else { |
| Nathan Scott | 0f751e9 | 2023-08-22 16:11:05 +1000 | [diff] [blame] | 84 | this->pid = Process_getPid(process); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 85 | } |
| Peter VandeHaar | 27a1883 | 2021-09-03 00:16:43 -0400 | [diff] [blame] | 86 | return (OpenFilesScreen*) InfoScreen_init(&this->super, process, NULL, LINES - 2, " FD TYPE MODE DEVICE SIZE OFFSET NODE NAME"); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 87 | } |
| 88 | |
| Hisham Muhammad | 466d4da | 2016-01-12 06:00:58 -0200 | [diff] [blame] | 89 | void OpenFilesScreen_delete(Object* this) { |
| 90 | free(InfoScreen_done((InfoScreen*)this)); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 91 | } |
| 92 | |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 93 | static void OpenFilesScreen_draw(InfoScreen* this) { |
| Narendran Gopalakrishnan | 09fe94d | 2020-10-17 16:24:45 +0530 | [diff] [blame] | 94 | InfoScreen_drawTitled(this, "Snapshot of files open in process %d - %s", ((OpenFilesScreen*)this)->pid, Process_getCommand(this->process)); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 95 | } |
| 96 | |
| Hisham Muhammad | 7d7118b | 2011-03-22 22:09:42 +0000 | [diff] [blame] | 97 | static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) { |
| Hisham | b54d2dd | 2016-02-02 15:53:02 +0100 | [diff] [blame] | 98 | OpenFiles_ProcessData* pdata = xCalloc(1, sizeof(OpenFiles_ProcessData)); |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 99 | pdata->cols[getIndexForType('s')] = 8; |
| 100 | pdata->cols[getIndexForType('o')] = 8; |
| 101 | pdata->cols[getIndexForType('i')] = 8; |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 102 | |
| 103 | int fdpair[2] = {0, 0}; |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 104 | if (pipe(fdpair) == -1) { |
| 105 | pdata->error = 1; |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 106 | return pdata; |
| Hisham Muhammad | 7dcd2be | 2009-10-16 20:15:01 +0000 | [diff] [blame] | 107 | } |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 108 | |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 109 | pid_t child = fork(); |
| 110 | if (child == -1) { |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 111 | close(fdpair[1]); |
| 112 | close(fdpair[0]); |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 113 | pdata->error = 1; |
| 114 | return pdata; |
| 115 | } |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 116 | |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 117 | if (child == 0) { |
| 118 | close(fdpair[0]); |
| 119 | dup2(fdpair[1], STDOUT_FILENO); |
| 120 | close(fdpair[1]); |
| 121 | int fdnull = open("/dev/null", O_WRONLY); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 122 | if (fdnull < 0) { |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 123 | exit(1); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 124 | } |
| 125 | |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 126 | dup2(fdnull, STDERR_FILENO); |
| 127 | close(fdnull); |
| Benny Baumann | 6921000 | 2020-09-15 22:02:57 +0200 | [diff] [blame] | 128 | char buffer[32] = {0}; |
| 129 | xSnprintf(buffer, sizeof(buffer), "%d", pid); |
| Explorer09 | 4409170 | 2022-05-17 19:15:37 +0800 | [diff] [blame] | 130 | // Use of NULL in variadic functions must have a pointer cast. |
| 131 | // The NULL constant is not required by standard to have a pointer type. |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 132 | execlp("lsof", "lsof", "-P", "-o", "-p", buffer, "-F", (char*)NULL); |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 133 | exit(127); |
| 134 | } |
| 135 | close(fdpair[1]); |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 136 | |
| 137 | OpenFiles_Data* item = &(pdata->data); |
| 138 | OpenFiles_FileData* fdata = NULL; |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 139 | bool lsofIncludesFileSize = false; |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 140 | |
| Explorer09 | a46b3f0 | 2024-04-17 16:45:46 +0800 | [diff] [blame] | 141 | FILE* fp = fdopen(fdpair[0], "r"); |
| 142 | if (!fp) { |
| Christian Göttsche | 1efddaf | 2020-09-15 19:56:52 +0200 | [diff] [blame] | 143 | pdata->error = 1; |
| 144 | return pdata; |
| 145 | } |
| Hisham Muhammad | 0fa0332 | 2016-06-19 18:55:35 -0300 | [diff] [blame] | 146 | for (;;) { |
| Explorer09 | a46b3f0 | 2024-04-17 16:45:46 +0800 | [diff] [blame] | 147 | char* line = String_readLine(fp); |
| Hisham Muhammad | 0fa0332 | 2016-06-19 18:55:35 -0300 | [diff] [blame] | 148 | if (!line) { |
| Hisham Muhammad | 282f16c | 2010-03-03 21:10:51 +0000 | [diff] [blame] | 149 | break; |
| 150 | } |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 151 | |
| Hisham Muhammad | 0fa0332 | 2016-06-19 18:55:35 -0300 | [diff] [blame] | 152 | unsigned char cmd = line[0]; |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 153 | switch (cmd) { |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 154 | case 'f': /* file descriptor */ |
| 155 | { |
| 156 | OpenFiles_FileData* nextFile = xCalloc(1, sizeof(OpenFiles_FileData)); |
| 157 | if (fdata == NULL) { |
| 158 | pdata->files = nextFile; |
| 159 | } else { |
| 160 | fdata->next = nextFile; |
| 161 | } |
| 162 | fdata = nextFile; |
| 163 | item = &(fdata->data); |
| 164 | } /* FALLTHRU */ |
| 165 | case 'a': /* file access mode */ |
| 166 | case 'D': /* file's major/minor device number */ |
| 167 | case 'i': /* file's inode number */ |
| 168 | case 'n': /* file name, comment, Internet address */ |
| 169 | case 's': /* file's size */ |
| 170 | case 't': /* file's type */ |
| 171 | { |
| 172 | size_t index = getIndexForType(cmd); |
| Peter VandeHaar | 5beef3e | 2021-09-03 00:18:30 -0400 | [diff] [blame] | 173 | free_and_xStrdup(&item->data[index], line + 1); |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 174 | size_t dlen = strlen(item->data[index]); |
| 175 | if (dlen > (size_t)pdata->cols[index]) { |
| 176 | pdata->cols[index] = (int)CLAMP(dlen, 0, INT16_MAX); |
| 177 | } |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 178 | break; |
| Peter VandeHaar | 5beef3e | 2021-09-03 00:18:30 -0400 | [diff] [blame] | 179 | } |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 180 | case 'o': /* file's offset */ |
| 181 | { |
| 182 | size_t index = getIndexForType(cmd); |
| 183 | if (String_startsWith(line + 1, "0t")) { |
| 184 | free_and_xStrdup(&item->data[index], line + 3); |
| 185 | } else { |
| 186 | free_and_xStrdup(&item->data[index], line + 1); |
| 187 | } |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 188 | size_t dlen = strlen(item->data[index]); |
| 189 | if (dlen > (size_t)pdata->cols[index]) { |
| 190 | pdata->cols[index] = (int)CLAMP(dlen, 0, INT16_MAX); |
| 191 | } |
| Benny Baumann | 6aa9ef2 | 2023-11-23 12:22:02 +0100 | [diff] [blame] | 192 | break; |
| 193 | } |
| 194 | case 'c': /* process command name */ |
| 195 | case 'd': /* file's device character code */ |
| 196 | case 'g': /* process group ID */ |
| 197 | case 'G': /* file flags */ |
| 198 | case 'k': /* link count */ |
| 199 | case 'l': /* file's lock status */ |
| 200 | case 'L': /* process login name */ |
| 201 | case 'p': /* process ID */ |
| 202 | case 'P': /* protocol name */ |
| 203 | case 'R': /* parent process ID */ |
| 204 | case 'T': /* TCP/TPI information, identified by prefixes */ |
| 205 | case 'u': /* process user ID */ |
| 206 | /* ignore */ |
| 207 | break; |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 208 | } |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 209 | |
| 210 | if (cmd == 's') |
| 211 | lsofIncludesFileSize = true; |
| 212 | |
| Hisham Muhammad | 0fa0332 | 2016-06-19 18:55:35 -0300 | [diff] [blame] | 213 | free(line); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 214 | } |
| Explorer09 | a46b3f0 | 2024-04-17 16:45:46 +0800 | [diff] [blame] | 215 | fclose(fp); |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 216 | |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 217 | int wstatus; |
| Tobias Stoeckmann | d0d9f20 | 2022-01-11 22:25:29 +0100 | [diff] [blame] | 218 | while (waitpid(child, &wstatus, 0) == -1) |
| 219 | if (errno != EINTR) { |
| 220 | pdata->error = 1; |
| 221 | return pdata; |
| 222 | } |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 223 | |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 224 | if (!WIFEXITED(wstatus)) { |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 225 | pdata->error = 1; |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 226 | } else { |
| wangqr | a042cfe | 2018-03-16 22:39:03 +0800 | [diff] [blame] | 227 | pdata->error = WEXITSTATUS(wstatus); |
| Benny Baumann | 4586951 | 2020-11-01 01:09:51 +0100 | [diff] [blame] | 228 | } |
| Benny Baumann | 443a943 | 2020-09-15 22:07:52 +0200 | [diff] [blame] | 229 | |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 230 | /* We got all information we need; no post-processing needed */ |
| 231 | if (lsofIncludesFileSize) |
| 232 | return pdata; |
| 233 | |
| 234 | /* On linux, `lsof -o -F` omits SIZE, so add it back. */ |
| 235 | /* On macOS, `lsof -o -F` includes SIZE, so this block isn't needed. If no open files have a filesize, this will still run, unfortunately. */ |
| 236 | size_t fileSizeIndex = getIndexForType('s'); |
| 237 | for (fdata = pdata->files; fdata != NULL; fdata = fdata->next) { |
| 238 | item = &fdata->data; |
| 239 | const char* filename = getDataForType(item, 'n'); |
| 240 | |
| Explorer09 | 7017b86 | 2024-04-17 16:50:34 +0800 | [diff] [blame] | 241 | struct stat sb; |
| 242 | if (stat(filename, &sb) == 0) { |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 243 | char fileSizeBuf[21]; /* 20 (long long) + 1 (NULL) */ |
| Explorer09 | 7017b86 | 2024-04-17 16:50:34 +0800 | [diff] [blame] | 244 | xSnprintf(fileSizeBuf, sizeof(fileSizeBuf), "%"PRIu64, (uint64_t)sb.st_size); /* sb.st_size is long long on macOS, long on linux */ |
| Peter VandeHaar | ddfacb8 | 2021-09-03 00:20:15 -0400 | [diff] [blame] | 245 | free_and_xStrdup(&item->data[fileSizeIndex], fileSizeBuf); |
| 246 | } |
| 247 | } |
| 248 | |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 249 | return pdata; |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 250 | } |
| 251 | |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 252 | static void OpenFiles_Data_clear(OpenFiles_Data* data) { |
| 253 | for (size_t i = 0; i < ARRAYSIZE(data->data); i++) |
| 254 | free(data->data[i]); |
| Hisham Muhammad | 1de8762 | 2014-04-22 18:45:47 -0300 | [diff] [blame] | 255 | } |
| 256 | |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 257 | static void OpenFilesScreen_scan(InfoScreen* super) { |
| 258 | Panel* panel = super->display; |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 259 | int idx = Panel_getSelectedIndex(panel); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 260 | Panel_prune(panel); |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 261 | OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(((OpenFilesScreen*)super)->pid); |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 262 | if (pdata->error == 127) { |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 263 | InfoScreen_addLine(super, "Could not execute 'lsof'. Please make sure it is available in your $PATH."); |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 264 | } else if (pdata->error == 1) { |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 265 | InfoScreen_addLine(super, "Failed listing open files."); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 266 | } else { |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 267 | char hdrbuf[128] = {0}; |
| 268 | snprintf(hdrbuf, sizeof(hdrbuf), "%5.5s %-7.7s %-4.4s %6.6s %*s %*s %*s %s", |
| 269 | "FD", "TYPE", "MODE", "DEVICE", |
| 270 | pdata->cols[getIndexForType('s')], "SIZE", |
| 271 | pdata->cols[getIndexForType('o')], "OFFSET", |
| 272 | pdata->cols[getIndexForType('i')], "NODE", |
| 273 | "NAME" |
| 274 | ); |
| 275 | Panel_setHeader(panel, hdrbuf); |
| 276 | |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 277 | OpenFiles_FileData* fdata = pdata->files; |
| 278 | while (fdata) { |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 279 | OpenFiles_Data* data = &fdata->data; |
| Benny Baumann | 958057f | 2023-07-28 12:56:00 +0200 | [diff] [blame] | 280 | char* entry = NULL; |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 281 | xAsprintf(&entry, "%5.5s %-7.7s %-4.4s %6.6s %*s %*s %*s %s", |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 282 | getDataForType(data, 'f'), |
| 283 | getDataForType(data, 't'), |
| 284 | getDataForType(data, 'a'), |
| 285 | getDataForType(data, 'D'), |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 286 | pdata->cols[getIndexForType('s')], |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 287 | getDataForType(data, 's'), |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 288 | pdata->cols[getIndexForType('o')], |
| Peter VandeHaar | 27a1883 | 2021-09-03 00:16:43 -0400 | [diff] [blame] | 289 | getDataForType(data, 'o'), |
| наб | 4bcea76 | 2023-12-23 22:46:44 +0100 | [diff] [blame] | 290 | pdata->cols[getIndexForType('i')], |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 291 | getDataForType(data, 'i'), |
| 292 | getDataForType(data, 'n')); |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 293 | InfoScreen_addLine(super, entry); |
| Benny Baumann | 958057f | 2023-07-28 12:56:00 +0200 | [diff] [blame] | 294 | free(entry); |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 295 | OpenFiles_Data_clear(data); |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 296 | OpenFiles_FileData* old = fdata; |
| 297 | fdata = fdata->next; |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 298 | free(old); |
| 299 | } |
| Hisham Muhammad | 1de8762 | 2014-04-22 18:45:47 -0300 | [diff] [blame] | 300 | OpenFiles_Data_clear(&pdata->data); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 301 | } |
| Hisham Muhammad | 2a73405 | 2012-11-10 00:31:37 +0000 | [diff] [blame] | 302 | free(pdata); |
| Benny Baumann | 338baa4 | 2023-12-29 12:11:24 +0100 | [diff] [blame] | 303 | Vector_insertionSort(super->lines); |
| Hisham Muhammad | 7ca1081 | 2011-11-18 06:08:56 +0000 | [diff] [blame] | 304 | Vector_insertionSort(panel->items); |
| Hisham Muhammad | 02a30bf | 2010-02-25 01:43:18 +0000 | [diff] [blame] | 305 | Panel_setSelected(panel, idx); |
| Hisham Muhammad | 7ee2646 | 2009-06-02 19:28:19 +0000 | [diff] [blame] | 306 | } |
| Christian Göttsche | f8b9ced | 2020-10-07 19:02:23 +0200 | [diff] [blame] | 307 | |
| 308 | const InfoScreenClass OpenFilesScreen_class = { |
| 309 | .super = { |
| 310 | .extends = Class(Object), |
| 311 | .delete = OpenFilesScreen_delete |
| 312 | }, |
| 313 | .scan = OpenFilesScreen_scan, |
| 314 | .draw = OpenFilesScreen_draw |
| 315 | }; |