toaruos/apps/stat.c

132 lines
3.2 KiB
C
Raw Normal View History

/**
* @brief Display file status.
*
* The format for this is terrible and we're missing a bunch
* of data we provide in our statbuf...
*
* @copyright
2018-08-12 11:14:06 +03:00
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
2018-08-12 11:14:06 +03:00
* Copyright (C) 2013-2018 K. Lange
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
2018-08-12 11:14:06 +03:00
#include <unistd.h>
2018-11-25 06:57:58 +03:00
#include <errno.h>
2021-12-08 09:55:56 +03:00
#include <time.h>
2018-08-12 11:14:06 +03:00
#include <sys/stat.h>
#include <sys/time.h>
2018-08-12 11:14:06 +03:00
static void show_usage(int argc, char * argv[]) {
printf(
"stat - display file status\n"
"\n"
"usage: %s [-Lq] PATH\n"
"\n"
" -L \033[3mdereference symlinks\033[0m\n"
" -q \033[3mdon't print anything, just return 0 if file exists\033[0m\n"
" -? \033[3mshow this help text\033[0m\n"
"\n", argv[0]);
}
2018-11-25 06:57:58 +03:00
static int dereference = 0, quiet = 0;
2018-08-12 11:14:06 +03:00
2018-11-25 06:57:58 +03:00
static int stat_file(char * file) {
2018-08-12 11:14:06 +03:00
struct stat _stat;
2018-11-25 06:57:58 +03:00
int result;
if (dereference) {
2018-11-25 06:57:58 +03:00
result = stat(file, &_stat);
} else {
2018-11-25 06:57:58 +03:00
result = lstat(file, &_stat);
}
if (result == -1) {
if (!quiet) {
fprintf(stderr, "stat: %s: %s\n", file, strerror(errno));
}
return 1;
}
2018-08-12 11:14:06 +03:00
if (quiet) return 0;
2021-12-08 09:55:56 +03:00
const char * file_type = "regular file";
if (S_ISDIR(_stat.st_mode)) file_type = "directory";
else if (S_ISFIFO(_stat.st_mode)) file_type = "fifo";
else if (S_ISLNK(_stat.st_mode)) file_type = "symbolic link";
else if (S_ISBLK(_stat.st_mode)) file_type = "block device";
else if (S_ISCHR(_stat.st_mode)) file_type = "character device";
struct stat * f = &_stat;
2021-12-08 09:55:56 +03:00
printf(" File: %s\n", file);
/* TODO: st_blocks is not being set, skip it */
printf(" Size: %-10lu %s\n", f->st_size, file_type);
printf("Device: %-10u Inode: %-10u Links: %u\n", f->st_dev, f->st_ino, f->st_nlink);
printf("Access: ");
/* Copied from apps/ls.c */
if (S_ISLNK(f->st_mode)) { printf("l"); }
else if (S_ISCHR(f->st_mode)) { printf("c"); }
else if (S_ISBLK(f->st_mode)) { printf("b"); }
else if (S_ISDIR(f->st_mode)) { printf("d"); }
else { printf("-"); }
printf( (f->st_mode & S_IRUSR) ? "r" : "-");
printf( (f->st_mode & S_IWUSR) ? "w" : "-");
printf( (f->st_mode & S_ISUID) ? "s" : ((f->st_mode & S_IXUSR) ? "x" : "-"));
printf( (f->st_mode & S_IRGRP) ? "r" : "-");
printf( (f->st_mode & S_IWGRP) ? "w" : "-");
printf( (f->st_mode & S_IXGRP) ? "x" : "-");
printf( (f->st_mode & S_IROTH) ? "r" : "-");
printf( (f->st_mode & S_IWOTH) ? "w" : "-");
printf( (f->st_mode & S_IXOTH) ? "x" : "-");
printf(" Uid: %-8u Gid: %-8u\n", f->st_uid, f->st_gid);
char time_buf[80];
strftime(time_buf, 80, "%c", localtime((time_t*)&f->st_atime));
printf("Access: %s\n", time_buf);
strftime(time_buf, 80, "%c", localtime((time_t*)&f->st_mtime));
printf("Modify: %s\n", time_buf);
strftime(time_buf, 80, "%c", localtime((time_t*)&f->st_ctime));
printf("Change: %s\n", time_buf);
return 0;
2018-11-25 06:57:58 +03:00
}
int main(int argc, char ** argv) {
int opt;
while ((opt = getopt(argc, argv, "?Lq")) != -1) {
switch (opt) {
case 'L':
dereference = 1;
break;
case 'q':
quiet = 1;
break;
case '?':
show_usage(argc,argv);
return 1;
}
}
if (optind >= argc) {
show_usage(argc, argv);
return 1;
}
int ret = 0;
while (optind < argc) {
ret |= stat_file(argv[optind]);
optind++;
}
return ret;
}