Changeset 55c64fc in rtems


Ignore:
Timestamp:
Apr 11, 2008, 10:57:54 PM (13 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, 4.9, 5, master
Children:
58b9db5
Parents:
377cf106
Message:

2008-04-12 Chris Johns <chrisj@…>

  • libmisc/shell/shell.c, libmisc/shell/shell.h, libmisc/shell/shell_script.c: Add support to echo the commands to stdout. This is useful with the -v script option to show commands as the run. Also added support to chdir to the directory the task invoking the script is in.
  • libmisc/shell/extern-cp.h, libmisc/shell/main_cp.c, libmisc/shell/utils-cp.c: Update tro the latest FreeBSD version.
  • libcsupport/Makefile.am, libcsupport/src/fchown.c: Add fchown support.
Location:
cpukit
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • cpukit/ChangeLog

    r377cf106 r55c64fc  
     12008-04-12      Chris Johns <chrisj@rtems.org>
     2
     3        * libmisc/shell/shell.c, libmisc/shell/shell.h,
     4        libmisc/shell/shell_script.c: Add support to echo the commands to
     5        stdout. This is useful with the -v script option to show commands
     6        as the run. Also added support to chdir to the directory the task
     7        invoking the script is in.
     8        * libmisc/shell/extern-cp.h, libmisc/shell/main_cp.c,
     9        libmisc/shell/utils-cp.c: Update tro the latest FreeBSD version.
     10        * libcsupport/Makefile.am, libcsupport/src/fchown.c: Add fchown
     11        support.
     12
    1132008-04-09      Madhusudan.C.S <madhusudancs@gmail.com>
    214
  • cpukit/libcsupport/Makefile.am

    r377cf106 r55c64fc  
    5959    src/write_r.c \
    6060    src/lseek.c src/ioctl.c src/mkdir.c src/mknod.c src/mkfifo.c src/rmdir.c \
    61     src/chdir.c src/chmod.c src/fchdir.c src/fchmod.c src/chown.c src/link.c \
    62     src/unlink.c src/umask.c src/ftruncate.c src/utime.c src/fstat.c \
     61    src/chdir.c src/chmod.c src/fchdir.c src/fchmod.c src/fchown.c src/chown.c \
     62    src/link.c src/unlink.c src/umask.c src/ftruncate.c src/utime.c src/fstat.c \
    6363    src/fcntl.c src/fpathconf.c src/getdents.c src/fsync.c src/fdatasync.c \
    6464    src/pipe.c src/dup.c src/dup2.c src/symlink.c src/readlink.c src/creat.c \
  • cpukit/libmisc/shell/extern-cp.h

    r377cf106 r55c64fc  
    4747typedef struct {
    4848  PATH_T to;
     49  int info;
    4950  uid_t myuid;
    50   int Rflag, fflag, iflag, pflag, rflag, vflag, Nflag;
     51  int fflag, iflag, lflag, nflag, pflag, vflag;
    5152  mode_t myumask;
    5253  jmp_buf exit_jmp;
     
    5455
    5556#define to           cp_globals->to
     57#define info         cp_globals->info
    5658#define myuid        cp_globals->myuid
    57 #define Rflag        cp_globals->Rflag
    5859#define fflag        cp_globals->fflag
    5960#define iflag        cp_globals->iflag
     61#define lflag        cp_globals->lflag
     62#define nflag        cp_globals->nflag
    6063#define pflag        cp_globals->pflag
    61 #define rflag        cp_globals->rflag
    6264#define vflag        cp_globals->vflag
    63 #define Nflag        cp_globals->Nflag
    6465#define myumask      cp_globals->myumask
    6566#define exit_jump    &(cp_globals->exit_jmp)
     
    8283int     set_utimes(const char *, struct stat *);
    8384int     setfile(rtems_shell_cp_globals* cp_globals, struct stat *, int);
     85int     preserve_dir_acls(struct stat *, char *, char *);
     86int     preserve_fd_acls(int, int);
    8487void    usage();
     88
    8589__END_DECLS
    8690
  • cpukit/libmisc/shell/main_cp.c

    r377cf106 r55c64fc  
    7474#include <errno.h>
    7575#include <fts.h>
    76 #include <locale.h>
     76#include <limits.h>
     77#include <signal.h>
     78#include <stdio.h>
    7779#include <stdlib.h>
    78 #include <stdio.h>
    7980#include <string.h>
    8081#include <unistd.h>
     
    8283#include "extern-cp.h"
    8384
    84 #define  STRIP_TRAILING_SLASH(p) {                              \
    85     while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/')  \
    86       *--(p).p_end = '\0';                                      \
    87   }
    88 
    89 static char empty[] = "";
     85#define S_ISTXT 0
     86
     87#define STRIP_TRAILING_SLASH(p) {                                       \
     88        while ((p).p_end > (p).p_path + 1 && (p).p_end[-1] == '/')      \
     89                *--(p).p_end = 0;                                       \
     90}
    9091
    9192enum op { FILE_TO_FILE, FILE_TO_DIR, DIR_TO_DNE };
     93
     94static int Rflag, rflag;
    9295
    9396static int main_cp(rtems_shell_cp_globals* cp_globals, int, char *[]);
     
    106109  rtems_shell_cp_globals cp_globals;
    107110  memset (&cp_globals, 0, sizeof (cp_globals));
     111  Rflag = rflag = 0;
    108112  if (setjmp (cp_globals.exit_jmp) == 0)
    109113    return main_cp (&cp_globals, argc, argv);
     
    114118main_cp(rtems_shell_cp_globals* cp_globals, int argc, char *argv[])
    115119{
    116   struct stat to_stat, tmp_stat;
    117   enum op type;
    118   int Hflag, Lflag, Pflag, ch, fts_options, r;
    119   char *target;
     120        struct stat to_stat, tmp_stat;
     121        enum op type;
     122        int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
     123        char *target;
    120124  struct getopt_data getopt_reent;
    121125
    122   to.p_end = to.p_path;
    123   to.target_end = empty;
    124 
    125   (void)setlocale(LC_ALL, "");
    126 
    127   Hflag = Lflag = Pflag = Rflag = 0;
     126        Hflag = Lflag = Pflag = 0;
    128127  memset(&getopt_reent, 0, sizeof(getopt_data));
    129128
    130   while ((ch = getopt_r(argc, argv, "HLNPRfiprv", &getopt_reent)) != -1)
    131     switch (ch) {
    132       case 'H':
    133         Hflag = 1;
    134         Lflag = Pflag = 0;
    135         break;
    136       case 'L':
    137         Lflag = 1;
    138         Hflag = Pflag = 0;
    139         break;
    140       case 'N':
    141         Nflag = 1;
    142         break;
    143       case 'P':
    144         Pflag = 1;
    145         Hflag = Lflag = 0;
    146         break;
    147       case 'R':
    148         Rflag = 1;
    149         break;
    150       case 'f':
    151         fflag = 1;
    152         iflag = 0;
    153         break;
    154       case 'i':
    155         iflag = isatty(fileno(stdin));
    156         fflag = 0;
    157         break;
    158       case 'p':
    159         pflag = 1;
    160         break;
    161       case 'r':
    162         rflag = 1;
    163         break;
    164       case 'v':
    165         vflag = 1;
    166         break;
    167       case '?':
    168       default:
    169         usage();
    170         return 1;
    171     }
    172   argc -= optind;
    173   argv += optind;
    174 
    175   if (argc < 2)
    176     usage();
    177 
    178   fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
    179   if (rflag) {
    180     if (Rflag) {
    181       errx(exit_jump, EXIT_FAILURE,
    182            "the -R and -r options may not be specified together.");
    183       /* NOTREACHED */
    184     }
    185     if (Hflag || Lflag || Pflag) {
    186       errx(exit_jump, EXIT_FAILURE,
    187            "the -H, -L, and -P options may not be specified with the -r option.");
    188       /* NOTREACHED */
    189     }
    190     fts_options &= ~FTS_PHYSICAL;
    191     fts_options |= FTS_LOGICAL;
    192   }
    193   if (Rflag) {
    194     if (Hflag)
    195       fts_options |= FTS_COMFOLLOW;
    196     if (Lflag) {
    197       fts_options &= ~FTS_PHYSICAL;
    198       fts_options |= FTS_LOGICAL;
    199     }
    200   } else {
    201     fts_options &= ~FTS_PHYSICAL;
    202     fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
    203   }
    204 
    205   myuid = getuid();
    206 
    207   /* Copy the umask for explicit mode setting. */
    208   myumask = umask(0);
    209   (void)umask(myumask);
    210 
    211   /* Save the target base in "to". */
    212   target = argv[--argc];
    213   if (strlen(target) > MAXPATHLEN) {
    214     errx(exit_jump, EXIT_FAILURE, "%s: name too long", target);
    215     /* NOTREACHED */
    216   }
    217   (void)strcpy(to.p_path, target);
    218   to.p_end = to.p_path + strlen(to.p_path);
    219   STRIP_TRAILING_SLASH(to);
    220   to.target_end = to.p_end;
    221 
    222   /* Set end of argument list for fts(3). */
    223   argv[argc] = NULL;     
     129        while ((ch = getopt_r(argc, argv, "HLPRafilnprv", &getopt_reent)) != -1)
     130                switch (ch) {
     131                case 'H':
     132                        Hflag = 1;
     133                        Lflag = Pflag = 0;
     134                        break;
     135                case 'L':
     136                        Lflag = 1;
     137                        Hflag = Pflag = 0;
     138                        break;
     139                case 'P':
     140                        Pflag = 1;
     141                        Hflag = Lflag = 0;
     142                        break;
     143                case 'R':
     144                        Rflag = 1;
     145                        break;
     146                case 'a':
     147                        Pflag = 1;
     148                        pflag = 1;
     149                        Rflag = 1;
     150                        Hflag = Lflag = 0;
     151                        break;
     152                case 'f':
     153                        fflag = 1;
     154                        iflag = nflag = 0;
     155                        break;
     156                case 'i':
     157                        iflag = 1;
     158                        fflag = nflag = 0;
     159                        break;
     160                case 'l':
     161                        lflag = 1;
     162                        break;
     163                case 'n':
     164                        nflag = 1;
     165                        fflag = iflag = 0;
     166                        break;
     167                case 'p':
     168                        pflag = 1;
     169                        break;
     170                case 'r':
     171                        rflag = Lflag = 1;
     172                        Hflag = Pflag = 0;
     173                        break;
     174                case 'v':
     175                        vflag = 1;
     176                        break;
     177                default:
     178                        usage();
     179                        break;
     180                }
     181        argc -= getopt_reent.optind;
     182        argv += getopt_reent.optind;
     183
     184        if (argc < 2)
     185                usage();
     186
     187        fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
     188        if (Rflag && rflag)
     189                errx(exit_jump, 1, "the -R and -r options may not be specified together");
     190        if (rflag)
     191                Rflag = 1;
     192        if (Rflag) {
     193                if (Hflag)
     194                        fts_options |= FTS_COMFOLLOW;
     195                if (Lflag) {
     196                        fts_options &= ~FTS_PHYSICAL;
     197                        fts_options |= FTS_LOGICAL;
     198                }
     199        } else {
     200                fts_options &= ~FTS_PHYSICAL;
     201                fts_options |= FTS_LOGICAL | FTS_COMFOLLOW;
     202        }
     203#if 0
     204        (void)signal(SIGINFO, siginfo);
     205#endif
    224206 
    225   /*
    226    * Cp has two distinct cases:
    227    *
    228    * cp [-R] source target
    229    * cp [-R] source1 ... sourceN directory
    230    *
    231    * In both cases, source can be either a file or a directory.
    232    *
    233    * In (1), the target becomes a copy of the source. That is, if the
    234    * source is a file, the target will be a file, and likewise for
    235    * directories.
    236    *
    237    * In (2), the real target is not directory, but "directory/source".
    238    */
    239   r = stat(to.p_path, &to_stat);
    240   if (r == -1 && errno != ENOENT) {
    241     err(exit_jump, EXIT_FAILURE, "%s", to.p_path);
    242     /* NOTREACHED */
    243   }
    244   if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
    245     /*
    246      * Case (1).  Target is not a directory.
    247      */
    248     if (argc > 1)
    249       usage();
    250     /*
    251      * Need to detect the case:
    252      *  cp -R dir foo
    253      * Where dir is a directory and foo does not exist, where
    254      * we want pathname concatenations turned on but not for
    255      * the initial mkdir().
    256      */
    257     if (r == -1) {
    258       if (rflag || (Rflag && (Lflag || Hflag)))
    259         r = stat(*argv, &tmp_stat);
    260       else
    261         r = lstat(*argv, &tmp_stat);
    262       if (r == -1) {
    263         err(exit_jump, EXIT_FAILURE, "%s", *argv);
    264         /* NOTREACHED */
    265       }
    266      
    267       if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag))
    268         type = DIR_TO_DNE;
    269       else
    270         type = FILE_TO_FILE;
    271     } else
    272       type = FILE_TO_FILE;
    273   } else {
    274     /*
    275      * Case (2).  Target is a directory.
    276      */
    277     type = FILE_TO_DIR;
    278   }
     207        /* Save the target base in "to". */
     208        target = argv[--argc];
     209        if (strlcpy(to.p_path, target, sizeof(to.p_path)) >= sizeof(to.p_path))
     210                errx(exit_jump, 1, "%s: name too long", target);
     211        to.p_end = to.p_path + strlen(to.p_path);
     212        if (to.p_path == to.p_end) {
     213                *to.p_end++ = '.';
     214                *to.p_end = 0;
     215        }
     216        have_trailing_slash = (to.p_end[-1] == '/');
     217        if (have_trailing_slash)
     218                STRIP_TRAILING_SLASH(to);
     219        to.target_end = to.p_end;
     220
     221        /* Set end of argument list for fts(3). */
     222        argv[argc] = NULL;
     223
     224        /*
     225         * Cp has two distinct cases:
     226         *
     227         * cp [-R] source target
     228         * cp [-R] source1 ... sourceN directory
     229         *
     230         * In both cases, source can be either a file or a directory.
     231         *
     232         * In (1), the target becomes a copy of the source. That is, if the
     233         * source is a file, the target will be a file, and likewise for
     234         * directories.
     235         *
     236         * In (2), the real target is not directory, but "directory/source".
     237         */
     238        r = stat(to.p_path, &to_stat);
     239        if (r == -1 && errno != ENOENT)
     240                err(exit_jump, 1, "%s", to.p_path);
     241        if (r == -1 || !S_ISDIR(to_stat.st_mode)) {
     242                /*
     243                 * Case (1).  Target is not a directory.
     244                 */
     245                if (argc > 1)
     246                        errx(exit_jump, 1, "%s is not a directory", to.p_path);
     247
     248                /*
     249                 * Need to detect the case:
     250                 *      cp -R dir foo
     251                 * Where dir is a directory and foo does not exist, where
     252                 * we want pathname concatenations turned on but not for
     253                 * the initial mkdir().
     254                 */
     255                if (r == -1) {
     256                        if (Rflag && (Lflag || Hflag))
     257                                stat(*argv, &tmp_stat);
     258                        else
     259                                lstat(*argv, &tmp_stat);
     260
     261                        if (S_ISDIR(tmp_stat.st_mode) && Rflag)
     262                                type = DIR_TO_DNE;
     263                        else
     264                                type = FILE_TO_FILE;
     265                } else
     266                        type = FILE_TO_FILE;
     267
     268                if (have_trailing_slash && type == FILE_TO_FILE) {
     269                        if (r == -1)
     270                                errx(exit_jump, 1, "directory %s does not exist",
     271                                     to.p_path);
     272                        else
     273                                errx(exit_jump, 1, "%s is not a directory", to.p_path);
     274                }
     275        } else
     276                /*
     277                 * Case (2).  Target is a directory.
     278                 */
     279                type = FILE_TO_DIR;
    279280
    280281  return copy(cp_globals, argv, type, fts_options);
     
    285286     char *argv[], enum op type, int fts_options)
    286287{
    287   struct stat to_stat;
    288   FTS *ftsp;
    289   FTSENT *curr;
    290   int base, dne, rval;
    291   size_t nlen;
    292   char *p, *tmp;
    293 
    294   base = 0;  /* XXX gcc -Wuninitialized (see comment below) */
    295 
    296   if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
    297     err(exit_jump, EXIT_FAILURE, "%s", argv[0]);
    298   /* NOTREACHED */
    299   for (rval = 0; (curr = fts_read(ftsp)) != NULL;) {
    300     switch (curr->fts_info) {
    301       case FTS_NS:
    302       case FTS_DNR:
    303       case FTS_ERR:
    304         warnx("%s: %s", curr->fts_path,
    305               strerror(curr->fts_errno));
    306         rval = 1;
    307         continue;
    308       case FTS_DC:      /* Warn, continue. */
    309         warnx("%s: directory causes a cycle", curr->fts_path);
    310         rval = 1;
    311         continue;
    312     }
    313 
    314     /*
    315      * If we are in case (2) or (3) above, we need to append the
    316      * source name to the target name. 
    317      */
    318     if (type != FILE_TO_FILE) {
    319       if ((curr->fts_namelen +
    320            to.target_end - to.p_path + 1) > MAXPATHLEN) {
    321         warnx("%s/%s: name too long (not copied)",
    322               to.p_path, curr->fts_name);
    323         rval = 1;
    324         continue;
    325       }
    326 
    327       /*
    328        * Need to remember the roots of traversals to create
    329        * correct pathnames.  If there's a directory being
    330        * copied to a non-existent directory, e.g.
    331        *  cp -R a/dir noexist
    332        * the resulting path name should be noexist/foo, not
    333        * noexist/dir/foo (where foo is a file in dir), which
    334        * is the case where the target exists.
    335        *
    336        * Also, check for "..".  This is for correct path
    337        * concatentation for paths ending in "..", e.g.
    338        *  cp -R .. /tmp
    339        * Paths ending in ".." are changed to ".".  This is
    340        * tricky, but seems the easiest way to fix the problem.
    341        *
    342        * XXX
    343        * Since the first level MUST be FTS_ROOTLEVEL, base
    344        * is always initialized.
    345        */
    346       if (curr->fts_level == FTS_ROOTLEVEL) {
    347         if (type != DIR_TO_DNE) {
    348           p = strrchr(curr->fts_path, '/');
    349           base = (p == NULL) ? 0 :
    350             (int)(p - curr->fts_path + 1);
    351 
    352           if (!strcmp(&curr->fts_path[base],
    353                       ".."))
    354             base += 1;
    355         } else
    356           base = curr->fts_pathlen;
    357       }
    358 
    359       p = &curr->fts_path[base];
    360       nlen = curr->fts_pathlen - base;
    361 
    362       tmp = to.target_end;
    363       if (*p != '/' && *(tmp - 1) != '/')
    364         *tmp++ = '/';
    365       *tmp = 0;
    366 
    367       (void)strncat(tmp, p, nlen);
    368       to.p_end = tmp + nlen;
    369       *to.p_end = 0;
    370       STRIP_TRAILING_SLASH(to);
    371     }
    372 
    373     /* Not an error but need to remember it happened */
    374     if (stat(to.p_path, &to_stat) == -1)
    375       dne = 1;
    376     else {
    377       if (to_stat.st_dev == curr->fts_statp->st_dev &&
    378           to_stat.st_ino == curr->fts_statp->st_ino) {
    379         warnx("%s and %s are identical (not copied).",
    380               to.p_path, curr->fts_path);
    381         rval = 1;
    382         if (S_ISDIR(curr->fts_statp->st_mode))
    383           (void)fts_set(ftsp, curr, FTS_SKIP);
    384         continue;
    385       }
    386       if (!S_ISDIR(curr->fts_statp->st_mode) &&
    387           S_ISDIR(to_stat.st_mode)) {
    388         warnx("cannot overwrite directory %s with non-directory %s",
    389               to.p_path, curr->fts_path);
    390         rval = 1;
    391         continue;
    392       }
    393       dne = 0;
    394     }
    395 
    396     switch (curr->fts_statp->st_mode & S_IFMT) {
    397       case S_IFLNK:
    398         /* Catch special case of a non dangling symlink */
    399         if((fts_options & FTS_LOGICAL) ||
    400            ((fts_options & FTS_COMFOLLOW) && curr->fts_level == 0)) {
    401           if (copy_file(cp_globals, curr, dne))
    402             rval = 1;
    403         } else { 
    404           if (copy_link(cp_globals, curr, !dne))
    405             rval = 1;
    406         }
    407         break;
    408       case S_IFDIR:
    409         if (!Rflag && !rflag) {
    410           if (curr->fts_info == FTS_D)
    411             warnx("%s is a directory (not copied).",
    412                   curr->fts_path);
    413           (void)fts_set(ftsp, curr, FTS_SKIP);
    414           rval = 1;
    415           break;
    416         }
    417 
    418         /*
    419          * Directories get noticed twice:
    420          *  In the first pass, create it if needed.
    421          *  In the second pass, after the children have been copied,
    422          *  set the permissions.
    423          */
    424         if (curr->fts_info == FTS_D) /* First pass */
    425         {
    426           /*
    427            * If the directory doesn't exist, create the new
    428            * one with the from file mode plus owner RWX bits,
    429            * modified by the umask.  Trade-off between being
    430            * able to write the directory (if from directory is
    431            * 555) and not causing a permissions race.  If the
    432            * umask blocks owner writes, we fail..
    433            */
    434           if (dne) {
    435             if (mkdir(to.p_path,
    436                       curr->fts_statp->st_mode | S_IRWXU) < 0)
    437               err(exit_jump, EXIT_FAILURE, "%s",
    438                   to.p_path);
    439             /* NOTREACHED */
    440           } else if (!S_ISDIR(to_stat.st_mode)) {
    441             errno = ENOTDIR;
    442             err(exit_jump, EXIT_FAILURE, "%s",
    443                 to.p_path);
    444             /* NOTREACHED */
    445           }
    446         }
    447         else if (curr->fts_info == FTS_DP) /* Second pass */
    448         {
    449           /*
    450            * If not -p and directory didn't exist, set it to be
    451            * the same as the from directory, umodified by the
    452            * umask; arguably wrong, but it's been that way
    453            * forever.
    454            */
    455           if (pflag && setfile(cp_globals, curr->fts_statp, 0))
    456             rval = 1;
    457           else if (dne)
    458             (void)chmod(to.p_path,
    459                         curr->fts_statp->st_mode);
    460         }
    461         else
    462         {
    463           warnx("directory %s encountered when not expected.",
    464                 curr->fts_path);
    465           rval = 1;
    466           break;
    467         }
    468 
    469         break;
    470       case S_IFBLK:
    471       case S_IFCHR:
    472         if (Rflag) {
    473           if (copy_special(cp_globals, curr->fts_statp, !dne))
    474             rval = 1;
    475         } else
    476           if (copy_file(cp_globals, curr, dne))
    477             rval = 1;
    478         break;
    479       case S_IFIFO:
    480         if (Rflag) {
    481           if (copy_fifo(cp_globals, curr->fts_statp, !dne))
    482             rval = 1;
    483         } else
    484           if (copy_file(cp_globals, curr, dne))
    485             rval = 1;
    486         break;
    487       default:
    488         if (copy_file(cp_globals, curr, dne))
    489           rval = 1;
    490         break;
    491     }
    492     if (vflag && !rval)
    493       (void)printf("%s -> %s\n", curr->fts_path, to.p_path);
    494   }
    495   if (errno) {
    496     err(exit_jump, EXIT_FAILURE, "fts_read");
    497     /* NOTREACHED */
    498   }
    499   return (rval);
     288        struct stat to_stat;
     289        FTS *ftsp;
     290        FTSENT *curr;
     291        int base = 0, dne, badcp, rval;
     292        size_t nlen;
     293        char *p, *target_mid;
     294        mode_t mask, mode;
     295
     296        /*
     297         * Keep an inverted copy of the umask, for use in correcting
     298         * permissions on created directories when not using -p.
     299         */
     300        mask = ~umask(0777);
     301        umask(~mask);
     302
     303        if ((ftsp = fts_open(argv, fts_options, mastercmp)) == NULL)
     304                err(exit_jump, 1, "fts_open");
     305        for (badcp = rval = 0; (curr = fts_read(ftsp)) != NULL; badcp = 0) {
     306                switch (curr->fts_info) {
     307                case FTS_NS:
     308                case FTS_DNR:
     309                case FTS_ERR:
     310                        warnx("%s: %s",
     311                            curr->fts_path, strerror(curr->fts_errno));
     312                        badcp = rval = 1;
     313                        continue;
     314                case FTS_DC:                    /* Warn, continue. */
     315                        warnx("%s: directory causes a cycle", curr->fts_path);
     316                        badcp = rval = 1;
     317                        continue;
     318                default:
     319                        ;
     320                }
     321
     322                /*
     323                 * If we are in case (2) or (3) above, we need to append the
     324                 * source name to the target name.
     325                 */
     326                if (type != FILE_TO_FILE) {
     327                        /*
     328                         * Need to remember the roots of traversals to create
     329                         * correct pathnames.  If there's a directory being
     330                         * copied to a non-existent directory, e.g.
     331                         *      cp -R a/dir noexist
     332                         * the resulting path name should be noexist/foo, not
     333                         * noexist/dir/foo (where foo is a file in dir), which
     334                         * is the case where the target exists.
     335                         *
     336                         * Also, check for "..".  This is for correct path
     337                         * concatenation for paths ending in "..", e.g.
     338                         *      cp -R .. /tmp
     339                         * Paths ending in ".." are changed to ".".  This is
     340                         * tricky, but seems the easiest way to fix the problem.
     341                         *
     342                         * XXX
     343                         * Since the first level MUST be FTS_ROOTLEVEL, base
     344                         * is always initialized.
     345                         */
     346                        if (curr->fts_level == FTS_ROOTLEVEL) {
     347                                if (type != DIR_TO_DNE) {
     348                                        p = strrchr(curr->fts_path, '/');
     349                                        base = (p == NULL) ? 0 :
     350                                            (int)(p - curr->fts_path + 1);
     351
     352                                        if (!strcmp(&curr->fts_path[base],
     353                                            ".."))
     354                                                base += 1;
     355                                } else
     356                                        base = curr->fts_pathlen;
     357                        }
     358
     359                        p = &curr->fts_path[base];
     360                        nlen = curr->fts_pathlen - base;
     361                        target_mid = to.target_end;
     362                        if (*p != '/' && target_mid[-1] != '/')
     363                                *target_mid++ = '/';
     364                        *target_mid = 0;
     365                        if (target_mid - to.p_path + nlen >= PATH_MAX) {
     366                                warnx("%s%s: name too long (not copied)",
     367                                    to.p_path, p);
     368                                badcp = rval = 1;
     369                                continue;
     370                        }
     371                        (void)strncat(target_mid, p, nlen);
     372                        to.p_end = target_mid + nlen;
     373                        *to.p_end = 0;
     374                        STRIP_TRAILING_SLASH(to);
     375                }
     376
     377                if (curr->fts_info == FTS_DP) {
     378                        /*
     379                         * We are nearly finished with this directory.  If we
     380                         * didn't actually copy it, or otherwise don't need to
     381                         * change its attributes, then we are done.
     382                         */
     383                        if (!curr->fts_number)
     384                                continue;
     385                        /*
     386                         * If -p is in effect, set all the attributes.
     387                         * Otherwise, set the correct permissions, limited
     388                         * by the umask.  Optimise by avoiding a chmod()
     389                         * if possible (which is usually the case if we
     390                         * made the directory).  Note that mkdir() does not
     391                         * honour setuid, setgid and sticky bits, but we
     392                         * normally want to preserve them on directories.
     393                         */
     394                        if (pflag) {
     395                                if (setfile(cp_globals, curr->fts_statp, -1))
     396                                        rval = 1;
     397                                if (preserve_dir_acls(curr->fts_statp,
     398                                    curr->fts_accpath, to.p_path) != 0)
     399                                        rval = 1;
     400                        } else {
     401                                mode = curr->fts_statp->st_mode;
     402                                if ((mode & (S_ISUID | S_ISGID | S_ISTXT)) ||
     403                                    ((mode | S_IRWXU) & mask) != (mode & mask))
     404                                        if (chmod(to.p_path, mode & mask) != 0){
     405                                                warn("chmod: %s", to.p_path);
     406                                                rval = 1;
     407                                        }
     408                        }
     409                        continue;
     410                }
     411
     412                /* Not an error but need to remember it happened */
     413                if (stat(to.p_path, &to_stat) == -1)
     414                        dne = 1;
     415                else {
     416                        if (to_stat.st_dev == curr->fts_statp->st_dev &&
     417                            to_stat.st_ino == curr->fts_statp->st_ino) {
     418                                warnx("%s and %s are identical (not copied).",
     419                                    to.p_path, curr->fts_path);
     420                                badcp = rval = 1;
     421                                if (S_ISDIR(curr->fts_statp->st_mode))
     422                                        (void)fts_set(ftsp, curr, FTS_SKIP);
     423                                continue;
     424                        }
     425                        if (!S_ISDIR(curr->fts_statp->st_mode) &&
     426                            S_ISDIR(to_stat.st_mode)) {
     427                                warnx("cannot overwrite directory %s with "
     428                                    "non-directory %s",
     429                                    to.p_path, curr->fts_path);
     430                                badcp = rval = 1;
     431                                continue;
     432                        }
     433                        dne = 0;
     434                }
     435
     436                switch (curr->fts_statp->st_mode & S_IFMT) {
     437                case S_IFLNK:
     438                        /* Catch special case of a non-dangling symlink */
     439                        if ((fts_options & FTS_LOGICAL) ||
     440                            ((fts_options & FTS_COMFOLLOW) &&
     441                            curr->fts_level == 0)) {
     442                                if (copy_file(cp_globals, curr, dne))
     443                                        badcp = rval = 1;
     444                        } else {       
     445                                if (copy_link(cp_globals, curr, !dne))
     446                                        badcp = rval = 1;
     447                        }
     448                        break;
     449                case S_IFDIR:
     450                        if (!Rflag) {
     451                                warnx("%s is a directory (not copied).",
     452                                    curr->fts_path);
     453                                (void)fts_set(ftsp, curr, FTS_SKIP);
     454                                badcp = rval = 1;
     455                                break;
     456                        }
     457                        /*
     458                         * If the directory doesn't exist, create the new
     459                         * one with the from file mode plus owner RWX bits,
     460                         * modified by the umask.  Trade-off between being
     461                         * able to write the directory (if from directory is
     462                         * 555) and not causing a permissions race.  If the
     463                         * umask blocks owner writes, we fail..
     464                         */
     465                        if (dne) {
     466                                if (mkdir(to.p_path,
     467                                    curr->fts_statp->st_mode | S_IRWXU) < 0)
     468                                        err(exit_jump, 1, "%s", to.p_path);
     469                        } else if (!S_ISDIR(to_stat.st_mode)) {
     470                                errno = ENOTDIR;
     471                                err(exit_jump, 1, "%s", to.p_path);
     472                        }
     473                        /*
     474                         * Arrange to correct directory attributes later
     475                         * (in the post-order phase) if this is a new
     476                         * directory, or if the -p flag is in effect.
     477                         */
     478                        curr->fts_number = pflag || dne;
     479                        break;
     480                case S_IFBLK:
     481                case S_IFCHR:
     482                        if (Rflag) {
     483                                if (copy_special(cp_globals, curr->fts_statp, !dne))
     484                                        badcp = rval = 1;
     485                        } else {
     486                                if (copy_file(cp_globals, curr, dne))
     487                                        badcp = rval = 1;
     488                        }
     489                        break;
     490                case S_IFSOCK:
     491                        warnx("%s is a socket (not copied).",
     492                                    curr->fts_path);
     493                case S_IFIFO:
     494                        if (Rflag) {
     495                                if (copy_fifo(cp_globals, curr->fts_statp, !dne))
     496                                        badcp = rval = 1;
     497                        } else {
     498                                if (copy_file(cp_globals, curr, dne))
     499                                        badcp = rval = 1;
     500                        }
     501                        break;
     502                default:
     503                        if (copy_file(cp_globals, curr, dne))
     504                                badcp = rval = 1;
     505                        break;
     506                }
     507                if (vflag && !badcp)
     508                        (void)printf("%s -> %s\n", curr->fts_path, to.p_path);
     509        }
     510        if (errno)
     511                err(exit_jump, 1, "fts_read");
     512        fts_close(ftsp);
     513        return (rval);
    500514}
    501515
    502516/*
    503517 * mastercmp --
    504  *  The comparison function for the copy order.  The order is to copy
    505  *  non-directory files before directory files.  The reason for this
    506  *  is because files tend to be in the same cylinder group as their
    507  *  parent directory, whereas directories tend not to be.  Copying the
    508  *  files first reduces seeking.
     518 *      The comparison function for the copy order.  The order is to copy
     519 *      non-directory files before directory files.  The reason for this
     520 *      is because files tend to be in the same cylinder group as their
     521 *      parent directory, whereas directories tend not to be.  Copying the
     522 *      files first reduces seeking.
    509523 */
    510524int
    511525mastercmp(const FTSENT **a, const FTSENT **b)
    512526{
    513   int a_info, b_info;
    514 
    515   a_info = (*a)->fts_info;
    516   if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
    517     return (0);
    518   b_info = (*b)->fts_info;
    519   if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
    520     return (0);
    521   if (a_info == FTS_D)
    522     return (-1);
    523   if (b_info == FTS_D)
    524     return (1);
    525   return (0);
     527        int a_info, b_info;
     528
     529        a_info = (*a)->fts_info;
     530        if (a_info == FTS_ERR || a_info == FTS_NS || a_info == FTS_DNR)
     531                return (0);
     532        b_info = (*b)->fts_info;
     533        if (b_info == FTS_ERR || b_info == FTS_NS || b_info == FTS_DNR)
     534                return (0);
     535        if (a_info == FTS_D)
     536                return (-1);
     537        if (b_info == FTS_D)
     538                return (1);
     539        return (0);
    526540}
    527541
     
    534548  NULL                                                 /* next */
    535549};
     550 
  • cpukit/libmisc/shell/shell.c

    r377cf106 r55c64fc  
    807807                  shell_env->devname);
    808808        }
     809
     810        if (input_file)
     811          chdir(shell_env->cwd);
     812        else
     813          chdir("/"); /* XXX: chdir to getpwent homedir */
    809814       
    810         chdir("/"); /* XXX: chdir to getpwent homedir */
    811815        shell_env->exit_shell = FALSE;
    812816
     
    833837          line++;
    834838
     839          if (shell_env->echo)
     840            fprintf(stdout, "%d: %s\n", line, cmds[cmd]);
     841         
    835842          /* evaluate cmd section */
    836843          c = cmds[cmd];
     
    912919  const char*          output,
    913920  int                  output_append,
    914   rtems_id             wake_on_end
     921  rtems_id             wake_on_end,
     922  int                  echo
    915923)
    916924{
     
    950958  shell_env->exit_shell    = FALSE;
    951959  shell_env->forever       = forever;
     960  shell_env->echo          = echo;
    952961  shell_env->input         = strdup (input);
    953962  shell_env->output        = strdup (output);
    954963  shell_env->output_append = output_append;
    955964  shell_env->wake_on_end   = wake_on_end;
     965
     966  getcwd(shell_env->cwd, sizeof(shell_env->cwd));
    956967
    957968  return rtems_task_start(task_id, rtems_shell_task,
     
    970981  return rtems_shell_run (task_name, task_stacksize, task_priority,
    971982                          devname, tcflag, forever,
    972                           "stdin", "stdout", 0, RTEMS_INVALID_ID);
     983                          "stdin", "stdout", 0, RTEMS_INVALID_ID, 0);
    973984}
    974985
     
    980991  const char*          output,
    981992  int                  output_append,
    982   int                  wait
     993  int                  wait,
     994  int                  echo
    983995)
    984996{
     
    9941006  sc = rtems_shell_run (task_name, task_stacksize, task_priority,
    9951007                        NULL, 0, 0, input, output, output_append,
    996                         current_task);
     1008                        current_task, echo);
    9971009  if (sc != RTEMS_SUCCESSFUL)
    9981010    return sc;
  • cpukit/libmisc/shell/shell.h

    r377cf106 r55c64fc  
    171171  const char          *output,
    172172  int                  output_append,
    173   int                  wait
     173  int                  wait,
     174  int                  echo
    174175);
    175176
     
    189190  int         forever   ; /* repeat login */
    190191  int         errorlevel;
     192  int         echo;
     193  char        cwd[256];
    191194  const char* input;
    192195  const char* output;
  • cpukit/libmisc/shell/shell_script.c

    r377cf106 r55c64fc  
    190190    outputFile,      /* where to redirect the script */
    191191    0,               /* run once and exit */
    192     1                /* we will wait */
     192    1,               /* we will wait */
     193    verbose          /* do we echo */
    193194  );
    194195  if (result)
  • cpukit/libmisc/shell/utils-cp.c

    r377cf106 r55c64fc  
    5353#include <fcntl.h>
    5454#include <fts.h>
     55#include <limits.h>
    5556#include <stdio.h>
    5657#include <stdlib.h>
     
    6263#define lchmod  chmod
    6364#define lchown  chown
     65
     66#define cp_pct(x, y)    ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
    6467
    6568int
     
    8285{
    8386        static char buf[MAXBSIZE];
    84         struct stat to_stat, *fs;
    85         int ch, checkch, from_fd, rcount, rval, to_fd, wcount;
    86        
     87        struct stat *fs;
     88        ssize_t wcount;
     89        size_t wresid;
     90        off_t wtotal;
     91        int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
     92        char *bufp;
     93#ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
     94        char *p;
     95#endif
     96
    8797        if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
    8898                warn("%s", entp->fts_path);
     
    101111         */
    102112        if (!dne) {
    103                 if (iflag) {
    104                         (void)fprintf(stderr, "overwrite %s? ", to.p_path);
     113#define YESNO "(y/n [n]) "
     114                if (nflag) {
     115                        if (vflag)
     116                                printf("%s not overwritten\n", to.p_path);
     117                        (void)close(from_fd);
     118                        return (0);
     119                } else if (iflag) {
     120                        (void)fprintf(stderr, "overwrite %s? %s",
     121                                        to.p_path, YESNO);
    105122                        checkch = ch = getchar();
    106123                        while (ch != '\n' && ch != EOF)
     
    108125                        if (checkch != 'y' && checkch != 'Y') {
    109126                                (void)close(from_fd);
    110                                 return (0);
     127                                (void)fprintf(stderr, "not overwritten\n");
     128                                return (1);
    111129                        }
    112130                }
    113                 /* overwrite existing destination file name */
    114                 to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
    115         } else
    116                 to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
    117                     fs->st_mode & ~(S_ISUID | S_ISGID));
    118 
    119         if (to_fd == -1 && fflag) {
    120                 /*
    121                  * attempt to remove existing destination file name and
    122                  * create a new file
    123                  */
    124                 (void)unlink(to.p_path);
    125                 to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
    126                              fs->st_mode & ~(S_ISUID | S_ISGID));
     131               
     132                if (fflag) {
     133                    /* remove existing destination file name,
     134                     * create a new file  */
     135                    (void)unlink(to.p_path);
     136                                if (!lflag)
     137                        to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
     138                                  fs->st_mode & ~(S_ISUID | S_ISGID));
     139                } else {
     140                                if (!lflag)
     141                        /* overwrite existing destination file name */
     142                        to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
     143                }
     144        } else {
     145                if (!lflag)
     146                        to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
     147                  fs->st_mode & ~(S_ISUID | S_ISGID));
    127148        }
    128149
     
    135156        rval = 0;
    136157
    137         /*
    138          * There's no reason to do anything other than close the file
    139          * now if it's empty, so let's not bother.
    140          */
    141 
    142         if (fs->st_size) {
    143 
     158        if (!lflag) {
    144159                /*
    145                  * Mmap and write if less than 8M (the limit is so
    146                  * we don't totally trash memory on big files).
    147                  * This is really a minor hack, but it wins some CPU back.
     160                 * Mmap and write if less than 8M (the limit is so we don't totally
     161                 * trash memory on big files.  This is really a minor hack, but it
     162                 * wins some CPU back.
    148163                 */
    149 #if 0
    150                 if (fs->st_size <= 8 * 1048576) {
    151                         size_t fsize = (size_t)fs->st_size;
    152                         p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED,
    153                             from_fd, (off_t)0);
    154                         if (p == MAP_FAILED) {
    155                                 goto mmap_failed;
     164#ifdef CCJ_REMOVED_VM_AND_BUFFER_CACHE_SYNCHRONIZED
     165                if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
     166                fs->st_size <= 8 * 1048576) {
     167                        if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
     168                        MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
     169                                warn("%s", entp->fts_path);
     170                                rval = 1;
    156171                        } else {
    157                                 (void) madvise(p, (size_t)fs->st_size,
    158                                      MADV_SEQUENTIAL);
    159                                 if (write(to_fd, p, fsize) !=
    160                                     fs->st_size) {
     172                                wtotal = 0;
     173                                for (bufp = p, wresid = fs->st_size; ;
     174                                bufp += wcount, wresid -= (size_t)wcount) {
     175                                        wcount = write(to_fd, bufp, wresid);
     176                                        if (wcount <= 0)
     177                                                break;
     178                                        wtotal += wcount;
     179                                        if (info) {
     180                                                info = 0;
     181                                                (void)fprintf(stderr,
     182                                                    "%s -> %s %3d%%\n",
     183                                                    entp->fts_path, to.p_path,
     184                                                    cp_pct(wtotal, fs->st_size));
     185                                        }
     186                                        if (wcount >= (ssize_t)wresid)
     187                                                break;
     188                                }
     189                                if (wcount != (ssize_t)wresid) {
    161190                                        warn("%s", to.p_path);
    162191                                        rval = 1;
    163192                                }
    164                                 if (munmap(p, fsize) < 0) {
     193                                /* Some systems don't unmap on close(2). */
     194                                if (munmap(p, fs->st_size) < 0) {
    165195                                        warn("%s", entp->fts_path);
    166196                                        rval = 1;
    167197                                }
    168198                        }
    169                 } else {
    170 mmap_failed:
     199                } else
    171200#endif
    172201                {
     202                        wtotal = 0;
    173203                        while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) {
    174                                 wcount = write(to_fd, buf, (size_t)rcount);
    175                                 if (rcount != wcount || wcount == -1) {
     204                                for (bufp = buf, wresid = rcount; ;
     205                                bufp += wcount, wresid -= wcount) {
     206                                        wcount = write(to_fd, bufp, wresid);
     207                                        if (wcount <= 0)
     208                                                break;
     209                                        wtotal += wcount;
     210                                        if (info) {
     211                                                info = 0;
     212                                                (void)fprintf(stderr,
     213                                                    "%s -> %s %3d%%\n",
     214                                                    entp->fts_path, to.p_path,
     215                                                    cp_pct(wtotal, fs->st_size));
     216                                        }
     217                                        if (wcount >= (ssize_t)wresid)
     218                                                break;
     219                                }
     220                                if (wcount != (ssize_t)wresid) {
    176221                                        warn("%s", to.p_path);
    177222                                        rval = 1;
     
    184229                        }
    185230                }
    186         }
    187 
    188         if (rval == 1) {
     231        } else {
     232                if (link(entp->fts_path, to.p_path)) {
     233                        warn("%s", to.p_path);
     234                        rval = 1;
     235                }
     236        }
     237        (void)close(from_fd);
     238       
     239        /*
     240         * Don't remove the target even after an error.  The target might
     241         * not be a regular file, or its attributes might be important,
     242         * or its contents might be irreplaceable.  It would only be safe
     243         * to remove it if we created it and its length is 0.
     244         */
     245
     246        if (!lflag) {
     247                if (pflag && setfile(cp_globals, fs, to_fd))
     248                        rval = 1;
     249                if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
     250                        rval = 1;
    189251                (void)close(from_fd);
    190                 (void)close(to_fd);
    191                 return (1);
    192         }
    193 
    194         if (pflag && setfile(cp_globals, fs, to_fd))
    195                 rval = 1;
    196         /*
    197          * If the source was setuid or setgid, lose the bits unless the
    198          * copy is owned by the same user and group.
    199          */
    200 #define RETAINBITS \
    201         (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
    202         else if (fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) {
    203                 if (fstat(to_fd, &to_stat)) {
     252                if (close(to_fd)) {
    204253                        warn("%s", to.p_path);
    205254                        rval = 1;
    206                 } else if (fs->st_gid == to_stat.st_gid &&
    207                     fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) {
    208                         warn("%s", to.p_path);
    209                         rval = 1;
    210                 }
    211         }
    212         (void)close(from_fd);
    213         if (close(to_fd)) {
    214                 warn("%s", to.p_path);
    215                 rval = 1;
    216         }
    217         /* set the mod/access times now after close of the fd */
    218         if (pflag && set_utimes(to.p_path, fs)) {
    219             rval = 1;
     255                }
    220256        }
    221257        return (rval);
     
    226262{
    227263        int len;
    228         char target[MAXPATHLEN];
    229 
    230         if ((len = readlink(p->fts_path, target, sizeof(target)-1)) == -1) {
     264        char llink[PATH_MAX];
     265
     266        if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
    231267                warn("readlink: %s", p->fts_path);
    232268                return (1);
    233269        }
    234         target[len] = '\0';
     270        llink[len] = '\0';
    235271        if (exists && unlink(to.p_path)) {
    236272                warn("unlink: %s", to.p_path);
    237273                return (1);
    238274        }
    239         if (symlink(target, to.p_path)) {
    240                 warn("symlink: %s", target);
    241                 return (1);
    242         }
    243         return (pflag ? setfile(cp_globals, p->fts_statp, 0) : 0);
     275        if (symlink(llink, to.p_path)) {
     276                warn("symlink: %s", llink);
     277                return (1);
     278        }
     279        return (pflag ? setfile(cp_globals, p->fts_statp, -1) : 0);
    244280}
    245281
     
    255291                return (1);
    256292        }
    257         return (pflag ? setfile(cp_globals, from_stat, 0) : 0);
     293        return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
    258294}
    259295
     
    269305                return (1);
    270306        }
    271         return (pflag ? setfile(cp_globals, from_stat, 0) : 0);
    272 }
    273 
    274 
    275 /*
    276  * Function: setfile
    277  *
    278  * Purpose:
    279  *   Set the owner/group/permissions for the "to" file to the information
    280  *   in the stat structure.  If fd is zero, also call set_utimes() to set
    281  *   the mod/access times.  If fd is non-zero, the caller must do a utimes
    282  *   itself after close(fd).
    283  */
    284 #define st_flags st_mode
     307        return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
     308}
     309
     310#define TIMESPEC_TO_TIMEVAL(tv, ts) {                                   \
     311        (tv)->tv_sec = *(ts);                                           \
     312        (tv)->tv_usec = 0;                                              \
     313}
     314
     315#define st_atimespec st_atime
     316#define st_mtimespec st_mtime
     317#define lutimes utimes
    285318
    286319int
    287320setfile(rtems_shell_cp_globals* cp_globals, struct stat *fs, int fd)
    288321{
    289         int rval, islink;
     322        static struct timeval tv[2];
     323        struct stat ts;
     324        int rval, gotstat, islink, fdval;
    290325
    291326        rval = 0;
    292         islink = S_ISLNK(fs->st_mode);
    293         fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO;
    294 
     327        fdval = fd != -1;
     328        islink = !fdval && S_ISLNK(fs->st_mode);
     329        fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
     330                       S_IRWXU | S_IRWXG | S_IRWXO;
     331
     332        TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
     333        TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
     334#if 0
     335        if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
     336                warn("%sutimes: %s", islink ? "l" : "", to.p_path);
     337                rval = 1;
     338        }
     339#endif
     340        if (fdval ? fstat(fd, &ts) :
     341            (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
     342                gotstat = 0;
     343        else {
     344                gotstat = 1;
     345                ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
     346                              S_IRWXU | S_IRWXG | S_IRWXO;
     347        }
    295348        /*
    296349         * Changing the ownership probably won't succeed, unless we're root
     
    299352         * chown.  If chown fails, lose setuid/setgid bits.
    300353         */
    301 #if 0
    302         if (fd ? fchown(fd, fs->st_uid, fs->st_gid) :
    303             lchown(to.p_path, fs->st_uid, fs->st_gid)) {
    304 #endif
    305         if (lchown(to.p_path, fs->st_uid, fs->st_gid)) {
    306                 if (errno != EPERM) {
    307                         warn("chown: %s", to.p_path);
    308                         rval = 1;
    309                 }
    310                 fs->st_mode &= ~(S_ISUID | S_ISGID);
    311         }
    312         if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) {
    313                 warn("chmod: %s", to.p_path);
    314                 rval = 1;
    315         }
    316 
    317 #if 0
    318         if (!islink && !Nflag) {
    319                 unsigned long fflags = fs->st_flags;
    320                 /*
    321                  * XXX
    322                  * NFS doesn't support chflags; ignore errors unless
    323                  * there's reason to believe we're losing bits.
    324                  * (Note, this still won't be right if the server
    325                  * supports flags and we were trying to *remove* flags
    326                  * on a file that we copied, i.e., that we didn't create.)
    327                  */
    328                 errno = 0;
    329                 if ((fd ? fchflags(fd, fflags) :
    330                     chflags(to.p_path, fflags)) == -1)
    331                         if (errno != EOPNOTSUPP || fs->st_flags != 0) {
    332                                 warn("chflags: %s", to.p_path);
     354        if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
     355                if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
     356                    (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
     357                    chown(to.p_path, fs->st_uid, fs->st_gid))) {
     358                        if (errno != EPERM) {
     359                                warn("chown: %s", to.p_path);
    333360                                rval = 1;
    334361                        }
    335         }
    336 #endif
    337         /* if fd is non-zero, caller must call set_utimes() after close() */
    338         if (fd == 0 && set_utimes(to.p_path, fs))
    339             rval = 1;
     362                        fs->st_mode &= ~(S_ISUID | S_ISGID);
     363                }
     364
     365        if (!gotstat || fs->st_mode != ts.st_mode)
     366                if (fdval ? fchmod(fd, fs->st_mode) :
     367                    (islink ? lchmod(to.p_path, fs->st_mode) :
     368                    chmod(to.p_path, fs->st_mode))) {
     369                        warn("chmod: %s", to.p_path);
     370                        rval = 1;
     371                }
     372
     373#if 0
     374        if (!gotstat || fs->st_flags != ts.st_flags)
     375                if (fdval ?
     376                    fchflags(fd, fs->st_flags) :
     377                    (islink ? (errno = ENOSYS) :
     378                    chflags(to.p_path, fs->st_flags))) {
     379                        warn("chflags: %s", to.p_path);
     380                        rval = 1;
     381                }
     382#endif
     383 
    340384        return (rval);
     385}
     386
     387int
     388preserve_fd_acls(int source_fd, int dest_fd)
     389{
     390#if 0
     391        struct acl *aclp;
     392        acl_t acl;
     393
     394        if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
     395            fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
     396                return (0);
     397        acl = acl_get_fd(source_fd);
     398        if (acl == NULL) {
     399                warn("failed to get acl entries while setting %s", to.p_path);
     400                return (1);
     401        }
     402        aclp = &acl->ats_acl;
     403        if (aclp->acl_cnt == 3)
     404                return (0);
     405        if (acl_set_fd(dest_fd, acl) < 0) {
     406                warn("failed to set acl entries for %s", to.p_path);
     407                return (1);
     408        }
     409#endif
     410        return (0);
     411}
     412
     413int
     414preserve_dir_acls(struct stat *fs, char *source_dir, char *dest_dir)
     415{
     416#if 0
     417        acl_t (*aclgetf)(const char *, acl_type_t);
     418        int (*aclsetf)(const char *, acl_type_t, acl_t);
     419        struct acl *aclp;
     420        acl_t acl;
     421
     422        if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
     423            pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
     424                return (0);
     425        /*
     426         * If the file is a link we will not follow it
     427         */
     428        if (S_ISLNK(fs->st_mode)) {
     429                aclgetf = acl_get_link_np;
     430                aclsetf = acl_set_link_np;
     431        } else {
     432                aclgetf = acl_get_file;
     433                aclsetf = acl_set_file;
     434        }
     435        /*
     436         * Even if there is no ACL_TYPE_DEFAULT entry here, a zero
     437         * size ACL will be returned. So it is not safe to simply
     438         * check the pointer to see if the default ACL is present.
     439         */
     440        acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
     441        if (acl == NULL) {
     442                warn("failed to get default acl entries on %s",
     443                    source_dir);
     444                return (1);
     445        }
     446        aclp = &acl->ats_acl;
     447        if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
     448            ACL_TYPE_DEFAULT, acl) < 0) {
     449                warn("failed to set default acl entries on %s",
     450                    dest_dir);
     451                return (1);
     452        }
     453        acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
     454        if (acl == NULL) {
     455                warn("failed to get acl entries on %s", source_dir);
     456                return (1);
     457        }
     458        aclp = &acl->ats_acl;
     459        if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
     460                warn("failed to set acl entries on %s", dest_dir);
     461                return (1);
     462        }
     463#endif
     464        return (0);
    341465}
    342466
     
    344468usage(void)
    345469{
    346         (void)fprintf(stderr,
    347             "usage: %s [-R [-H | -L | -P]] [-f | -i] [-pv] src target\n"
    348             "       %s [-R [-H | -L | -P]] [-f | -i] [-pv] src1 ... srcN directory\n",
    349             "cp", "cp");
    350 }
     470
     471        (void)fprintf(stderr, "%s\n%s\n",
     472"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",
     473"       cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
     474"target_directory");
     475}
Note: See TracChangeset for help on using the changeset viewer.