@@ -331,10 +331,18 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
331331 assert (to .dir < 0 );
332332 assert (root_stat == NULL );
333333 mode = curr_stat -> st_mode | S_IRWXU ;
334+ /*
335+ * Will our umask prevent us from entering
336+ * the directory after we create it?
337+ */
338+ if (~mask & S_IRWXU )
339+ umask (~mask & ~S_IRWXU );
334340 if (mkdir (to .base , mode ) != 0 ) {
335341 warn ("%s" , to .base );
336342 fts_set (ftsp , curr , FTS_SKIP );
337343 badcp = rval = 1 ;
344+ if (~mask & S_IRWXU )
345+ umask (~mask );
338346 continue ;
339347 }
340348 to .dir = open (to .base , O_DIRECTORY | O_SEARCH );
@@ -343,6 +351,8 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
343351 (void )rmdir (to .base );
344352 fts_set (ftsp , curr , FTS_SKIP );
345353 badcp = rval = 1 ;
354+ if (~mask & S_IRWXU )
355+ umask (~mask );
346356 continue ;
347357 }
348358 if (fstat (to .dir , & created_root_stat ) != 0 ) {
@@ -352,9 +362,14 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
352362 fts_set (ftsp , curr , FTS_SKIP );
353363 to .dir = -1 ;
354364 badcp = rval = 1 ;
365+ if (~mask & S_IRWXU )
366+ umask (~mask );
355367 continue ;
356368 }
369+ if (~mask & S_IRWXU )
370+ umask (~mask );
357371 root_stat = & created_root_stat ;
372+ curr -> fts_number = 1 ;
358373 } else {
359374 /* entering a directory; append its name to to.path */
360375 len = snprintf (to .end , END (to .path ) - to .end , "%s%s" ,
@@ -432,9 +447,7 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
432447 } else if (curr -> fts_number ) {
433448 const char * path = * to .path ? to .path : dot ;
434449 mode = curr_stat -> st_mode ;
435- if (((mode & (S_ISUID | S_ISGID | S_ISTXT )) ||
436- ((mode | S_IRWXU ) & mask ) != (mode & mask )) &&
437- fchmodat (to .dir , path , mode & mask , 0 ) != 0 ) {
450+ if (fchmodat (to .dir , path , mode & mask , 0 ) != 0 ) {
438451 warn ("chmod: %s/%s" , to .base , to .path );
439452 rval = 1 ;
440453 }
@@ -538,12 +551,22 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
538551 */
539552 if (dne ) {
540553 mode = curr_stat -> st_mode | S_IRWXU ;
554+ /*
555+ * Will our umask prevent us from entering
556+ * the directory after we create it?
557+ */
558+ if (~mask & S_IRWXU )
559+ umask (~mask & ~S_IRWXU );
541560 if (mkdirat (to .dir , to .path , mode ) != 0 ) {
542561 warn ("%s/%s" , to .base , to .path );
543562 fts_set (ftsp , curr , FTS_SKIP );
544563 badcp = rval = 1 ;
564+ if (~mask & S_IRWXU )
565+ umask (~mask );
545566 break ;
546567 }
568+ if (~mask & S_IRWXU )
569+ umask (~mask );
547570 } else if (!S_ISDIR (to_stat .st_mode )) {
548571 warnc (ENOTDIR , "%s/%s" , to .base , to .path );
549572 fts_set (ftsp , curr , FTS_SKIP );
@@ -554,8 +577,10 @@ copy(char *argv[], enum op type, int fts_options, struct stat *root_stat)
554577 * Arrange to correct directory attributes later
555578 * (in the post-order phase) if this is a new
556579 * directory, or if the -p flag is in effect.
580+ * Note that fts_number may already be set if this
581+ * is the newly created destination directory.
557582 */
558- curr -> fts_number = pflag || dne ;
583+ curr -> fts_number | = pflag || dne ;
559584 break ;
560585 case S_IFBLK :
561586 case S_IFCHR :
0 commit comments