1
1
/* Parsing FTP `ls' output.
2
2
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3
2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3
2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
5
6
This file is part of GNU Wget.
101
100
int next, len, i, error, ignore;
102
101
int year, month, day; /* for time analysis */
102
int hour, min, sec, ptype;
104
103
struct tm timestruct, *tnow;
453
455
column 39 of the listing. This way we could also recognize
454
456
filenames that begin with a series of space characters (but who
455
457
really wants to use such filenames anyway?). */
456
if (len < 40) continue;
458
if (len < 40) goto continue_loop;
458
460
cur.name = xstrdup(tok);
459
DEBUGP(("Name: '%s'\n", cur.name));
461
DEBUGP (("Name: '%s'\n", cur.name));
461
463
/* First column: mm-dd-yy. Should atoi() on the month fail, january
462
464
will be assumed. */
463
465
tok = strtok(line, "-");
464
if (tok == NULL) continue;
466
if (tok == NULL) goto continue_loop;
465
467
month = atoi(tok) - 1;
466
468
if (month < 0) month = 0;
467
469
tok = strtok(NULL, "-");
468
if (tok == NULL) continue;
470
if (tok == NULL) goto continue_loop;
470
472
tok = strtok(NULL, " ");
471
if (tok == NULL) continue;
473
if (tok == NULL) goto continue_loop;
472
474
year = atoi(tok);
473
475
/* Assuming the epoch starting at 1.1.1970 */
474
476
if (year <= 70) year += 100;
476
478
/* Second column: hh:mm[AP]M, listing does not contain value for
478
480
tok = strtok(NULL, ":");
479
if (tok == NULL) continue;
481
if (tok == NULL) goto continue_loop;
480
482
hour = atoi(tok);
481
483
tok = strtok(NULL, "M");
482
if (tok == NULL) continue;
484
if (tok == NULL) goto continue_loop;
484
486
/* Adjust hour from AM/PM. Just for the record, the sequence goes
485
487
11:00AM, 12:00PM, 01:00PM ... 11:00PM, 12:00AM, 01:00AM . */
487
489
if (hour == 12) hour = 0;
488
490
if (*tok == 'P') hour += 12;
490
DEBUGP(("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n",
492
DEBUGP (("YYYY/MM/DD HH:MM - %d/%02d/%02d %02d:%02d\n",
491
493
year+1900, month, day, hour, min));
493
495
/* Build the time-stamp (copy & paste from above) */
501
503
timestruct.tm_yday = 0;
502
504
timestruct.tm_isdst = -1;
503
505
cur.tstamp = mktime (×truct); /* store the time-stamp */
506
cur.ptype = TT_HOUR_MIN;
505
DEBUGP(("Timestamp: %ld\n", cur.tstamp));
508
DEBUGP (("Timestamp: %ld\n", cur.tstamp));
507
510
/* Third column: Either file length, or <DIR>. We also set the
508
511
permissions (guessed as 0644 for plain files and 0755 for
509
512
directories as the listing does not give us a clue) and filetype
511
514
tok = strtok(NULL, " ");
512
if (tok == NULL) continue;
515
if (tok == NULL) goto continue_loop;
513
516
while ((tok != NULL) && (*tok == '\0')) tok = strtok(NULL, " ");
514
if (tok == NULL) continue;
517
if (tok == NULL) goto continue_loop;
517
520
cur.type = FT_DIRECTORY;
519
522
cur.perms = 0755;
520
DEBUGP(("Directory\n"));
523
DEBUGP (("Directory\n"));
749
753
tok = strtok(line, " ");
750
754
if (tok == NULL) tok = line;
751
DEBUGP(("file name: '%s'\n", tok));
755
DEBUGP (("file name: '%s'\n", tok));
753
757
/* Stripping the version number on a VMS system would be wrong.
754
758
It may be foolish on a non-VMS system, too, but that's someone
773
777
Eliminate "^" escape characters from ODS5 extended file name.
774
778
(A caret is invalid in an ODS2 name, so this is always safe.)
777
DEBUGP(("file name-^: '%s'\n", tok));
781
DEBUGP (("file name-^: '%s'\n", tok));
779
783
/* Differentiate between a directory and any other file. A VMS
780
784
listing may not include file protections (permissions). Set a
783
787
".DIR;1" file type and version number, as the plain name is
784
788
what will work in a CWD command.
787
if (!strncasecmp( (tok+ (len- 4)), ".DIR", 4))
791
if (!strncasecmp((tok + (len - 4)), ".DIR", 4))
789
*(tok+ (len -= 4)) = '\0'; /* Discard ".DIR". */
793
*(tok+ (len - 4)) = '\0'; /* Discard ".DIR". */
790
794
cur.type = FT_DIRECTORY;
791
795
cur.perms = VMS_DEFAULT_PROT_DIR;
792
DEBUGP(("Directory (nv)\n"));
796
DEBUGP (("Directory (nv)\n"));
794
else if (!strncasecmp( (tok+ (len- 6)), ".DIR;1", 6))
798
else if (!strncasecmp ((tok + (len - 6)), ".DIR;1", 6))
796
*(tok+ (len -= 6)) = '\0'; /* Discard ".DIR;1". */
800
*(tok+ (len - 6)) = '\0'; /* Discard ".DIR;1". */
797
801
cur.type = FT_DIRECTORY;
798
802
cur.perms = VMS_DEFAULT_PROT_DIR;
799
DEBUGP(("Directory (v)\n"));
803
DEBUGP (("Directory (v)\n"));
803
807
cur.type = FT_PLAINFILE;
804
808
cur.perms = VMS_DEFAULT_PROT_FILE;
807
cur.name = xstrdup(tok);
808
DEBUGP(("Name: '%s'\n", cur.name));
811
cur.name = xstrdup (tok);
812
DEBUGP (("Name: '%s'\n", cur.name));
810
814
/* Null the date and time string. */
811
815
*date_str = '\0';
817
821
hence useless for an integrity check based on byte-count.
818
822
Set size to unknown.
822
826
/* Get token 2, if any. A long name may force all other data onto
823
827
a second line. If needed, read the second line.
826
tok = strtok(NULL, " ");
830
tok = strtok (NULL, " ");
829
DEBUGP(("Getting additional line.\n"));
833
DEBUGP (("Getting additional line.\n"));
831
835
line = read_whole_line (fp);
834
DEBUGP(("EOF. Leaving listing parser.\n"));
838
DEBUGP (("EOF. Leaving listing parser.\n"));
839
843
line (and we may be confused).
843
847
/* Blank line. End of significant file listing. */
844
DEBUGP(("Blank line. Leaving listing parser.\n"));
848
DEBUGP (("Blank line. Leaving listing parser.\n"));
845
849
xfree (line); /* Free useless line storage. */
848
852
else if (line[ 0] != ' ')
850
DEBUGP(("Non-blank in column 1. Must be a new file name?\n"));
854
DEBUGP (("Non-blank in column 1. Must be a new file name?\n"));
871
875
Time: HH:MM or HH:MM:SS or HH:MM:SS.CC
872
876
Owner: [user] or [user,group]
873
877
Protection: (ppp,ppp,ppp,ppp) (where "ppp" is "RWED" or some
874
subset thereof, for System, Owner, Group, World.
878
subset thereof, for System, Owner, Group, World.
876
880
If permission is lacking, info may be replaced by the string:
877
881
"No privilege for attempted operation".
879
883
while (tok != NULL)
881
DEBUGP (("Token: >%s<: ", tok));
885
DEBUGP (("Token: >%s<: ", tok));
883
if ((strlen( tok) < 12) && (strchr( tok, '-') != NULL))
886
DEBUGP (("Date.\n"));
887
strcpy( date_str, tok);
888
strcat( date_str, " ");
890
else if ((strlen( tok) < 12) && (strchr( tok, ':') != NULL))
896
(sizeof( date_str)- strlen( date_str)- 1));
897
DEBUGP (("Date time: >%s<\n", date_str));
899
else if (strchr( tok, '[') != NULL)
901
/* Owner. (Ignore.) */
902
DEBUGP (("Owner.\n"));
904
else if (strchr( tok, '(') != NULL)
906
/* Protections (permissions). */
909
for (i = 0; i < strlen( tok); i++)
943
DEBUGP (("Prot. perms = %0o.\n", cur.perms));
947
/* Nondescript. Probably size(s), probably in blocks.
887
if ((strlen (tok) < 12) && (strchr( tok, '-') != NULL))
890
DEBUGP (("Date.\n"));
891
strcpy( date_str, tok);
892
strcat( date_str, " ");
894
else if ((strlen (tok) < 12) && (strchr( tok, ':') != NULL))
900
(sizeof( date_str)- strlen (date_str) - 1));
901
DEBUGP (("Date time: >%s<\n", date_str));
903
else if (strchr ( tok, '[') != NULL)
905
/* Owner. (Ignore.) */
906
DEBUGP (("Owner.\n"));
908
else if (strchr (tok, '(') != NULL)
910
/* Protections (permissions). */
913
for (i = 0; i < strlen( tok); i++)
947
DEBUGP (("Prot. perms = %0o.\n", cur.perms));
951
/* Nondescript. Probably size(s), probably in blocks.
948
952
Could be "No privilege ..." message. (Ignore.)
950
DEBUGP (("Ignored (size?).\n"));
954
DEBUGP (("Ignored (size?).\n"));
953
tok = strtok (NULL, " ");
957
tok = strtok (NULL, " ");
956
960
/* Tokens exhausted. Interpret the data, and fill in the
967
971
/* Convert struct tm local time to time_t local time. */
968
972
timenow = mktime (timestruct);
969
973
/* Offset local time according to environment variable (seconds). */
970
if ((tok = getenv( "WGET_TIMEZONE_DIFFERENTIAL")) != NULL)
974
if ((tok = getenv ( "WGET_TIMEZONE_DIFFERENTIAL")) != NULL)
973
977
DEBUGP (("Time differential = %d.\n", dt));
988
987
cur.tstamp = timenow; /* Store the time-stamp. */
989
DEBUGP(("Timestamp: %ld\n", cur.tstamp));
988
DEBUGP (("Timestamp: %ld\n", cur.tstamp));
989
cur.ptype = TT_HOUR_MIN;
991
991
/* Add the data for this item to the linked list, */