home *** CD-ROM | disk | FTP | other *** search
/ ftp.ncftp.com / ftp.ncftp.com.zip / ftp.ncftp.com / ncftp / older_versions / ncftp-3.2.2-src.tar.bz2 / ncftp-3.2.2-src.tar / ncftp-3.2.2 / libncftp / linelist.c < prev    next >
C/C++ Source or Header  |  2005-01-01  |  16KB  |  802 lines

  1. /* linelist.c
  2.  *
  3.  * Copyright (c) 1996-2005 Mike Gleason, NcFTP Software.
  4.  * All rights reserved.
  5.  *
  6.  */
  7.  
  8. #include "syshdrs.h"
  9. #ifdef PRAGMA_HDRSTOP
  10. #    pragma hdrstop
  11. #endif
  12.  
  13. /* Dynamically make a copy of a string. */
  14. char *
  15. StrDup(const char *buf)
  16. {
  17.     char *cp;
  18.     size_t len;
  19.  
  20.     if (buf == NULL)
  21.         return (NULL);
  22.  
  23.     len = strlen(buf) + 1;
  24.     cp = (char *) malloc(len);
  25.     if (cp != NULL)
  26.         (void) memcpy(cp, buf, len);
  27.     return (cp);
  28. }    /* StrDup */
  29.  
  30.  
  31.  
  32. /* Disposes each node of a FTPLineList.  Does a few extra things
  33.  * so the disposed memory won't be very useful after it is freed.
  34.  */
  35. void
  36. DisposeLineListContents(FTPLineListPtr list)
  37. {
  38.     FTPLinePtr lp, lp2;
  39.     
  40.     for (lp = list->first; lp != NULL; ) {
  41.         lp2 = lp;
  42.         lp = lp->next;
  43.         if (lp2->line != NULL) {
  44.             lp2->line[0] = '\0';
  45.             free(lp2->line);
  46.         }
  47.         free(lp2);
  48.     }
  49.     InitLineList(list);
  50. }    /* DisposeLineListContents */
  51.  
  52.  
  53.  
  54.  
  55. void
  56. InitLineList(FTPLineListPtr list)
  57. {
  58.     list->nLines = 0;
  59.     list->first = list->last = NULL;
  60. }    /* InitLineList */
  61.  
  62.  
  63.  
  64.  
  65. FTPLinePtr
  66. RemoveLine(FTPLineListPtr list, FTPLinePtr killMe)
  67. {
  68.     FTPLinePtr nextLine, prevLine;
  69.     
  70.     nextLine = killMe->next;    
  71.     prevLine = killMe->prev;    
  72.     if (killMe->line != NULL) {
  73.         killMe->line[0] = '\0';        /* Make it useless just in case. */
  74.         free(killMe->line);
  75.     }
  76.  
  77.     if (list->first == killMe)
  78.         list->first = nextLine;
  79.     if (list->last == killMe)
  80.         list->last = prevLine;
  81.  
  82.     if (nextLine != NULL)
  83.         nextLine->prev = prevLine;
  84.     if (prevLine != NULL)
  85.         prevLine->next = nextLine;
  86.  
  87.     free(killMe);    
  88.     list->nLines--;
  89.     return (nextLine);
  90. }    /* RemoveLine */
  91.  
  92.  
  93.  
  94.  
  95. /* Adds a string to the FTPLineList specified. */
  96. FTPLinePtr
  97. AddLine(FTPLineListPtr list, const char *buf1)
  98. {
  99.     FTPLinePtr lp;
  100.     char *buf;
  101.     
  102.     lp = (FTPLinePtr) malloc(sizeof(FTPLine));
  103.     if (lp != NULL) {
  104.         buf = StrDup(buf1);
  105.         if (buf == NULL) {
  106.             free(lp);
  107.             lp = NULL;
  108.         } else {
  109.             lp->line = buf;
  110.             lp->next = NULL;
  111.             if (list->first == NULL) {
  112.                 list->first = list->last = lp;
  113.                 lp->prev = NULL;
  114.                 list->nLines = 1;
  115.             } else {
  116.                 lp->prev = list->last;
  117.                 list->last->next = lp;
  118.                 list->last = lp;
  119.                 list->nLines++;
  120.             }
  121.         }
  122.     }
  123.     return lp;
  124. }    /* AddLine */
  125.  
  126.  
  127.  
  128.  
  129. int
  130. CopyLineList(FTPLineListPtr dst, FTPLineListPtr src)
  131. {
  132.     FTPLinePtr lp, lp2;
  133.     
  134.     InitLineList(dst);
  135.     for (lp = src->first; lp != NULL; ) {
  136.         lp2 = lp;
  137.         lp = lp->next;
  138.         if (lp2->line != NULL) {
  139.             if (AddLine(dst, lp2->line) == NULL) {
  140.                 DisposeLineListContents(dst);
  141.                 return (-1);
  142.             }
  143.         }
  144.     }
  145.     return (0);
  146. }    /* CopyLineList */
  147.  
  148.  
  149.  
  150.  
  151. /* Disposes each node of a FTPFileInfoList.  Does a few extra things
  152.  * so the disposed memory won't be very useful after it is freed.
  153.  */
  154. void
  155. DisposeFileInfoListContents(FTPFileInfoListPtr list)
  156. {
  157.     FTPFileInfoPtr lp, lp2;
  158.     
  159.     for (lp = list->first; lp != NULL; ) {
  160.         lp2 = lp;
  161.         lp = lp->next;
  162.         if (lp2->relname != NULL) {
  163.             lp2->relname[0] = '\0';
  164.             free(lp2->relname);
  165.         }
  166.         if (lp2->lname != NULL) {
  167.             lp2->lname[0] = '\0';
  168.             free(lp2->lname);
  169.         }
  170.         if (lp2->rname != NULL) {
  171.             lp2->rname[0] = '\0';
  172.             free(lp2->rname);
  173.         }
  174.         if (lp2->rlinkto != NULL) {
  175.             lp2->rlinkto[0] = '\0';
  176.             free(lp2->rlinkto);
  177.         }
  178.         if (lp2->plug != NULL) {
  179.             lp2->plug[0] = '\0';
  180.             free(lp2->plug);
  181.         }
  182.         free(lp2);
  183.     }
  184.  
  185.     if (list->vec != NULL)
  186.         free(list->vec);
  187.  
  188.     InitFileInfoList(list);
  189. }    /* DisposeFileInfoListContents */
  190.  
  191.  
  192.  
  193.  
  194. void
  195. InitFileInfoList(FTPFileInfoListPtr list)
  196. {
  197.     (void) memset(list, 0, sizeof(FTPFileInfoList));
  198.  
  199.     /* Redundant, but needed to shush BoundsChecker. */
  200.     list->first = list->last = NULL;
  201.     list->vec = (FTPFileInfoVec) 0;
  202. }    /* InitFileInfoList */
  203.  
  204.  
  205.  
  206.  
  207. static int
  208. TimeCmp(const void *a, const void *b)
  209. {
  210.     const FTPFileInfo *const *fipa;
  211.     const FTPFileInfo *const *fipb;
  212.  
  213.     fipa = (const FTPFileInfo *const *) a;
  214.     fipb = (const FTPFileInfo *const *) b;
  215.     if ((**fipb).mdtm == (**fipa).mdtm)
  216.         return (0);
  217.     else if ((**fipb).mdtm < (**fipa).mdtm)
  218.         return (-1);
  219.     return (1);
  220. }    /* TimeCmp */
  221.  
  222.  
  223.  
  224.  
  225. static int
  226. ReverseTimeCmp(const void *a, const void *b)
  227. {
  228.     const FTPFileInfo *const *fipa;
  229.     const FTPFileInfo *const *fipb;
  230.  
  231.     fipa = (const FTPFileInfo *const *) a;
  232.     fipb = (const FTPFileInfo *const *) b;
  233.     if ((**fipa).mdtm == (**fipb).mdtm)
  234.         return (0);
  235.     else if ((**fipa).mdtm < (**fipb).mdtm)
  236.         return (-1);
  237.     return (1);
  238. }    /* ReverseTimeCmp */
  239.  
  240.  
  241.  
  242.  
  243. static int
  244. SizeCmp(const void *a, const void *b)
  245. {
  246.     const FTPFileInfo *const *fipa;
  247.     const FTPFileInfo *const *fipb;
  248.  
  249.     fipa = (const FTPFileInfo *const *) a;
  250.     fipb = (const FTPFileInfo *const *) b;
  251.     if ((**fipb).size == (**fipa).size)
  252.         return (0);
  253.     else if ((**fipb).size < (**fipa).size)
  254.         return (-1);
  255.     return (1);
  256. }    /* SizeCmp */
  257.  
  258.  
  259.  
  260.  
  261. static int
  262. ReverseSizeCmp(const void *a, const void *b)
  263. {
  264.     const FTPFileInfo *const *fipa;
  265.     const FTPFileInfo *const *fipb;
  266.  
  267.     fipa = (const FTPFileInfo *const *) a;
  268.     fipb = (const FTPFileInfo *const *) b;
  269.     if ((**fipa).size == (**fipb).size)
  270.         return (0);
  271.     else if ((**fipa).size < (**fipb).size)
  272.         return (-1);
  273.     return (1);
  274. }    /* ReverseSizeCmp */
  275.  
  276.  
  277.  
  278.  
  279. static int
  280. ReverseNameCmp(const void *a, const void *b)
  281. {
  282.     const FTPFileInfo *const *fipa;
  283.     const FTPFileInfo *const *fipb;
  284.  
  285.     fipa = (const FTPFileInfo *const *) a;
  286.     fipb = (const FTPFileInfo *const *) b;
  287. #ifdef HAVE_SETLOCALE
  288.     return (strcoll((**fipb).relname, (**fipa).relname));
  289. #else
  290.     return (strcmp((**fipb).relname, (**fipa).relname));
  291. #endif
  292. }    /* ReverseNameCmp */
  293.  
  294.  
  295.  
  296.  
  297. static int
  298. NameCmp(const void *a, const void *b)
  299. {
  300.     const FTPFileInfo *const *fipa;
  301.     const FTPFileInfo *const *fipb;
  302.  
  303.     fipa = (const FTPFileInfo *const *) a;
  304.     fipb = (const FTPFileInfo *const *) b;
  305. #ifdef HAVE_SETLOCALE
  306.     return (strcoll((**fipa).relname, (**fipb).relname));
  307. #else
  308.     return (strcmp((**fipa).relname, (**fipb).relname));
  309. #endif
  310. }    /* NameCmp */
  311.  
  312.  
  313.  
  314.  
  315. static int
  316. BreadthFirstCmp(const void *a, const void *b)
  317. {
  318.     char *cp, *cpa, *cpb;
  319.     int depth, deptha, depthb;
  320.     int c;
  321.     const FTPFileInfo *const *fipa;
  322.     const FTPFileInfo *const *fipb;
  323.  
  324.     fipa = (const FTPFileInfo *const *) a;
  325.     fipb = (const FTPFileInfo *const *) b;
  326.  
  327.     cpa = (**fipa).relname;
  328.     cpb = (**fipb).relname;
  329.  
  330.     for (cp = cpa, depth = 0;;) {
  331.         c = *cp++;
  332.         if (c == '\0')
  333.             break;
  334.         if ((c == '/') || (c == '\\')) {
  335.             depth++;
  336.         }
  337.     }
  338.     deptha = depth;
  339.  
  340.     for (cp = cpb, depth = 0;;) {
  341.         c = *cp++;
  342.         if (c == '\0')
  343.             break;
  344.         if ((c == '/') || (c == '\\')) {
  345.             depth++;
  346.         }
  347.     }
  348.     depthb = depth;
  349.  
  350.     if (deptha < depthb)
  351.         return (-1);
  352.     else if (deptha > depthb)
  353.         return (1);
  354.  
  355. #ifdef HAVE_SETLOCALE
  356.     return (strcoll(cpa, cpb));
  357. #else
  358.     return (strcmp(cpa, cpb));
  359. #endif
  360. }    /* BreadthFirstCmp */
  361.  
  362.  
  363.  
  364.  
  365. void
  366. SortFileInfoList(FTPFileInfoListPtr list, int sortKey, int sortOrder)
  367. {
  368.     FTPFileInfoVec fiv;
  369.     FTPFileInfoPtr fip;
  370.     int i, j, n, n2;
  371.  
  372.     fiv = list->vec;
  373.     if (fiv == NULL)
  374.         return;
  375.  
  376.     if (list->sortKey == sortKey) {
  377.         if (list->sortOrder == sortOrder)
  378.             return;        /* Already sorted they you want. */
  379.  
  380.         /* Reverse the sort. */
  381.         n = list->nFileInfos;
  382.         if (n > 1) {
  383.             n2 = n / 2;
  384.             for (i=0; i<n2; i++) {
  385.                 j = n - i - 1;
  386.                 fip = fiv[i];
  387.                 fiv[i] = fiv[j];
  388.                 fiv[j] = fip;
  389.             }
  390.         }
  391.  
  392.         list->sortOrder = sortOrder;
  393.     } else if ((sortKey == 'n') && (sortOrder == 'a')) {
  394.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  395.             NameCmp);
  396.         list->sortKey = sortKey;
  397.         list->sortOrder = sortOrder;
  398.     } else if ((sortKey == 'n') && (sortOrder == 'd')) {
  399.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  400.             ReverseNameCmp);
  401.         list->sortKey = sortKey;
  402.         list->sortOrder = sortOrder;
  403.     } else if ((sortKey == 't') && (sortOrder == 'a')) {
  404.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  405.             TimeCmp);
  406.         list->sortKey = sortKey;
  407.         list->sortOrder = sortOrder;
  408.     } else if ((sortKey == 't') && (sortOrder == 'd')) {
  409.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  410.             ReverseTimeCmp);
  411.         list->sortKey = sortKey;
  412.         list->sortOrder = sortOrder;
  413.     } else if ((sortKey == 's') && (sortOrder == 'a')) {
  414.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  415.             SizeCmp);
  416.         list->sortKey = sortKey;
  417.         list->sortOrder = sortOrder;
  418.     } else if ((sortKey == 's') && (sortOrder == 'd')) {
  419.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  420.             ReverseSizeCmp);
  421.         list->sortKey = sortKey;
  422.         list->sortOrder = sortOrder;
  423.     } else if (sortKey == 'b') {
  424.         /* This is different from the rest. */
  425.         list->sortKey = sortKey;
  426.         list->sortOrder = sortOrder;
  427.         qsort(fiv, (size_t) list->nFileInfos, sizeof(FTPFileInfoPtr),
  428.             BreadthFirstCmp);
  429.     }
  430. }    /* SortFileInfoList */
  431.  
  432.  
  433.  
  434.  
  435. void
  436. VectorizeFileInfoList(FTPFileInfoListPtr list)
  437. {
  438.     FTPFileInfoVec fiv;
  439.     FTPFileInfoPtr fip;
  440.     int i;
  441.  
  442.     fiv = (FTPFileInfoVec) calloc((size_t) (list->nFileInfos + 1), sizeof(FTPFileInfoPtr));
  443.     if (fiv != (FTPFileInfoVec) 0) {
  444.         for (i = 0, fip = list->first; fip != NULL; fip = fip->next, i++)
  445.             fiv[i] = fip;
  446.         list->vec = fiv;
  447.     }
  448. }    /* VectorizeFileInfoList */
  449.  
  450.  
  451.  
  452.  
  453. void
  454. UnvectorizeFileInfoList(FTPFileInfoListPtr list)
  455. {
  456.     FTPFileInfoVec fiv;
  457.     FTPFileInfoPtr fip;
  458.     int i, n;
  459.  
  460.     fiv = list->vec;
  461.     if (fiv != (FTPFileInfoVec) 0) {
  462.         list->first = fiv[0];
  463.         n = list->nFileInfos;
  464.         if (n > 0) {
  465.             list->last = fiv[n - 1];
  466.             fip = fiv[0];
  467.             fip->prev = NULL;
  468.             fip->next = fiv[1];
  469.             for (i = 1; i < n; i++) {
  470.                 fip = fiv[i];
  471.                 fip->prev = fiv[i - 1];
  472.                 fip->next = fiv[i + 1];
  473.             }
  474.         }
  475.         free(fiv);
  476.         list->vec = (FTPFileInfoVec) 0;
  477.     }
  478. }    /* UnvectorizeFileInfoList */
  479.  
  480.  
  481.  
  482.  
  483. void
  484. InitFileInfo(FTPFileInfoPtr fip)
  485. {
  486.     (void) memset(fip, 0, sizeof(FTPFileInfo));
  487.  
  488.     fip->type = '-';
  489.     fip->size = kSizeUnknown;
  490.     fip->mdtm = kModTimeUnknown;
  491.  
  492.     /* Redundant, but needed to shush BoundsChecker. */
  493.     fip->relname = fip->rname = fip->rlinkto = fip->lname = fip->plug = NULL;
  494.     fip->prev = fip->next = NULL;
  495. }    /* InitFileInfo */
  496.  
  497.  
  498.  
  499.  
  500. FTPFileInfoPtr
  501. RemoveFileInfo(FTPFileInfoListPtr list, FTPFileInfoPtr killMe)
  502. {
  503.     FTPFileInfoPtr nextFileInfo, prevFileInfo;
  504.     
  505.     nextFileInfo = killMe->next;    
  506.     prevFileInfo = killMe->prev;    
  507.     if (killMe->lname != NULL) {
  508.         killMe->lname[0] = '\0';        /* Make it useless just in case. */
  509.         free(killMe->lname);
  510.     }
  511.     if (killMe->relname != NULL) {
  512.         killMe->relname[0] = '\0';
  513.         free(killMe->relname);
  514.     }
  515.     if (killMe->rname != NULL) {
  516.         killMe->rname[0] = '\0';
  517.         free(killMe->rname);
  518.     }
  519.     if (killMe->rlinkto != NULL) {
  520.         killMe->rlinkto[0] = '\0';
  521.         free(killMe->rlinkto);
  522.     }
  523.     if (killMe->plug != NULL) {
  524.         killMe->plug[0] = '\0';
  525.         free(killMe->plug);
  526.     }
  527.  
  528.     if (list->first == killMe)
  529.         list->first = nextFileInfo;
  530.     if (list->last == killMe)
  531.         list->last = prevFileInfo;
  532.  
  533.     if (nextFileInfo != NULL)
  534.         nextFileInfo->prev = prevFileInfo;
  535.     if (prevFileInfo != NULL)
  536.         prevFileInfo->next = nextFileInfo;
  537.  
  538.     free(killMe);    
  539.     list->nFileInfos--;
  540.     return (nextFileInfo);
  541. }    /* RemoveFileInfo */
  542.  
  543.  
  544.  
  545.  
  546. /* Adds a string to the FTPFileInfoList specified. */
  547. FTPFileInfoPtr
  548. AddFileInfo(FTPFileInfoListPtr list, FTPFileInfoPtr src)
  549. {
  550.     FTPFileInfoPtr lp;
  551.     
  552.     lp = (FTPFileInfoPtr) malloc(sizeof(FTPFileInfo));
  553.     if (lp != NULL) {
  554.         (void) memcpy(lp, src, sizeof(FTPFileInfo));
  555.         lp->next = NULL;
  556.         if (list->first == NULL) {
  557.             list->first = list->last = lp;
  558.             lp->prev = NULL;
  559.             list->nFileInfos = 1;
  560.         } else {
  561.             lp->prev = list->last;
  562.             list->last->next = lp;
  563.             list->last = lp;
  564.             list->nFileInfos++;
  565.         }
  566.     }
  567.     return lp;
  568. }    /* AddFileInfo */
  569.  
  570.  
  571.  
  572.  
  573. int
  574. ConcatFileInfoList(FTPFileInfoListPtr dst, FTPFileInfoListPtr src)
  575. {
  576.     FTPFileInfoPtr lp, lp2;
  577.     FTPFileInfo newfi;
  578.     
  579.     for (lp = src->first; lp != NULL; lp = lp2) {
  580.         lp2 = lp->next;
  581.         newfi = *lp;
  582.         newfi.relname = StrDup(lp->relname);
  583.         newfi.lname = StrDup(lp->lname);
  584.         newfi.rname = StrDup(lp->rname);
  585.         newfi.rlinkto = StrDup(lp->rlinkto);
  586.         newfi.plug = StrDup(lp->plug);
  587.         if (AddFileInfo(dst, &newfi) == NULL)
  588.             return (-1);
  589.     }
  590.     return (0);
  591. }    /* ConcatFileInfoList */
  592.  
  593.  
  594.  
  595.  
  596. int
  597. ComputeRNames(FTPFileInfoListPtr dst, const char *dstdir, int pflag, int nochop)
  598. {
  599.     FTPFileInfoPtr lp, lp2;
  600.     char *buf;
  601.     char *cp;
  602.  
  603.     if (dstdir == NULL)
  604.         dstdir = ".";
  605.  
  606.     for (lp = dst->first; lp != NULL; lp = lp2) {
  607.         lp2 = lp->next;
  608.  
  609.         buf = NULL;
  610.         if (nochop != 0) {
  611.             if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) {
  612.                 if (Dynscat(&buf, dstdir, "/", lp->relname, 0) == NULL)
  613.                     goto memerr;
  614.  
  615.                 if (pflag != 0) {
  616.                     /* Init lname to parent dir name of remote dir */
  617.                     cp = strrchr(dstdir, '/');
  618.                     if (cp == NULL)
  619.                         cp = strrchr(dstdir, '\\');
  620.                     if (cp != NULL) {
  621.                         if (Dynscat(&lp->lname, cp + 1, 0) == NULL)
  622.                             goto memerr;
  623.                         TVFSPathToLocalPath(lp->lname);
  624.                     }
  625.                 }
  626.             } else {
  627.                 if (Dynscat(&buf, lp->relname, 0) == NULL)
  628.                     goto memerr;
  629.             }
  630.         } else {
  631.             if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) {
  632.                 cp = strrchr(lp->relname, '/');
  633.                 if (cp == NULL)
  634.                     cp = strrchr(lp->relname, '\\');
  635.                 if (cp != NULL) {
  636.                     cp++;
  637.                 } else {
  638.                     cp = lp->relname;
  639.                 }
  640.                 if (Dynscat(&buf, dstdir, "/", cp, 0) == NULL)
  641.                     goto memerr;
  642.  
  643.                 if (pflag != 0) {
  644.                     /* Init lname to parent dir name of remote dir */
  645.                     cp = strrchr(dstdir, '/');
  646.                     if (cp == NULL)
  647.                         cp = strrchr(dstdir, '\\');
  648.                     if (cp != NULL) {
  649.                         if (Dynscat(&lp->lname, cp + 1, 0) == NULL)
  650.                             goto memerr;
  651.                         TVFSPathToLocalPath(lp->lname);
  652.                     }
  653.                 }
  654.             } else {
  655.                 cp = strrchr(lp->relname, '/');
  656.                 if (cp == NULL)
  657.                     cp = strrchr(lp->relname, '\\');
  658.                 if (cp != NULL) {
  659.                     cp++;
  660.                 } else {
  661.                     cp = lp->relname;
  662.                 }
  663.                 if (Dynscat(&buf, cp, 0) == NULL)
  664.                     goto memerr;
  665.             }
  666.         }
  667.         lp->rname = buf;
  668.         if (lp->rname == NULL) {
  669. memerr:
  670.             return (-1);
  671.         }
  672.         LocalPathToTVFSPath(lp->rname);
  673.     }
  674.     return (0);
  675. }    /* ComputeRNames */
  676.  
  677.  
  678.  
  679.  
  680. int
  681. ComputeLNames(FTPFileInfoListPtr dst, const char *srcdir, const char *dstdir, int nochop)
  682. {
  683.     FTPFileInfoPtr lp, lp2;
  684.     char *buf;
  685.     char *cp;
  686.  
  687.     if (srcdir != NULL) {
  688.         cp = strrchr(srcdir, '/');
  689.         if (cp == NULL)
  690.             cp = strrchr(srcdir, '\\');
  691.         if (cp != NULL)
  692.             srcdir = cp + 1;
  693.     }
  694.     if (dstdir == NULL)
  695.         dstdir = ".";
  696.  
  697.     for (lp = dst->first; lp != NULL; lp = lp2) {
  698.         lp2 = lp->next;
  699.  
  700.         buf = NULL;
  701.         if (nochop != 0) {
  702.             if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) {
  703.                 if (Dynscat(&buf, dstdir, "/", 0) == NULL)
  704.                     goto memerr;
  705.             }
  706.             if (lp->lname != NULL) {
  707.                 if (Dynscat(&buf, lp->lname, "/", 0) == NULL)
  708.                     goto memerr;
  709.             } else if (srcdir != NULL) {
  710.                 if (Dynscat(&buf, srcdir, "/", 0) == NULL)
  711.                     goto memerr;
  712.             }
  713.             if (Dynscat(&buf, lp->relname, 0) == NULL)
  714.                 goto memerr;
  715.         } else {
  716.             if ((dstdir[0] != '\0') && (strcmp(dstdir, "."))) {
  717.                 cp = strrchr(lp->relname, '/');
  718.                 if (cp == NULL)
  719.                     cp = strrchr(lp->relname, '\\');
  720.                 if (cp == NULL) {
  721.                     cp = lp->relname;
  722.                 } else {
  723.                     cp++;
  724.                 }
  725.                 if (Dynscat(&buf, dstdir, "/", cp, 0) == NULL)
  726.                     goto memerr;
  727.             } else {
  728.                 cp = strrchr(lp->relname, '/');
  729.                 if (cp == NULL)
  730.                     cp = strrchr(lp->relname, '\\');
  731.                 if (cp == NULL) {
  732.                     cp = lp->relname;
  733.                 } else {
  734.                     cp++;
  735.                 }
  736.                 if (Dynscat(&buf, cp, 0) == NULL)
  737.                     goto memerr;
  738.             }
  739.         }
  740.         if (buf == NULL) {
  741. memerr:
  742.             return (-1);
  743.         }
  744.         if (lp->lname != NULL) {
  745.             free(lp->lname);
  746.             lp->lname = NULL;
  747.         }
  748.         lp->lname = buf;
  749.         TVFSPathToLocalPath(lp->lname);
  750.     }
  751.     return (0);
  752. }    /* ComputeLNames */
  753.  
  754.  
  755.  
  756.  
  757. int
  758. ConcatFileToFileInfoList(FTPFileInfoListPtr dst, char *rfile)
  759. {
  760.     FTPFileInfo newfi;
  761.  
  762.     InitFileInfo(&newfi);    /* Use defaults. */
  763.     newfi.relname = StrDup(rfile);
  764.     newfi.rname = NULL;
  765.     newfi.lname = NULL;
  766.  
  767.     if (AddFileInfo(dst, &newfi) == NULL)
  768.         return (-1);
  769.     return (0);
  770. }    /* ConcatFileToFileInfoList */
  771.  
  772.  
  773.  
  774.  
  775. int
  776. LineListToFileInfoList(FTPLineListPtr src, FTPFileInfoListPtr dst)
  777. {
  778.     FTPLinePtr lp, lp2;
  779.  
  780.     InitFileInfoList(dst);
  781.     for (lp = src->first; lp != NULL; lp = lp2) {
  782.         lp2 = lp->next;
  783.         if (ConcatFileToFileInfoList(dst, lp->line) < 0)
  784.             return (-1);
  785.     }
  786.     return (0);
  787. }    /* LineListToFileList */
  788.  
  789.  
  790.  
  791.  
  792. int
  793. LineToFileInfoList(FTPLinePtr lp, FTPFileInfoListPtr dst)
  794. {
  795.     InitFileInfoList(dst);
  796.     if (ConcatFileToFileInfoList(dst, lp->line) < 0)
  797.         return (-1);
  798.     return (0);
  799. }    /* LineToFileInfoList */
  800.  
  801. /* eof */
  802.