Menu

#24 Failed to execute child process "tar" (Arg. list too long)

open
nobody
None
5
2009-08-31
2009-08-31
No

Hello,

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.

Discussion

  • Giuseppe Torelli

    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.

     
  • Giuseppe Torelli

    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.

     

Log in to post a comment.

MongoDB Logo MongoDB