rm -r --one-file-system

Version:

coreutils-8.0 (fixed in 8.3)

How it is diagnosed (reproduced or source analysis)?

Reproduce and source analysis

How to reproduce?

create directory ./temp/temp

$coreutils-8.0/src/rm -r --one-file-system ./temp

./src/rm: skipping `./temp/temp', since it's on a different device

Symptom:

In the wrong version, rm -r --one-file-system failed to delete the normal directory ./temp/temp, and reported a misleading error message: ./src/rm: skipping `./temp/temp', since it's on a different device

Root cause:

A simple mistake in the comparing logic:

The developers are meant to compare whether the device ID (fts_dev) are equal or not, but they made a typo and compared the inode number against a device number !

The relevant code is as follows:

static enum RM_status

rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)

{

           if (ent->fts_info == FTS_DP

               && x->one_file_system

     /* st_ino: inode number; fts_dev: device number */

--            && ent->fts_statp->st_ino != fts->fts_dev)

++       && ent->fts_statp->st_dev != fts->fts_dev)

             {

               mark_ancestor_dirs (ent);

               error (0, 0, _("skipping %s, since it's on a different device"),

                      quote (ent->fts_path));

               return RM_ERROR;

             }

}

Is there an error message?

Yes. It’s the pattern of input check (developers are checking the input: file’s dev number).

Can Errlog print an error message?

Yes. This branch decision above is not tested! (otherwise this simple bug would definitely manifest!). So we can insert an error message on this untested branch decision.