File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 #ifdef HAVE_CONFIG_H
0033 #include "config.h"
0034 #endif
0035
0036 #include <sys/cdefs.h>
0037 #if 0
0038 #ifndef lint
0039 #if 0
0040 static char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94";
0041 #else
0042 __RCSID("$NetBSD: utils.c,v 1.29 2005/10/15 18:22:18 christos Exp $");
0043 #endif
0044 #endif
0045 #endif
0046
0047 #if 0
0048 #include <sys/mman.h>
0049 #endif
0050 #include <sys/param.h>
0051 #include <sys/stat.h>
0052 #include <sys/time.h>
0053 #include <utime.h>
0054
0055 #include "err.h"
0056 #include <errno.h>
0057 #include <fcntl.h>
0058 #include "fts.h"
0059 #include <limits.h>
0060 #include <stdio.h>
0061 #include <stdlib.h>
0062 #include <string.h>
0063 #include <unistd.h>
0064
0065 #include "extern-cp.h"
0066
0067 #define lchmod chmod
0068 #define lchown chown
0069
0070 #define cp_pct(x, y) ((y == 0) ? 0 : (int)(100.0 * (x) / (y)))
0071
0072 int
0073 set_utimes(const char *file, struct stat *fs)
0074 {
0075 struct utimbuf tv;
0076
0077 tv.actime = fs->st_atime;
0078 tv.modtime = fs->st_mtime;
0079
0080 if (utime(file, &tv)) {
0081 warn("lutimes: %s", file);
0082 return (1);
0083 }
0084 return (0);
0085 }
0086
0087 int
0088 copy_file(rtems_shell_cp_globals* cp_globals RTEMS_UNUSED, FTSENT *entp, int dne)
0089 {
0090 #define MAX_READ max_read
0091 int max_read;
0092 char* buf;
0093 struct stat *fs;
0094 ssize_t wcount;
0095 size_t wresid;
0096 off_t wtotal;
0097 int ch, checkch, from_fd = 0, rcount, rval, to_fd = 0;
0098 char *bufp;
0099 #ifdef VM_AND_BUFFER_CACHE_SYNCHRONIZED
0100 char *p;
0101 #endif
0102
0103 fs = entp->fts_statp;
0104
0105 max_read = fs->st_blksize;
0106 if (max_read < (8 * 1024))
0107 max_read = 8 * 1024;
0108 buf = malloc (max_read);
0109 if (!buf)
0110 {
0111 warn("no memory");
0112 return (1);
0113 }
0114
0115 if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) {
0116 warn("%s", entp->fts_path);
0117 (void)free(buf);
0118 return (1);
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 if (!dne) {
0130 #define YESNO "(y/n [n]) "
0131 if (nflag) {
0132 if (vflag)
0133 printf("%s not overwritten\n", to.p_path);
0134 (void)close(from_fd);
0135 (void)free(buf);
0136 return (0);
0137 } else if (iflag) {
0138 (void)fprintf(stderr, "overwrite %s? %s",
0139 to.p_path, YESNO);
0140 checkch = ch = getchar();
0141 while (ch != '\n' && ch != EOF)
0142 ch = getchar();
0143 if (checkch != 'y' && checkch != 'Y') {
0144 (void)close(from_fd);
0145 (void)free(buf);
0146 (void)fprintf(stderr, "not overwritten\n");
0147 return (1);
0148 }
0149 }
0150
0151 if (fflag) {
0152
0153
0154 (void)unlink(to.p_path);
0155 if (!lflag)
0156 to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
0157 fs->st_mode & ~(S_ISUID | S_ISGID));
0158 } else {
0159 if (!lflag)
0160
0161 to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0);
0162 }
0163 } else {
0164 if (!lflag)
0165 to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT,
0166 fs->st_mode & ~(S_ISUID | S_ISGID));
0167 }
0168
0169 if (to_fd == -1) {
0170 warn("%s", to.p_path);
0171 (void)close(from_fd);
0172 (void)free(buf);
0173 return (1);
0174 }
0175
0176 rval = 0;
0177
0178 if (!lflag) {
0179
0180
0181
0182
0183
0184 #ifdef CCJ_REMOVED_VM_AND_BUFFER_CACHE_SYNCHRONIZED
0185 if (S_ISREG(fs->st_mode) && fs->st_size > 0 &&
0186 fs->st_size <= 8 * 1048576) {
0187 if ((p = mmap(NULL, (size_t)fs->st_size, PROT_READ,
0188 MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) {
0189 warn("%s", entp->fts_path);
0190 rval = 1;
0191 } else {
0192 wtotal = 0;
0193 for (bufp = p, wresid = fs->st_size; ;
0194 bufp += wcount, wresid -= (size_t)wcount) {
0195 wcount = write(to_fd, bufp, wresid);
0196 if (wcount <= 0)
0197 break;
0198 wtotal += wcount;
0199 if (info) {
0200 info = 0;
0201 (void)fprintf(stderr,
0202 "%s -> %s %3d%%\n",
0203 entp->fts_path, to.p_path,
0204 cp_pct(wtotal, fs->st_size));
0205 }
0206 if (wcount >= (ssize_t)wresid)
0207 break;
0208 }
0209 if (wcount != (ssize_t)wresid) {
0210 warn("%s", to.p_path);
0211 rval = 1;
0212 }
0213
0214 if (munmap(p, fs->st_size) < 0) {
0215 warn("%s", entp->fts_path);
0216 rval = 1;
0217 }
0218 }
0219 } else
0220 #endif
0221 {
0222 wtotal = 0;
0223 while ((rcount = read(from_fd, buf, MAX_READ)) > 0) {
0224 for (bufp = buf, wresid = rcount; ;
0225 bufp += wcount, wresid -= wcount) {
0226 wcount = write(to_fd, bufp, wresid);
0227 if (wcount <= 0)
0228 break;
0229 wtotal += wcount;
0230 if (info) {
0231 info = 0;
0232 (void)fprintf(stderr,
0233 "%s -> %s %3d%%\n",
0234 entp->fts_path, to.p_path,
0235 cp_pct(wtotal, fs->st_size));
0236 }
0237 if (wcount >= (ssize_t)wresid)
0238 break;
0239 }
0240 if (wcount != (ssize_t)wresid) {
0241 warn("%s", to.p_path);
0242 rval = 1;
0243 break;
0244 }
0245 }
0246 if (rcount < 0) {
0247 warn("%s", entp->fts_path);
0248 rval = 1;
0249 }
0250 }
0251 } else {
0252 if (link(entp->fts_path, to.p_path)) {
0253 warn("%s", to.p_path);
0254 rval = 1;
0255 }
0256 }
0257 (void)close(from_fd);
0258
0259
0260
0261
0262
0263
0264
0265
0266 if (!lflag) {
0267 if (pflag && setfile(cp_globals, fs, to_fd))
0268 rval = 1;
0269 if (pflag && preserve_fd_acls(from_fd, to_fd) != 0)
0270 rval = 1;
0271 (void)close(from_fd);
0272 if (close(to_fd)) {
0273 warn("%s", to.p_path);
0274 rval = 1;
0275 }
0276 }
0277 (void)free(buf);
0278 return (rval);
0279 }
0280
0281 int
0282 copy_link(rtems_shell_cp_globals* cp_globals, FTSENT *p, int exists)
0283 {
0284 ssize_t len;
0285 char llink[PATH_MAX];
0286
0287 if ((len = readlink(p->fts_path, llink, sizeof(llink) - 1)) == -1) {
0288 warn("readlink: %s", p->fts_path);
0289 return (1);
0290 }
0291 llink[len] = '\0';
0292 if (exists && unlink(to.p_path)) {
0293 warn("unlink: %s", to.p_path);
0294 return (1);
0295 }
0296 if (symlink(llink, to.p_path)) {
0297 warn("symlink: %s", llink);
0298 return (1);
0299 }
0300 return (pflag ? setfile(cp_globals, p->fts_statp, -1) : 0);
0301 }
0302
0303 int
0304 copy_fifo(rtems_shell_cp_globals* cp_globals, struct stat *from_stat, int exists)
0305 {
0306 if (exists && unlink(to.p_path)) {
0307 warn("unlink: %s", to.p_path);
0308 return (1);
0309 }
0310 if (mkfifo(to.p_path, from_stat->st_mode)) {
0311 warn("mkfifo: %s", to.p_path);
0312 return (1);
0313 }
0314 return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
0315 }
0316
0317 int
0318 copy_special(rtems_shell_cp_globals* cp_globals, struct stat *from_stat, int exists)
0319 {
0320 if (exists && unlink(to.p_path)) {
0321 warn("unlink: %s", to.p_path);
0322 return (1);
0323 }
0324 if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) {
0325 warn("mknod: %s", to.p_path);
0326 return (1);
0327 }
0328 return (pflag ? setfile(cp_globals, from_stat, -1) : 0);
0329 }
0330
0331 #if defined(__rtems__)
0332
0333
0334
0335
0336
0337 #undef TIMESPEC_TO_TIMEVAL
0338 #endif
0339
0340 #define TIMESPEC_TO_TIMEVAL(tv, ts) { \
0341 (tv)->tv_sec = *(ts); \
0342 (tv)->tv_usec = 0; \
0343 }
0344
0345 #define st_atimespec st_atime
0346 #define st_mtimespec st_mtime
0347 #define lutimes utimes
0348
0349 int
0350 setfile(rtems_shell_cp_globals* cp_globals, struct stat *fs, int fd)
0351 {
0352 static struct timeval tv[2];
0353 struct stat ts;
0354 int rval, gotstat, islink, fdval;
0355
0356 rval = 0;
0357 fdval = fd != -1;
0358 islink = !fdval && S_ISLNK(fs->st_mode);
0359 fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
0360 S_IRWXU | S_IRWXG | S_IRWXO;
0361
0362 TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
0363 TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
0364 #if 0
0365 if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
0366 warn("%sutimes: %s", islink ? "l" : "", to.p_path);
0367 rval = 1;
0368 }
0369 #endif
0370 if (fdval ? fstat(fd, &ts) :
0371 (islink ? lstat(to.p_path, &ts) : stat(to.p_path, &ts)))
0372 gotstat = 0;
0373 else {
0374 gotstat = 1;
0375 ts.st_mode &= S_ISUID | S_ISGID | S_ISVTX |
0376 S_IRWXU | S_IRWXG | S_IRWXO;
0377 }
0378
0379
0380
0381
0382
0383
0384 if (!gotstat || fs->st_uid != ts.st_uid || fs->st_gid != ts.st_gid)
0385 if (fdval ? fchown(fd, fs->st_uid, fs->st_gid) :
0386 (islink ? lchown(to.p_path, fs->st_uid, fs->st_gid) :
0387 chown(to.p_path, fs->st_uid, fs->st_gid))) {
0388 if (errno != EPERM) {
0389 warn("chown: %s", to.p_path);
0390 rval = 1;
0391 }
0392 fs->st_mode &= ~(S_ISUID | S_ISGID);
0393 }
0394
0395 if (!gotstat || fs->st_mode != ts.st_mode)
0396 if (fdval ? fchmod(fd, fs->st_mode) :
0397 (islink ? lchmod(to.p_path, fs->st_mode) :
0398 chmod(to.p_path, fs->st_mode))) {
0399 warn("chmod: %s", to.p_path);
0400 rval = 1;
0401 }
0402
0403 #if 0
0404 if (!gotstat || fs->st_flags != ts.st_flags)
0405 if (fdval ?
0406 fchflags(fd, fs->st_flags) :
0407 (islink ? (errno = ENOSYS) :
0408 chflags(to.p_path, fs->st_flags))) {
0409 warn("chflags: %s", to.p_path);
0410 rval = 1;
0411 }
0412 #endif
0413
0414 return (rval);
0415 }
0416
0417 int
0418 preserve_fd_acls(int source_fd RTEMS_UNUSED, int dest_fd RTEMS_UNUSED)
0419 {
0420 #if 0
0421 struct acl *aclp;
0422 acl_t acl;
0423
0424 if (fpathconf(source_fd, _PC_ACL_EXTENDED) != 1 ||
0425 fpathconf(dest_fd, _PC_ACL_EXTENDED) != 1)
0426 return (0);
0427 acl = acl_get_fd(source_fd);
0428 if (acl == NULL) {
0429 warn("failed to get acl entries while setting %s", to.p_path);
0430 return (1);
0431 }
0432 aclp = &acl->ats_acl;
0433 if (aclp->acl_cnt == 3)
0434 return (0);
0435 if (acl_set_fd(dest_fd, acl) < 0) {
0436 warn("failed to set acl entries for %s", to.p_path);
0437 return (1);
0438 }
0439 #endif
0440 return (0);
0441 }
0442
0443 int
0444 preserve_dir_acls(struct stat *fs RTEMS_UNUSED, char *source_dir RTEMS_UNUSED, char *dest_dir RTEMS_UNUSED)
0445 {
0446 #if 0
0447 acl_t (*aclgetf)(const char *, acl_type_t);
0448 int (*aclsetf)(const char *, acl_type_t, acl_t);
0449 struct acl *aclp;
0450 acl_t acl;
0451
0452 if (pathconf(source_dir, _PC_ACL_EXTENDED) != 1 ||
0453 pathconf(dest_dir, _PC_ACL_EXTENDED) != 1)
0454 return (0);
0455
0456
0457
0458 if (S_ISLNK(fs->st_mode)) {
0459 aclgetf = acl_get_link_np;
0460 aclsetf = acl_set_link_np;
0461 } else {
0462 aclgetf = acl_get_file;
0463 aclsetf = acl_set_file;
0464 }
0465
0466
0467
0468
0469
0470 acl = aclgetf(source_dir, ACL_TYPE_DEFAULT);
0471 if (acl == NULL) {
0472 warn("failed to get default acl entries on %s",
0473 source_dir);
0474 return (1);
0475 }
0476 aclp = &acl->ats_acl;
0477 if (aclp->acl_cnt != 0 && aclsetf(dest_dir,
0478 ACL_TYPE_DEFAULT, acl) < 0) {
0479 warn("failed to set default acl entries on %s",
0480 dest_dir);
0481 return (1);
0482 }
0483 acl = aclgetf(source_dir, ACL_TYPE_ACCESS);
0484 if (acl == NULL) {
0485 warn("failed to get acl entries on %s", source_dir);
0486 return (1);
0487 }
0488 aclp = &acl->ats_acl;
0489 if (aclsetf(dest_dir, ACL_TYPE_ACCESS, acl) < 0) {
0490 warn("failed to set acl entries on %s", dest_dir);
0491 return (1);
0492 }
0493 #endif
0494 return (0);
0495 }
0496
0497 void
0498 usage(rtems_shell_cp_globals* cp_globals)
0499 {
0500 (void)fprintf(stderr, "%s\n%s\n",
0501 "usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",
0502 " cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
0503 "target_directory");
0504 longjmp (cp_globals->exit_jmp, 1);
0505 }