Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site pucc-k Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxn!ihnp4!inuxc!pur-ee!CS-Mordred!Pucc-H:Pucc-I:Pucc-K:rsk From: rsk@pucc-k (Wombat) Newsgroups: net.sources Subject: stat(1)-print out inode contents Message-ID: <1182@pucc-k> Date: Sat, 13-Jul-85 11:02:34 EDT Article-I.D.: pucc-k.1182 Posted: Sat Jul 13 11:02:34 1985 Date-Received: Sun, 14-Jul-85 09:19:06 EDT Reply-To: rsk@pucc-k.UUCP (Wombat) Organization: Purdue University Lines: 253 Keywords: stat, inode, ls This is the nth rewrite of stat(1), which I believe was originally written by Phil Hochstetler (now of Sequent). Essentially, it prints out the structure returned by stat(2). Defining SINCE will cause stat(1) to print the difference between "now" and "then" for each of the three dates associated with the inode--this is probably easy to demo than to explain. Here's a sample of the output: ----- File: "." Size: 2048 Allocated Blocks: 4 Filetype: Directory Mode: (0751/drwxr-x--x) Uid: (18506/ rsk) Gid: ( 4/ staff) Device: 5 Inode: 41167 Links: 3 Access: Sat Jul 13 09:54:12 1985(00000.00:04:11) Modify: Sat Jul 13 09:58:22 1985(00000.00:00:01) Change: Sat Jul 13 09:58:22 1985(00000.00:00:01) ----- The times in ()'s are generated by the SINCE-defined code; note that they are of the format ddddd.hh.mm.ss, which should be more than sufficient to cover times back as far as the Epoch. Please report bugs to me; also please note that this is for 4.2bsd; although I have little doubt that it would be easily adaptable to other species--such mods are also welcome in my mailbox. /* * Stat.c Dump out inode info in nice form. * pur-ee!pucc-j!rsk, rsk@purdue-asc.arpa * Original version by Hoch in the dark days of v6; * this one by Rsk for 4.2 BSD. */ #include#include #include #include #include #include #include #define FAIL -1 /* Failure return code from call */ #define OKAY 0 /* Success return code from call */ struct stat Sbuf; /* for return values from stat() call */ char *ctime(); /* Time conversion */ struct passwd *getpwuid(); /* User entry */ struct passwd *pwent; /* User structure */ struct group *getgrgid(); /* Group entry */ struct group *grent; /* Group structure */ char Mode[10]; /* File protection mode */ #define LBUFSIZ 256 /* Length for symbolic link translation buffer */ char Lbuf[LBUFSIZ]; /* Symbolic link translation buffer */ main(argc, argv) int argc; char *argv[]; { int i; i = 1; if(argc == 1) { fprintf(stderr,"Usage: stat file1 [file2 ...]\n"); exit(1); } do { stat_it(argv[i]); if( (argc > 1) && (i < (argc-1)) ) printf("\n"); } while(++i < argc); exit(0); } /* * stat_it() - Actually stat and format results from file. * exit - OKAY if no problems encountered * FAIL if couldn't open or other nastiness * */ stat_it(filename) char *filename; { int count; if( lstat(filename,&Sbuf) == FAIL) { fprintf(stderr,"Can't lstat %s\n",filename); return(FAIL); } if( (Sbuf.st_mode & S_IFMT) == S_IFLNK) { if( (count=readlink(filename,Lbuf,LBUFSIZ)) == FAIL) { fprintf(stderr,"Can't readlink %s\n", filename); return(FAIL); } if( count < LBUFSIZ) Lbuf[count] = '\0'; printf(" File: \"%s\" -> \"%s\"\n",filename,Lbuf); } else printf(" File: \"%s\"\n", filename); printf(" Size: %-10d", Sbuf.st_size); printf(" Allocated Blocks: %-10ld", Sbuf.st_blocks); printf(" Filetype: "); switch( Sbuf.st_mode & S_IFMT) { case S_IFDIR: printf("Directory\n"); break; case S_IFCHR: printf("Character Device\n"); break; case S_IFBLK: printf("Block Device\n"); break; case S_IFREG: printf("Regular File\n"); break; case S_IFLNK: printf("Symbolic Link\n"); break; case S_IFSOCK: printf("Socket\n"); break; default : printf("Unknown\n"); } strcpy(Mode,"----------"); if(Sbuf.st_mode & 0000001) /* Other execute */ Mode[9] = 'x'; if(Sbuf.st_mode & 0000002) /* Other write */ Mode[8] = 'w'; if(Sbuf.st_mode & 0000004) /* Other read */ Mode[7] = 'r'; if(Sbuf.st_mode & 0000010) /* Group execute */ Mode[6] = 'x'; if(Sbuf.st_mode & 0000020) /* Group write */ Mode[5] = 'w'; if(Sbuf.st_mode & 0000040) /* Group read */ Mode[4] = 'r'; if(Sbuf.st_mode & 0000100) /* User execute */ Mode[3] = 'x'; if(Sbuf.st_mode & 0000200) /* User write */ Mode[2] = 'w'; if(Sbuf.st_mode & 0000400) /* User read */ Mode[1] = 'r'; if(Sbuf.st_mode & 0001000) /* Sticky bit */ Mode[9] = 't'; if(Sbuf.st_mode & 0002000) /* Set group id */ Mode[6] = 's'; if(Sbuf.st_mode & 0004000) /* Set user id */ Mode[4] = 's'; switch( Sbuf.st_mode & S_IFMT) { case S_IFDIR: Mode[0] = 'd'; break; case S_IFCHR: Mode[0] = 'c'; break; case S_IFBLK: Mode[0] = 'b'; break; case S_IFREG: Mode[0] = '-'; break; case S_IFLNK: Mode[0] = 'l'; break; case S_IFSOCK: Mode[0] = 's'; break; default : Mode[0] = '?'; } printf(" Mode: (%04o/%s)", Sbuf.st_mode&07777,Mode); (void) setpwent(); if( (pwent = getpwuid(Sbuf.st_uid)) == NULL) { fprintf(stderr,"getpwuid() failed\n"); exit(1); } printf(" Uid: (%5d/%8s)", Sbuf.st_uid, pwent->pw_name); (void) setgrent(); if( (grent = getgrgid(Sbuf.st_gid)) == NULL) { fprintf(stderr,"getgrgid() failed\n"); exit(1); } printf(" Gid: (%5d/%8s)\n", Sbuf.st_gid, grent->gr_name); printf("Device: %-5d", Sbuf.st_dev); printf(" Inode: %-10d", Sbuf.st_ino); printf("Links: %-5d", Sbuf.st_nlink); /* Only meaningful if file is device */ if( ( (Sbuf.st_mode & S_IFMT) == S_IFCHR) || ( (Sbuf.st_mode & S_IFMT) == S_IFBLK) ) printf(" Device type: %d\n",Sbuf.st_rdev); else printf("\n"); /* The %.24s strips the newline from the ctime() string */ #ifdef SINCE printf("Access: %.24s",ctime(&Sbuf.st_atime)); tsince(Sbuf.st_atime); printf("Modify: %.24s",ctime(&Sbuf.st_mtime)); tsince(Sbuf.st_mtime); printf("Change: %.24s",ctime(&Sbuf.st_ctime)); tsince(Sbuf.st_ctime); #else SINCE printf("Access: %s",ctime(&Sbuf.st_atime)); printf("Modify: %s",ctime(&Sbuf.st_mtime)); printf("Change: %s",ctime(&Sbuf.st_ctime)); #endif SINCE /* * Should I put this in somewhere? No. * * printf("Optimal Blocksize: %ld\n", Sbuf.st_blksize); */ return(OKAY); } #ifdef SINCE tsince(time_sec) long time_sec; { long time_buf; long d_since; /* days elapsed since time */ long h_since; /* hours elapsed since time */ long m_since; /* minutes elapsed since time */ long s_since; /* seconds elapsed since time */ time(&time_buf); if(time_sec > time_buf) { fprintf(stderr,"Time going backwards\n"); exit(1); } s_since = time_buf - time_sec; d_since = s_since / 86400l ; s_since -= d_since * 86400l ; h_since = s_since / 3600l ; s_since -= h_since * 3600l ; m_since = s_since / 60l ; s_since -= m_since * 60l ; printf("(%05ld.%02ld:%02ld:%02ld)\n",d_since,h_since,m_since,s_since); return(OKAY); } #endif SINCE -- Rich Kulawiec rsk@{pur-ee,purdue}.uucp, rsk@purdue-asc.csnet rsk@purdue-asc.arpa (soon to be) rsk@asc.purdue.edu