switch to fork/exec/dup2 instead of popen

To get rid of the problems from having to escape certain special chars
when using popen to call the find and du system commands, on suggestion
of N-R-K this switches popen with a fork/exec/dup2 based approach.
See https://github.com/jarun/advcpmv/pull/14#issuecomment-1035880454 and
https://github.com/jarun/advcpmv/pull/14#issuecomment-1035892465.
This commit is contained in:
Michael Wehr
2022-02-13 15:50:06 +01:00
parent fb08e1aba6
commit 2532fc3ca3

View File

@@ -1,7 +1,7 @@
diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
--- coreutils-9.0/src/copy.c 2021-09-24 13:31:05.000000000 +0200 --- coreutils-9.0/src/copy.c 2021-09-24 13:31:05.000000000 +0200
+++ coreutils-9.0-patched/src/copy.c 2022-01-11 23:26:31.735507217 +0100 +++ coreutils-9.0-patched/src/copy.c 2022-02-13 13:20:13.643469909 +0100
@@ -129,6 +129,121 @@ @@ -129,6 +129,133 @@
dev_t dev; dev_t dev;
}; };
@@ -14,29 +14,41 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
+ struct stat src_open_sb; + struct stat src_open_sb;
+}; +};
+ +
+char * escape_double_quotes ( char * _cUnescapedString ) +FILE * spawn( const char *cmd, char *const argv[] )
+{ +{
+ char * _cEscapedString; + FILE *ret = NULL;
+ _cEscapedString = (char *) calloc( sizeof(char) * strlen(_cUnescapedString) * 2, sizeof(char) ); + int pfd_read[2];
+ size_t ipos = 0; + pid_t pid;
+ size_t rpos = 0; +
+ for(rpos = 0, ipos = 0; _cUnescapedString[rpos] != '\0'; rpos++, ipos++) + if (cmd == NULL || argv == NULL)
+ { + return ret;
+ if(_cUnescapedString[rpos] == '"') +
+ { + if (pipe(pfd_read) < 0) {
+ _cEscapedString[ipos] = '\\'; + error(0, errno, "pipe: %s", cmd);
+ ipos++; + return ret;
+ } + }
+ if(_cUnescapedString[rpos] == '`') +
+ { + if ((pid = fork()) == 0) {
+ _cEscapedString[ipos] = '\\'; + int err = dup2(pfd_read[1], 1) < 0;
+ ipos++; + close(pfd_read[0]);
+ close(pfd_read[1]);
+
+ if (err)
+ error(EXIT_FAILURE, errno, "dup2: %s", cmd);
+ execvp(cmd, argv);
+ error(EXIT_FAILURE, errno, "exec: %s", cmd);
+ } + }
+ _cEscapedString[ipos] = _cUnescapedString[rpos]; +
+ } + close(pfd_read[1]);
+ ipos++; +
+ _cEscapedString[ipos] = '\0'; + if (pid < 0) {
+ return _cEscapedString; + close(pfd_read[0]);
+ error(0, errno, "fork: %s", cmd);
+ return ret;
+ }
+
+ ret = fdopen(pfd_read[0], "r");
+ return ret;
+} +}
+ +
+void format_time ( char * _cDest, double seconds, bool showall ) +void format_time ( char * _cDest, double seconds, bool showall )
@@ -123,7 +135,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
/* Initial size of the cp.dest_info hash table. */ /* Initial size of the cp.dest_info hash table. */
#define DEST_INFO_INITIAL_CAPACITY 61 #define DEST_INFO_INITIAL_CAPACITY 61
@@ -300,13 +415,28 @@ @@ -300,13 +427,28 @@
static bool static bool
sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size,
size_t hole_size, bool punch_holes, bool allow_reflink, size_t hole_size, bool punch_holes, bool allow_reflink,
@@ -153,7 +165,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
/* If not looking for holes, use copy_file_range if functional, /* If not looking for holes, use copy_file_range if functional,
but don't use if reflink disallowed as that may be implicit. */ but don't use if reflink disallowed as that may be implicit. */
if ((! hole_size) && allow_reflink && functional_copy_file_range ()) if ((! hole_size) && allow_reflink && functional_copy_file_range ())
@@ -362,6 +492,103 @@ @@ -362,6 +504,103 @@
while (max_n_read) while (max_n_read)
{ {
@@ -257,7 +269,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size)); ssize_t n_read = read (src_fd, buf, MIN (max_n_read, buf_size));
if (n_read < 0) if (n_read < 0)
{ {
@@ -446,6 +673,14 @@ @@ -446,6 +685,14 @@
certain files in /proc or /sys with linux kernels. */ certain files in /proc or /sys with linux kernels. */
} }
@@ -272,7 +284,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
/* Ensure a trailing hole is created, so that subsequent /* Ensure a trailing hole is created, so that subsequent
calls of sparse_copy() start at the correct offset. */ calls of sparse_copy() start at the correct offset. */
if (make_hole && ! create_hole (dest_fd, dst_name, punch_holes, psize)) if (make_hole && ! create_hole (dest_fd, dst_name, punch_holes, psize))
@@ -517,8 +752,16 @@ @@ -517,8 +764,16 @@
lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size, lseek_copy (int src_fd, int dest_fd, char *buf, size_t buf_size,
size_t hole_size, off_t ext_start, off_t src_total_size, size_t hole_size, off_t ext_start, off_t src_total_size,
enum Sparse_type sparse_mode, enum Sparse_type sparse_mode,
@@ -290,7 +302,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
{ {
off_t last_ext_start = 0; off_t last_ext_start = 0;
off_t last_ext_len = 0; off_t last_ext_len = 0;
@@ -590,10 +833,26 @@ @@ -590,10 +845,26 @@
is conservative and may miss some holes. */ is conservative and may miss some holes. */
off_t n_read; off_t n_read;
bool read_hole; bool read_hole;
@@ -319,7 +331,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
return false; return false;
dest_pos = ext_start + n_read; dest_pos = ext_start + n_read;
@@ -1374,8 +1633,82 @@ @@ -1374,8 +1645,82 @@
buf_alloc = xmalloc (buf_size + buf_alignment); buf_alloc = xmalloc (buf_size + buf_alignment);
buf = ptr_align (buf_alloc, buf_alignment); buf = ptr_align (buf_alloc, buf_alignment);
@@ -402,7 +414,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
if (! ( if (! (
#ifdef SEEK_HOLE #ifdef SEEK_HOLE
scantype == LSEEK_SCANTYPE scantype == LSEEK_SCANTYPE
@@ -1383,15 +1716,30 @@ @@ -1383,15 +1728,30 @@
scan_inference.ext_start, src_open_sb.st_size, scan_inference.ext_start, src_open_sb.st_size,
make_holes ? x->sparse_mode : SPARSE_NEVER, make_holes ? x->sparse_mode : SPARSE_NEVER,
x->reflink_mode != REFLINK_NEVER, x->reflink_mode != REFLINK_NEVER,
@@ -435,7 +447,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
{ {
return_val = false; return_val = false;
goto close_src_and_dst_desc; goto close_src_and_dst_desc;
@@ -1402,6 +1750,14 @@ @@ -1402,6 +1762,14 @@
return_val = false; return_val = false;
goto close_src_and_dst_desc; goto close_src_and_dst_desc;
} }
@@ -452,7 +464,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
if (x->preserve_timestamps) if (x->preserve_timestamps)
diff -aur coreutils-9.0/src/copy.h coreutils-9.0-patched/src/copy.h diff -aur coreutils-9.0/src/copy.h coreutils-9.0-patched/src/copy.h
--- coreutils-9.0/src/copy.h 2021-09-24 13:31:05.000000000 +0200 --- coreutils-9.0/src/copy.h 2021-09-24 13:31:05.000000000 +0200
+++ coreutils-9.0-patched/src/copy.h 2022-01-11 23:26:31.739507270 +0100 +++ coreutils-9.0-patched/src/copy.h 2022-02-13 13:20:13.643469909 +0100
@@ -236,6 +236,11 @@ @@ -236,6 +236,11 @@
Create destination directories as usual. */ Create destination directories as usual. */
bool symbolic_link; bool symbolic_link;
@@ -470,7 +482,7 @@ diff -aur coreutils-9.0/src/copy.h coreutils-9.0-patched/src/copy.h
mode_t cached_umask (void); mode_t cached_umask (void);
+/* BEGIN progress mod */ +/* BEGIN progress mod */
+char * escape_double_quotes ( char * _cUnescapedString ); +FILE * spawn( const char *cmd, char *const argv[] );
+void format_time ( char * _cDst, double seconds, bool showall ); +void format_time ( char * _cDst, double seconds, bool showall );
+ +
+int file_size_format ( char * _cDst, long _lSize, int _iCounter ); +int file_size_format ( char * _cDst, long _lSize, int _iCounter );
@@ -490,7 +502,7 @@ diff -aur coreutils-9.0/src/copy.h coreutils-9.0-patched/src/copy.h
#endif #endif
diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
--- coreutils-9.0/src/cp.c 2021-09-24 13:31:05.000000000 +0200 --- coreutils-9.0/src/cp.c 2021-09-24 13:31:05.000000000 +0200
+++ coreutils-9.0-patched/src/cp.c 2022-01-11 23:26:31.743507323 +0100 +++ coreutils-9.0-patched/src/cp.c 2022-02-13 13:20:13.647469904 +0100
@@ -131,6 +131,9 @@ @@ -131,6 +131,9 @@
{"symbolic-link", no_argument, NULL, 's'}, {"symbolic-link", no_argument, NULL, 's'},
{"target-directory", required_argument, NULL, 't'}, {"target-directory", required_argument, NULL, 't'},
@@ -515,7 +527,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
-i, --interactive prompt before overwrite (overrides a previous -n\ -i, --interactive prompt before overwrite (overrides a previous -n\
\n\ \n\
option)\n\ option)\n\
@@ -634,6 +644,83 @@ @@ -634,6 +644,84 @@
die (EXIT_FAILURE, 0, _("target %s is not a directory"), die (EXIT_FAILURE, 0, _("target %s is not a directory"),
quoteaf (file[n_files - 1])); quoteaf (file[n_files - 1]));
} }
@@ -549,33 +561,34 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
+ int j; + int j;
+ +
+ /* how many files are we copying */ + /* how many files are we copying */
+ char command[1024];
+ char * _cEscapedString = escape_double_quotes( file[0] );
+ sprintf( command, "find \"%s\" -type f | wc -l", _cEscapedString );
+ free( _cEscapedString );
+ FILE *fp ; + FILE *fp ;
+ char output[1024]; + char output[1024];
+ fp = popen(command,"r"); + char fcmd[] = "find";
+ if ( fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) + fp = spawn(fcmd, (char *[]){ fcmd, file[0], NULL, "-type", "f", NULL });
+ if ( fp == NULL)
+ printf("failed to run find\r"); + printf("failed to run find\r");
+ else + else
+ if ( atoi(output) > n_files ) + {
+ g_iTotalFiles = atoi( output ); + char *line_buf = NULL;
+ size_t line_buf_size = 0;
+ int line_count = 0;
+ ssize_t line_size;
+ line_size = getline(&line_buf, &line_buf_size, fp);
+ while (line_size > 0)
+ {
+ line_count++;
+ line_size = getline(&line_buf, &line_buf_size, fp);
+ }
+ free (line_buf);
+ if ( line_count > n_files )
+ g_iTotalFiles = line_count;
+ }
+ +
+ for (j = 0; j < iFiles; j++) + for (j = 0; j < iFiles; j++)
+ { + {
+ /* call du -s for each file */ + /* call du -s for each file */
+ /* create command */ + char dcmd[] = "du";
+ char command[1024]; + fp = spawn(dcmd, (char *[]){ dcmd, "-s", file[j], NULL });
+ char * _cEscapedString = escape_double_quotes( file[j] );
+ sprintf ( command, "du -s \"%s\"", _cEscapedString );
+ free( _cEscapedString );
+
+ FILE *fp;
+ char output[1024];
+
+ /* run command */
+ fp = popen(command, "r");
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
+ printf("failed to run du\r" ); + printf("failed to run du\r" );
+ } + }
@@ -599,7 +612,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
if (target_directory) if (target_directory)
{ {
@@ -781,6 +868,56 @@ @@ -781,6 +869,56 @@
ok = copy (source, new_dest, 0, x, &unused, NULL); ok = copy (source, new_dest, 0, x, &unused, NULL);
} }
@@ -656,7 +669,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
return ok; return ok;
} }
@@ -816,6 +953,11 @@ @@ -816,6 +954,11 @@
x->recursive = false; x->recursive = false;
x->sparse_mode = SPARSE_AUTO; x->sparse_mode = SPARSE_AUTO;
x->symbolic_link = false; x->symbolic_link = false;
@@ -668,7 +681,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
x->set_mode = false; x->set_mode = false;
x->mode = 0; x->mode = 0;
@@ -954,7 +1096,8 @@ @@ -954,7 +1097,8 @@
selinux_enabled = (0 < is_selinux_enabled ()); selinux_enabled = (0 < is_selinux_enabled ());
cp_option_init (&x); cp_option_init (&x);
@@ -678,7 +691,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
long_opts, NULL)) long_opts, NULL))
!= -1) != -1)
{ {
@@ -1011,6 +1154,12 @@ @@ -1011,6 +1155,12 @@
x.unlink_dest_after_failed_open = true; x.unlink_dest_after_failed_open = true;
break; break;
@@ -691,7 +704,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
case 'H': case 'H':
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS; x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
break; break;
@@ -1171,6 +1320,11 @@ @@ -1171,6 +1321,11 @@
usage (EXIT_FAILURE); usage (EXIT_FAILURE);
} }
@@ -705,7 +718,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
version_control_string) version_control_string)
diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
--- coreutils-9.0/src/mv.c 2021-09-24 13:31:05.000000000 +0200 --- coreutils-9.0/src/mv.c 2021-09-24 13:31:05.000000000 +0200
+++ coreutils-9.0-patched/src/mv.c 2022-01-11 23:26:31.743507323 +0100 +++ coreutils-9.0-patched/src/mv.c 2022-02-13 13:20:13.647469904 +0100
@@ -66,6 +66,9 @@ @@ -66,6 +66,9 @@
{"target-directory", required_argument, NULL, 't'}, {"target-directory", required_argument, NULL, 't'},
{"update", no_argument, NULL, 'u'}, {"update", no_argument, NULL, 'u'},
@@ -716,7 +729,7 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
{GETOPT_HELP_OPTION_DECL}, {GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL}, {GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@@ -170,8 +173,124 @@ @@ -170,8 +173,130 @@
{ {
bool copy_into_self; bool copy_into_self;
bool rename_succeeded; bool rename_succeeded;
@@ -743,30 +756,36 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
+ g_oStartTime = start_time; + g_oStartTime = start_time;
+ +
+ /* how many files are we copying */ + /* how many files are we copying */
+ char command[1024];
+ char output[1024];
+ FILE *fp ; + FILE *fp ;
+ + char output[1024];
+ char * _cEscapedString = escape_double_quotes( (unsigned char *)(size_t)source ); + char fcmd[] = "find";
+ sprintf( command, "find \"%s\" -type f | wc -l", _cEscapedString ); + fp = spawn(fcmd, (char *[]){ fcmd, (unsigned char *)(size_t)source, NULL, "-type", "f", NULL });
+ free( _cEscapedString ); + if ( fp == NULL)
+ fp = popen(command,"r");
+ if ( fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL)
+ printf("failed to run find\r"); + printf("failed to run find\r");
+ else + else
+ g_iTotalFiles = atoi( output ); + {
+ char *line_buf = NULL;
+ size_t line_buf_size = 0;
+ int line_count = 0;
+ ssize_t line_size;
+ line_size = getline(&line_buf, &line_buf_size, fp);
+ while (line_size > 0)
+ {
+ line_count++;
+ line_size = getline(&line_buf, &line_buf_size, fp);
+ }
+ free (line_buf);
+ g_iTotalFiles = line_count;
+ }
+ /* close */
+ pclose(fp);
+ +
+ printf ("calculating total size... \r"); + printf ("calculating total size... \r");
+ fflush (stdout); + fflush (stdout);
+ long iTotalSize = 0; + long iTotalSize = 0;
+ /* call du -s for each file */ + /* call du -s for each file */
+ /* create command */ + char dcmd[] = "du";
+ _cEscapedString = escape_double_quotes( (unsigned char *)(size_t)source ); + fp = spawn(dcmd, (char *[]){ dcmd, "-s", (unsigned char *)(size_t)source, NULL });
+ sprintf ( command, "du -s \"%s\"", _cEscapedString );
+ free( _cEscapedString );
+
+ /* run command */
+ fp = popen(command, "r");
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) { + if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
+ printf("failed to run du\r" ); + printf("failed to run du\r" );
+ } + }
@@ -841,7 +860,7 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
if (ok) if (ok)
{ {
char const *dir_to_remove; char const *dir_to_remove;
@@ -306,6 +425,11 @@ @@ -306,6 +431,11 @@
\n\ \n\
-b like --backup but does not accept an argument\n\ -b like --backup but does not accept an argument\n\
-f, --force do not prompt before overwriting\n\ -f, --force do not prompt before overwriting\n\
@@ -853,7 +872,7 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
-i, --interactive prompt before overwrite\n\ -i, --interactive prompt before overwrite\n\
-n, --no-clobber do not overwrite an existing file\n\ -n, --no-clobber do not overwrite an existing file\n\
If you specify more than one of -i, -f, -n, only the final one takes effect.\n\ If you specify more than one of -i, -f, -n, only the final one takes effect.\n\
@@ -361,7 +485,8 @@ @@ -361,7 +491,8 @@
/* Try to disable the ability to unlink a directory. */ /* Try to disable the ability to unlink a directory. */
priv_set_remove_linkdir (); priv_set_remove_linkdir ();
@@ -863,7 +882,7 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
!= -1) != -1)
{ {
switch (c) switch (c)
@@ -407,6 +532,11 @@ @@ -407,6 +538,11 @@
case 'v': case 'v':
x.verbose = true; x.verbose = true;
break; break;