aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--findutils/xargs.c105
1 files changed, 103 insertions, 2 deletions
diff --git a/findutils/xargs.c b/findutils/xargs.c
index a3a15bfbc..f0abf1a23 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -336,6 +336,8 @@ static int xargs_exec(void)
336#endif 336#endif
337 337
338#if ENABLE_PLATFORM_MINGW32 338#if ENABLE_PLATFORM_MINGW32
339 /* Any change to the logic for NOFORK applets must be duplicated
340 * in xargs_main() below. */
339# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 341# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
340 if (G.max_procs == 1) { 342 if (G.max_procs == 1) {
341# endif 343# endif
@@ -720,6 +722,20 @@ static int xargs_ask_confirmation(void)
720# define xargs_ask_confirmation() 1 722# define xargs_ask_confirmation() 1
721#endif 723#endif
722 724
725#if ENABLE_PLATFORM_MINGW32
726// Maximum command length (less a few bytes)
727# define WIN32_MAX_CHARS (32750)
728
729static size_t quote_len(const char *arg)
730{
731 char *s = quote_arg(arg);
732 size_t len = strlen(s);
733
734 free(s);
735 return len;
736}
737#endif
738
723//usage:#define xargs_trivial_usage 739//usage:#define xargs_trivial_usage
724//usage: "[OPTIONS] [PROG ARGS]" 740//usage: "[OPTIONS] [PROG ARGS]"
725//usage:#define xargs_full_usage "\n\n" 741//usage:#define xargs_full_usage "\n\n"
@@ -765,6 +781,11 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
765 unsigned opt; 781 unsigned opt;
766 int n_max_chars; 782 int n_max_chars;
767 int n_max_arg; 783 int n_max_arg;
784#if ENABLE_PLATFORM_MINGW32
785 int delta = 0;
786 int quote = TRUE;
787 char *old_buf = NULL;
788#endif
768#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \ 789#if ENABLE_FEATURE_XARGS_SUPPORT_ZERO_TERM \
769 || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR 790 || ENABLE_FEATURE_XARGS_SUPPORT_REPL_STR
770 char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin; 791 char* FAST_FUNC (*read_args)(int, int, char*) = process_stdin;
@@ -820,6 +841,24 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
820 //argc++; 841 //argc++;
821 } 842 }
822 843
844#if ENABLE_PLATFORM_MINGW32
845 /* On Windows the command line may be expanded by the need to quote
846 * arguments, but not if the command is a NOFORK applet. If the rules
847 * to detect this situation change xargs_exec() above will also need
848 * to be updated. */
849# if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
850 if (G.max_procs == 1)
851# endif
852 {
853# if ENABLE_FEATURE_PREFER_APPLETS && (NUM_APPLETS > 1)
854 int applet = find_applet_by_name(argv[0]);
855 if (applet >= 0 && APPLET_IS_NOFORK(applet)) {
856 quote = FALSE;
857 }
858 }
859# endif
860#endif
861
823 /* 862 /*
824 * The Open Group Base Specifications Issue 6: 863 * The Open Group Base Specifications Issue 6:
825 * "The xargs utility shall limit the command line length such that 864 * "The xargs utility shall limit the command line length such that
@@ -844,7 +883,12 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
844 { 883 {
845 size_t n_chars = 0; 884 size_t n_chars = 0;
846 for (i = 0; argv[i]; i++) { 885 for (i = 0; argv[i]; i++) {
847 n_chars += strlen(argv[i]) + 1; 886#if ENABLE_PLATFORM_MINGW32
887 if (quote)
888 n_chars += quote_len(argv[i]) + 1;
889 else
890#endif
891 n_chars += strlen(argv[i]) + 1;
848 } 892 }
849 n_max_chars -= n_chars; 893 n_max_chars -= n_chars;
850 } 894 }
@@ -903,11 +947,36 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
903 initial_idx = G.idx; 947 initial_idx = G.idx;
904 while (1) { 948 while (1) {
905 char *rem; 949 char *rem;
950#if ENABLE_PLATFORM_MINGW32
951 char **args;
952 char **tail = NULL;
953 char *saved_arg = NULL;
954 size_t n_chars;
955#endif
906 956
907 G.idx = initial_idx; 957 G.idx = initial_idx IF_PLATFORM_MINGW32(+ delta);
908 rem = read_args(n_max_chars, n_max_arg, buf); 958 rem = read_args(n_max_chars, n_max_arg, buf);
909 store_param(NULL); 959 store_param(NULL);
910 960
961#if ENABLE_PLATFORM_MINGW32
962 /* Check if quoting expands the command line. If it does we
963 * truncate args[] and preserve the tail for processing later. */
964 args = G.args;
965 if (quote) {
966 skip_read:
967 n_chars = 0;
968 for (i = initial_idx; args[i]; i++) {
969 n_chars += quote_len(args[i]) + 1;
970 if (n_chars > WIN32_MAX_CHARS) {
971 tail = args + i;
972 saved_arg = *tail;
973 *tail = NULL;
974 break;
975 }
976 }
977 }
978#endif
979
911 if (!G.args[initial_idx]) { /* not even one ARG was added? */ 980 if (!G.args[initial_idx]) { /* not even one ARG was added? */
912 if (*rem != '\0') 981 if (*rem != '\0')
913 bb_simple_error_msg_and_die("argument line too long"); 982 bb_simple_error_msg_and_die("argument line too long");
@@ -918,7 +987,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
918 987
919 if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) { 988 if (opt & (OPT_INTERACTIVE | OPT_VERBOSE)) {
920 const char *fmt = " %s" + 1; 989 const char *fmt = " %s" + 1;
990#if !ENABLE_PLATFORM_MINGW32
921 char **args = G.args; 991 char **args = G.args;
992#endif
922 for (i = 0; args[i]; i++) { 993 for (i = 0; args[i]; i++) {
923 fprintf(stderr, fmt, args[i]); 994 fprintf(stderr, fmt, args[i]);
924 fmt = " %s"; 995 fmt = " %s";
@@ -932,6 +1003,33 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
932 break; /* G.xargs_exitcode is set by xargs_exec() */ 1003 break; /* G.xargs_exitcode is set by xargs_exec() */
933 } 1004 }
934 1005
1006#if ENABLE_PLATFORM_MINGW32
1007 delta = 0;
1008 if (quote && tail) {
1009 /* The command line was truncated. Preload args[] with
1010 * the tail we saved earlier. */
1011 *tail = saved_arg;
1012 n_chars = 0;
1013 for (i = 0; tail[i]; i++) {
1014 args[initial_idx + i] = tail[i];
1015 n_chars += quote_len(tail[i]) + 1;
1016 }
1017 args[initial_idx + i] = NULL;
1018 delta = i;
1019
1020 /* The command line still overflows after quoting.
1021 * Truncate the new args[] and exec it. */
1022 if (n_chars > WIN32_MAX_CHARS)
1023 goto skip_read;
1024
1025 /* The first elements of args[] point to strings in the
1026 * current buf, so we need to preserve it. Allocate a
1027 * new buf for future use. */
1028 free(old_buf);
1029 old_buf = buf;
1030 buf = xzalloc(n_max_chars + 1);
1031 }
1032#endif
935 overlapping_strcpy(buf, rem); 1033 overlapping_strcpy(buf, rem);
936 } /* while */ 1034 } /* while */
937 1035
@@ -939,6 +1037,9 @@ int xargs_main(int argc UNUSED_PARAM, char **argv)
939 free(G.args); 1037 free(G.args);
940 free(buf); 1038 free(buf);
941 } 1039 }
1040#if ENABLE_FEATURE_CLEAN_UP && ENABLE_PLATFORM_MINGW32
1041 free(old_buf);
1042#endif
942 1043
943#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL 1044#if ENABLE_FEATURE_XARGS_SUPPORT_PARALLEL
944 G.max_procs = 0; 1045 G.max_procs = 0;