# pass in a file name, a file handle or nothing
# returns a unique string that changes when the file changes
sub FileMeta {
if (my $fh = shift) {
my ($dev, $inode, $size, $mtime) = (stat($fh))[0,1,7,9];
return "$size:$dev;$inode:$mtime";
}
else {
my ($dev, $inode, $size, $mtime) = (stat(_))[0,1,7,9];
return "$size:$dev;$inode:$mtime";
}
}
sub FileMeta {
my $fh = shift;
my ($dev, $inode, $size, $mtime) = ($fh ? stat($fh) : stat(_))[0,1,7,9];
return join ":", $size, $dev, $inode, $mtime;
}
(i also assumed the ';' in the return string was a typo)
sub FileMeta {
my $fh = shift;
# glue together the size, dev, inode, and mtime
return join ":", ($fh ? stat($fh) : stat(_))[7,0,1,9];
}
Another approach (though you noted avoiding modules) would be to MD5 the string and return that so that .. or to include in the unique string the MD5 of the contents (of course that's more overhead as well).
# note: order of the joined parts is not particularily important
sub FileMeta { join ":", (stat(shift || *_))[0,1,7,9] }
File size is certainly a "feel good" item to include. But if you want a fool-proof system, then you shouldn't need to check file size. If your system might miss certain types of changes if file size weren't included, then it can certainly miss those same types of changes that also preserve file size.
What types of changes might your system miss? The simplest is restoring mtime via utime. Recently it was proposed that simply testing mtime and ctime would be enough. But that can be fooled by renaming directories, so I would personally use dev, inode, mtime, and ctime and might leave size out of it.
Of course, adding ctime into the picture means that "chmod" will caues the file to appear changed. Of course, you can also touch(1) the file (or quite a few other similar actions) to make the file appeared changed even though the data inside of it remains the same. So I don't mind that ctime adds a few more false positives, in part because it removes some important false negatives, but especially because it removes all of the false negatives (I believe) that are possible without root access (on common Unix file systems).
Note that ctime is a bit different on some file systems and dev and/or inode number might be useless on some file systems. I'm disappointed and surprised that Perl doesn't provide inode numbers on Win32 -- I thought there was an equivalent available, but I don't have those details "swapped in" at the moment. So I'd probably still include size just for such systems. YMMV.
- tye
I'm disappointed and surprised that Perl doesn't provide inode numbers on Win32 -- I thought there was an equivalent available, but I don't have those details "swapped in" at the moment.
This may help.
perlmonks.org content © perlmonks.org and BrowserUk, davidrw, ruzam, tye, whio
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03