notes blog about

2014-09-09

Unix filesystem consists of two parts:

Entries in the index are called inodes (index nodes). Inodes contain metadata (data about data) on the files, like:

There is also a time information among the metadata. Actually three types of them:

.-------------+------------+---------+------------------------------------------------------------------.
| Type        | Short name | ls opts | Defines the last time when ...                                   |
+-------------+------------+---------+------------------------------------------------------------------+
| Access Time | atime      | -lu     | file was read, directory was searched                            |
| Modify Time | mtime      | -l      | file was written to, directory's entry was added/renamed/removed |
| Change Time | ctime      | -lc     | inode information (the metadata) was changed                     |
'-------------+------------+---------+------------------------------------------------------------------'

Using timestamps

To get information about a file (actually about its inode) run the shell command stat or find:

Getting time info with Perl

To access an inode from within Perl, use:

1. stat function (returns pretty much everything that the underlying stat() Unix system call returns):

my($atime, $mtime, $ctime) = (stat($filename))[8,9,10] or die "Couldn't stat '$filename': $!";

.. $atime, $mtime, and $ctime – The three timestamps represented in the system’s timestamp format: a 32-bit number telling how many seconds have passed since the “Epoch”, an arbitrary starting point for measuring system time (it’s the beginning of 1970 at midnight Universal Time on Unix systems).

2. File::stat:

use File::stat;

my $file  = "/bin/ls";
my $inode = stat($file) or die "No $file: $!";
my $ctime = $inode->ctime;
my $size  = $inode->size;

3. -X operators, modeled on the shell’s test operators:

my @original_files = qw/ file1 file2 file2 /;  # in practice - read from the FS using a glob 
                                               #  or directory handle
my @big_old_files;                             # files we want to put on backup tapes
foreach my $filename (@original_files) {
    push @big_old_files, $filename             
      if -s $filename > 100_000 and -A _ > 90; # -X operators cache value returned by stat(2); 
                                               #  access it via _
}

Changing timestamps with Perl

In those rare cases when you want to lie to other programs about when a file was most recently accessed (atime) or modified (mtime), use the utime function:

my $atime = time;                 # now
my $mtime = $time - 24 * 60 * 60; # one day (86400 secs) ago
utime $atime, $mtime, glob "*";   # set access to now, mod to a day ago

.. the third timestamp (ctime) is always set to “now” whenever anything alters a file - there’s no way to set it with utime

.. the primary purpose of ctime is for incremental backups - if the file’s ctime is newer that the date on the backup tape, it’s time to back it up again

Sources