Simplify if-else block
[eleutheria.git] / proplib / prop_parse_du.c
blob370ecc92d6d6682c1b568889626b0380ca911e32
1 /*
2 * [root dictionary]
3 * [child dictionary]
4 * [path]
5 * [size]
6 * [type]
7 * [child dictionary]
8 * [path]
9 * [size]
10 * [type]
11 * ...
13 * Compile with:
14 * gcc prop_parse_du.c -o prop_parse_du -lprop -Wall -W -Wextra -ansi -pedantic
17 #include <err.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <prop/proplib.h>
22 #include <sys/stat.h> /* for lstat() */
24 #define INIT_ROOT_CAPACITY 100 /* root's dict initial capacity */
25 #define INIT_CHILD_CAPACITY 3 /* child's dict initial capacity */
26 #define MAX_STR 100
27 #define MAX_TOKENS 3
29 /* Resources */
30 FILE *fp = NULL;
31 prop_dictionary_t prd = NULL; /* root dictionary */
32 prop_dictionary_t pcd = NULL; /* child dictionary */
33 prop_string_t ps = NULL; /* path name */
34 prop_number_t pn = NULL; /* size in bytes */
35 prop_bool_t pb = NULL; /* true = dir */
37 int main(void)
39 struct stat sb;
40 char str[MAX_STR];
41 char *tokens[MAX_TOKENS]; /* for du(1) output parse */
42 char *last, *p;
43 int i;
45 /* Initiate pipe stream to du(1)
46 * -a flag: Display an entry for each file in the file hierarchy.
47 * -P flag: No symbolic links are followed.
49 fp = popen("du -a -P", "r");
50 if (fp == NULL)
51 exit(EXIT_FAILURE);
53 /* Create root dictionary */
54 prd = prop_dictionary_create_with_capacity(INIT_ROOT_CAPACITY);
55 if (prd == NULL)
56 err(EXIT_FAILURE, "prop_dictionary_create_with_capacity()");
58 /* Read from stream */
59 while (fgets(str, MAX_STR, fp) != NULL) {
60 /* Parse output of du(1) command */
61 i = 0;
62 p = strtok_r(str, "\t", &last);
63 while (p && i < MAX_TOKENS - 1) {
64 tokens[i++] = p;
65 p = strtok_r(NULL, "\t", &last);
67 tokens[i] = NULL;
69 /* Trim '\n' from tokens[1] */
70 (tokens[1])[strlen(tokens[1]) - 1] = '\0';
72 /* Create child dictionary */
73 pcd = prop_dictionary_create_with_capacity(INIT_CHILD_CAPACITY);
74 if (pcd == NULL)
75 err(EXIT_FAILURE, "prop_dictionary_create_with_capacity()");
78 * tokens[0] holds the size in bytes
80 * We use a signed prop_number_t object, so that
81 * when externalized it will be represented as decimal
82 * (unsigned numbers are externalized in base-16).
84 * Note: atoi() does not detect errors, but we trust
85 * du(1) to provide us with valid input. Otherwise,
86 * we should use strtol(3) or sscanf(3).
88 pn = prop_number_create_integer(atoi(tokens[0]));
90 /* tokens[1] holds the path */
91 ps = prop_string_create_cstring(tokens[1]);
93 /* Is it a directory ? Find out with lstat(2) */
94 if (lstat(tokens[1], &sb) == -1)
95 err(EXIT_FAILURE, "lstat()");
97 pb = prop_bool_create(sb.st_mode & S_IFDIR ? TRUE : FALSE);
99 /* Add path, size and type to child dictionary */
100 if ((prop_dictionary_set(pcd, "path", ps) == FALSE)
101 || (prop_dictionary_set(pcd, "size in bytes", pn) == FALSE)
102 || (prop_dictionary_set(pcd, "is it dir?", pb) == FALSE))
103 err(EXIT_FAILURE, "prop_dictionary_set()");
105 /* Add child dictionary to root dictionary */
106 if (prop_dictionary_set(prd, tokens[1], pcd) == FALSE)
107 err(EXIT_FAILURE, "prop_dictionary_set()");
109 /* Release `pn' and `ps' */
110 prop_object_release(pn);
111 prop_object_release(ps);
112 prop_object_release(pb);
114 /* Release child dictionary */
115 prop_object_release(pcd);
118 /* Externalize root dictionary to file in XML representation */
119 if (prop_dictionary_externalize_to_file(prd, "./data.xml") == FALSE)
120 err(EXIT_FAILURE, "prop_dictionary_externalize_to_file()");
122 /* Release root dictionary */
123 prop_object_release(prd);
125 /* Close pipe stream */
126 if (pclose(fp) == -1)
127 err(EXIT_FAILURE, "pclose()");
129 return EXIT_SUCCESS;