Add stat submission to new "pending" directory, along with infrastructure to support pending.
This commit is contained in:
parent
b9bde7b403
commit
b1c002ac55
@ -29,11 +29,13 @@ genconfig()
|
||||
# and capitalization in the menu
|
||||
for j in toys/*/README
|
||||
do
|
||||
DIR="$(dirname "$j")"
|
||||
|
||||
[ $(ls "$DIR" | wc -l) -lt 2 ] && continue
|
||||
|
||||
echo "menu \"$(head -n 1 $j)\""
|
||||
echo
|
||||
|
||||
DIR="$(dirname "$j")"
|
||||
|
||||
# extract config stanzas from each source file, in alphabetical order
|
||||
for i in $(ls -1 $DIR/*.c)
|
||||
do
|
||||
|
1
toys.h
1
toys.h
@ -34,6 +34,7 @@
|
||||
#include <sys/mount.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/swap.h>
|
||||
|
3
toys/pending/README
Normal file
3
toys/pending/README
Normal file
@ -0,0 +1,3 @@
|
||||
pending
|
||||
|
||||
These commands await additional review and/or cleanup.
|
316
toys/pending/stat.c
Normal file
316
toys/pending/stat.c
Normal file
@ -0,0 +1,316 @@
|
||||
/* vi: set sw=4 ts=4
|
||||
*
|
||||
* stat.c : display file or file system status
|
||||
* anand.sinha85@gmail.com
|
||||
* Copyright 2012 <warior.linux@gmail.com>
|
||||
*
|
||||
* See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/stat.html
|
||||
USE_STAT(NEWTOY(stat, "LZfc", TOYFLAG_BIN))
|
||||
config STAT
|
||||
bool st
|
||||
default n
|
||||
help
|
||||
Usage: stat [OPTION] FILE...
|
||||
display file or file system status
|
||||
-Z, --context
|
||||
print the security context information if available
|
||||
-f, --file-system
|
||||
display file system status instead of file status
|
||||
-c --format=FORMAT
|
||||
use the specified FORMAT instead of the default; output a newline after each use of FORMAT
|
||||
--help display this help and exit
|
||||
The valid format sequences for files (without --file-system):
|
||||
%a Access rights in octal
|
||||
%A Access rights in human readable form
|
||||
%b Number of blocks allocated (see
|
||||
%B The size in bytes of each block reported by
|
||||
%d Device number in decimal
|
||||
%D Device number in hex
|
||||
%f Raw mode in hex
|
||||
%F File type
|
||||
%G Group name of owner
|
||||
%h Number of hard links
|
||||
%i Inode number
|
||||
%n File name
|
||||
%N Quoted file name with dereference if symbolic link
|
||||
%o I/O block size
|
||||
%s Total size, in bytes
|
||||
%t Major device type in hex
|
||||
%T Minor device type in hex
|
||||
%u User ID of owner
|
||||
%U User name of owner
|
||||
%x Time of last access
|
||||
%X Time of last access as seconds since Epoch
|
||||
%y Time of last modification
|
||||
%Y Time of last modification as seconds since Epoch
|
||||
%z Time of last change
|
||||
%Z Time of last change as seconds since Epoch
|
||||
*/
|
||||
|
||||
#define FOR_stat
|
||||
#include "toys.h"
|
||||
#define SIZE_DATE_TIME_STAT 36
|
||||
#define access_string(x, s, i) if((x&7) & 1) \
|
||||
s[9 - i * 3] = 'x'; \
|
||||
else \
|
||||
s[9 - i * 3] = '-'; \
|
||||
if(((x&7) >> 1) & 1) \
|
||||
s[9 - (i * 3 + 1)] = 'w'; \
|
||||
else \
|
||||
s[9 - (i * 3 + 1)] = '-'; \
|
||||
if(((x&7) >> 2) & 1) \
|
||||
s[9 - (i * 3 + 2)] = 'r'; \
|
||||
else \
|
||||
s[9 - (i * 3 + 2)] = '-';
|
||||
|
||||
static char * check_type_file(mode_t, size_t);
|
||||
static char * get_access_str(unsigned long, mode_t);
|
||||
static char * date_stat_format(time_t );
|
||||
static int do_stat(const char *);
|
||||
static int do_statfs(const char *);
|
||||
inline void print_stat_format(char *, int);
|
||||
|
||||
GLOBALS(
|
||||
char * access_str;
|
||||
char * file_type;
|
||||
struct passwd * user_name; struct group * group_name; struct tm *time_toy;
|
||||
struct stat * toystat;
|
||||
struct statfs * toystatfs;
|
||||
int toy_obj_file_arg;
|
||||
)
|
||||
|
||||
|
||||
static int do_stat(const char * file_name){
|
||||
TT.toystat = (struct stat*)malloc(sizeof(struct stat));
|
||||
if(stat(file_name, TT.toystat) < 0){
|
||||
perror_msg("Error: unable to get information about the file, stat\n", file_name);
|
||||
toys.exitval = EXIT_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_statfs(const char * file_name){
|
||||
TT.toystatfs = (struct statfs *)malloc(sizeof(struct statfs));
|
||||
if(statfs(file_name, TT.toystatfs) < 0){
|
||||
perror_msg("Error: unable to get information about the file, statfs\n", file_name);
|
||||
toys.exitval = EXIT_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char * check_type_file(mode_t mode, size_t size){
|
||||
if(S_ISREG(mode)){
|
||||
if(size)
|
||||
return "regular file";
|
||||
return "regular empty file";
|
||||
}
|
||||
if(S_ISDIR(mode))
|
||||
return "directory";
|
||||
if(S_ISCHR(mode))
|
||||
return "character device";
|
||||
if(S_ISBLK(mode))
|
||||
return "block device";
|
||||
if(S_ISFIFO(mode))
|
||||
return "FIFO (named pipe)";
|
||||
if(S_ISLNK(mode))
|
||||
return "symbolic link";
|
||||
if(S_ISSOCK(mode))
|
||||
return "socket";
|
||||
}
|
||||
|
||||
static char * get_access_str(unsigned long pernission, mode_t mode){
|
||||
static char access_string[10];
|
||||
int i;
|
||||
if(S_ISDIR(mode))
|
||||
access_string[0] = 'd';
|
||||
else
|
||||
access_string[0] = '-';
|
||||
for(i = 0; i < 3; i++){
|
||||
access_string(pernission >> (i * 3) & 7, access_string, i);
|
||||
}
|
||||
access_string[10] = '\0';
|
||||
return access_string;
|
||||
}
|
||||
|
||||
static char * date_stat_format(time_t time){
|
||||
static char buf[SIZE_DATE_TIME_STAT];
|
||||
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time));
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline void print_stat_format(char *format, int flag){
|
||||
format++;
|
||||
switch(*format){
|
||||
case 'a':
|
||||
if(flag)
|
||||
xprintf("%lu\n", TT.toystatfs->f_bavail);
|
||||
else
|
||||
xprintf("%04lo\n",TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO));
|
||||
break;
|
||||
case 'A':
|
||||
xprintf("%s\n",TT.access_str);
|
||||
break;
|
||||
case 'b':
|
||||
if(flag)
|
||||
xprintf("%lu\n", TT.toystatfs->f_blocks);
|
||||
else
|
||||
xprintf("%llu\n", TT.toystat->st_blocks);
|
||||
break;
|
||||
case 'B':
|
||||
xprintf("%lu\n", TT.toystat->st_blksize);
|
||||
break;
|
||||
case 'c':
|
||||
if(flag)
|
||||
xprintf("%lu\n", TT.toystatfs->f_files);
|
||||
break;
|
||||
case 'C':
|
||||
xprintf("Currently feature is not supported\n");
|
||||
break;
|
||||
case 'd':
|
||||
if(flag)
|
||||
xprintf("%lu\n", TT.toystatfs->f_ffree);
|
||||
else
|
||||
xprintf("%ldd\n", TT.toystat->st_dev);
|
||||
break;
|
||||
case 'D':
|
||||
xprintf("%llxh\n", TT.toystat->st_dev);
|
||||
break;
|
||||
case 'f':
|
||||
if(flag)
|
||||
xprintf("%lu\n", TT.toystatfs->f_bfree);
|
||||
else
|
||||
xprintf("%lx\n", TT.toystat->st_mode);
|
||||
break;
|
||||
case 'F':
|
||||
xprintf("%s\n", TT.file_type);
|
||||
break;
|
||||
case 'g':
|
||||
xprintf("%lu\n", TT.toystat->st_uid);
|
||||
break;
|
||||
case 'G':
|
||||
xprintf("%8s\n", TT.user_name->pw_name);
|
||||
break;
|
||||
case 'h':
|
||||
xprintf("%lu\n", TT.toystat->st_nlink);
|
||||
break;
|
||||
case 'i':
|
||||
if(flag)
|
||||
xprintf("%d%d\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1]);
|
||||
else
|
||||
xprintf("%llu\n", TT.toystat->st_ino);
|
||||
break;
|
||||
case 'l':
|
||||
if(flag)
|
||||
xprintf("need to implement\n");
|
||||
break;
|
||||
case 'n':
|
||||
xprintf("%s\n", toys.optargs[TT.toy_obj_file_arg]);
|
||||
break;
|
||||
case 'N':
|
||||
xprintf("`%s\n'", toys.optargs[TT.toy_obj_file_arg]);
|
||||
break;
|
||||
case 'o':
|
||||
xprintf("%lu\n", TT.toystat->st_blksize);
|
||||
break;
|
||||
case 's':
|
||||
if(flag)
|
||||
xprintf("%d\n", TT.toystatfs->f_frsize);
|
||||
else
|
||||
xprintf("%llu\n", TT.toystat->st_size);
|
||||
break;
|
||||
case 'S':
|
||||
if(flag)
|
||||
xprintf("%d\n", TT.toystatfs->f_bsize);
|
||||
break;
|
||||
case 't':
|
||||
if(flag)
|
||||
xprintf("%lx\n", TT.toystatfs->f_type);
|
||||
break;
|
||||
case 'T':
|
||||
if(flag)
|
||||
xprintf("Needs to be implemented\n");
|
||||
break;
|
||||
case 'u':
|
||||
xprintf("%lu\n", TT.toystat->st_uid);
|
||||
break;
|
||||
case 'U':
|
||||
xprintf("%8s\n", TT.user_name->pw_name);
|
||||
break;
|
||||
case 'x':
|
||||
xprintf("%s\n", date_stat_format(TT.toystat->st_atime));
|
||||
break;
|
||||
case 'X':
|
||||
xprintf("%llu\n", TT.toystat->st_atime);
|
||||
break;
|
||||
case 'y':
|
||||
xprintf("%s\n", date_stat_format(TT.toystat->st_mtime));
|
||||
break;
|
||||
case 'Y':
|
||||
xprintf("%llu\n", TT.toystat->st_mtime);
|
||||
break;
|
||||
case 'z':
|
||||
xprintf("%s\n", date_stat_format(TT.toystat->st_ctime));
|
||||
break;
|
||||
case 'Z':
|
||||
xprintf("%llu\n", TT.toystat->st_ctime);
|
||||
default:
|
||||
xprintf("%c\n", *format);
|
||||
break;
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void stat_main(void){
|
||||
int stat_flag_Z = 0, stat_flag_f = 0, stat_flag_c = 0, stat_format = 0;
|
||||
if(toys.optargs){
|
||||
if(toys.optflags & 1){
|
||||
stat_flag_c = 1;
|
||||
TT.toy_obj_file_arg = 1;
|
||||
stat_format = 1;
|
||||
}
|
||||
if(toys.optflags & (1 << 1)){
|
||||
stat_flag_f = 1;
|
||||
if(do_statfs(toys.optargs[TT.toy_obj_file_arg]) != 0)
|
||||
xprintf("Error STATFS\n");
|
||||
}else
|
||||
if(do_stat(toys.optargs[TT.toy_obj_file_arg]) != 0)
|
||||
xprintf("Error STAT\n");
|
||||
if(toys.optflags & (1 << 2)){
|
||||
stat_flag_Z = 1;
|
||||
xprintf("SELinux feature has not been implemented so far..\n");
|
||||
}
|
||||
}
|
||||
// function to check the type/mode of file
|
||||
if(!stat_flag_f){
|
||||
TT.file_type = check_type_file(TT.toystat->st_mode, TT.toystat->st_size);
|
||||
// check user and group name
|
||||
TT.user_name = getpwuid(TT.toystat->st_uid);
|
||||
TT.group_name = getgrgid(TT.toystat->st_gid);
|
||||
// function to get access in human readable format
|
||||
TT.access_str = get_access_str((TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.toystat->st_mode);
|
||||
TT.time_toy = gmtime(&(TT.toystat->st_atime));
|
||||
}
|
||||
if(!(stat_flag_f |stat_flag_Z)){
|
||||
if(stat_format)
|
||||
print_stat_format(toys.optargs[0], stat_flag_f);
|
||||
xprintf(" File: `%s'\n", toys.optargs[TT.toy_obj_file_arg]);
|
||||
xprintf(" Size: %llu\t Blocks: %llu\t IO Blocks: %lu\t", TT.toystat->st_size, TT.toystat->st_blocks, TT.toystat->st_blksize);
|
||||
xprintf("%s\n", TT.file_type);
|
||||
xprintf("Device: %llxh\t Inode: %llu\t Links: %lu\n", TT.toystat->st_dev, TT.toystat->st_ino, TT.toystat->st_nlink);
|
||||
xprintf("Access: (%04lo/%s)\tUid: (%lu/%8s)\tGid: (%lu/%8s)\n", (TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.access_str, TT.toystat->st_uid, TT.user_name->pw_name, TT.toystat->st_gid, TT.group_name->gr_name);
|
||||
xprintf("Access: %s\nModify: %s\nChange: %s\n", date_stat_format(TT.toystat->st_atime), date_stat_format(TT.toystat->st_mtime), date_stat_format(TT.toystat->st_ctime));
|
||||
}else if(stat_flag_f){
|
||||
// implementation of statfs -f, file system
|
||||
if(stat_format)
|
||||
print_stat_format(toys.optargs[0], stat_flag_f);
|
||||
xprintf(" File: \"%s\"\n", toys.optargs[TT.toy_obj_file_arg]);
|
||||
xprintf(" ID: %d%d Namelen: %ld Type: %lx\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1], TT.toystatfs->f_namelen, TT.toystatfs->f_type);
|
||||
xprintf("Block Size: %d Fundamental block size: %d\n", TT.toystatfs->f_bsize, TT.toystatfs->f_frsize);
|
||||
xprintf("Blocks: Total: %lu\t", TT.toystatfs->f_blocks);
|
||||
xprintf("Free: %lu\t", TT.toystatfs->f_bfree);
|
||||
xprintf("Available: %lu\n", TT.toystatfs->f_bavail);
|
||||
xprintf("Inodes: Total: %lu\t", TT.toystatfs->f_files);
|
||||
xprintf("\tFree: %d\n", TT.toystatfs->f_ffree);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user