/* 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;
}