I won't have a chance to look at the patch below until later this week,
but had two comments--

1) This method of handling recursive nodump is far superior to any actual
   inheritence of the flag as part of file system operations, as currently
   no other file flags are inherited from the parent directory -- the only
   property that is inherited is the group.  With ACLs, the parent's
   default ACL will also play a role in the new access ACL.  In any case,
   there is no precedent for file flag inheritence.

2) Please run the patch by freebsd-audit -- there have been a fair number
   of vulnerabilities in the fts code in the past due to race conditions
   of various sorts, and it's important that any modifications be
   carefully scrutinized to prevent the reintroduction of vulnerabilites.

However, the general idea sounds very useful, and something that I'd find
applicable on a daily basis :-).

Robert N M Watson             FreeBSD Core Team, TrustedBSD Project
[EMAIL PROTECTED]      NAI Labs, Safeport Network Services

On Mon, 26 Feb 2001, Dima Dorfman wrote:

> Hello -hackers
> 
> Some time ago, on -arch, phk proposed that the nodump flag should be
> inherited (see 'inheriting the "nodump" flag ?' around Dec. 2000).
> This was generally considered a good idea, however, the patch to the
> kernel he proposed was thought an ugly hack.  In addition, jeroen
> pointed out that NetBSD had implemented this functionality the Right
> Way(tm), in dump(8).
> 
> Attached below is a port of NetBSD's patch to FreeBSD's dump(8).
> dump's tree walker is a little weird, so the patch is a little more
> complicated than calling fts_set with FTS_SKIP.  For the technical
> details of what it does, see:
> http://lists.openresources.com/NetBSD/tech-kern/msg00453.html.
> 
> I've been using this on two of my hosts for a while, and it works as
> expected.  Given the additional fact that NetBSD has had this for
> almost two years, and that the patch below looks very similar to the
> one they applied, I doubt it significantly breaks anything.
> 
> Comments?
> 
> Thanks in advance
> 
>                                       Dima Dorfman
>                                       [EMAIL PROTECTED]
> 
> 
> Index: traverse.c
> ===================================================================
> RCS file: /st/src/FreeBSD/src/sbin/dump/traverse.c,v
> retrieving revision 1.11
> diff -u -r1.11 traverse.c
> --- traverse.c        2000/04/14 06:14:59     1.11
> +++ traverse.c        2001/02/20 01:39:06
> @@ -74,9 +74,11 @@
>  typedef      long fsizeT;
>  #endif
>  
> -static       int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size));
> +static       int dirindir __P((ino_t ino, daddr_t blkno, int level, long *size,
> +    long *tapesize, int nodump));
>  static       void dmpindir __P((ino_t ino, daddr_t blk, int level, fsizeT *size));
> -static       int searchdir __P((ino_t ino, daddr_t blkno, long size, long 
>filesize));
> +static       int searchdir __P((ino_t ino, daddr_t blkno, long size, long filesize,
> +    long *tapesize, int nodump));
>  
>  /*
>   * This is an estimation of the number of TP_BSIZE blocks in the file.
> @@ -152,10 +154,14 @@
>               dp = getino(ino);
>               if ((mode = (dp->di_mode & IFMT)) == 0)
>                       continue;
> -             SETINO(ino, usedinomap);
> +             /*
> +              * All dirs go in dumpdirmap; only inodes that are to
> +              * be dumped go in usedinomap and dumpinomap, however.
> +              */
>               if (mode == IFDIR)
>                       SETINO(ino, dumpdirmap);
>               if (WANTTODUMP(dp)) {
> +                     SETINO(ino, usedinomap);
>                       SETINO(ino, dumpinomap);
>                       if (mode != IFREG && mode != IFDIR && mode != IFLNK)
>                               *tapesize += 1;
> @@ -192,9 +198,10 @@
>       long *tapesize;
>  {
>       register struct dinode *dp;
> -     register int i, isdir;
> +     register int i, isdir, nodump;
>       register char *map;
>       register ino_t ino;
> +     struct dinode di;
>       long filesize;
>       int ret, change = 0;
>  
> @@ -204,24 +211,34 @@
>                       isdir = *map++;
>               else
>                       isdir >>= 1;
> -             if ((isdir & 1) == 0 || TSTINO(ino, dumpinomap))
> +             /*
> +              * If a directory has been removed from usedinomap, it
> +              * either has the nodump flag set, or has inherited
> +              * it.  Although a directory can't be in dumpinomap if
> +              * it isn't in usedinomap, we have to go through it to
> +              * propogate the nodump flag.
> +              */
> +             nodump = (TSTINO(ino, usedinomap) == 0);
> +             if ((isdir & 1) == 0 || (TSTINO(ino, dumpinomap) && !nodump))
>                       continue;
>               dp = getino(ino);
> -             filesize = dp->di_size;
> +             di = *dp;       /* inode buf may change in searchdir(). */
> +             filesize = di.di_size;
>               for (ret = 0, i = 0; filesize > 0 && i < NDADDR; i++) {
> -                     if (dp->di_db[i] != 0)
> -                             ret |= searchdir(ino, dp->di_db[i],
> +                     if (di.di_db[i] != 0)
> +                             ret |= searchdir(ino, di.di_db[i],
>                                       (long)dblksize(sblock, dp, i),
> -                                     filesize);
> +                                     filesize, tapesize, nodump);
>                       if (ret & HASDUMPEDFILE)
>                               filesize = 0;
>                       else
>                               filesize -= sblock->fs_bsize;
>               }
>               for (i = 0; filesize > 0 && i < NIADDR; i++) {
> -                     if (dp->di_ib[i] == 0)
> +                     if (di.di_ib[i] == 0)
>                               continue;
> -                     ret |= dirindir(ino, dp->di_ib[i], i, &filesize);
> +                     ret |= dirindir(ino, di.di_ib[i], i, &filesize,
> +                         tapesize, nodump);
>               }
>               if (ret & HASDUMPEDFILE) {
>                       SETINO(ino, dumpinomap);
> @@ -229,12 +246,15 @@
>                       change = 1;
>                       continue;
>               }
> -             if ((ret & HASSUBDIRS) == 0) {
> +             if (nodump) {
> +                     if (ret & HASSUBDIRS)
> +                             change = 1;     /* subdirs inherit nodump */
> +                     CLRINO(ino, dumpdirmap);
> +             } else if ((ret & HASSUBDIRS) == 0)
>                       if (!TSTINO(ino, dumpinomap)) {
>                               CLRINO(ino, dumpdirmap);
>                               change = 1;
>                       }
> -             }
>       }
>       return (change);
>  }
> @@ -245,11 +265,13 @@
>   * require the directory to be dumped.
>   */
>  static int
> -dirindir(ino, blkno, ind_level, filesize)
> +dirindir(ino, blkno, ind_level, filesize, tapesize, nodump)
>       ino_t ino;
>       daddr_t blkno;
>       int ind_level;
>       long *filesize;
> +     long *tapesize;
> +     int nodump;
>  {
>       int ret = 0;
>       register int i;
> @@ -261,7 +283,7 @@
>                       blkno = idblk[i];
>                       if (blkno != 0)
>                               ret |= searchdir(ino, blkno, sblock->fs_bsize,
> -                                     *filesize);
> +                                     *filesize, tapesize, nodump);
>                       if (ret & HASDUMPEDFILE)
>                               *filesize = 0;
>                       else
> @@ -273,7 +295,8 @@
>       for (i = 0; *filesize > 0 && i < NINDIR(sblock); i++) {
>               blkno = idblk[i];
>               if (blkno != 0)
> -                     ret |= dirindir(ino, blkno, ind_level, filesize);
> +                     ret |= dirindir(ino, blkno, ind_level, filesize,
> +                         tapesize, nodump);
>       }
>       return (ret);
>  }
> @@ -284,13 +307,16 @@
>   * contains any subdirectories.
>   */
>  static int
> -searchdir(ino, blkno, size, filesize)
> +searchdir(ino, blkno, size, filesize, tapesize, nodump)
>       ino_t ino;
>       daddr_t blkno;
>       register long size;
>       long filesize;
> +     long *tapesize;
> +     int nodump;
>  {
>       register struct direct *dp;
> +     register struct dinode *ip;
>       register long loc, ret = 0;
>       char dblk[MAXBSIZE];
>  
> @@ -311,16 +337,30 @@
>                               continue;
>                       if (dp->d_name[1] == '.' && dp->d_name[2] == '\0')
>                               continue;
> -             }
> -             if (TSTINO(dp->d_ino, dumpinomap)) {
> -                     ret |= HASDUMPEDFILE;
> -                     if (ret & HASSUBDIRS)
> -                             break;
>               }
> -             if (TSTINO(dp->d_ino, dumpdirmap)) {
> -                     ret |= HASSUBDIRS;
> -                     if (ret & HASDUMPEDFILE)
> -                             break;
> +             if (nodump) {
> +                     ip = getino(dp->d_ino);
> +                     if (TSTINO(dp->d_ino, dumpinomap)) {
> +                             CLRINO(dp->d_ino, dumpinomap);
> +                             CLRINO(dp->d_ino, usedinomap);
> +                             *tapesize -= blockest(ip);
> +                     }
> +                     /* Add back to dumpdirmap to propogate nodump. */
> +                     if ((ip->di_mode & IFMT) == IFDIR) {
> +                             SETINO(dp->d_ino, dumpdirmap);
> +                             ret |= HASSUBDIRS;
> +                     }
> +             } else {
> +                     if (TSTINO(dp->d_ino, dumpinomap)) {
> +                             ret |= HASDUMPEDFILE;
> +                             if (ret & HASSUBDIRS)
> +                                     break;
> +                     }
> +                     if (TSTINO(dp->d_ino, dumpdirmap)) {
> +                             ret |= HASSUBDIRS;
> +                             if (ret & HASDUMPEDFILE)
> +                                     break;
> +                     }
>               }
>       }
>       return (ret);
> 
> 
> To Unsubscribe: send mail to [EMAIL PROTECTED]
> with "unsubscribe freebsd-hackers" in the body of the message
> 


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to