Don't print an error message for empty courses
[nci.git] / nci-list-files.c
blob9b6cc0b9e409cac90a6a78c8cfeb1a1d27e3775d
1 /*
2 * Copyright (c) 2016-2019 S. Gilles <sgilles@math.umd.edu>
4 * Permission to use, copy, modify, and/or distribute this software
5 * for any purpose with or without fee is hereby granted, provided
6 * that the above copyright notice and this permission notice appear
7 * in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <errno.h>
19 #include <locale.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
26 #include <curl/curl.h>
27 #include <yajl_parse.h>
29 #include "macros.h"
30 #include "util.h"
32 enum {
33 FN_FOL_ID = 0,
34 FN_FOL_FULL_NAME = 1,
35 FN_FOL_END = 2,
38 enum {
39 FN_FIL_ID = 0,
40 FN_FIL_FOL_ID = 1,
41 FN_FIL_FILENAME = 2,
42 FN_FIL_END = 3,
45 static int
46 write_out_everything(map *folders, map *files)
48 int ret = EINVAL;
49 size_t j = 0;
50 size_t k = 0;
51 char **folder_keys = 0;
52 size_t folder_num = 0;
53 char **file_keys = 0;
54 size_t file_num = 0;
55 char **folder = 0;
56 char **file = 0;
57 const char *folder_print_name = 0;
58 char *printed_files = 0;
60 map_get_keys(folders, &folder_keys, &folder_num);
61 map_get_keys(files, &file_keys, &file_num);
63 if (!(printed_files = calloc(file_num, sizeof *printed_files))) {
64 ret = errno;
65 perror(L("calloc"));
66 goto cleanup;
69 for (j = 0; j < folder_num; ++j) {
70 folder = map_get(folders, folder_keys[j]);
72 if (!folder) {
73 continue;
76 folder_print_name = folder[FN_FOL_FULL_NAME - 1];
78 if (!strncmp(folder_print_name, "course files", 12)) {
79 folder_print_name = folder_print_name + 12;
81 while (folder_print_name[0] == '/') {
82 folder_print_name++;
86 for (k = 0; k < file_num; ++k) {
87 if (printed_files[k]) {
88 continue;
91 file = map_get(files, file_keys[k]);
93 if (!file) {
94 continue;
97 if (strcmp(file[FN_FIL_FOL_ID - 1], folder_keys[j])) {
98 continue;
101 if (folder_print_name[0]) {
102 printf("%s/%s\n", folder_print_name,
103 file[FN_FIL_FILENAME - 1]);
104 } else {
105 printf("%s\n", file[FN_FIL_FILENAME - 1]);
108 printed_files[k] = 1;
112 for (k = 0; k < file_num; ++k) {
113 if (printed_files[k]) {
114 continue;
117 file = map_get(files, file_keys[j]);
119 if (!file) {
120 continue;
123 printf("At unknown location: %s\n", file[FN_FIL_FILENAME - 1]);
126 ret = 0;
127 cleanup:
128 free(folder_keys);
129 free(file_keys);
130 free(printed_files);
132 return ret;
136 main(int argc, char **argv)
138 int ret = EINVAL;
139 char *url_base = 0;
140 char *auth_token = 0;
141 char *course_id = 0;
142 const char *fn_folders[] = {
143 /* */
144 [FN_FOL_ID] = "id", /* */
145 [FN_FOL_FULL_NAME] = "full_name", /* */
146 [FN_FOL_END] = 0 /* */
148 const char *fn_files[] = {
149 /* */
150 [FN_FIL_ID] = "id", /* */
151 [FN_FIL_FOL_ID] = "folder_id", /* */
152 [FN_FIL_FILENAME] = "filename", /* */
153 [FN_FIL_END] = 0 /* */
155 map folders = { 0 };
156 map files = { 0 };
157 size_t len = 0;
158 char *built_uri = 0;
159 int opt;
161 setlocale(LC_ALL, "");
163 while ((opt = getopt(argc, argv, "c:")) != -1) {
164 switch (opt) {
165 case 'c':
166 course_id = optarg;
167 break;
168 default:
169 break;
173 if (!course_id) {
174 ret = EINVAL;
175 fprintf(stderr, "course-id is mandatory\n");
176 goto cleanup;
179 curl_global_init(CURL_GLOBAL_DEFAULT);
181 if (!(url_base = get_url_base())) {
182 ret = ENOENT;
184 /* Error should have already been printed */
185 goto cleanup;
188 if (!(auth_token = get_auth_token())) {
189 ret = ENOENT;
191 /* Error should have already been printed */
192 goto cleanup;
195 len = snprintf(0, 0, "%s/api/v1/courses/%s/folders", url_base,
196 course_id);
198 if (len + 1 < len) {
199 ret = errno = EOVERFLOW;
200 perror(L(""));
201 goto cleanup;
204 if (!(built_uri = malloc(len + 1))) {
205 ret = errno;
206 perror(L("malloc"));
207 goto cleanup;
210 sprintf(built_uri, "%s/api/v1/courses/%s/folders", url_base, course_id);
212 if ((ret = key_value_extract(built_uri, auth_token, fn_folders, 0,
213 &folders))) {
214 goto cleanup;
217 free(built_uri);
218 built_uri = 0;
219 len = snprintf(0, 0, "%s/api/v1/courses/%s/files", url_base, course_id);
221 if (len + 1 < len) {
222 ret = errno = EOVERFLOW;
223 perror(L(""));
224 goto cleanup;
227 if (!(built_uri = malloc(len + 1))) {
228 ret = errno;
229 perror(L("malloc"));
230 goto cleanup;
233 sprintf(built_uri, "%s/api/v1/courses/%s/files", url_base, course_id);
235 if ((ret = key_value_extract(built_uri, auth_token, fn_files, 0,
236 &files))) {
237 goto cleanup;
240 if ((ret = write_out_everything(&folders, &files))) {
241 goto cleanup;
244 ret = 0;
245 cleanup:
246 free(built_uri);
247 map_clean(&folders);
248 map_clean(&files);
249 free(url_base);
250 free(auth_token);
251 curl_global_cleanup();
253 return ret;