Don't cast void * to prop_dictionary_t. It's done implicitly
[eleutheria.git] / proplib / prop_parse_du.c
blobab598bd7d74584dfdb59a4b8d1b4d86296adc0d1
1 /*
2 * This program executes du(1) via pipe(), then parses
3 * the resulted output and populates a dictionary which
4 * looks like this:
5 *
6 * [root dictionary]
7 * [child dictionary]
8 * [path]
9 * [size]
10 * [type]
11 * [child dictionary]
12 * [path]
13 * [size]
14 * [type]
15 * ...
17 * It then gets a reference to the child dictionary
18 * pertaining to `.' path and extracts all <key, value>
19 * pairs before it prints them to stdout.
21 * Compile with:
22 * gcc prop_parse_du.c -o prop_parse_du -lprop -Wall -W -Wextra -ansi
25 #include <err.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <prop/proplib.h>
30 #include <sys/stat.h> /* for lstat(2) */
32 #define INIT_ROOT_CAPACITY 100 /* root's dict initial capacity */
33 #define INIT_CHILD_CAPACITY 3 /* child's dict initial capacity */
34 #define MAX_STR 100
35 #define MAX_TOKENS 3
37 int main(void)
39 char str[MAX_STR];
40 struct stat sb; /* for lstat(2) */
41 prop_dictionary_t prd; /* root dictionary */
42 prop_dictionary_t pcd; /* child dictionary */
43 prop_string_t ps; /* path name */
44 prop_number_t pn; /* size in bytes */
45 prop_bool_t pb; /* true = dir */
46 prop_object_t po;
47 char *tokens[MAX_TOKENS]; /* for du(1) output parse */
48 char *last, *p;
49 FILE *fp;
50 int i;
53 * Initiate pipe stream to du(1)
54 * -a flag: Display an entry for each file in the file hierarchy.
55 * -P flag: No symbolic links are followed.
57 fp = popen("du -a -P", "r");
58 if (fp == NULL)
59 err(EXIT_FAILURE, "popen()");
61 /* Create root dictionary */
62 prd = prop_dictionary_create_with_capacity(INIT_ROOT_CAPACITY);
63 if (prd == NULL)
64 err(EXIT_FAILURE, "prop_dictionary_create_with_capacity()");
66 /* Read from stream */
67 while (fgets(str, MAX_STR, fp) != NULL) {
68 /* Parse output of du(1) command */
69 i = 0;
70 p = strtok_r(str, "\t", &last);
71 while (p && i < MAX_TOKENS - 1) {
72 tokens[i++] = p;
73 p = strtok_r(NULL, "\t", &last);
75 tokens[i] = NULL;
77 /* Trim '\n' from tokens[1] */
78 (tokens[1])[strlen(tokens[1]) - 1] = '\0';
80 /* Create child dictionary */
81 pcd = prop_dictionary_create_with_capacity(INIT_CHILD_CAPACITY);
82 if (pcd == NULL)
83 err(EXIT_FAILURE, "prop_dictionary_create_with_capacity()");
86 * tokens[0] holds the size in bytes
88 * We use a signed prop_number_t object, so that
89 * when externalized it will be represented as decimal
90 * (unsigned numbers are externalized in base-16).
92 * Note: atoi() does not detect errors, but we trust
93 * du(1) to provide us with valid input. Otherwise,
94 * we should use strtol(3) or sscanf(3).
96 pn = prop_number_create_integer(atoi(tokens[0]));
97 if (pn == NULL)
98 err(EXIT_FAILURE, "prop_number_create_integer()");
100 /* tokens[1] holds the path */
101 ps = prop_string_create_cstring(tokens[1]);
102 if (ps == NULL)
103 err(EXIT_FAILURE, "prop_string_create_cstring()");
105 /* Is it a directory ? Find out with lstat(2) */
106 if (lstat(tokens[1], &sb) == -1)
107 err(EXIT_FAILURE, "lstat()");
109 pb = prop_bool_create(sb.st_mode & S_IFDIR ? TRUE : FALSE);
110 if (pb == NULL)
111 err(EXIT_FAILURE, "prop_bool_create()");
113 /* Add path, size and type to child dictionary */
114 if ((prop_dictionary_set(pcd, "path", ps) == FALSE)
115 || (prop_dictionary_set(pcd, "size in bytes", pn) == FALSE)
116 || (prop_dictionary_set(pcd, "is it dir?", pb) == FALSE))
117 err(EXIT_FAILURE, "prop_dictionary_set()");
119 /* Add child dictionary to root dictionary */
120 if (prop_dictionary_set(prd, tokens[1], pcd) == FALSE)
121 err(EXIT_FAILURE, "prop_dictionary_set()");
123 /* Release all objects except for the root dictionary */
124 prop_object_release(pn);
125 prop_object_release(ps);
126 prop_object_release(pb);
127 prop_object_release(pcd);
130 /* Externalize root dictionary to file in XML representation */
131 if (prop_dictionary_externalize_to_file(prd, "./data.xml") == FALSE)
132 err(EXIT_FAILURE, "prop_dictionary_externalize_to_file()");
134 /* Get child dictionary pertaining to `.' path */
135 po = prop_dictionary_get(prd, ".");
136 if (po == NULL) {
137 prop_object_release(prd);
138 err(EXIT_FAILURE, "prop_dictionary_get()");
141 /* Extract all <key, value> pairs and print them to stdout */
142 printf("Path: %s\nSize in bytes: %lld\nIs it dir?: %s\n",
143 prop_string_cstring(
144 prop_dictionary_get(po, "path")),
145 prop_number_integer_value(
146 prop_dictionary_get(po, "size in bytes")),
147 prop_bool_true(
148 prop_dictionary_get(po, "is it dir?")) == TRUE ?
149 "TRUE" : "FALSE");
151 /* Release root dictionary */
152 prop_object_release(prd);
154 /* Close pipe stream */
155 if (pclose(fp) == -1)
156 err(EXIT_FAILURE, "pclose()");
158 return EXIT_SUCCESS;