Currently, sed pre-opens all files, which may cause EMFILE errors
on systems with low ulimit -n.  Change sed to open one file at a time.

Ok, make bloatcheck output seems rather odd...

With this patch, status = EXIT_FAILURE is never set.  I welcome any
comments on this.

-dborca
function                                             old     new   delta
get_next_line                                        169     257     +88
__stat                                                 -      16     +16
__fstat                                               15       -     -15
sed_main                                             744     683     -61
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 1/1 up/down: 104/-76)            Total: 28 bytes
   text    data     bss     dec     hex filename
  16698     906    8304   25908    6534 busybox_old
  16647     898    8304   25849    64f9 busybox_unstripped
Signed-off-by: Daniel Borca <[email protected]>
---
 editors/sed.c |   40 +++++++++++++++++++++-------------------
 1 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/editors/sed.c b/editors/sed.c
index 777f383..570c6a2 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -23,7 +23,7 @@
  * resulting sed_cmd_t structures are appended to a linked list
  * (G.sed_cmd_head/G.sed_cmd_tail).
  *
- * add_input_file() adds a FILE* to the list of input files.  We need to
+ * add_input_file() adds a char* to the list of input files.  We need to
  * know all input sources ahead of time to find the last line for the $ match.
  *
  * process_files() does actual sedding, reading data lines from each input 
FILE*
@@ -140,7 +140,8 @@ struct globals {
 
        /* List of input files */
        int input_file_count, current_input_file;
-       FILE **input_file_list;
+       char **input_file_list;
+       FILE *current_fp;
 
        regmatch_t regmatch[10];
        regex_t *previous_regex_ptr;
@@ -200,8 +201,8 @@ static void sed_free_and_close_stuff(void)
 
        free(G.hold_space);
 
-       while (G.current_input_file < G.input_file_count)
-               fclose(G.input_file_list[G.current_input_file++]);
+       if (G.current_fp)
+               fclose(G.current_fp);
 }
 #else
 void sed_free_and_close_stuff(void);
@@ -939,8 +940,14 @@ static char *get_next_line(char *gets_char, char 
*last_puts_char, char last_gets
        /* will be returned if last line in the file
         * doesn't end with either '\n' or '\0' */
        gc = NO_EOL_CHAR;
-       while (G.current_input_file < G.input_file_count) {
-               FILE *fp = G.input_file_list[G.current_input_file];
+       for (; G.current_input_file < G.input_file_count; 
G.current_input_file++) {
+               FILE *fp = G.current_fp;
+               if (!fp) {
+                       const char *path = 
G.input_file_list[G.current_input_file];
+                       fp = G.current_fp = path ? fopen_or_warn(path, "r") : 
stdin;
+                       if (!fp)
+                               continue;
+               }
                /* Read line up to a newline or NUL byte, inclusive,
                 * return malloc'ed char[]. length of the chunk read
                 * is stored in len. NULL if EOF/error */
@@ -971,8 +978,9 @@ static char *get_next_line(char *gets_char, char 
*last_puts_char, char last_gets
                 * (note: *no* newline after "b bang"!) */
                }
                /* Close this file and advance to next one */
-               fclose(fp);
-               G.current_input_file++;
+               if (G.input_file_list[G.current_input_file])
+                       fclose(fp);
+               G.current_fp = NULL;
        }
        *gets_char = gc;
        return temp;
@@ -1399,7 +1407,7 @@ static void add_cmd_block(char *cmdstr)
        free(sv);
 }
 
-static void add_input_file(FILE *file)
+static void add_input_file(char *file)
 {
        G.input_file_list = xrealloc_vector(G.input_file_list, 2, 
G.input_file_count);
        G.input_file_list[G.input_file_count++] = file;
@@ -1491,27 +1499,21 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
        if (argv[0] == NULL) {
                if (opt & OPT_in_place)
                        bb_error_msg_and_die(bb_msg_requires_arg, "-i");
-               add_input_file(stdin);
+               add_input_file(NULL);
        } else {
                int i;
 
                for (i = 0; argv[i]; i++) {
                        struct stat statbuf;
                        int nonstdoutfd;
-                       FILE *file;
                        sed_cmd_t *sed_cmd;
 
                        if (LONE_DASH(argv[i]) && !(opt & OPT_in_place)) {
-                               add_input_file(stdin);
+                               add_input_file(NULL);
                                process_files();
                                continue;
                        }
-                       file = fopen_or_warn(argv[i], "r");
-                       if (!file) {
-                               status = EXIT_FAILURE;
-                               continue;
-                       }
-                       add_input_file(file);
+                       add_input_file(argv[i]);
                        if (!(opt & OPT_in_place)) {
                                continue;
                        }
@@ -1523,7 +1525,7 @@ int sed_main(int argc UNUSED_PARAM, char **argv)
                        G.nonstdout = xfdopen_for_write(nonstdoutfd);
 
                        /* Set permissions/owner of output file */
-                       fstat(fileno(file), &statbuf);
+                       stat(argv[i], &statbuf);
                        /* chmod'ing AFTER chown would preserve suid/sgid bits,
                         * but GNU sed 4.2.1 does not preserve them either */
                        fchmod(nonstdoutfd, statbuf.st_mode);
-- 
1.7.4.4

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to