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
--- 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
@@ -129,6 +129,121 @@
+++ coreutils-9.0-patched/src/copy.c 2022-02-13 13:20:13.643469909 +0100
@@ -129,6 +129,133 @@
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;
+};
+
+char * escape_double_quotes ( char * _cUnescapedString )
+FILE * spawn( const char *cmd, char *const argv[] )
+{
+ char * _cEscapedString;
+ _cEscapedString = (char *) calloc( sizeof(char) * strlen(_cUnescapedString) * 2, sizeof(char) );
+ size_t ipos = 0;
+ size_t rpos = 0;
+ for(rpos = 0, ipos = 0; _cUnescapedString[rpos] != '\0'; rpos++, ipos++)
+ {
+ if(_cUnescapedString[rpos] == '"')
+ {
+ _cEscapedString[ipos] = '\\';
+ ipos++;
+ FILE *ret = NULL;
+ int pfd_read[2];
+ pid_t pid;
+
+ if (cmd == NULL || argv == NULL)
+ return ret;
+
+ if (pipe(pfd_read) < 0) {
+ error(0, errno, "pipe: %s", cmd);
+ return ret;
+ }
+ if(_cUnescapedString[rpos] == '`')
+ {
+ _cEscapedString[ipos] = '\\';
+ ipos++;
+
+ if ((pid = fork()) == 0) {
+ int err = dup2(pfd_read[1], 1) < 0;
+ 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]);
+
+ if (pid < 0) {
+ close(pfd_read[0]);
+ error(0, errno, "fork: %s", cmd);
+ return ret;
+ }
+ ipos++;
+ _cEscapedString[ipos] = '\0';
+ return _cEscapedString;
+
+ ret = fdopen(pfd_read[0], "r");
+ return ret;
+}
+
+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. */
#define DEST_INFO_INITIAL_CAPACITY 61
@@ -300,13 +415,28 @@
@@ -300,13 +427,28 @@
static bool
sparse_copy (int src_fd, int dest_fd, char *buf, size_t buf_size,
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,
but don't use if reflink disallowed as that may be implicit. */
if ((! hole_size) && allow_reflink && functional_copy_file_range ())
@@ -362,6 +492,103 @@
@@ -362,6 +504,103 @@
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));
if (n_read < 0)
{
@@ -446,6 +673,14 @@
@@ -446,6 +685,14 @@
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
calls of sparse_copy() start at the correct offset. */
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,
size_t hole_size, off_t ext_start, off_t src_total_size,
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_len = 0;
@@ -590,10 +833,26 @@
@@ -590,10 +845,26 @@
is conservative and may miss some holes. */
off_t n_read;
bool read_hole;
@@ -319,7 +331,7 @@ diff -aur coreutils-9.0/src/copy.c coreutils-9.0-patched/src/copy.c
return false;
dest_pos = ext_start + n_read;
@@ -1374,8 +1633,82 @@
@@ -1374,8 +1645,82 @@
buf_alloc = xmalloc (buf_size + 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 (! (
#ifdef SEEK_HOLE
scantype == LSEEK_SCANTYPE
@@ -1383,15 +1716,30 @@
@@ -1383,15 +1728,30 @@
scan_inference.ext_start, src_open_sb.st_size,
make_holes ? x->sparse_mode : SPARSE_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;
goto close_src_and_dst_desc;
@@ -1402,6 +1750,14 @@
@@ -1402,6 +1762,14 @@
return_val = false;
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)
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-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 @@
Create destination directories as usual. */
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);
+/* 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 );
+
+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
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-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 @@
{"symbolic-link", no_argument, NULL, 's'},
{"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\
\n\
option)\n\
@@ -634,6 +644,83 @@
@@ -634,6 +644,84 @@
die (EXIT_FAILURE, 0, _("target %s is not a directory"),
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;
+
+ /* 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 ;
+ char output[1024];
+ fp = popen(command,"r");
+ if ( fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL)
+ char fcmd[] = "find";
+ fp = spawn(fcmd, (char *[]){ fcmd, file[0], NULL, "-type", "f", NULL });
+ if ( fp == NULL)
+ printf("failed to run find\r");
+ 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++)
+ {
+ /* call du -s for each file */
+ /* create command */
+ char command[1024];
+ 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");
+ char dcmd[] = "du";
+ fp = spawn(dcmd, (char *[]){ dcmd, "-s", file[j], NULL });
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
+ 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)
{
@@ -781,6 +868,56 @@
@@ -781,6 +869,56 @@
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;
}
@@ -816,6 +953,11 @@
@@ -816,6 +954,11 @@
x->recursive = false;
x->sparse_mode = SPARSE_AUTO;
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->mode = 0;
@@ -954,7 +1096,8 @@
@@ -954,7 +1097,8 @@
selinux_enabled = (0 < is_selinux_enabled ());
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))
!= -1)
{
@@ -1011,6 +1154,12 @@
@@ -1011,6 +1155,12 @@
x.unlink_dest_after_failed_open = true;
break;
@@ -691,7 +704,7 @@ diff -aur coreutils-9.0/src/cp.c coreutils-9.0-patched/src/cp.c
case 'H':
x.dereference = DEREF_COMMAND_LINE_ARGUMENTS;
break;
@@ -1171,6 +1320,11 @@
@@ -1171,6 +1321,11 @@
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)
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-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 @@
{"target-directory", required_argument, NULL, 't'},
{"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_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -170,8 +173,124 @@
@@ -170,8 +173,130 @@
{
bool copy_into_self;
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;
+
+ /* how many files are we copying */
+ char command[1024];
+ char output[1024];
+ FILE *fp ;
+
+ char * _cEscapedString = escape_double_quotes( (unsigned char *)(size_t)source );
+ sprintf( command, "find \"%s\" -type f | wc -l", _cEscapedString );
+ free( _cEscapedString );
+ fp = popen(command,"r");
+ if ( fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL)
+ char output[1024];
+ char fcmd[] = "find";
+ fp = spawn(fcmd, (char *[]){ fcmd, (unsigned char *)(size_t)source, NULL, "-type", "f", NULL });
+ if ( fp == NULL)
+ printf("failed to run find\r");
+ 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");
+ fflush (stdout);
+ long iTotalSize = 0;
+ /* call du -s for each file */
+ /* create command */
+ _cEscapedString = escape_double_quotes( (unsigned char *)(size_t)source );
+ sprintf ( command, "du -s \"%s\"", _cEscapedString );
+ free( _cEscapedString );
+
+ /* run command */
+ fp = popen(command, "r");
+ char dcmd[] = "du";
+ fp = spawn(dcmd, (char *[]){ dcmd, "-s", (unsigned char *)(size_t)source, NULL });
+ if (fp == NULL || fgets(output, sizeof(output)-1, fp) == NULL) {
+ 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)
{
char const *dir_to_remove;
@@ -306,6 +425,11 @@
@@ -306,6 +431,11 @@
\n\
-b like --backup but does not accept an argument\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\
-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\
@@ -361,7 +485,8 @@
@@ -361,7 +491,8 @@
/* Try to disable the ability to unlink a directory. */
priv_set_remove_linkdir ();
@@ -863,7 +882,7 @@ diff -aur coreutils-9.0/src/mv.c coreutils-9.0-patched/src/mv.c
!= -1)
{
switch (c)
@@ -407,6 +532,11 @@
@@ -407,6 +538,11 @@
case 'v':
x.verbose = true;
break;