Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

How to convert absolute (octal) file permission to Unix notation...

by snafu (Chaplain)
on May 24, 2001 at 01:53 UTC ( [id://82756]=perlquestion: print w/replies, xml ) Need Help??

snafu has asked for the wisdom of the Perl Monks concerning the following question:

In my search I found the following nodes File permission converter and Converting Permission string to Octal. However, these are working the problem I am faced with in a backward manner to my situation.

I have written a lil perl script that stats files for mac times (mtime, atime, ctime) and some other various tidbits of data. One these data is the absolute permissions mode. I want to convert these modes to the all too recognizeable masked notation eg. drwxrwxrwx.

I am currently using bitwise operations to get something (not sure what it is though because it isn't the real permissions mode of the file as far as I can tell). I will post the script and the output.

#!/usr/local/bin/perl -w # Written by Jim Conner # 4/10/2001 # Nifty lil utility I wrote to be able to # get the mtime, ctime, and atime values from # any file of your choice. ################################################### # HOW TO USE!! # It is quite simple. All you do is supply this # script with the directory(ies)/file(s) you want to get # info on and voila! there's your info. # # Examples: # # macls /tmp # This will give you a listing of all files in /tmp # # macls file1 file2 file3 # This will give you a listing of files 1 2 and 3. # # macls # This will give you a listing of all files in the # present working directory. # # TODO: # Add command line args and options. One of the # most important of which would be -h (help) # # Fix the mode. Currently, it does not report # an understandable mode. # # Translate the mode to human readable (laman) # terms (drwxrwxr-x) # # Audit Trail: # 4/9/2k1 - First conceptualized and started on authoring # 4/10/2k1 - Released version 1.0 # ################################################### use strict; use File::Basename; use vars qw($DEBUG); #################### $DEBUG = "0"; #################### my $plProgName = basename($0); my $count = "0"; my $total = "0"; my @filename; #################### if ( $#ARGV == "-1" ) { @filename = &readall(); } elsif ( $#ARGV >= "0" ) { if ( -d $ARGV[0] ) { @filename = &readall($ARGV[0]); } else { @filename = @ARGV; } } print "\n"; for ( @filename ) { my $filename = $_; my($dev,$inode,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$c +time,$blksize,$blocks); if ( $count >= "1" ) { print "******************************************************* +\n\n"; } warn "$0: $filename: $!\n" and next if ( ! open (F,"$filename") ); # I just found this :( # 0 dev device number of filesystem # 1 ino inode number # 2 mode file mode (type and permissions) # 3 nlink number of (hard) links to the file # 4 uid numeric user ID of file's owner # 5 gid numeric group ID of file's owner # 6 rdev the device identifier (special files only) # 7 size total size of file, in bytes # 8 atime last access time since the epoch # 9 mtime last modify time since the epoch # 10 ctime inode change time (NOT creation time!) since the epoch +<-- NNNOOOTTT GOOD!! :( # 11 blksize preferred block size for file system I/O # 12 blocks actual number of blocks allocated # #(The epoch was at 00:00 January 1, 1970 GMT.) ($dev, $inode, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks ) = lstat(F); # from mknod(2) (good info!) # S_ISUID 04000 Set user ID on execution. # S_ISGID 020#0 Set group ID on execution if # is 7, 5, 3, +or 1. # Enable mandatory file/record locking if # i +s # 6, 4, 2, or 0. # S_ISVTX 01000 Save text image after execution. # S_IRWXU 00700 Read, write, execute by owner. # S_IRUSR 00400 Read by owner. # S_IWUSR 00200 Write by owner. # S_IXUSR 00100 Execute (search if a directory) by owner. # S_IRWXG 00070 Read, write, execute by group. # S_IRGRP 00040 Read by group. # S_IWGRP 00020 Write by group. # S_IXGRP 00010 Execute by group. # S_IRWXO 00007 Read, write, execute (search) by others. # S_IROTH 00004 Read by others. # S_IWOTH 00002 Write by others # S_IXOTH 00001 Execute by others. # S_ISVTX On directories, restricted deletion flag. $mode &= 07777; my $username = getpwuid($uid); my $grpname = getgrgid($gid); my @atime_readable = &fixgmt("$atime",'atime'); my @mtime_readable = &fixgmt("$mtime",'mtime'); my @ctime_readable = &fixgmt("$ctime",'ctime'); print "MACtime for: $filename\n"; print "Mode($mode) $username($uid) $grpname($gid)\t$size bytes $b +locks blocks\n"; print "Modified time\t........ @mtime_readable\n"; print "Access time \t........ @atime_readable\n"; print "Inode Change \t........ @ctime_readable\n\n"; close(F); $count++; $total = $total + $size; } print "\nTotal files checked : $count\n"; print "Total size in bytes : $total\n"; printf("Total size in Kbytes: %iK\n", $total / 1024); printf("Total size in Mbytes: %iM\n\n", ($total / 1024) / 1024); sub fixgmt() { my ($object, $type) = @_ ; print gmtime($object) ."\n" if $DEBUG == "1"; my($aday,$mon,$nday,$gmtime,$year) = split(/\s+/,gmtime($object)); my($hour,$min,$sec) = split(/:/,$gmtime); # Do math on gmt time to make it localtime. # Should get this from system LCTIME but I dunno # how to do that yet...sooo # Im gonna brute force the math for now. $hour = abs($hour - 4); $hour = "0$hour" if ( $hour < 10 ); $nday = "0$nday" if ( $nday < 10 ); my $ltime = "$hour:$min:$sec"; if ( $DEBUG == "1" ) { print "Object type is: $type\n"; print "Object value is: $object\n"; print "Alpha day = $aday\nMonth = $mon\nNumber day = + $nday\nGMTTime = $gmtime\nYear = $year\n"; print "Hour = $hour\nMinute = $min\nSecond = $sec\n" +; print "LocalTime = $ltime\n\n"; } return($aday,$mon,$nday,$ltime,$year); } sub readall() { my $dir = "@_" ; if ( $dir ) { chdir($dir); opendir(ALL,".") or die("Unable to read: $!\n"); } else { opendir(ALL,".") or die("Unable to read: $!\n"); } my @files = grep(!/(^\.\.?)/,readdir(ALL)) or die("Unable to get f +ile list: $!\n"); return(@files); }
I would appreciate a couple of things. Constructive code criticism. This will help me learn as I am still (what I consider to be) extremely new to Perl. May hurt my pride some but oh well. I would also like to find out how to get the permissions thing to work right. More specifically, how to get the proper permissions (ie 0755, or 0644, or 4750). Once I get to that point, I believe I can take it from there (to be seen). Here is what I get for output:
[jconner@kwan ~/bin/dev]$ perl macls macls

MACtime for: macls
Mode(416) jconner(10036) other(1)       5727 bytes  12 blocks
Modified time   ........ Wed May 23 17:37:57 2001
Access time     ........ Wed May 23 17:42:24 2001
Inode Change    ........ Wed May 23 17:37:57 2001


Total files checked : 1
Total size in bytes : 5727
Total size in Kbytes: 5K
Total size in Mbytes: 0M

The part that says: mode (416) is the obvious broken part and where I need the most help. The permissions the filesystem sees is 640.
[jconner@kwan ~/bin/dev]$ ls -l macls
-rw-r-----    1 jconner  other        5727 May 23 17:37 macls
I appreciate any assistance in advance. Thanks everyone!

----------
- Jim

Edited 2001-05-24 by Ovid

Replies are listed 'Best First'.
Re: Fellow Monks please lend an ear...suggestions/comments on how to convert absolute (octal) file permission to Unix notation...
by mikfire (Deacon) on May 24, 2001 at 02:34 UTC
    Hmm. I hate it when this happens. You are printing the number in its *decimal* representation, not the octal. To see the mode in octal, you need printf:
    printf "Mode(%04o) $username(%s) $grpname(%s)\t%d bytes %d blocks\n", + $mode, $uid, $gid, $size, $blocks;
    should show you what you are expecting.

    mikfire

Re: Fellow Monks please lend an ear...suggestions/comments on how to convert absolute (octal) file permission to Unix notation...
by traveler (Parson) on May 24, 2001 at 02:48 UTC
    Your mode code is correct (sort of). The *nix mode is octal (which is base 8). You printed it in base 10! 0x640 == 416. You need to break out the bits of the mode with, say, bitwise and (&) (depending on your algorithm you might be able to use vec). If you require 'sys/stat.ph'; you'll get some useful constants to help you decode the mode. Check the *nix manual for stat(2) to find out more about those useful constants...

    localtime might be useful, too.

    --traveler

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://82756]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (4)
As of 2025-07-16 07:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.