aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dir_monitor.c164
1 files changed, 132 insertions, 32 deletions
diff --git a/src/dir_monitor.c b/src/dir_monitor.c
index 9e993a8..8d70262 100644
--- a/src/dir_monitor.c
+++ b/src/dir_monitor.c
@@ -35,6 +35,7 @@
/* === DEFINITIONS === */
#define PATH_SEP '/'
+enum esort_type { SORT_BY_SIZE, SORT_BY_TIME, SORT_UNDEFINED };
struct list_node {
struct list_node *next;
size_t fsize;
@@ -47,28 +48,34 @@ struct list_head {
};
struct list_node *create_node(char *fname, size_t fsize, time_t ftime);
+struct list_head *create_list_sort_reversed(struct list_head *list);
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 insert_sorted_by_time(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);
+void usage(char *executable);
/* === GLOBAL VARIABLES === */
struct option long_options[] = {
+ { "reverse-sort", no_argument, 0, 0 },
{ "show-hidden-entries", no_argument, 0, 0 },
+ { "sort-by", required_argument, 0, 0 },
{ "long-timestamp", no_argument, 0, 0 },
{ 0, 0, 0, 0 }
};
+bool option_sort_reverse_order = false;
+enum esort_type option_sort_type = SORT_BY_SIZE;
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;
@@ -137,10 +144,21 @@ inline int fputc_width_x(char c, size_t x, FILE *fdout) {
}
+#define INSERT_BY_NUMERIC_FIELD(list, node, field) \
+{ struct list_node *ptr = NULL; \
+ if (node->field > list->first->field) { \
+ 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->field > ptr->next->field) { \
+ node->next = ptr->next; ptr->next = node; \
+ return 0; } \
+ ptr = ptr->next; } }
+
+
/* 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; }
@@ -148,41 +166,40 @@ inline int insert_sorted_by_size(struct list_head *list, struct list_node *node)
list->first = node;
return 0;
}
+ INSERT_BY_NUMERIC_FIELD(list, node, fsize);
+ return -3;
+}
+
+int insert_sorted_by_time(struct list_head *list, struct list_node *node) {
+ if (list == NULL) { LOGERR("ERROR: No list given.\n"); return -1; }
+ if (node == NULL) { LOGERR("ERROR: No node given.\n"); return -2; }
- if (node->fsize > list->first->fsize) {
- node->next = list->first;
+ if (list->first == NULL) {
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;
+ INSERT_BY_NUMERIC_FIELD(list, node, ftime);
}
-
+#undef INSERT_BY_NUMERIC_FIELD
/* The most simple default output, formatted output is planned */
void print_list(struct list_head *list) {
+ struct list_head *lh = list;
struct list_node *ptr;
struct tm *tm = NULL;
char timestamp[128];
size_t total_size = 0;
if (list == NULL) return;
+ if (option_sort_reverse_order) {
+ lh = create_list_sort_reversed(list);
+ /* be tolerant */
+ if (lh == NULL) {
+ lh = list;
+ }
+ }
- ptr = list->first;
+ ptr = lh->first;
while (ptr != NULL) {
printf(" %8lu %2s ", ((ptr->fsize>=1024) ? (ptr->fsize/1024) : ptr->fsize),
((ptr->fsize >= 1024) ? "kB" : ""));
@@ -202,6 +219,39 @@ void print_list(struct list_head *list) {
fputc_all_cols('=', stdout);
printf("\nTotal size: %llu %s\n", ((total_size>1024) ? total_size/1024 : total_size),
((total_size >= 1024) ? "kB" : ""));
+
+ if (lh != list) destroy_list(lh);
+}
+
+
+
+struct list_head *create_list_sort_reversed(struct list_head *list) {
+ struct list_head *lh = NULL;
+ struct list_node *cpynode = NULL, *ptr = NULL;
+ if (list == NULL) {
+ LOGERR("ERROR: No list given\n");
+ return NULL;
+ }
+ if ((lh = calloc(1, sizeof(struct list_head))) == NULL) {
+ LOGERR("ERROR: Failed to allocate memory for a struct list_head\n");
+ return NULL;
+ }
+
+ lh->first = NULL;
+ ptr = list->first;
+
+ while (ptr != NULL) {
+ cpynode = create_node(ptr->fname, ptr->fsize, ptr->ftime);
+ if (cpynode == NULL) {
+ destroy_list(lh);
+ return NULL;
+ }
+ cpynode->next = lh->first;
+ lh->first = cpynode;
+ ptr = ptr->next;
+ }
+
+ return lh;
}
@@ -257,7 +307,14 @@ struct list_head *get_data_from_directory(char *path) {
}
/* currently ignoring return values */
tmp = create_node(de->d_name, stat_res.st_size, stat_res.st_mtime);
- insert_sorted_by_size(list, tmp);
+ switch (option_sort_type) {
+ case SORT_BY_SIZE:
+ insert_sorted_by_size(list, tmp);
+ break;
+ case SORT_BY_TIME:
+ insert_sorted_by_time(list, tmp);
+ break;
+ };
}
free(fullpath);
@@ -267,9 +324,14 @@ struct list_head *get_data_from_directory(char *path) {
void set_option(const char *option_name, char *option_argument) {
+
+ DBGTRC("DEBUG: called with option_name '%s' and option_argument '%s'\n",
+ option_name, option_argument);
+
if (option_name == NULL)
return;
+ /* options WITHOUT arguments */
if (strcmp(option_name, "show-hidden-entries") == 0) {
option_show_hidden_entries = true;
return;
@@ -280,6 +342,30 @@ void set_option(const char *option_name, char *option_argument) {
return;
}
+ if (strcmp("reverse-sort", option_name) == 0) {
+ option_sort_reverse_order = true;
+ return;
+ }
+
+ /* options WITH arguments */
+ if (option_argument == NULL || option_argument[0] == '\0') {
+ LOGERR("ERROR: option_name %s with missing option_argument\n",
+ option_name);
+ return;
+ }
+
+ if (strcmp(option_name, "sort-by") == 0) {
+ if (strncmp("size", option_argument, 4) == 0) {
+ option_sort_type = SORT_BY_SIZE;
+ } else if (strncmp("time", option_argument, 4) == 0) {
+ option_sort_type = SORT_BY_TIME;
+ } else {
+ LOGERR("WARNING: '%s' is an invalig argument for %s\n",
+ option_argument, option_name);
+ }
+ return;
+ }
+
LOGERR("ERROR: Option '%s' not recognized\n.", option_name);
}
@@ -304,8 +390,10 @@ int parse_arguments(int argc, char **argv) {
case 'v':
option_show_hidden_entries = true;
break;
+ case '?':
+ break;
default:
- LOGERR("ERROR: unrecognized option '0x%02X'\n", c);
+ LOGERR("ERROR: unrecognized option 0x%02X '%c'\n", c);
break;
}
}
@@ -314,21 +402,33 @@ int parse_arguments(int argc, char **argv) {
}
+void usage(char *executable) {
+ fprintf(stderr, "Call: %s OPTIONS path_to_open\n", executable);
+ 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", "--reverse-sort", "", "",
+ "Sort reversed");
+ fprintf(stderr, " %-25s %2s %10s %s\n", "--show-hidden-entries", "-v", "",
+ "Show hidden entries in the directory");
+ fprintf(stderr, " %-25s %2s %10s %s\n", "--sort-by", "", "size|time",
+ "Sort either by time or size");
+}
+
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");
+ usage(argv[0]);
return EXIT_FAILURE;
}
path_index = parse_arguments(argc, argv);
+ if (path_index == argc) {
+ usage(argv[0]);
+ return EXIT_FAILURE;
+ }
list = get_data_from_directory(argv[path_index]);
print_list(list);
destroy_list(list);