X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fftp-ls.c;h=4f0878f2afed26565853c98fc2ca9c179ab74b1e;hp=61fdfa2a70148aeebb7ca4ab53b29cf2cacde2aa;hb=7b5ad90acfc8c101a6cf919cd2a00217f0194e93;hpb=518fe8d06d01b194989637ca3c74863633db256e diff --git a/src/ftp-ls.c b/src/ftp-ls.c index 61fdfa2a..4f0878f2 100644 --- a/src/ftp-ls.c +++ b/src/ftp-ls.c @@ -76,7 +76,7 @@ symperms (const char *s) The time stamps are stored in a separate variable, time_t compatible (I hope). The timezones are ignored. */ static struct fileinfo * -ftp_parse_unix_ls (const char *file) +ftp_parse_unix_ls (const char *file, int ignore_perms) { FILE *fp; static const char *months[] = { @@ -149,10 +149,28 @@ ftp_parse_unix_ls (const char *file) break; } - cur.perms = symperms (tok + 1); - DEBUGP (("perms %0o; ", cur.perms)); + if (ignore_perms) + { + switch (cur.type) + { + case FT_PLAINFILE: + cur.perms = 420; + break; + case FT_DIRECTORY: + cur.perms = 493; + break; + default: + cur.perms = 1023; + } + DEBUGP (("implicite perms %0o; ", cur.perms)); + } + else + { + cur.perms = symperms (tok + 1); + DEBUGP (("perms %0o; ", cur.perms)); + } - error = ignore = 0; /* Errnoeous and ignoring entries are + error = ignore = 0; /* Erroneous and ignoring entries are treated equally for now. */ year = hour = min = sec = 0; /* Silence the compiler. */ month = day = 0; @@ -385,6 +403,133 @@ ftp_parse_unix_ls (const char *file) return dir; } +static struct fileinfo * +ftp_parse_winnt_ls (const char *file) +{ + FILE *fp; + int len; + int year, month, day; /* for time analysis */ + int hour, min, sec; + struct tm timestruct; + + char *line, *tok; /* tokenizer */ + struct fileinfo *dir, *l, cur; /* list creation */ + + fp = fopen (file, "rb"); + if (!fp) + { + logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno)); + return NULL; + } + dir = l = NULL; + + /* Line loop to end of file: */ + while ((line = read_whole_line (fp))) + { + DEBUGP (("%s\n", line)); + len = strlen (line); + /* Destroy if present. */ + if (len && line[len - 1] == '\n') + line[--len] = '\0'; + if (len && line[len - 1] == '\r') + line[--len] = '\0'; + + /* Extracting name is a bit of black magic and we have to do it + before `strtok' inserted extra \0 characters in the line + string. For the moment let us just suppose that the name starts at + column 39 of the listing. This way we could also recognize + filenames that begin with a series of space characters (but who + really wants to use such filenames anyway?). */ + if (len < 40) continue; + tok = line + 39; + cur.name = xstrdup(tok); + DEBUGP(("Name: '%s'\n", cur.name)); + + /* First column: mm-dd-yy */ + tok = strtok(line, "-"); + month = atoi(tok); + tok = strtok(NULL, "-"); + day = atoi(tok); + tok = strtok(NULL, " "); + year = atoi(tok); + /* Assuming the epoch starting at 1.1.1970 */ + if (year <= 70) year += 100; + + /* Second column: hh:mm[AP]M */ + tok = strtok(NULL, ":"); + hour = atoi(tok); + tok = strtok(NULL, "M"); + min = atoi(tok); + /* Adjust hour from AM/PM */ + tok+=2; + if (*tok == 'P') hour += 12; + /* Listing does not contain value for seconds */ + sec = 0; + + DEBUGP(("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n", + year+1900, month, day, hour, min)); + + /* Build the time-stamp (copy & paste from above) */ + timestruct.tm_sec = sec; + timestruct.tm_min = min; + timestruct.tm_hour = hour; + timestruct.tm_mday = day; + timestruct.tm_mon = month; + timestruct.tm_year = year; + timestruct.tm_wday = 0; + timestruct.tm_yday = 0; + timestruct.tm_isdst = -1; + cur.tstamp = mktime (×truct); /* store the time-stamp */ + + DEBUGP(("Timestamp: %ld\n", cur.tstamp)); + + /* Third column: Either file length, or . We also set the + permissions (guessed as 0644 for plain files and 0755 for + directories as the listing does not give us a clue) and filetype + here. */ + tok = strtok(NULL, " "); + while (*tok == '\0') tok = strtok(NULL, " "); + if (*tok == '<') + { + cur.type = FT_DIRECTORY; + cur.size = 0; + cur.perms = 493; /* my gcc does not like 0755 ?? */ + DEBUGP(("Directory\n")); + } + else + { + cur.type = FT_PLAINFILE; + cur.size = atoi(tok); + cur.perms = 420; /* 0664 octal */ + DEBUGP(("File, size %ld bytes\n", cur.size)); + } + + cur.linkto = NULL; + + /* And put everything into the linked list */ + if (!dir) + { + l = dir = (struct fileinfo *)xmalloc (sizeof (struct fileinfo)); + memcpy (l, &cur, sizeof (cur)); + l->prev = l->next = NULL; + } + else + { + cur.prev = l; + l->next = (struct fileinfo *)xmalloc (sizeof (struct fileinfo)); + l = l->next; + memcpy (l, &cur, sizeof (cur)); + l->next = NULL; + } + + xfree(line); + } + + fclose(fp); + return dir; +} + + #ifdef HAVE_FTPPARSE /* This is a "glue function" that connects the ftpparse interface to @@ -477,12 +622,31 @@ ftp_parse_nonunix_ls (const char *file) struct fileinfo * ftp_parse_ls (const char *file, const enum stype system_type) { - if (system_type == ST_UNIX) + switch (system_type) { - return ftp_parse_unix_ls (file); + case ST_UNIX: + return ftp_parse_unix_ls (file, FALSE); + case ST_WINNT: + { + /* Detect whether the listing is simulating the UNIX format */ + FILE *fp; + int c; + fp = fopen (file, "rb"); + if (!fp) + { + logprintf (LOG_NOTQUIET, "%s: %s\n", file, strerror (errno)); + return NULL; } + c = fgetc(fp); + fclose(fp); + /* If the first character of the file is '0'-'9', it's WINNT + format. */ + if (c >= '0' && c <='9') + return ftp_parse_winnt_ls (file); else - { + return ftp_parse_unix_ls (file, TRUE); + } + default: #ifdef HAVE_FTPPARSE return ftp_parse_nonunix_ls (file); #else