Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.busybox.net/busybox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2022-01-04 21:42:36 +0300
committerDenys Vlasenko <vda.linux@googlemail.com>2022-01-04 21:42:36 +0300
commit286b33721d5f6afd615f752ea83bbd72658c6bb9 (patch)
tree93c9efb8b08a9674eca57c5ce1f30bdc6f54f9b3 /editors
parented2af2e82dbcfccb7392e9fbc3f837de1594c103 (diff)
sed: correctly handle 'w FILE' commands writing to the same file
function old new delta sed_xfopen_w - 84 +84 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors')
-rw-r--r--editors/sed.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/editors/sed.c b/editors/sed.c
index e8c82ac63..48b0dbf67 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -97,6 +97,12 @@ enum {
OPT_in_place = 1 << 0,
};
+struct sed_FILE {
+ struct sed_FILE *next; /* Next (linked list, NULL terminated) */
+ const char *fname;
+ FILE *fp;
+};
+
/* Each sed command turns into one of these structures. */
typedef struct sed_cmd_s {
/* Ordered by alignment requirements: currently 36 bytes on x86 */
@@ -151,6 +157,11 @@ struct globals {
/* linked list of append lines */
llist_t *append_head;
+ /* linked list of FILEs opened for 'w' and s///w'.
+ * Needed to handle duplicate fnames: sed '/a/w F;/b/w F'
+ */
+ struct sed_FILE *FILE_head;
+
char *add_cmd_line;
struct pipeline {
@@ -211,6 +222,22 @@ static void sed_free_and_close_stuff(void)
void sed_free_and_close_stuff(void);
#endif
+static FILE *sed_xfopen_w(const char *fname)
+{
+ struct sed_FILE **pp = &G.FILE_head;
+ struct sed_FILE *cur;
+ while ((cur = *pp) != NULL) {
+ if (strcmp(cur->fname, fname) == 0)
+ return cur->fp;
+ pp = &cur->next;
+ }
+ *pp = cur = xzalloc(sizeof(*cur));
+ /*cur->next = NULL; - already is */
+ cur->fname = xstrdup(fname);
+ cur->fp = xfopen_for_write(fname);
+ return cur->fp;
+}
+
/* If something bad happens during -i operation, delete temp file */
static void cleanup_outname(void)
@@ -446,7 +473,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr)
{
char *fname;
idx += parse_file_cmd(/*sed_cmd,*/ substr+idx+1, &fname);
- sed_cmd->sw_file = xfopen_for_write(fname);
+ sed_cmd->sw_file = sed_xfopen_w(fname);
sed_cmd->sw_last_char = '\n';
free(fname);
break;
@@ -561,7 +588,7 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr)
}
cmdstr += parse_file_cmd(/*sed_cmd,*/ cmdstr, &sed_cmd->string);
if (sed_cmd->cmd == 'w') {
- sed_cmd->sw_file = xfopen_for_write(sed_cmd->string);
+ sed_cmd->sw_file = sed_xfopen_w(sed_cmd->string);
sed_cmd->sw_last_char = '\n';
}
}