When I try to extracte some tar.gz file, xarchiver returns the following error
-> Failed to execute child process "tar" (Argument list too long). Untaring the
same file into terminal with command line work.
There is already a function in archive.c:113 that does this. The problem are
the parameters, they are concatenated to the command and there is no way to
know where to cut string so to have more strings with the same parameters as in
the examples above. The solution to this is to fill the arrays argcp and argv
in in archive.c:67.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
For me, 5000 was not my MAX_CMD_ARGS.
Apparently, mine is 131072.
First, you should directly use MAX_CMD_ARGS (or CARGS, or ARG_MAX) if it is
defined, otherwise default to your 5000.
you have:
#ifndef NCARGS
#define NCARGS _POSIX_ARG_MAX
#endif
#define MAX_CMD_LEN (NCARGS * 2 / 3)
Try the following to be more careful and catch more weird cases:
#ifndef NCARGS
#ifdef _POSIX_ARG_MAX
#define NCARGS _POSIX_ARG_MAX
#else
#ifdef ARG_MAX
#define NCARGS ARG_MAX
#else
#define NCARGS 4096
#endif /* ARG_MAX */
#endif /* _POSIX_ARG_MAX */
#endif
#define MAX_CMD_LEN (NCARGS * 2 / 3)
I used 4096 instead of 5000, because I saw that in a few cases _POSIX_ARG_MAX
was defined as 4096..
Now, as far as your test function.
Why not just return the location of the parameter that went over the size
limit.
Here is what I turned your function into to do be used in the above logic:
so for an example of 12 words where each are 1000 characters in length and
using a MAX_CMD_LEN of 5000, this function would be called 3 times, the
returned unsigned integers would be: 5, 10, 12
so you would call three functions as such:
execute with parameters 1 -> 4
execute with parameters 5 -> 9
execute with parameters 10 -> 12
where the code "if ((scan != NULL) && (length >= MAX_CMD_LEN)) split_here++;"
is my attempt at handling the case where the stopping point would be 12 because
(scan == NULL) and our execute parameters would go to 10 -> 11.
Also, is "XArchive *archive" even needed in the above function?
FIXME:
I just noticed the function above is incomplete, it needs to somehow be passed
a starting position so things can be picked up where they were stopped for each
iteration. This way, on the second pass, start at parameter 5 and not 1..
I don't know anything about GSList to solve this almost-oversight on my part.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
To fix this bug the long command causing the error should be splitted in
several chunks like this:
tar -xvf /home/gt/Xarchiver_Test/AAA.tar --keep-old-files --no-wildcards -C
/tmp/xa-iQyQFq archive1.c archive2.c archive3.c archive4.c ... archive1930.c
tar -xvf /home/gt/Xarchiver_Test/AAA.tar --keep-old-files --no-wildcards -C
/tmp/xa-iQyQFq archive1931.c archive1932.c archive1933.c ... archive3334.c
tar -xvf /home/gt/Xarchiver_Test/AAA.tar --keep-old-files --no-wildcards -C
/tmp/xa-iQyQFq archive3335.c archive3336.c archive3337.c ... archive6334.c
There is already a function in archive.c:113 that does this. The problem are
the parameters, they are concatenated to the command and there is no way to
know where to cut string so to have more strings with the same parameters as in
the examples above. The solution to this is to fill the arrays argcp and argv
in in archive.c:67.
I looked at your test function.
For me, 5000 was not my MAX_CMD_ARGS.
Apparently, mine is 131072.
First, you should directly use MAX_CMD_ARGS (or CARGS, or ARG_MAX) if it is
defined, otherwise default to your 5000.
you have:
#ifndef NCARGS
#define NCARGS _POSIX_ARG_MAX
#endif
#define MAX_CMD_LEN (NCARGS * 2 / 3)
Try the following to be more careful and catch more weird cases:
#ifndef NCARGS
#ifdef _POSIX_ARG_MAX
#define NCARGS _POSIX_ARG_MAX
#else
#ifdef ARG_MAX
#define NCARGS ARG_MAX
#else
#define NCARGS 4096
#endif /* ARG_MAX */
#endif /* _POSIX_ARG_MAX */
#endif
#define MAX_CMD_LEN (NCARGS * 2 / 3)
I used 4096 instead of 5000, because I saw that in a few cases _POSIX_ARG_MAX
was defined as 4096..
Now, as far as your test function.
Why not just return the location of the parameter that went over the size
limit.
Here is what I turned your function into to do be used in the above logic:
guint xa_split_command_line(XArchive *archive,GSList *list)
{
GSList *scan = NULL;
guint length = 0;
guint split_here = 0;
for (scan = list; scan != NULL; length = 0)
{
for (; (length < MAX_CMD_LEN); split_here++)
{
length += strnlen (scan->data, MAX_CMD_LEN);
scan = scan->next;
if ((scan != NULL) && (length >= MAX_CMD_LEN))
split_here++;
}
}
return split_here;
}
so for an example of 12 words where each are 1000 characters in length and
using a MAX_CMD_LEN of 5000, this function would be called 3 times, the
returned unsigned integers would be: 5, 10, 12
so you would call three functions as such:
execute with parameters 1 -> 4
execute with parameters 5 -> 9
execute with parameters 10 -> 12
where the code "if ((scan != NULL) && (length >= MAX_CMD_LEN)) split_here++;"
is my attempt at handling the case where the stopping point would be 12 because
(scan == NULL) and our execute parameters would go to 10 -> 11.
Also, is "XArchive *archive" even needed in the above function?
FIXME:
I just noticed the function above is incomplete, it needs to somehow be passed
a starting position so things can be picked up where they were stopped for each
iteration. This way, on the second pass, start at parameter 5 and not 1..
I don't know anything about GSList to solve this almost-oversight on my part.