From 42ba755c425682f1f54fdb40a39227035e833cfd Mon Sep 17 00:00:00 2001 From: Thorsten Töpper Date: Sat, 14 Jun 2025 16:21:27 +0200 Subject: source and output reorganized --- dir_monitor.c | 337 ---------------------------------------------------------- 1 file changed, 337 deletions(-) delete mode 100644 dir_monitor.c (limited to 'dir_monitor.c') diff --git a/dir_monitor.c b/dir_monitor.c deleted file mode 100644 index 9e993a8..0000000 --- a/dir_monitor.c +++ /dev/null @@ -1,337 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -/* Copyright 2025 Thorsten Töpper - * - * dir_monitor - print specified stat() information from entries of a given - * directory to stdout. Call it via watch for repeated output to a terminal. - * - * vim:ts=4:sw=4:expandtab - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define LOGERR(...) {fprintf(stderr, "[%s:%d] %s: ", __FILE__, __LINE__, __func__); fprintf(stderr, __VA_ARGS__);} - -#ifdef DEBUGBUILD -#define DBGTRC(...) LOGERR(__VA_ARGS__) -#else -#define DBGTRC(...) -#endif - - - -/* === DEFINITIONS === */ -#define PATH_SEP '/' - -struct list_node { - struct list_node *next; - size_t fsize; - char fname[256]; - time_t ftime; /* can be creation, access or modification */ -}; - -struct list_head { - struct list_node *first; -}; - -struct list_node *create_node(char *fname, size_t fsize, time_t ftime); -void destroy_list(struct list_head *list); -int fputc_all_cols(char c, FILE *fdout); -int fputc_width_x(char c, size_t x, FILE *fdout); -struct list_head *get_data_from_directory(char *path); -int insert_sorted_by_size(struct list_head *list, struct list_node *node); -int parse_arguments(int argc, char **argv); -void print_list(struct list_head *list); -void set_option(const char *option_name, char *option_argument); - - - -/* === GLOBAL VARIABLES === */ -struct option long_options[] = { - { "show-hidden-entries", no_argument, 0, 0 }, - { "long-timestamp", no_argument, 0, 0 }, - { 0, 0, 0, 0 } -}; -bool option_show_hidden_entries = false; -bool option_timestamp_long = false; - - - -/* === IMPLEMENTATION === */ -inline struct list_node *create_node(char *fname, size_t fsize, time_t ftime) { - struct list_node *node = NULL; - - if (fname == NULL || fname[0] == '\0') { - LOGERR("ERROR: No valid filename given\n"); - return NULL; - } - - if ((node = calloc(1, sizeof(struct list_node))) == NULL) { - LOGERR("ERROR: Failed allocate memory for node: %s\n", strerror(errno)); - return NULL; - } - - node->next = NULL; - node->fsize = fsize; - node->ftime = ftime; - strncpy(node->fname, fname, 256); - return node; -} - - -inline void destroy_list(struct list_head *list) { - struct list_node *ptr = NULL; - if (list == NULL) - return; - while (list->first != NULL) { - ptr = list->first->next; - if (ptr == NULL) { - free(list->first); - break; - } - list->first->next = ptr->next; - free(ptr); - } - free(list); -} - - -inline int fputc_all_cols(char c, FILE *fdout) { - struct winsize terminal; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminal); - return fputc_width_x(c, ((terminal.ws_col == 0) ? 72 : terminal.ws_col), fdout); -} - - -/* Not the most performant way, but during output the time critical tasks are already done. */ -inline int fputc_width_x(char c, size_t x, FILE *fdout) { - size_t i=0; - - if (fdout == NULL) { - LOGERR("ERROR: No output stream given.\n"); - return EOF; - } - - if ( ! isprint(c) ) { c = '?'; } - - for (i=0; i_fileno); - return EOF; - } - } - - return 1; -} - - -/* TODO: later when, other parameters are actively used move the action to a template */ -inline int insert_sorted_by_size(struct list_head *list, struct list_node *node) { - struct list_node *ptr = NULL; - - if (list == NULL) { LOGERR("ERROR: No list given.\n"); return -1; } - if (node == NULL) { LOGERR("ERROR: No node given.\n"); return -2; } - - if (list->first == NULL) { - list->first = node; - return 0; - } - - if (node->fsize > list->first->fsize) { - node->next = list->first; - list->first = node; - return 0; - } - - ptr = list->first; - while (ptr != NULL) { - if (ptr->next == NULL) { - ptr->next = node; - return 0; - } - if (node->fsize > ptr->next->fsize) { - node->next = ptr->next; - ptr->next = node; - return 0; - } - ptr = ptr->next; - } - - return -3; -} - - -/* The most simple default output, formatted output is planned */ -void print_list(struct list_head *list) { - struct list_node *ptr; - struct tm *tm = NULL; - char timestamp[128]; - size_t total_size = 0; - - if (list == NULL) return; - - ptr = list->first; - while (ptr != NULL) { - printf(" %8lu %2s ", ((ptr->fsize>=1024) ? (ptr->fsize/1024) : ptr->fsize), - ((ptr->fsize >= 1024) ? "kB" : "")); - - tm = localtime(&ptr->ftime); - if (option_timestamp_long) { - strftime(timestamp, sizeof(timestamp), "%Y%m%d %H:%M:%S %Z", tm); - printf(" %20s ", timestamp); - } else { - strftime(timestamp, sizeof(timestamp), "%H:%M:%S", tm); - printf(" %8s ", timestamp); - } - printf(" %s\n", ptr->fname); - total_size += ptr->fsize; - ptr = ptr->next; - } - fputc_all_cols('=', stdout); - printf("\nTotal size: %llu %s\n", ((total_size>1024) ? total_size/1024 : total_size), - ((total_size >= 1024) ? "kB" : "")); -} - - -/* TODO: When sorting via different parameters is possible, the call needs adjustments */ -struct list_head *get_data_from_directory(char *path) { - char *fullpath = NULL, *fname_in_path = NULL; - DIR *dir = NULL; - size_t l; - struct dirent *de = NULL; - struct list_node *tmp = NULL; - struct list_head *list = NULL; - struct stat stat_res; - - if (path == NULL) { - LOGERR("ERROR: No path given.\n"); - return NULL; - } - - l = strlen(path); - /* 258 filename and possibly required PATH_SEP and of course string termination */ - if ((fullpath = calloc(l+258, sizeof(char))) == NULL) { - LOGERR("ERROR: Failed to allocate memory for list head.\n"); - return NULL; - } - sprintf(fullpath, "%s%c", path, ((path[l-1] == PATH_SEP) ? '\0' : PATH_SEP)); - fname_in_path = (fullpath[l] == PATH_SEP) ? &(fullpath[l+1]) : &(fullpath[l]) ; - - if ((dir = opendir(path)) == NULL) { - LOGERR("ERROR: Failed to open directory '%s': %s (errno %d)\n", - path, strerror(errno), errno); - return NULL; - } - - /* TBH: In case those few bytes are not available, the process will be killed anyways */ - if ((list = calloc(1, sizeof(struct list_head))) == NULL) { - LOGERR("ERROR: Failed to allocate memory for list head.\n"); - closedir(dir); - return NULL; - } - - errno = 0; - /* Show hidden entries code is UNIXoid specific, needs to be adjusted for portability */ - while ((de = readdir(dir)) != NULL) { - if (de->d_name[0] == '.' && option_show_hidden_entries == false) - continue; - - sprintf(fname_in_path, "%s", de->d_name); - DBGTRC("DEBUG: fullpath: '%s'\n", fullpath); - if (lstat(fullpath, &stat_res) != 0) { - LOGERR("ERROR: lstat call on '%s' failed: %s (errno %d)\n", - fullpath, strerror(errno), errno); - continue; - } - /* currently ignoring return values */ - tmp = create_node(de->d_name, stat_res.st_size, stat_res.st_mtime); - insert_sorted_by_size(list, tmp); - } - - free(fullpath); - closedir(dir); - return list; -} - - -void set_option(const char *option_name, char *option_argument) { - if (option_name == NULL) - return; - - if (strcmp(option_name, "show-hidden-entries") == 0) { - option_show_hidden_entries = true; - return; - } - - if (strcmp(option_name, "long-timestamp") == 0) { - option_timestamp_long = true; - return; - } - - LOGERR("ERROR: Option '%s' not recognized\n.", option_name); -} - -int parse_arguments(int argc, char **argv) { - int c = 0, index; - - while(1) { - index = 0; - c = getopt_long(argc, argv, "tv", long_options, &index); - - if (c == -1) { - break; - } - - switch (c) { - case 0: - set_option(long_options[index].name, optarg); - break; - case 't': - option_timestamp_long = true; - break; - case 'v': - option_show_hidden_entries = true; - break; - default: - LOGERR("ERROR: unrecognized option '0x%02X'\n", c); - break; - } - } - - return optind; -} - - -int main(int argc, char **argv) { - struct list_head *list = NULL; - int path_index = 1; - /* TODO: Handle options */ - if (argc < 2) { - fprintf(stderr, "Call: %s OPTIONS path_to_open\n", argv[0]); - fprintf(stderr, "\nOPTIONS are\n"); - /* long name, short name, optional argument, explanation */ - fprintf(stderr, " %-25s %2s %10s %s\n", "--long-timestamp", "-t", "", - "Print timestamp in long form yyyymmdd HH:MM:SS ZONE"); - fprintf(stderr, " %-25s %2s %10s %s\n", "--show-hidden-entries", "-v", "", - "Show hidden entries in the directory"); - return EXIT_FAILURE; - } - path_index = parse_arguments(argc, argv); - list = get_data_from_directory(argv[path_index]); - print_list(list); - destroy_list(list); - return EXIT_SUCCESS; -} - -- cgit v1.2.3-70-g09d2