L4Re/departure

fsaccess/op_list_objects.c

298:1afd6b4b1fd6
2022-03-21 Paul Boddie Make sure pipes are closed when listing directories in order to avoid pipe server memory exhaustion.
     1 /*     2  * List filesystem objects using the client library.     3  *     4  * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk>     5  *     6  * This program is free software; you can redistribute it and/or     7  * modify it under the terms of the GNU General Public License as     8  * published by the Free Software Foundation; either version 2 of     9  * the License, or (at your option) any later version.    10  *    11  * This program is distributed in the hope that it will be useful,    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    14  * GNU General Public License for more details.    15  *    16  * You should have received a copy of the GNU General Public License    17  * along with this program; if not, write to the Free Software    18  * Foundation, Inc., 51 Franklin Street, Fifth Floor,    19  * Boston, MA  02110-1301, USA    20  */    21     22 #include <stdio.h>    23 #include <stdlib.h>    24 #include <string.h>    25     26 #include <sys/stat.h>    27 #include <sys/types.h>    28     29 #include <e2access/format.h>    /* get_permission_string */    30 #include <e2access/path.h>    31 #include <fsclient/client.h>    32     33 #include "ops.h"    34     35     36     37 /* Show object details. */    38     39 static void _show_object(const char *basename, struct stat *st)    40 {    41     printf("%s%s   %5d %5d      %6ld %6ld %s\n",    42         S_ISDIR(st->st_mode) ? "d" : "-",    43         get_permission_string(st->st_mode),    44         st->st_uid,    45         st->st_gid,    46         st->st_size,    47         st->st_nlink,    48         basename);    49 }    50     51 /* Show an object in a directory. */    52     53 static int _show_dirent(const char *dirname, struct dirent *dirent)    54 {    55     struct stat st;    56     char path[strlen(dirname) + 1 + strlen(dirent->d_name) + 1];    57     58     sprintf(path, "%s/%s", dirname, dirent->d_name);    59     60     if (client_stat(path, &st))    61         return 1;    62     63     _show_object(dirent->d_name, &st);    64     65     return 0;    66 }    67     68 /* List a directory or file. */    69     70 static int _list_object(const char *path)    71 {    72     struct stat st;    73     file_t *reader;    74     struct dirent *dirent;    75     76     if (client_stat(path, &st))    77         return 1;    78     79     if (S_ISDIR(st.st_mode))    80     {    81         reader = client_opendir(path);    82     83         if (reader == NULL)    84             return 1;    85     86         /* Show the directory entries. */    87     88         while ((dirent = client_readdir(reader)) != NULL)    89         {    90             if (_show_dirent(path, dirent))    91             {    92                 free(dirent);    93                 return 1;    94             }    95     96             free(dirent);    97         }    98     99         client_close(reader);   100     }   101     else   102         _show_object(path_basename(path), &st);   103    104     return 0;   105 }   106    107 /* List objects in the filesystem image. */   108    109 int list_objects(int argc, char *argv[])   110 {   111     int i;   112     char *path;   113    114     for (i = 0; i < argc; i++)   115     {   116         path = argv[i];   117    118         /* Emit each object. */   119    120         puts(path);   121    122         /* List individual files or directories. */   123    124         if (_list_object(path))   125         {   126             fprintf(stderr, "Failed to list object: %s\n", path);   127             return 1;   128         }   129     }   130    131     return 0;   132 }   133    134 /* vim: tabstop=4 expandtab shiftwidth=4   135 */