Codebase list distro-info / 6c31ef0
Change previous commit to my personal programming style. Benjamin Drung 10 years ago
2 changed file(s) with 227 addition(s) and 220 deletion(s). Raw diff Collapse all Expand all
5050 distro_list = distro_list->next;
5151 if(distro_list) {
5252 if(date_ge(MILESTONE(distro_list->distro, MILESTONE_RELEASE),
53 MILESTONE(newest, MILESTONE_RELEASE))) {
53 MILESTONE(newest, MILESTONE_RELEASE))) {
5454 second = newest;
5555 newest = distro_list->distro;
56 } else if(second && date_ge(MILESTONE(distro_list->distro, MILESTONE_RELEASE),
56 } else if(second && date_ge(MILESTONE(distro_list->distro,
57 MILESTONE_RELEASE),
5758 MILESTONE(second, MILESTONE_RELEASE))) {
5859 second = distro_list->distro;
5960 }
1414 */
1515
1616 // C standard libraries
17 #include <assert.h>
1718 #include <errno.h>
1819 #include <stdbool.h>
1920 #include <stdio.h>
2021 #include <stdlib.h>
2122 #include <string.h>
2223 #include <time.h>
23 #include <assert.h>
2424
2525 #include <getopt.h>
2626 #include <sys/stat.h>
4848 assert(milestone);
4949
5050 for(i = 0; i < (int)MILESTONE_COUNT; i++) {
51 if (! strcmp(milestone, milestones[i]))
51 if (!strcmp(milestone, milestones[i])) {
5252 return i;
53 }
5354 }
5455
5556 return -1;
100101 date->month == 1 ? 29 : days_in_month[date->month-1]);
101102 }
102103
103
104104 static time_t date_to_secs(const date_t *date) {
105105 time_t seconds = 0;
106106 struct tm tm;
119119 }
120120
121121 static inline size_t date_diff(const date_t *date1, const date_t *date2) {
122
123 time_t time1;
124 time_t time2;
125 time_t diff;
126 unsigned int days;
127
128 time1 = date_to_secs(date1);
129 time2 = date_to_secs(date2);
130
131 diff = (time_t)difftime(time1, time2);
132
133 days = (unsigned int)diff / (60 * 60 * 24);
134
135 return days;
122 time_t time1;
123 time_t time2;
124 time_t diff;
125 unsigned int days;
126
127 time1 = date_to_secs(date1);
128 time2 = date_to_secs(date2);
129
130 diff = (time_t)difftime(time1, time2);
131
132 days = (unsigned int)diff / (60 * 60 * 24);
133
134 return days;
136135 }
137136
138137 static inline bool is_valid_codename(const char *codename) {
169168 }
170169
171170 static inline bool created(const date_t *date, const distro_t *distro) {
172 return MILESTONE(distro, MILESTONE_CREATED)
173 && date_ge(date, MILESTONE(distro, MILESTONE_CREATED));
171 return MILESTONE(distro, MILESTONE_CREATED) &&
172 date_ge(date, MILESTONE(distro, MILESTONE_CREATED));
174173 }
175174
176175 static inline bool released(const date_t *date, const distro_t *distro) {
181180
182181 static inline bool eol(const date_t *date, const distro_t *distro) {
183182 return MILESTONE(distro, MILESTONE_EOL) &&
184 date_ge(date, MILESTONE(distro, MILESTONE_EOL)) &&
185 (!MILESTONE(distro, MILESTONE_EOL_SERVER) ||
186 (MILESTONE(distro, MILESTONE_EOL_SERVER) &&
187 date_ge(date, MILESTONE(distro, MILESTONE_EOL_SERVER))));
183 date_ge(date, MILESTONE(distro, MILESTONE_EOL)) &&
184 (!MILESTONE(distro, MILESTONE_EOL_SERVER) ||
185 (MILESTONE(distro, MILESTONE_EOL_SERVER) &&
186 date_ge(date, MILESTONE(distro, MILESTONE_EOL_SERVER))));
188187 }
189188
190189 // Filter callbacks
215214 selected = distro_list->distro;
216215 while(distro_list != NULL) {
217216 distro_list = distro_list->next;
218 if(distro_list && date_ge(MILESTONE(distro_list->distro, MILESTONE_CREATED),
217 if(distro_list && date_ge(MILESTONE(distro_list->distro,
218 MILESTONE_CREATED),
219219 MILESTONE(selected, MILESTONE_CREATED))) {
220220 selected = distro_list->distro;
221221 }
229229 selected = distro_list->distro;
230230 while(distro_list != NULL) {
231231 distro_list = distro_list->next;
232 if(distro_list && date_ge(MILESTONE(distro_list->distro, MILESTONE_RELEASE),
232 if(distro_list && date_ge(MILESTONE(distro_list->distro,
233 MILESTONE_RELEASE),
233234 MILESTONE(selected, MILESTONE_RELEASE))) {
234235 selected = distro_list->distro;
235236 }
237238 return selected;
238239 }
239240
240 static bool calculate_days(const distro_t *distro, const date_t *date, int date_index, ssize_t *days) {
241 static bool calculate_days(const distro_t *distro, const date_t *date,
242 int date_index, ssize_t *days) {
241243 const date_t *first;
242244 const date_t *second;
243245 date_t *milestone = NULL;
244246 int direction;
245247
246 if (date_index == milestone_to_index(MILESTONE_CREATED))
248 if(date_index == milestone_to_index(MILESTONE_CREATED)) {
247249 milestone = MILESTONE(distro, MILESTONE_CREATED);
248 else if (date_index == milestone_to_index(MILESTONE_RELEASE))
250 } else if(date_index == milestone_to_index(MILESTONE_RELEASE)) {
249251 milestone = MILESTONE(distro, MILESTONE_RELEASE);
250 else if (date_index == milestone_to_index(MILESTONE_EOL))
252 } else if(date_index == milestone_to_index(MILESTONE_EOL)) {
251253 milestone = MILESTONE(distro, MILESTONE_EOL);
252 else if (date_index == milestone_to_index(MILESTONE_EOL_SERVER)) {
254 } else if(date_index == milestone_to_index(MILESTONE_EOL_SERVER)) {
253255 milestone = MILESTONE(distro, MILESTONE_EOL_SERVER);
254 if (!milestone) {
256 if(!milestone) {
255257 fprintf(stderr, NAME ": no %s milestone for release codename %s\n",
256258 MILESTONE_EOL_SERVER, distro->series);
257259 return false;
260262
261263 assert(milestone);
262264
263 if (date_ge(date, milestone)) {
265 if(date_ge(date, milestone)) {
264266 first = date;
265267 second = milestone;
266268 direction = -1;
276278
277279 // Print callbacks
278280
279 static bool print_codename(const distro_t *distro,
280 const date_t *date,
281 static bool print_codename(const distro_t *distro, const date_t *date,
281282 int date_index) {
282283 ssize_t days;
283284
284 if (date_index == -1)
285 if(date_index == -1) {
285286 printf("%s\n", distro->series);
286 else {
287 if (! calculate_days(distro, date, date_index, &days))
287 } else {
288 if(!calculate_days(distro, date, date_index, &days)) {
288289 return false;
290 }
289291 printf("%s %ld\n", distro->series, (long int)days);
290 }
292 }
291293
292294 return true;
293295 }
294296
295 static bool print_fullname(const distro_t *distro,
296 const date_t *date,
297 static bool print_fullname(const distro_t *distro, const date_t *date,
297298 int date_index) {
298299 ssize_t days;
299300
300 if (date_index == -1)
301 if(date_index == -1) {
301302 printf(DISTRO_NAME " %s \"%s\"\n", distro->version, distro->codename);
302 else {
303 if (!calculate_days(distro, date, date_index, &days))
303 } else {
304 if(!calculate_days(distro, date, date_index, &days)) {
304305 return false;
305 printf(DISTRO_NAME " %s \"%s\" %ld\n", distro->version, distro->codename,
306 (long int)days);
306 }
307 printf(DISTRO_NAME " %s \"%s\" %ld\n", distro->version,
308 distro->codename, (long int)days);
307309 }
308310 return true;
309311 }
310312
311 static bool print_release(const distro_t *distro,
312 const date_t *date,
313 int date_index) {
313 static bool print_release(const distro_t *distro, const date_t *date,
314 int date_index) {
314315 ssize_t days;
315316 char *str;
316317
317 str = unlikely(*distro->version == '\0')
318 ? distro->series : distro->version;
319
320 if (date_index == -1)
318 str = unlikely(*distro->version == '\0') ? distro->series : distro->version;
319
320 if(date_index == -1) {
321321 printf("%s\n", str);
322 else {
323 if (!calculate_days(distro, date, date_index, &days))
322 } else {
323 if(!calculate_days(distro, date, date_index, &days)) {
324324 return false;
325 }
325326 printf("%s %ld\n", str, (long int)days);
326327 }
327328
379380 distro->series = strsep(&line, ",");
380381
381382 for(milestone_index = 0; milestone_index < (int)MILESTONE_COUNT;
382 milestone_index++) {
383 milestone_index++) {
383384 distro->milestones[milestone_index] =
384385 read_date(strsep(&line, ","), &failures, filename,
385 lineno, index_to_milestone(milestone_index));
386 lineno, index_to_milestone(milestone_index));
386387 }
387388
388389 current = malloc(sizeof(distro_elem_t));
411412 }
412413
413414 static bool filter_data(const distro_elem_t *distro_list, const date_t *date,
414 int date_index,
415 bool (*filter_cb)(const date_t*, const distro_t*),
416 bool (*print_cb)(const distro_t*, const date_t*, int)) {
415 int date_index,
416 bool (*filter_cb)(const date_t*, const distro_t*),
417 bool (*print_cb)(const distro_t*, const date_t*, int)) {
417418 while(distro_list != NULL) {
418419 if(filter_cb(date, distro_list->distro)) {
419 if (print_cb(distro_list->distro, date, date_index) != true)
420 if(print_cb(distro_list->distro, date, date_index) != true) {
420421 goto error;
422 }
421423 }
422424 distro_list = distro_list->next;
423425 }
425427 return false;
426428 }
427429
428 static const distro_t *get_distro(const distro_elem_t *distro_list, const date_t *date,
429 bool (*filter_cb)(const date_t*, const distro_t*),
430 const distro_t *(*select_cb)(const distro_elem_t*)) {
430 static const distro_t *get_distro(const distro_elem_t *distro_list,
431 const date_t *date,
432 bool (*filter_cb)(const date_t*, const distro_t*),
433 const distro_t *(*select_cb)(const distro_elem_t*)) {
431434 distro_elem_t *current;
432435 distro_elem_t *filtered_list = NULL;
433436 distro_elem_t *last = NULL;
465468
466469 static void print_help(void) {
467470 printf("Usage: " NAME " [options]\n"
468 "\n"
469 "Options:\n"
470 " -h --help show this help message and exit\n"
471 " --date=DATE date for calculating the version (default: today)\n"
472 " -y[MILESTONE] additionally, display days until milestone\n"
473 " --days=[MILESTONE]\n"
474 #ifdef DEBIAN
475 " --alias=DIST print the alias (stable, testing, unstable) relative to\n"
476 " the distribution codename passed as an argument\n"
477 #endif
478 " -a --all list all known versions\n"
479 " -d --devel latest development version\n"
471 "\n"
472 "Options:\n"
473 " -h --help show this help message and exit\n"
474 " --date=DATE date for calculating the version (default: today)\n"
475 " -y[MILESTONE] additionally, display days until milestone\n"
476 " --days=[MILESTONE]\n"
477 #ifdef DEBIAN
478 " --alias=DIST print the alias (stable, testing, unstable) relative to\n"
479 " the distribution codename passed as an argument\n"
480 #endif
481 " -a --all list all known versions\n"
482 " -d --devel latest development version\n"
480483 #ifdef UBUNTU
481 " --lts latest long term support (LTS) version\n"
482 #endif
483 #ifdef DEBIAN
484 " -o --oldstable latest oldstable version\n"
485 #endif
486 " -s --stable latest stable version\n"
487 " --supported list of all supported stable versions\n"
488 #ifdef DEBIAN
489 " -t --testing current testing version\n"
490 #endif
491 " --unsupported list of all unsupported stable versions\n"
492 " -c --codename print the codename (default)\n"
493 " -f --fullname print the full name\n"
494 " -r --release print the release version\n"
495 "\n"
496 "See " NAME "(1) for more info.\n");
484 " --lts latest long term support (LTS) version\n"
485 #endif
486 #ifdef DEBIAN
487 " -o --oldstable latest oldstable version\n"
488 #endif
489 " -s --stable latest stable version\n"
490 " --supported list of all supported stable versions\n"
491 #ifdef DEBIAN
492 " -t --testing current testing version\n"
493 #endif
494 " --unsupported list of all unsupported stable versions\n"
495 " -c --codename print the codename (default)\n"
496 " -f --fullname print the full name\n"
497 " -r --release print the release version\n"
498 "\n"
499 "See " NAME "(1) for more info.\n");
497500 }
498501
499502 static inline int not_exactly_one(void) {
517520 }
518521
519522 int main(int argc, char *argv[]) {
523 bool show_days = false;
520524 char *content;
521525 date_t *date = NULL;
522526 distro_elem_t *distro_list;
523527 const distro_t *selected;
524528 int i;
529 int date_index = -1;
525530 int option;
526531 int option_index;
527532 int return_value = EXIT_SUCCESS;
532537 #ifdef DEBIAN
533538 char *alias_codename = NULL;
534539 #endif
535 int date_index = -1;
536 bool show_days = false;
537540
538541 const struct option long_options[] = {
539542 {"help", no_argument, NULL, 'h' },
569572 opterr = 0;
570573
571574 while ((option = getopt_long(argc, argv, short_options,
572 long_options, &option_index)) != -1) {
575 long_options, &option_index)) != -1) {
573576 switch (option) {
574577 #ifdef DEBIAN
575 case 'A':
576 // Only long option --alias is used
577 if(unlikely(alias_codename != NULL)) {
578 fprintf(stderr, NAME ": --alias requested multiple times.\n");
579 free(date);
580 return EXIT_FAILURE;
581 }
582 if(!is_valid_codename(optarg)) {
583 fprintf(stderr, NAME ": invalid distribution codename `%s'\n",
584 optarg);
585 free(date);
586 return EXIT_FAILURE;
587 }
588 selected_filters++;
589 alias_codename = optarg;
590 break;
591 #endif
592
593 case 'a':
594 selected_filters++;
595 filter_cb = filter_all;
596 select_cb = NULL;
597 break;
598
599 case 'c':
600 print_cb = print_codename;
601 break;
602
603 case 'd':
604 selected_filters++;
605 filter_cb = filter_devel;
606 #ifdef UBUNTU
607 select_cb = select_latest_created;
608 #endif
609 #ifdef DEBIAN
610 select_cb = select_first;
611 #endif
612 break;
613
614 case 'D':
615 // Only long option --date is used
616 if(unlikely(date != NULL)) {
617 fprintf(stderr, NAME ": Date specified multiple times.\n");
618 free(date);
619 return EXIT_FAILURE;
620 }
621 date = malloc(sizeof(date_t));
622 i = sscanf(optarg, "%u-%u-%u", &date->year, &date->month,
623 &date->day);
624 if(i != 3 || !is_valid_date(date)) {
625 fprintf(stderr, NAME ": invalid date `%s'\n", optarg);
626 free(date);
627 return EXIT_FAILURE;
628 }
629 break;
630
631 case 'f':
632 print_cb = print_fullname;
633 break;
634
635 case 'h':
636 print_help();
637 free(date);
638 return EXIT_SUCCESS;
639
640 #ifdef UBUNTU
641 case 'L':
642 // Only long option --lts is used
643 selected_filters++;
644 filter_cb = filter_lts;
645 select_cb = select_latest_release;
646 break;
647 #endif
648
649 #ifdef DEBIAN
650 case 'o':
651 selected_filters++;
652 filter_cb = filter_oldstable;
653 select_cb = select_oldstable;
654 break;
655 #endif
656
657 case 'r':
658 print_cb = print_release;
659 break;
660
661 case 's':
662 selected_filters++;
663 filter_cb = filter_stable;
664 select_cb = select_latest_release;
665 break;
666
667 case 'S':
668 // Only long option --supported is used
669 selected_filters++;
670 filter_cb = filter_supported;
671 select_cb = NULL;
672 break;
673
674 #ifdef DEBIAN
675 case 't':
676 selected_filters++;
677 filter_cb = filter_testing;
678 select_cb = select_latest_created;
679 break;
680 #endif
681
682 case 'U':
683 // Only long option --unsupported is used
684 selected_filters++;
685 filter_cb = filter_unsupported;
686 select_cb = NULL;
687 break;
688
689 case 'y':
690 show_days = true;
691 if (optarg) {
692 date_index = milestone_to_index (optarg);
693 if (date_index < 0) {
694 fprintf(stderr, NAME ": invalid milestone: %s\n", optarg);
578 case 'A':
579 // Only long option --alias is used
580 if(unlikely(alias_codename != NULL)) {
581 fprintf(stderr, NAME ": --alias requested multiple times.\n");
582 free(date);
695583 return EXIT_FAILURE;
696584 }
697 }
698 break;
585 if(!is_valid_codename(optarg)) {
586 fprintf(stderr, NAME ": invalid distribution codename `%s'\n",
587 optarg);
588 free(date);
589 return EXIT_FAILURE;
590 }
591 selected_filters++;
592 alias_codename = optarg;
593 break;
594 #endif
595
596 case 'a':
597 selected_filters++;
598 filter_cb = filter_all;
599 select_cb = NULL;
600 break;
601
602 case 'c':
603 print_cb = print_codename;
604 break;
605
606 case 'd':
607 selected_filters++;
608 filter_cb = filter_devel;
609 #ifdef UBUNTU
610 select_cb = select_latest_created;
611 #endif
612 #ifdef DEBIAN
613 select_cb = select_first;
614 #endif
615 break;
616
617 case 'D':
618 // Only long option --date is used
619 if(unlikely(date != NULL)) {
620 fprintf(stderr, NAME ": Date specified multiple times.\n");
621 free(date);
622 return EXIT_FAILURE;
623 }
624 date = malloc(sizeof(date_t));
625 i = sscanf(optarg, "%u-%u-%u", &date->year, &date->month,
626 &date->day);
627 if(i != 3 || !is_valid_date(date)) {
628 fprintf(stderr, NAME ": invalid date `%s'\n", optarg);
629 free(date);
630 return EXIT_FAILURE;
631 }
632 break;
633
634 case 'f':
635 print_cb = print_fullname;
636 break;
637
638 case 'h':
639 print_help();
640 free(date);
641 return EXIT_SUCCESS;
642
643 #ifdef UBUNTU
644 case 'L':
645 // Only long option --lts is used
646 selected_filters++;
647 filter_cb = filter_lts;
648 select_cb = select_latest_release;
649 break;
650 #endif
651
652 #ifdef DEBIAN
653 case 'o':
654 selected_filters++;
655 filter_cb = filter_oldstable;
656 select_cb = select_oldstable;
657 break;
658 #endif
659
660 case 'r':
661 print_cb = print_release;
662 break;
663
664 case 's':
665 selected_filters++;
666 filter_cb = filter_stable;
667 select_cb = select_latest_release;
668 break;
669
670 case 'S':
671 // Only long option --supported is used
672 selected_filters++;
673 filter_cb = filter_supported;
674 select_cb = NULL;
675 break;
676
677 #ifdef DEBIAN
678 case 't':
679 selected_filters++;
680 filter_cb = filter_testing;
681 select_cb = select_latest_created;
682 break;
683 #endif
684
685 case 'U':
686 // Only long option --unsupported is used
687 selected_filters++;
688 filter_cb = filter_unsupported;
689 select_cb = NULL;
690 break;
691
692 case 'y':
693 show_days = true;
694 if(optarg) {
695 date_index = milestone_to_index(optarg);
696 if(date_index < 0) {
697 fprintf(stderr, NAME ": invalid milestone: %s\n",
698 optarg);
699 return EXIT_FAILURE;
700 }
701 }
702 break;
699703
700704 case '?':
701705 if(optopt == '\0') {
726730 }
727731 }
728732
729 if (show_days && date_index < 0)
733 if(show_days && date_index < 0) {
730734 date_index = milestone_to_index(MILESTONE_RELEASE);
735 }
731736
732737 if(unlikely(optind < argc)) {
733738 fprintf(stderr, NAME ": unrecognized arguments: %s", argv[optind]);
793798 fprintf(stderr, NAME ": " OUTDATED_ERROR "\n");
794799 return_value = EXIT_FAILURE;
795800 } else {
796 if (print_cb(selected, date, date_index) != true)
801 if(print_cb(selected, date, date_index) != true) {
797802 return_value = EXIT_FAILURE;
803 }
798804 }
799805 }
800806 free(date);