1#!/usr/local/bin/perl -w
2use File::stat qw/:FIELDS/;
3#=head1 NAME
4#stat - display information about a file
5#=head1 SYNOPSIS
6#stat [--follow] [--octal] [--modeoct] [--raw] [--<key>] file
7#=head1 DESCRIPTION
8#stat prints information about a file:
9#         dev      device number of filesystem
10#         ino      inode number
11#         mode     file mode  (type and permissions)
12#         nlink    number of (hard) links to the file
13#         uid      numeric user ID of file's owner
14#         gid      numeric group ID of file's owner
15#         rdev     the device identifier (special files only)
16#         size     total size of file, in bytes
17#         atime    last access time since the epoch
18#         mtime    last modify time since the epoch
19#         ctime    inode change time (NOT creation time!) since the epoch
20#         Atime    last access time in YYYYMMDDhhmmss format
21#         Mtime    last modify time in YYYYMMDDhhmmss format
22#         Ctime    inode change time in YYYYMMDDhhmmss format
23#         blksize  preferred block size for file system I/O
24#         blocks   actual number of blocks allocated
25#
26#Each of the keys in the first column above may be used as an option. Only that
27#information will then be printed for the file. More than one key option can be
28#used. If no key options are used, all information will be printed, one line
29#per key, in the format key<tab>value.
30#
31#For links the --follow option may be used to follow the link, i.e. to print the
32#information for the file at the end of the link.
33#The --octal prints numbers (excluding the time keys) in octal.
34#The --raw option just prints out the value, and not the key name. If more than
35# one key is used, they are space separated.
36#The --modeoct option prints only the mode in octal, and only the lower byte.
37#=head1 AUTHOR
38#wybo@servalys.nl
39#=cut
40use Getopt::Long;
41use vars qw /$opt_octal $opt_follow $opt_raw $opt_modeoct/;
42
43@h=qw/ dev ino mode nlink
44       uid gid rdev size
45       atime mtime ctime
46       Atime Mtime Ctime
47       blksize blocks
48/;
49@h2=();
50Getopt::Long::Configure(no_ignore_case);
51GetOptions(@h,'follow','octal','raw','modeoct');
52
53for (@h) {
54  $o="opt_$_";
55  $$o and push @h2,$_;
56}
57
58@h2=@h if (@h2 < 1);
59
60$file=shift or die "Usage: stat file\n";
61if ($file eq '-') {
62	while (defined($file=<STDIN>)) {
63		chomp($file);
64		last unless $file;
65		&do_it();
66	}
67}
68else {
69	&do_it();
70}
71
72exit;
73
74sub do_it {
75-e $file or do { print STDERR "File $file does not exist\n"; return; };
76if ($opt_follow) { stat $file } else { lstat $file }
77for (@h2) {
78  if (/^[AMC]/) {
79    $v="st_\l$_";
80    $v=conv($$v);
81  } else {
82    $v="st_$_";
83    $v=$$v;
84  }
85  $opt_octal && ! /time/ and ($v=sprintf("0%o",$v))=~s/^00/0/;
86  if ($opt_modeoct && /mode/) {$v=sprintf("%04o",$v & 07777)}
87  if (@h2>1 && ! $opt_raw) { write } else { print "$v " }
88}
89
90print "\n" if ($opt_raw);
91
92format =
93@>>>>> @<<<<<<<<<<<<<  @<<<<<<<<<<<<<
94$_,      $v,            '' # $link ? $y : ''
95.
96
97return;
98}
99
100sub conv {
101  my $t=shift;
102  my @s=(localtime($t))[0..5];
103  $s[4]++;
104  $s[5]+=1900;
105  sprintf("%04d%02d%02d%02d%02d%02d",reverse @s);
106}
107