/* Prints stat() parameters except the unused st_spare[1-4] */ #ifdef ournix /* { */ #include "ournix.h" #endif /* } */ #ifdef SCCS /* { */ static char sccsID[] = "@(#) statv.c V1.3 Copyright Julian H. Stacey, Munich, 1990 04 17 & 1998\n"; #endif /* } */ /* Copyright: This code was written independently by Julian H. Stacey before being used or delivered with any code for Stacey/VSL clients. Clients who receive such code are permitted to use & resell code etc, but copyright to this file is Not assigned to the client. & no Liability is accepted, nor Warranty granted for this free code that the client/recipient has not paid for development of. */ #include #include #include #ifdef scs /* { BSD */ #ifndef BSD /* { */ #define BSD #endif /* } */ #endif /* } */ #ifdef __386BSD__ /* { BSD */ #ifndef BSD /* { */ #define BSD #endif /* } */ #endif /* } */ #if ( __FreeBSD__ || __OpenBSD__ ) /* { BSD */ #define BSD #endif /* } */ #ifdef BSD /* { BSD */ #define major_dev_no major #define minor_dev_no minor #else /* }{ */ #ifdef i386 /* { */ /* this next bit either for esix or sco, cant remember which or both */ #ifndef sco /* { this SCO is unfortunately not defined by gcc on sco-open-server-5.0.5, & probably not by native cc either */ #include #include #endif /* } */ #define major_dev_no major #define minor_dev_no minor #ifndef sco /* { */ #include #endif /* } */ /* I have no idea if an esix 486 has seperate internal & external numbers, as mentioned by the manual, or whether this is just a 3b2 weirdness */ #endif /* } */ #endif /* } */ /* #include / * for user_from_uid() & group_from_gid() */ #include /* for getpwuid */ #include /* for getgrgid */ static char **ARGV ; static int err_no = 0 ; extern char *ctime() ; static void syntax() { fprintf(stderr,"Error, correct syntax is:\n%s file[s]\n",*ARGV); } int #ifndef EMBEDDED /* { */ main(argc,argv) #else /* }{ */ stat_js(argc, argv) /* cant call it stat as there''s a sys call of that name */ #endif /* } */ int argc ; char **argv ; { struct stat stat_buf, lstat_buf, *stat_buf_p ; char *cmt ; typedef char FLAG ; FLAG found = 0 ; /* if we found a valid pathname to examine */ #ifdef sco /* { */ #include struct ustat sco_buf; /* daddr_t f_tfree; Total free blocks ino_t f_tinode; Number of free inodes char f_fname[6]; Filsys name char f_fpack[6]; Filsys pack name */ #endif /* } */ struct passwd *pwd ; struct group *grp ; ARGV = argv ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ if (argc < 2) { syntax() ; return(++err_no) ; } else while (--argc) { argv++ ; #define STRADR & if (stat(*argv, &stat_buf) || lstat(*argv, &lstat_buf)) { err_no++ ; perror(*ARGV) ; fprintf(stderr,"%s\n",*argv); continue ; } found = 1 ; /* all types shown in comment delimeters inside printf s in this procedure are from the BSD 4.2 man stat manual page listing */ printf("Name\t%s%s\n", (strlen(*argv) > strlen( "Mon Jan 25 11:06:36 1999 \040 \040 \040 ")) /* I originally put in backslashes before spaces above, to defeat tabulators on source, but gcc warns unknown escape sequence ``\ '' & SCO cc warns dubious escape: so I use alternate \040 */ ? "" : "\t\t\t\t\t", *argv) ; /* shift long names to left, saves user scrolling */ stat_buf_p = STRADR lstat_buf; for(;;) { /* If symbolic link print symbolic attributes, then normal, else just normal attributes */ if ((stat_buf_p->st_mode & S_IFMT) == S_IFLNK) printf( "Symbolic link attributes from lstat()\n"); else stat_buf_p = STRADR stat_buf ; #ifdef sco /* { */ if (ustat(stat_buf_p->st_dev,&sco_buf)) fprintf(stderr,"ustat failed\n"); else { sco_buf.f_fname[0] = sco_buf.f_fpack[0] = '\0' ; sco_buf.f_tfree = (daddr_t)0 ; sco_buf.f_tinode = (ino_t)0 ; } #endif /* } */ printf("Size\t\t(Bytes)\t\t\t\t%ld\n", /* off_t */ (long)(stat_buf_p->st_size) ); printf("Permissions\t(Octal, U rwx, G rwx, O rwx)\t0%o\n", /* u_short */ (unsigned)(~S_IFMT & (stat_buf_p->st_mode)) ); /* JJLATER add rwx display, per FreeBSD 3.0.0-RELEASE/src/bin/ls/print.c which uses strmode */ switch( (stat_buf_p->st_mode) & S_IFMT) { case S_IFDIR: cmt = "Directory" ; break ; case S_IFCHR: cmt = "Character special" ; break ; case S_IFBLK: cmt = "Block special" ; break ; case S_IFREG: cmt = "Regular File" ; break ; case S_IFLNK: cmt = "Symbolic link" ; break ; #ifndef sco /* { */ case S_IFSOCK: cmt = "Socket" ; break ; #endif /* } */ case S_IFIFO: cmt = "Fifo" ; break ; default: cmt = "Unknown" ; break ; } #ifndef scs /* { */ if (((stat_buf_p->st_mode & S_IFMT) == S_IFBLK) || ((stat_buf_p->st_mode & S_IFMT) == S_IFCHR) ) /* inode that is device */ printf( #ifndef sco /* { */ /* Assume BSD4.4 */ "Special device type pointed to (maj & min)\t%d\t\t%d\n", (int)/* dev_t */ major_dev_no(stat_buf_p->st_rdev), (int)/* dev_t */ minor_dev_no(stat_buf_p->st_rdev) #else /* }{ */ "Filsys name\t\t\t\t\t%s\nFilsys pack name\t\t\t\t%s\n", sco_buf.f_fname , sco_buf.f_fpack #endif /* } */ ); #ifndef sco /* { */ printf("Flags\t\t\t\t\t\t"); if (!(stat_buf_p->st_flags)) printf("\n"); else { if ((stat_buf_p->st_flags) & UF_NODUMP ) printf("UF_NODUMP "); /* do not dump file */ if ((stat_buf_p->st_flags) & UF_IMMUTABLE ) printf("UF_IMMUTABLE "); /* file may not be changed */ if ((stat_buf_p->st_flags) & UF_APPEND ) printf("UF_APPEND "); /* writes to file may only append */ if ((stat_buf_p->st_flags) & SF_ARCHIVED ) printf("SF_ARCHIVED "); /* file is archived */ if ((stat_buf_p->st_flags) & SF_IMMUTABLE ) printf("SF_IMMUTABLE "); /* file may not be changed */ if ((stat_buf_p->st_flags) & SF_APPEND ) printf("SF_APPEND "); /* writes to file may only append */ printf("\n"); } #endif /* } */ #endif /* } */ printf("Type\t\t(File, directory, etc)\t\t%s\n",cmt) ; /* JJLATER add `file` type info from /etc/magic here */ printf("Links\t\t(Usually 1)\t\t\t%d\n", /* short */ (int)(stat_buf_p->st_nlink) ); printf("User\t\t\t\t\t\t"); /* struct passwd *getpwuid (uid) getpwuid- searches for matching numerical user ID The getpwuid routine searches from the beginning of the /etc/passwd file until a numerical user ID matching the argument uid is found. getpwuid returns a pointer to the particular passwd structure in which the argument uid was found. Upon successful completion, the routines getpwent, getpwuid, getpwnam, and fgetpwent each return a pointer to a passwd structure. If an end-of-file or an error is encountered on reading, these routines return a NULL pointer. */ if ((struct passwd *)0 != ( pwd = getpwuid(stat_buf_p->st_uid))) printf("%s\n", pwd->pw_name ); else printf("%d\n", /* short */ (int)(stat_buf_p->st_uid) ); printf("Group\t\t\t\t\t\t"); if ((struct group *)0 != ( grp = getgrgid(stat_buf_p->st_gid))) printf("%s\n", grp->gr_name ); else printf("%d\n", /* short */ (int)(stat_buf_p->st_gid) ); /* FreeBSD 3.0.0-RELEASE/src/bin/ls/ls.c uses user_from_uid((stat_buf_p->st_gid, 0); group_from_gid(stat_buf_p->st_gid, 0); */ printf("Last Changed\t(st_ctime)\t\t\t%s", /* time_t */ ctime((long *)&(stat_buf_p->st_ctime)) ); printf("Last Accessed\t(st_atime)\t\t\t%s", /* time_t */ ctime((long *)&(stat_buf_p->st_atime)) ); printf("Last Modified\t(st_mtime)\t\t\t%s", /* time_t */ ctime((long *)&(stat_buf_p->st_mtime)) ); #if defined(__FreeBSD__) /* added 2007.06.22 */ printf("Birth time\t(st_birthtime)\t\t\t%s", ctime((long *)&(stat_buf_p->st_birthtime)) ); #endif #ifndef OPS_POING /* { Omit, Too much info. for OCE end users. */ printf("Blocks\t\t\t\t\t\t%ld\n", /* long */ (long)(stat_buf_p->st_blocks) ); printf("Optimal I/O\t\t\t\t\t%ld\n", /* long */ (long) (stat_buf_p->st_blksize) ); #ifndef sco /* { */ printf("Major\t\t\t\t\t\t%d\n", (int)/* dev_t */ major_dev_no(stat_buf_p->st_dev)); printf("Minor\t\t\t\t\t\t%d\n", (int)/* dev_t */ minor_dev_no(stat_buf_p->st_dev) ); #else /* }{ */ #ifdef DEBUG_JJLATER /* { */ /* ifdef''d cos it generates blank fields for some reason */ printf( "Filsys name\t\t\t\t\t%s\nFilsys pack name\t\t\t\t%s\n", sco_buf.f_fname , sco_buf.f_fpack ) ; #endif /* } */ #endif /* } */ printf("Inode Number\t\t\t\t\t%ld\n", /* ino_t */ (long)(stat_buf_p->st_ino) ); #ifdef SPARE /* { */ printf("st_spare1\t\t\t\t%d\n", /* int */ (int)(stat_buf_p->st_spare1) ); printf("st_spare2\t\t\t\t%d\n", /* int */ (int)(stat_buf_p->st_spare2) ); printf("st_spare3\t\t\t\t%d\n", /* int */ (int) (stat_buf_p->st_spare3) ); printf("st_spare4[1]\t\t\t\t%ld\n", /* long */ (long)(stat_buf_p->st_spare4[1]) ); printf("st_spare4[2]\t\t\t\t%ld\n", /* long */ (long)(stat_buf_p->st_spare4[2]) ); #endif /* } */ #endif /* } */ if (stat_buf_p == STRADR stat_buf) break ; stat_buf_p = STRADR stat_buf; } printf("\n"); } if (found) { #ifdef __FreeBSD__ /* { */ printf("%s\n%s\n", " st_atime = When file data was last read or modified. Changed by mknod,", " utimes, read, and write. Not set when a directory is searched.") ; printf("%s\n%s\n", " st_mtime = When data was last modified. Not set by changes of owner, group,", " link count, or mode. Changed by mknod, utimes, write.") ; printf("%s\n%s\n", " st_ctime = When file status was last changed. Set by writing or changing", " the i-node. Changed by chmod chown, link, mknod, unlink, utimes, write.") ; #endif /* } */ #ifdef sco /* { */ /* From SCO man stat: st_atime; Time of last access st_mtime; Time of last data modification st_ctime; Time of last file status change */ printf("%s:\n\t%s\n\t%s\n", "st_atime", "Time when file data was last accessed. Changed by the following", "system calls: creat(S), mknod(S), pipe(S), utime(S), and read(S)." ); printf("%s:\n\t%s\n\t%s\n\t%s\n", "st_mtime", "Time when data was last modified. Changed by the following system", "calls: creat(S), link(S), mknod(S), pipe(S), unlink(S), utime(S),", "and write(S)." ); printf("%s:\n\t%s\n\t%s\n\t%s\n", "st_ctime", "Time when file status was last changed. Changed by the following", "system calls: chmod(S), chown(S), creat(S), link(S), mknod(S), pipe", "(S), unlink(S), utime(S), and write(S)." ); #endif /* } */ } return(err_no); }