188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project/*
288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * Copyright 2005 The Android Open Source Project
388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project *
488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * Android "cp" replacement.
588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project *
688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * The GNU/Linux "cp" uses O_LARGEFILE in its open() calls, utimes() instead
788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * of utime(), and getxattr()/setxattr() instead of chmod().  These are
888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * probably "better", but are non-portable, and not necessary for our
988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * purposes.
1088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project */
1188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <stdlib.h>
1288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <stdio.h>
1388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <string.h>
1488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <unistd.h>
1588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <sys/types.h>
1688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <sys/stat.h>
1788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <getopt.h>
1888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <dirent.h>
1988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <fcntl.h>
2088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <utime.h>
2188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <limits.h>
2288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <errno.h>
2388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <assert.h>
2488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#include <host/CopyFile.h>
2588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
2688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project/*#define DEBUG_MSGS*/
2788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#ifdef DEBUG_MSGS
2888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project# define DBUG(x) printf x
2988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#else
3088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project# define DBUG(x) ((void)0)
3188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#endif
3288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
3388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project#define FSSEP '/'       /* filename separator char */
3488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
3588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
3688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project/*
3788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * Process the command-line file arguments.
3888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project *
3988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * Returns 0 on success.
4088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project */
4188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectint process(int argc, char* const argv[], unsigned int options)
4288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project{
4388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    int retVal = 0;
4488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    int i, cc;
4588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    char* stripDest = NULL;
4688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    int stripDestLen;
4788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    struct stat destStat;
4888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    bool destMustBeDir = false;
4988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    struct stat sb;
5088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
5188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    assert(argc >= 2);
5288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
5388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    /*
5488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * Check for and trim a trailing slash on the last arg.
5588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     *
5688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * It's useful to be able to say "cp foo bar/" when you want to copy
5788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * a single file into a directory.  If you say "cp foo bar", and "bar"
5888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * does not exist, it will create "bar", when what you really wanted
5988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * was for the cp command to fail with "directory does not exist".
6088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     */
6188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    stripDestLen = strlen(argv[argc-1]);
6288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    stripDest = malloc(stripDestLen+1);
6388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    memcpy(stripDest, argv[argc-1], stripDestLen+1);
6488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if (stripDest[stripDestLen-1] == FSSEP) {
6588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        stripDest[--stripDestLen] = '\0';
6688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        destMustBeDir = true;
6788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    }
6888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
6988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if (argc > 2)
7088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        destMustBeDir = true;
7188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
7288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    /*
7388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * Start with a quick check to ensure that, if we're expecting to copy
7488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * to a directory, the target already exists and is actually a directory.
7588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * It's okay if it's a symlink to a directory.
7688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     *
7788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * If it turns out to be a directory, go ahead and raise the
7888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * destMustBeDir flag so we do some path concatenation below.
7988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     */
8088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if (stat(stripDest, &sb) < 0) {
8188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (destMustBeDir) {
8288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            if (errno == ENOENT)
8388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                fprintf(stderr,
8488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                    "acp: destination directory '%s' does not exist\n",
8588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                    stripDest);
8688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            else
8788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                fprintf(stderr, "acp: unable to stat dest dir\n");
8888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            retVal = 1;
8988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            goto bail;
9088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        }
9188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    } else {
9288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (S_ISDIR(sb.st_mode)) {
9388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            DBUG(("--- dest exists and is a dir, setting flag\n"));
9488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            destMustBeDir = true;
9588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        } else if (destMustBeDir) {
9688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            fprintf(stderr,
9788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                "acp: destination '%s' is not a directory\n",
9888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                stripDest);
9988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            retVal = 1;
10088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            goto bail;
10188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        }
10288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    }
10388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
10488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    /*
10588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * Copying files.
10688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     *
10788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * Strip trailing slashes off.  They shouldn't be there, but
10888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * sometimes file completion will put them in for directories.
10988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     *
11088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * The observed behavior of GNU and BSD cp is that they print warnings
11188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * if something fails, but continue on.  If any part fails, the command
11288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     * exits with an error status.
11388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project     */
11488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    for (i = 0; i < argc-1; i++) {
11588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        const char* srcName;
11688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        char* src;
11788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        char* dst;
11888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        int copyResult;
11988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        int srcLen;
12088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
12188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        /* make a copy of the source name, and strip trailing '/' */
12288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        srcLen = strlen(argv[i]);
12388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        src = malloc(srcLen+1);
12488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        memcpy(src, argv[i], srcLen+1);
12588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
12688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (src[srcLen-1] == FSSEP)
12788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            src[--srcLen] = '\0';
12888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
12988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        /* find just the name part */
13088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        srcName = strrchr(src, FSSEP);
13188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (srcName == NULL) {
13288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            srcName = src;
13388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        } else {
13488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            srcName++;
13588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            assert(*srcName != '\0');
13688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        }
13788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
13888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (destMustBeDir) {
13988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            /* concatenate dest dir and src name */
14088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            int srcNameLen = strlen(srcName);
14188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
14288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            dst = malloc(stripDestLen +1 + srcNameLen +1);
14388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            memcpy(dst, stripDest, stripDestLen);
14488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            dst[stripDestLen] = FSSEP;
14588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            memcpy(dst + stripDestLen+1, srcName, srcNameLen+1);
14688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        } else {
14788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            /* simple */
14888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            dst = stripDest;
14988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        }
15088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
15188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        /*
15288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project         * Copy the source to the destination.
15388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project         */
15488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        copyResult = copyFile(src, dst, options);
15588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
15688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (copyResult != 0)
15788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            retVal = 1;
15888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
15988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        free(src);
16088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (dst != stripDest)
16188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            free(dst);
16288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    }
16388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
16488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectbail:
16588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    free(stripDest);
16688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return retVal;
16788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project}
16888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
16988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project/*
17088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project * Set up the options.
17188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project */
17288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Projectint main(int argc, char* const argv[])
17388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project{
17488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    bool wantUsage;
17588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    int ic, retVal;
17688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    int verboseLevel;
17788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    unsigned int options;
17888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
17988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    verboseLevel = 0;
18088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    options = 0;
18188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    wantUsage = false;
18288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
18388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    while (1) {
18488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        ic = getopt(argc, argv, "defprtuv");
18588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (ic < 0)
18688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            break;
18788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
18888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        switch (ic) {
18988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'd':
19088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_NO_DEREFERENCE;
19188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
19288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'e':
19388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_TRY_EXE;
19488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
19588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'f':
19688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_FORCE;
19788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
19888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'p':
19988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_PERMISSIONS;
20088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
20188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 't':
20288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_TIMESTAMPS;
20388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
20488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'r':
20588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_RECURSIVE;
20688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
20788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'u':
20888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                options |= COPY_UPDATE_ONLY;
20988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
21088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            case 'v':
21188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                verboseLevel++;
21288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
21388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            default:
21488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                fprintf(stderr, "Unexpected arg -%c\n", ic);
21588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                wantUsage = true;
21688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                break;
21788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        }
21888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
21988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        if (wantUsage)
22088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project            break;
22188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    }
22288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
22388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    options |= verboseLevel & COPY_VERBOSE_MASK;
22488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
22588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if (optind == argc-1) {
22688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "acp: missing destination file\n");
22788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        return 2;
22888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    } else if (optind+2 > argc)
22988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        wantUsage = true;
23088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
23188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    if (wantUsage) {
23288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "Usage: acp [OPTION]... SOURCE DEST\n");
23388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  or:  acp [OPTION]... SOURCE... DIRECTORY\n");
23488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "\nOptions:\n");
23588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -d  never follow (dereference) symbolic links\n");
23688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -e  if source file doesn't exist, try adding "
23788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                        "'.exe' [Win32 only]\n");
23888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -f  use force, removing existing file if it's "
23988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project                        "not writeable\n");
24088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -p  preserve mode, ownership\n");
24188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -r  recursive copy\n");
24288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -t  preserve timestamps\n");
24388b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -u  update only: don't copy if dest is newer\n");
24488b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        fprintf(stderr, "  -v  verbose output (-vv is more verbose)\n");
24588b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project        return 2;
24688b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    }
24788b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
24888b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    retVal = process(argc-optind, argv+optind, options);
24988b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    DBUG(("EXIT: %d\n", retVal));
25088b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project    return retVal;
25188b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project}
25288b607994a148f4af5bffee163e39ce8296750c6The Android Open Source Project
253