home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / ncftp-2.4.2-MIHS / src / DateSize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-21  |  6.9 KB  |  314 lines

  1. /* DateSize.c */
  2.  
  3. #include "Sys.h"
  4.  
  5. #include <ctype.h>
  6.  
  7. #include "Util.h"
  8. #include "RCmd.h"
  9. #include "Cmds.h"
  10. #include "Xfer.h"
  11. #include "List.h"
  12. #include "DateSize.h"
  13.  
  14.  
  15. /* Cheezy, but somewhat portable way to get GMT offset. */
  16. #ifdef HAVE_MKTIME
  17. static
  18. time_t GetUTCOffset(int year, int mon, int mday)
  19. {
  20.     struct tm local_tm, utc_tm, *utc_tmptr;
  21.     time_t local_t, utc_t, utcOffset;
  22.  
  23.     ZERO(local_tm);
  24.     ZERO(utc_tm);
  25.     utcOffset = 0;
  26.     
  27.     local_tm.tm_year = year;
  28.     local_tm.tm_mon = mon;
  29.     local_tm.tm_mday = mday;
  30.     local_tm.tm_hour = 12;
  31.     local_tm.tm_isdst = -1;
  32.     local_t = mktime(&local_tm);
  33.     
  34.     if (local_t != (time_t) -1) {
  35.         utc_tmptr = gmtime(&local_t);
  36.         utc_tm.tm_year = utc_tmptr->tm_year;
  37.         utc_tm.tm_mon = utc_tmptr->tm_mon;
  38.         utc_tm.tm_mday = utc_tmptr->tm_mday;
  39.         utc_tm.tm_hour = utc_tmptr->tm_hour;
  40.         utc_tm.tm_isdst = -1;
  41.         utc_t = mktime(&utc_tm);
  42.  
  43.         if (utc_t != (time_t) -1)
  44.             utcOffset = (local_t - utc_t);
  45.     }
  46.     return (utcOffset);
  47. }    /* GetUTCOffset */
  48. #endif    /* HAVE_MKTIME */
  49.  
  50.  
  51.  
  52.  
  53. /* Converts an "ls" date, in either the "Feb  4  1992" or "Jan 16 13:42"
  54.  * format to a time_t.
  55.  */
  56. time_t UnLSDate(char *dstr)
  57. {
  58. #ifndef HAVE_MKTIME
  59.     return (kModTimeUnknown);
  60. #else
  61.     char *cp = dstr;
  62.     int mon, day, year, hr, min;
  63.     time_t now, mt;
  64.     time_t result = kModTimeUnknown;
  65.     struct tm ut, *t;
  66.  
  67.     switch (*cp++) {
  68.         case 'A':
  69.             mon = (*cp == 'u') ? 7 : 3;
  70.             break;
  71.         case 'D':
  72.             mon = 11;
  73.             break;
  74.         case 'F':
  75.             mon = 1;
  76.             break;
  77.         default:                       /* shut up un-init warning */
  78.         case 'J':
  79.             if (*cp++ == 'u')
  80.                 mon = (*cp == 'l') ? 6 : 5;
  81.             else
  82.                 mon = 0;
  83.             break;
  84.         case 'M':
  85.             mon = (*++cp == 'r') ? 2 : 4;
  86.             break;
  87.         case 'N':
  88.             mon = 10;
  89.             break;
  90.         case 'O':
  91.             mon = 9;
  92.             break;
  93.         case 'S':
  94.             mon = 8;
  95.     }
  96.     cp = dstr + 4;
  97.     day = 0;
  98.     if (*cp != ' ')
  99.         day = 10 * (*cp - '0');
  100.     cp++;
  101.     day += *cp++ - '0';
  102.     min = 0;
  103.     
  104.     (void) time(&now);
  105.     t = localtime(&now);
  106.  
  107.     if (*++cp != ' ') {
  108.         /* It's a time, XX:YY, not a year. */
  109.         cp[2] = ' ';
  110.         (void) sscanf(cp, "%d %d", &hr, &min);
  111.         cp[2] = ':';
  112.         year = t->tm_year;
  113.         if (mon > t->tm_mon)
  114.             --year;
  115.     } else {
  116.         hr = min = 0;
  117.         (void) sscanf(cp, "%d", &year);
  118.         year -= 1900;
  119.     }
  120.     /* Copy the whole structure of the 'tm' pointed to by t, so it will
  121.      * also set all fields we don't specify explicitly to be the same as
  122.      * they were in t.  That way we copy non-standard fields such as
  123.      * tm_gmtoff, if it exists or not.
  124.      */
  125.     ut = *t;
  126.     ut.tm_sec = 1;
  127.     ut.tm_min = min;
  128.     ut.tm_hour = hr;
  129.     ut.tm_mday = day;
  130.     ut.tm_mon = mon;
  131.     ut.tm_year = year;
  132.     ut.tm_wday = ut.tm_yday = 0;
  133.     ut.tm_isdst = -1;    /* Let mktime figure this out for us. */
  134.     mt = mktime(&ut);
  135.     if (mt != (time_t) -1)
  136.         result = (time_t) mt;
  137.     return (result);
  138. #endif    /* HAVE_MKTIME */
  139. }    /* UnLSDate */
  140.  
  141.  
  142.  
  143. /* Converts a MDTM date, like "19930602204445"
  144.  * format to a time_t.
  145.  */
  146. time_t UnMDTMDate(char *dstr)
  147. {
  148. #ifndef HAVE_MKTIME
  149.     return (kModTimeUnknown);
  150. #else
  151.     struct tm ut, *t;
  152.     time_t mt, now;
  153.     time_t result = kModTimeUnknown;
  154.  
  155.     (void) time(&now);
  156.     t = localtime(&now);
  157.  
  158.     /* Copy the whole structure of the 'tm' pointed to by t, so it will
  159.      * also set all fields we don't specify explicitly to be the same as
  160.      * they were in t.  That way we copy non-standard fields such as
  161.      * tm_gmtoff, if it exists or not.
  162.      */
  163.     ut = *t;
  164.  
  165.     /* The time we get back from the server is (should be) in UTC. */
  166.     if (sscanf(dstr, "%04d%02d%02d%02d%02d%02d",
  167.         &ut.tm_year,
  168.         &ut.tm_mon,
  169.         &ut.tm_mday,
  170.         &ut.tm_hour,
  171.         &ut.tm_min,
  172.         &ut.tm_sec) == 6)
  173.     {    
  174.         --ut.tm_mon;
  175.         ut.tm_year -= 1900;
  176.         ut.tm_isdst = -1;
  177.         mt = mktime(&ut);
  178.         if (mt != (time_t) -1) {
  179.             mt += GetUTCOffset(ut.tm_year, ut.tm_mon, ut.tm_mday);
  180.             result = (time_t) mt;
  181.         }
  182.     }
  183.     return result;
  184. #endif    /* HAVE_MKTIME */
  185. }    /* UnMDTMDate */
  186.  
  187.  
  188.  
  189.  
  190. /* Given a filename, do an "ls -ld" and from the output determine the
  191.  * size and date of that file.  Since this is UNIX dependent, we
  192.  * would rather use the SIZE and MDTM commands if we can.
  193.  */
  194. long GetDateSizeFromLSLine(char *fName, time_t *modifTime)
  195. {
  196.     char *cp, *np;
  197.     string lsline;
  198.     long size = kSizeUnknown;
  199.     int n;
  200.     static int depth = 0;
  201.     LineList fileList;
  202.  
  203.     depth++;    /* Try to prevent infinite recursion. */
  204.     *modifTime = kModTimeUnknown;
  205.     InitLineList(&fileList);
  206.     ListToMemory(&fileList, "LIST", kListDirNamesOnlyMode, fName);
  207.     if (fileList.first == NULL)
  208.         goto aa;
  209.  
  210.     (void) STRNCPY(lsline, fileList.first->line);
  211.     DisposeLineListContents(&fileList);
  212.  
  213.     /* See if this line looks like a unix-style ls line. 
  214.      * If so, we can grab the date and size from it.
  215.      */    
  216.     if (strpbrk(lsline, "-dlsbcp") == lsline) {
  217.         /* See if it looks like a typical '-rwxrwxrwx' line. */
  218.         cp = lsline + 1;
  219.         if (*cp != 'r' && *cp != '-')
  220.             goto aa;
  221.         ++cp;
  222.         if (*cp != 'w' && *cp != '-')
  223.             goto aa;
  224.         cp += 2;
  225.         if (*cp != 'r' && *cp != '-')
  226.             goto aa;
  227.  
  228.          /* skip mode, links, owner (and possibly group) */
  229.          for (n = 0; n < 4; n++) {
  230.              np = cp;
  231.              while (*cp != '\0' && !isspace(*cp))
  232.                  cp++;
  233.              while (*cp != '\0' &&  isspace(*cp))
  234.                  cp++;
  235.          }
  236.          if (!isdigit(*cp))
  237.              cp = np;    /* back up (no group) */
  238.          (void) sscanf(cp, "%ld%n", &size, &n);
  239.  
  240.          *modifTime = UnLSDate(cp + n + 1);
  241.  
  242.         if (size <= 512L) {
  243.             /* May be the size of a link to the file, instead of the file. */
  244.             if ((cp = strstr(lsline, " -> ")) != NULL) {
  245.                 /* Yes, it was a link. */
  246.                 size = (depth>4) ? kSizeUnknown :
  247.                     GetDateAndSize(cp + 4, modifTime);
  248.                 /* Try the file. */
  249.             }
  250.         }
  251.     }    
  252. aa:
  253.     --depth;
  254.     return (size);
  255. }    /* GetDateSizeFromLSLine */
  256.  
  257.  
  258.  
  259.  
  260. /* The caller wanted to know the modification date and size of the remote
  261.  * file given to us.  We try to get this information by using the SIZE
  262.  * and MDTM ftp commands, and if that didn't work we try sending the site
  263.  * a "ls -l <fName>" and try to get that information from the line it
  264.  * sends us back.  It is possible that we won't be able to determine
  265.  * either of these, though.
  266.  */
  267. long GetDateAndSize(char *fName, time_t *modifTime)
  268. {
  269.     time_t mdtm, ls_mdtm;
  270.     long size, ls_size;
  271.     int have_mdtm, have_size;
  272.  
  273.     size = ls_size = kSizeUnknown;
  274.     mdtm = ls_mdtm = kModTimeUnknown;
  275.     if (fName != NULL) {
  276.         have_mdtm = have_size = 0;
  277.         have_size = ((DoSize(fName, &size)) == 0);
  278.  
  279. #ifdef HAVE_MKTIME
  280.         /* This would use mktime() to un-mangle the reply. */
  281.         have_mdtm = ((DoMdtm(fName, (time_t *) &mdtm)) == 0);
  282. #endif /* HAVE_MKTIME */
  283.  
  284.         if (!have_mdtm || !have_size)
  285.             ls_size = GetDateSizeFromLSLine(fName, &ls_mdtm);
  286.  
  287.         /* Try to use the information from the real SIZE/MDTM commands if
  288.          * we could, since some maverick ftp server may be using a non-standard
  289.          * ls command, and we could parse it wrong.
  290.          */
  291.         
  292.         if (!have_mdtm)
  293.             mdtm = ls_mdtm;
  294.         if (!have_size)
  295.             size = ls_size;
  296.  
  297.         DebugMsg("Used SIZE: %s.  Used MDTM: %s.\n",
  298.             have_size ? "yes" : "no",
  299.             have_mdtm ? "yes" : "no"
  300.         );
  301.  
  302.         if (size != kSizeUnknown)
  303.             DebugMsg("Size: %ld\n", size);
  304.         else
  305.             DebugMsg("Size: ??\n");
  306.         if (mdtm != kModTimeUnknown)
  307.             DebugMsg("Mdtm: %s", ctime(&mdtm));
  308.         else
  309.             DebugMsg("Mdtm: ??\n");
  310.     }
  311.     *modifTime = mdtm;
  312.     return size;
  313. }    /* GetDateAndSize */
  314.