| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <ctype.h> |
| #include <dirent.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <time.h> |
| |
| /* |
| * Compare a string to a mask |
| * Mask characters: |
| * @ - uppercase letter |
| * # - lowercase letter |
| * & - hex digit |
| * # - digit |
| * * - swallow remaining characters |
| * <x> - exact match for any other character |
| */ |
| static int checkmask(const char *data, const char *mask) |
| { |
| int i, ch, d; |
| |
| for (i = 0; mask[i] != '\0' && mask[i] != '*'; i++) { |
| ch = mask[i]; |
| d = data[i]; |
| if (ch == '@') { |
| if (!isupper(d)) |
| return 0; |
| } |
| else if (ch == '$') { |
| if (!islower(d)) |
| return 0; |
| } |
| else if (ch == '#') { |
| if (!isdigit(d)) |
| return 0; |
| } |
| else if (ch == '&') { |
| if (!isxdigit(d)) |
| return 0; |
| } |
| else if (ch != d) |
| return 0; |
| } |
| |
| if (mask[i] == '*') |
| return 1; |
| else |
| return (data[i] == '\0'); |
| } |
| |
| /* |
| * Converts 8 hex digits to a time integer |
| */ |
| static int hex2sec(const char *x) |
| { |
| int i, ch; |
| unsigned int j; |
| |
| for (i = 0, j = 0; i < 8; i++) { |
| ch = x[i]; |
| j <<= 4; |
| if (isdigit(ch)) |
| j |= ch - '0'; |
| else if (isupper(ch)) |
| j |= ch - ('A' - 10); |
| else |
| j |= ch - ('a' - 10); |
| } |
| if (j == 0xffffffff) |
| return -1; /* so that it works with 8-byte ints */ |
| else |
| return j; |
| } |
| |
| int main(int argc, char **argv) |
| { |
| int i, ver; |
| DIR *d; |
| struct dirent *e; |
| const char *s; |
| FILE *fp; |
| char path[FILENAME_MAX + 1]; |
| char line[1035]; |
| time_t date, lmod, expire; |
| unsigned int len; |
| struct tm ts; |
| char sdate[30], slmod[30], sexpire[30]; |
| const char time_format[] = "%e %b %Y %R"; |
| |
| if (argc != 2) { |
| printf("Usage: cls directory\n"); |
| exit(0); |
| } |
| |
| d = opendir(argv[1]); |
| if (d == NULL) { |
| perror("opendir"); |
| exit(1); |
| } |
| |
| for (;;) { |
| e = readdir(d); |
| if (e == NULL) |
| break; |
| s = e->d_name; |
| if (s[0] == '.' || s[0] == '#') |
| continue; |
| sprintf(path, "%s/%s", argv[1], s); |
| fp = fopen(path, "r"); |
| if (fp == NULL) { |
| perror("fopen"); |
| continue; |
| } |
| if (fgets(line, 1034, fp) == NULL) { |
| perror("fgets"); |
| fclose(fp); |
| continue; |
| } |
| if (!checkmask(line, "&&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&& &&&&&&&&\n")) { |
| fprintf(stderr, "Bad cache file\n"); |
| fclose(fp); |
| continue; |
| } |
| date = hex2sec(line); |
| lmod = hex2sec(line + 9); |
| expire = hex2sec(line + 18); |
| ver = hex2sec(line + 27); |
| len = hex2sec(line + 35); |
| if (fgets(line, 1034, fp) == NULL) { |
| perror("fgets"); |
| fclose(fp); |
| continue; |
| } |
| fclose(fp); |
| i = strlen(line); |
| if (strncmp(line, "X-URL: ", 7) != 0 || line[i - 1] != '\n') { |
| fprintf(stderr, "Bad cache file\n"); |
| continue; |
| } |
| line[i - 1] = '\0'; |
| if (date != -1) { |
| ts = *gmtime(&date); |
| strftime(sdate, 30, time_format, &ts); |
| } |
| else |
| strcpy(sdate, "-"); |
| |
| if (lmod != -1) { |
| ts = *gmtime(&lmod); |
| strftime(slmod, 30, time_format, &ts); |
| } |
| else |
| strcpy(slmod, "-"); |
| |
| if (expire != -1) { |
| ts = *gmtime(&expire); |
| strftime(sexpire, 30, time_format, &ts); |
| } |
| else |
| strcpy(sexpire, "-"); |
| |
| printf("%s: %d; %s %s %s\n", line + 7, ver, sdate, slmod, sexpire); |
| } |
| |
| closedir(d); |
| return 0; |
| } |