home *** CD-ROM | disk | FTP | other *** search
- /* DateSize.c */
-
- #include "Sys.h"
-
- #include <ctype.h>
-
- #include "Util.h"
- #include "RCmd.h"
- #include "Cmds.h"
- #include "Xfer.h"
- #include "List.h"
- #include "DateSize.h"
-
-
- /* Cheezy, but somewhat portable way to get GMT offset. */
- #ifdef HAVE_MKTIME
- static
- time_t GetUTCOffset(int year, int mon, int mday)
- {
- struct tm local_tm, utc_tm, *utc_tmptr;
- time_t local_t, utc_t, utcOffset;
-
- ZERO(local_tm);
- ZERO(utc_tm);
- utcOffset = 0;
-
- local_tm.tm_year = year;
- local_tm.tm_mon = mon;
- local_tm.tm_mday = mday;
- local_tm.tm_hour = 12;
- local_tm.tm_isdst = -1;
- local_t = mktime(&local_tm);
-
- if (local_t != (time_t) -1) {
- utc_tmptr = gmtime(&local_t);
- utc_tm.tm_year = utc_tmptr->tm_year;
- utc_tm.tm_mon = utc_tmptr->tm_mon;
- utc_tm.tm_mday = utc_tmptr->tm_mday;
- utc_tm.tm_hour = utc_tmptr->tm_hour;
- utc_tm.tm_isdst = -1;
- utc_t = mktime(&utc_tm);
-
- if (utc_t != (time_t) -1)
- utcOffset = (local_t - utc_t);
- }
- return (utcOffset);
- } /* GetUTCOffset */
- #endif /* HAVE_MKTIME */
-
-
-
-
- /* Converts an "ls" date, in either the "Feb 4 1992" or "Jan 16 13:42"
- * format to a time_t.
- */
- time_t UnLSDate(char *dstr)
- {
- #ifndef HAVE_MKTIME
- return (kModTimeUnknown);
- #else
- char *cp = dstr;
- int mon, day, year, hr, min;
- time_t now, mt;
- time_t result = kModTimeUnknown;
- struct tm ut, *t;
-
- switch (*cp++) {
- case 'A':
- mon = (*cp == 'u') ? 7 : 3;
- break;
- case 'D':
- mon = 11;
- break;
- case 'F':
- mon = 1;
- break;
- default: /* shut up un-init warning */
- case 'J':
- if (*cp++ == 'u')
- mon = (*cp == 'l') ? 6 : 5;
- else
- mon = 0;
- break;
- case 'M':
- mon = (*++cp == 'r') ? 2 : 4;
- break;
- case 'N':
- mon = 10;
- break;
- case 'O':
- mon = 9;
- break;
- case 'S':
- mon = 8;
- }
- cp = dstr + 4;
- day = 0;
- if (*cp != ' ')
- day = 10 * (*cp - '0');
- cp++;
- day += *cp++ - '0';
- min = 0;
-
- (void) time(&now);
- t = localtime(&now);
-
- if (*++cp != ' ') {
- /* It's a time, XX:YY, not a year. */
- cp[2] = ' ';
- (void) sscanf(cp, "%d %d", &hr, &min);
- cp[2] = ':';
- year = t->tm_year;
- if (mon > t->tm_mon)
- --year;
- } else {
- hr = min = 0;
- (void) sscanf(cp, "%d", &year);
- year -= 1900;
- }
- /* Copy the whole structure of the 'tm' pointed to by t, so it will
- * also set all fields we don't specify explicitly to be the same as
- * they were in t. That way we copy non-standard fields such as
- * tm_gmtoff, if it exists or not.
- */
- ut = *t;
- ut.tm_sec = 1;
- ut.tm_min = min;
- ut.tm_hour = hr;
- ut.tm_mday = day;
- ut.tm_mon = mon;
- ut.tm_year = year;
- ut.tm_wday = ut.tm_yday = 0;
- ut.tm_isdst = -1; /* Let mktime figure this out for us. */
- mt = mktime(&ut);
- if (mt != (time_t) -1)
- result = (time_t) mt;
- return (result);
- #endif /* HAVE_MKTIME */
- } /* UnLSDate */
-
-
-
- /* Converts a MDTM date, like "19930602204445"
- * format to a time_t.
- */
- time_t UnMDTMDate(char *dstr)
- {
- #ifndef HAVE_MKTIME
- return (kModTimeUnknown);
- #else
- struct tm ut, *t;
- time_t mt, now;
- time_t result = kModTimeUnknown;
-
- (void) time(&now);
- t = localtime(&now);
-
- /* Copy the whole structure of the 'tm' pointed to by t, so it will
- * also set all fields we don't specify explicitly to be the same as
- * they were in t. That way we copy non-standard fields such as
- * tm_gmtoff, if it exists or not.
- */
- ut = *t;
-
- /* The time we get back from the server is (should be) in UTC. */
- if (sscanf(dstr, "%04d%02d%02d%02d%02d%02d",
- &ut.tm_year,
- &ut.tm_mon,
- &ut.tm_mday,
- &ut.tm_hour,
- &ut.tm_min,
- &ut.tm_sec) == 6)
- {
- --ut.tm_mon;
- ut.tm_year -= 1900;
- ut.tm_isdst = -1;
- mt = mktime(&ut);
- if (mt != (time_t) -1) {
- mt += GetUTCOffset(ut.tm_year, ut.tm_mon, ut.tm_mday);
- result = (time_t) mt;
- }
- }
- return result;
- #endif /* HAVE_MKTIME */
- } /* UnMDTMDate */
-
-
-
-
- /* Given a filename, do an "ls -ld" and from the output determine the
- * size and date of that file. Since this is UNIX dependent, we
- * would rather use the SIZE and MDTM commands if we can.
- */
- long GetDateSizeFromLSLine(char *fName, time_t *modifTime)
- {
- char *cp, *np;
- string lsline;
- long size = kSizeUnknown;
- int n;
- static int depth = 0;
- LineList fileList;
-
- depth++; /* Try to prevent infinite recursion. */
- *modifTime = kModTimeUnknown;
- InitLineList(&fileList);
- ListToMemory(&fileList, "LIST", kListDirNamesOnlyMode, fName);
- if (fileList.first == NULL)
- goto aa;
-
- (void) STRNCPY(lsline, fileList.first->line);
- DisposeLineListContents(&fileList);
-
- /* See if this line looks like a unix-style ls line.
- * If so, we can grab the date and size from it.
- */
- if (strpbrk(lsline, "-dlsbcp") == lsline) {
- /* See if it looks like a typical '-rwxrwxrwx' line. */
- cp = lsline + 1;
- if (*cp != 'r' && *cp != '-')
- goto aa;
- ++cp;
- if (*cp != 'w' && *cp != '-')
- goto aa;
- cp += 2;
- if (*cp != 'r' && *cp != '-')
- goto aa;
-
- /* skip mode, links, owner (and possibly group) */
- for (n = 0; n < 4; n++) {
- np = cp;
- while (*cp != '\0' && !isspace(*cp))
- cp++;
- while (*cp != '\0' && isspace(*cp))
- cp++;
- }
- if (!isdigit(*cp))
- cp = np; /* back up (no group) */
- (void) sscanf(cp, "%ld%n", &size, &n);
-
- *modifTime = UnLSDate(cp + n + 1);
-
- if (size <= 512L) {
- /* May be the size of a link to the file, instead of the file. */
- if ((cp = strstr(lsline, " -> ")) != NULL) {
- /* Yes, it was a link. */
- size = (depth>4) ? kSizeUnknown :
- GetDateAndSize(cp + 4, modifTime);
- /* Try the file. */
- }
- }
- }
- aa:
- --depth;
- return (size);
- } /* GetDateSizeFromLSLine */
-
-
-
-
- /* The caller wanted to know the modification date and size of the remote
- * file given to us. We try to get this information by using the SIZE
- * and MDTM ftp commands, and if that didn't work we try sending the site
- * a "ls -l <fName>" and try to get that information from the line it
- * sends us back. It is possible that we won't be able to determine
- * either of these, though.
- */
- long GetDateAndSize(char *fName, time_t *modifTime)
- {
- time_t mdtm, ls_mdtm;
- long size, ls_size;
- int have_mdtm, have_size;
-
- size = ls_size = kSizeUnknown;
- mdtm = ls_mdtm = kModTimeUnknown;
- if (fName != NULL) {
- have_mdtm = have_size = 0;
- have_size = ((DoSize(fName, &size)) == 0);
-
- #ifdef HAVE_MKTIME
- /* This would use mktime() to un-mangle the reply. */
- have_mdtm = ((DoMdtm(fName, (time_t *) &mdtm)) == 0);
- #endif /* HAVE_MKTIME */
-
- if (!have_mdtm || !have_size)
- ls_size = GetDateSizeFromLSLine(fName, &ls_mdtm);
-
- /* Try to use the information from the real SIZE/MDTM commands if
- * we could, since some maverick ftp server may be using a non-standard
- * ls command, and we could parse it wrong.
- */
-
- if (!have_mdtm)
- mdtm = ls_mdtm;
- if (!have_size)
- size = ls_size;
-
- DebugMsg("Used SIZE: %s. Used MDTM: %s.\n",
- have_size ? "yes" : "no",
- have_mdtm ? "yes" : "no"
- );
-
- if (size != kSizeUnknown)
- DebugMsg("Size: %ld\n", size);
- else
- DebugMsg("Size: ??\n");
- if (mdtm != kModTimeUnknown)
- DebugMsg("Mdtm: %s", ctime(&mdtm));
- else
- DebugMsg("Mdtm: ??\n");
- }
- *modifTime = mdtm;
- return size;
- } /* GetDateAndSize */
-