diff --git a/bin/cp/cp.1 b/bin/cp/cp.1 index 76d785912811..4038aeeb8a50 100644 --- a/bin/cp/cp.1 +++ b/bin/cp/cp.1 @@ -32,7 +32,7 @@ .\" @(#)cp.1 8.3 (Berkeley) 4/18/94 .\" $FreeBSD$ .\" -.Dd August 24, 2006 +.Dd October 7, 2006 .Dt CP 1 .Os .Sh NAME @@ -252,8 +252,37 @@ utility had a .Fl r option. This implementation supports that option, however, its use is strongly -discouraged, as it does not correctly copy special files, symbolic links -or fifo's. +discouraged as its behavior is very implementation dependent. +In this version of +.Nm , +.Fl r +is just a synonym for +.Fl RL . +The +.Fl R +option gives the correct behavior while +.Fl L +preserves the sometimes-useful historical behavior of following symbolic links. +The +.Fl r +option is deprecated in +.Tn POSIX + and its behavior is likely to be different +in future versions of +.Nm +and its behavior is likely to be different +in future versions of +.Fx . +Previous versions of +.Nm +in +.Fx , +the +.Fl r +behavior was to not correctly copy special files, symbolic links +or fifos. +Symbolic links were followed, and the contents of special +files and fifos were copied to regular files. .Pp The .Fl v diff --git a/bin/cp/cp.c b/bin/cp/cp.c index cad071007b8a..13757f0b8ef7 100644 --- a/bin/cp/cp.c +++ b/bin/cp/cp.c @@ -138,7 +138,8 @@ main(int argc, char *argv[]) pflag = 1; break; case 'r': - rflag = 1; + rflag = Lflag = 1; + Hflag = Pflag = 0; break; case 'v': vflag = 1; @@ -155,15 +156,12 @@ main(int argc, char *argv[]) fts_options = FTS_NOCHDIR | FTS_PHYSICAL; if (rflag) { - if (Rflag) + if (Rflag) errx(1, "the -R and -r options may not be specified together."); - if (Hflag || Lflag || Pflag) - errx(1, - "the -H, -L, and -P options may not be specified with the -r option."); - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; - } + } + if (rflag && !Hflag && !Pflag) + Rflag = 1; if (Rflag) { if (Hflag) fts_options |= FTS_COMFOLLOW; @@ -227,12 +225,12 @@ main(int argc, char *argv[]) * the initial mkdir(). */ if (r == -1) { - if (rflag || (Rflag && (Lflag || Hflag))) + if (Rflag && (Lflag || Hflag)) stat(*argv, &tmp_stat); else lstat(*argv, &tmp_stat); - if (S_ISDIR(tmp_stat.st_mode) && (Rflag || rflag)) + if (S_ISDIR(tmp_stat.st_mode) && (Rflag)) type = DIR_TO_DNE; else type = FILE_TO_FILE; @@ -420,7 +418,7 @@ copy(char *argv[], enum op type, int fts_options) } break; case S_IFDIR: - if (!Rflag && !rflag) { + if (!Rflag) { warnx("%s is a directory (not copied).", curr->fts_path); (void)fts_set(ftsp, curr, FTS_SKIP);