static struct icaltimetype get_last_modified (icalcomponent *component) { icalcomponent *inner = icalcomponent_get_inner (component); icalproperty *prop; prop = icalcomponent_get_first_property (inner, ICAL_LASTMODIFIED_PROPERTY); if (prop == 0) { return icaltime_null_time (); } return icalproperty_get_lastmodified (prop); }
/* Add all ZONEs and LINKs in the given directory to the hash table */ void do_zonedir(const char *dir, struct hash_table *tzentries, struct zoneinfo *info) { DIR *dirp; struct dirent *dirent; signals_poll(); if (verbose) printf("Rebuilding %s\n", dir); dirp = opendir(dir); if (!dirp) { fprintf(stderr, "can't open zoneinfo directory %s\n", dir); } while ((dirent = readdir(dirp))) { char path[2048], *tzid; int plen; struct stat sbuf; struct zoneinfo *zi; if (*dirent->d_name == '.') continue; plen = snprintf(path, sizeof(path), "%s/%s", dir, dirent->d_name); lstat(path, &sbuf); if (S_ISDIR(sbuf.st_mode)) { /* Path is a directory (region) */ do_zonedir(path, tzentries, info); } else if (S_ISLNK(sbuf.st_mode)) { /* Path is a symlink (alias) */ char link[1024], *alias; ssize_t llen; /* Isolate tzid in path */ if ((llen = readlink(path, link, sizeof(link))) < 0) continue; link[llen-4] = '\0'; /* Trim ".ics" */ for (tzid = link; !strncmp(tzid, "../", 3); tzid += 3); /* Isolate alias in path */ path[plen-4] = '\0'; /* Trim ".ics" */ alias = path + strlen(config_dir) + strlen("zoneinfo") + 2; if (verbose) printf("\tLINK: %s -> %s\n", alias, tzid); /* Create hash entry for alias */ if (!(zi = hash_lookup(alias, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(alias, zi, tzentries); } zi->type = ZI_LINK; appendstrlist(&zi->data, tzid); /* Create/update hash entry for tzid */ if (!(zi = hash_lookup(tzid, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(tzid, zi, tzentries); } zi->type = ZI_ZONE; appendstrlist(&zi->data, alias); } else if (S_ISREG(sbuf.st_mode)) { /* Path is a regular file (zone) */ int fd; const char *base = NULL; size_t len = 0; icalcomponent *ical, *comp; icalproperty *prop; /* Parse the iCalendar file for important properties */ if ((fd = open(path, O_RDONLY)) == -1) continue; map_refresh(fd, 1, &base, &len, MAP_UNKNOWN_LEN, path, NULL); close(fd); ical = icalparser_parse_string(base); map_free(&base, &len); if (!ical) continue; /* skip non-iCalendar files */ comp = icalcomponent_get_first_component(ical, ICAL_VTIMEZONE_COMPONENT); prop = icalcomponent_get_first_property(comp, ICAL_TZID_PROPERTY); tzid = (char *) icalproperty_get_value_as_string(prop); if (verbose) printf("\tZONE: %s\n", tzid); /* Create/update hash entry for tzid */ if (!(zi = hash_lookup(tzid, tzentries))) { zi = xzmalloc(sizeof(struct zoneinfo)); hash_insert(tzid, zi, tzentries); } zi->type = ZI_ZONE; prop = icalcomponent_get_first_property(comp, ICAL_LASTMODIFIED_PROPERTY); zi->dtstamp = icaltime_as_timet(icalproperty_get_lastmodified(prop)); icalcomponent_free(ical); /* Check overall lastmod */ if (zi->dtstamp > info->dtstamp) info->dtstamp = zi->dtstamp; } else { fprintf(stderr, "unknown path type %s\n", path); } } closedir(dirp); }