3 * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
10 /* Dynamically make a copy of a string. */
12 StrDup(const char *buf
)
20 len
= strlen(buf
) + 1;
21 cp
= (char *) malloc(len
);
23 (void) memcpy(cp
, buf
, len
);
29 /* Disposes each node of a LineList. Does a few extra things
30 * so the disposed memory won't be very useful after it is freed.
33 DisposeLineListContents(LineListPtr list
)
37 for (lp
= list
->first
; lp
!= NULL
; ) {
40 if (lp2
->line
!= NULL
) {
46 /* Same as InitLineList. */
47 (void) memset(list
, 0, sizeof(LineList
));
48 } /* DisposeLineListContents */
54 InitLineList(LineListPtr list
)
56 (void) memset(list
, 0, sizeof(LineList
));
63 RemoveLine(LineListPtr list
, LinePtr killMe
)
65 LinePtr nextLine
, prevLine
;
67 nextLine
= killMe
->next
;
68 prevLine
= killMe
->prev
;
69 if (killMe
->line
!= NULL
) {
70 killMe
->line
[0] = '\0'; /* Make it useless just in case. */
74 if (list
->first
== killMe
)
75 list
->first
= nextLine
;
76 if (list
->last
== killMe
)
77 list
->last
= prevLine
;
80 nextLine
->prev
= prevLine
;
82 prevLine
->next
= nextLine
;
92 /* Adds a string to the LineList specified. */
94 AddLine(LineListPtr list
, const char *buf1
)
99 lp
= (LinePtr
) malloc(sizeof(Line
));
108 if (list
->first
== NULL
) {
109 list
->first
= list
->last
= lp
;
113 lp
->prev
= list
->last
;
114 list
->last
->next
= lp
;
127 CopyLineList(LineListPtr dst
, LineListPtr src
)
132 for (lp
= src
->first
; lp
!= NULL
; ) {
135 if (lp2
->line
!= NULL
) {
136 if (AddLine(dst
, lp2
->line
) == NULL
) {
137 DisposeLineListContents(dst
);
148 /* Disposes each node of a FileInfoList. Does a few extra things
149 * so the disposed memory won't be very useful after it is freed.
152 DisposeFileInfoListContents(FileInfoListPtr list
)
156 for (lp
= list
->first
; lp
!= NULL
; ) {
159 if (lp2
->relname
!= NULL
) {
160 lp2
->relname
[0] = '\0';
163 if (lp2
->lname
!= NULL
) {
164 lp2
->lname
[0] = '\0';
167 if (lp2
->rname
!= NULL
) {
168 lp2
->rname
[0] = '\0';
171 if (lp2
->rlinkto
!= NULL
) {
172 lp2
->rlinkto
[0] = '\0';
175 if (lp2
->plug
!= NULL
) {
182 if (list
->vec
!= NULL
)
185 /* Same as InitFileInfoList. */
186 (void) memset(list
, 0, sizeof(FileInfoList
));
187 } /* DisposeFileInfoListContents */
193 InitFileInfoList(FileInfoListPtr list
)
195 (void) memset(list
, 0, sizeof(FileInfoList
));
196 } /* InitFileInfoList */
202 TimeCmp(const void *a
, const void *b
)
204 FileInfoPtr
*fipa
, *fipb
;
206 fipa
= (FileInfoPtr
*) a
;
207 fipb
= (FileInfoPtr
*) b
;
208 if ((**fipb
).mdtm
== (**fipa
).mdtm
)
210 else if ((**fipb
).mdtm
< (**fipa
).mdtm
)
219 ReverseTimeCmp(const void *a
, const void *b
)
221 FileInfoPtr
*fipa
, *fipb
;
223 fipa
= (FileInfoPtr
*) a
;
224 fipb
= (FileInfoPtr
*) b
;
225 if ((**fipa
).mdtm
== (**fipb
).mdtm
)
227 else if ((**fipa
).mdtm
< (**fipb
).mdtm
)
230 } /* ReverseTimeCmp */
236 SizeCmp(const void *a
, const void *b
)
238 FileInfoPtr
*fipa
, *fipb
;
240 fipa
= (FileInfoPtr
*) a
;
241 fipb
= (FileInfoPtr
*) b
;
242 if ((**fipb
).size
== (**fipa
).size
)
244 else if ((**fipb
).size
< (**fipa
).size
)
253 ReverseSizeCmp(const void *a
, const void *b
)
255 FileInfoPtr
*fipa
, *fipb
;
257 fipa
= (FileInfoPtr
*) a
;
258 fipb
= (FileInfoPtr
*) b
;
259 if ((**fipa
).size
== (**fipb
).size
)
261 else if ((**fipa
).size
< (**fipb
).size
)
264 } /* ReverseSizeCmp */
270 ReverseNameCmp(const void *a
, const void *b
)
272 FileInfoPtr
*fipa
, *fipb
;
274 fipa
= (FileInfoPtr
*) a
;
275 fipb
= (FileInfoPtr
*) b
;
276 #ifdef HAVE_SETLOCALE
277 return (strcoll((**fipb
).relname
, (**fipa
).relname
));
279 return (strcmp((**fipb
).relname
, (**fipa
).relname
));
281 } /* ReverseNameCmp */
287 NameCmp(const void *a
, const void *b
)
289 FileInfoPtr
*fipa
, *fipb
;
291 fipa
= (FileInfoPtr
*) a
;
292 fipb
= (FileInfoPtr
*) b
;
293 #ifdef HAVE_SETLOCALE
294 return (strcoll((**fipa
).relname
, (**fipb
).relname
));
296 return (strcmp((**fipa
).relname
, (**fipb
).relname
));
304 BreadthFirstCmp(const void *a
, const void *b
)
306 FileInfoPtr
*fipa
, *fipb
;
307 char *cp
, *cpa
, *cpb
;
308 int depth
, deptha
, depthb
;
311 fipa
= (FileInfoPtr
*) a
;
312 fipb
= (FileInfoPtr
*) b
;
314 cpa
= (**fipa
).relname
;
315 cpb
= (**fipb
).relname
;
317 for (cp
= cpa
, depth
= 0;;) {
321 if ((c
== '/') || (c
== '\\')) {
327 for (cp
= cpb
, depth
= 0;;) {
331 if ((c
== '/') || (c
== '\\')) {
339 else if (deptha
> depthb
)
342 #ifdef HAVE_SETLOCALE
343 return (strcoll(cpa
, cpb
));
345 return (strcmp(cpa
, cpb
));
347 } /* BreadthFirstCmp */
353 SortFileInfoList(FileInfoListPtr list
, int sortKey
, int sortOrder
)
363 if (list
->sortKey
== sortKey
) {
364 if (list
->sortOrder
== sortOrder
)
365 return; /* Already sorted they you want. */
367 /* Reverse the sort. */
368 n
= list
->nFileInfos
;
371 for (i
=0; i
<n2
; i
++) {
379 list
->sortOrder
= sortOrder
;
380 } else if ((sortKey
== 'n') && (sortOrder
== 'a')) {
381 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
383 list
->sortKey
= sortKey
;
384 list
->sortOrder
= sortOrder
;
385 } else if ((sortKey
== 'n') && (sortOrder
== 'd')) {
386 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
388 list
->sortKey
= sortKey
;
389 list
->sortOrder
= sortOrder
;
390 } else if ((sortKey
== 't') && (sortOrder
== 'a')) {
391 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
393 list
->sortKey
= sortKey
;
394 list
->sortOrder
= sortOrder
;
395 } else if ((sortKey
== 't') && (sortOrder
== 'd')) {
396 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
398 list
->sortKey
= sortKey
;
399 list
->sortOrder
= sortOrder
;
400 } else if ((sortKey
== 's') && (sortOrder
== 'a')) {
401 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
403 list
->sortKey
= sortKey
;
404 list
->sortOrder
= sortOrder
;
405 } else if ((sortKey
== 's') && (sortOrder
== 'd')) {
406 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
408 list
->sortKey
= sortKey
;
409 list
->sortOrder
= sortOrder
;
410 } else if (sortKey
== 'b') {
411 /* This is different from the rest. */
412 list
->sortKey
= sortKey
;
413 list
->sortOrder
= sortOrder
;
414 qsort(fiv
, (size_t) list
->nFileInfos
, sizeof(FileInfoPtr
),
417 } /* SortFileInfoList */
423 VectorizeFileInfoList(FileInfoListPtr list
)
429 fiv
= (FileInfoVec
) calloc((size_t) (list
->nFileInfos
+ 1), sizeof(FileInfoPtr
));
430 if (fiv
!= (FileInfoVec
) 0) {
431 for (i
= 0, fip
= list
->first
; fip
!= NULL
; fip
= fip
->next
, i
++)
435 } /* VectorizeFileInfoList */
441 UnvectorizeFileInfoList(FileInfoListPtr list
)
448 if (fiv
!= (FileInfoVec
) 0) {
449 list
->first
= fiv
[0];
450 n
= list
->nFileInfos
;
452 list
->last
= fiv
[n
- 1];
456 for (i
= 1; i
< n
; i
++) {
458 fip
->prev
= fiv
[i
- 1];
459 fip
->next
= fiv
[i
+ 1];
463 list
->vec
= (FileInfoVec
) 0;
465 } /* UnvectorizeFileInfoList */
471 InitFileInfo(FileInfoPtr fip
)
473 (void) memset(fip
, 0, sizeof(FileInfo
));
475 fip
->size
= kSizeUnknown
;
476 fip
->mdtm
= kModTimeUnknown
;
477 } /* InitFileInfoList */
483 RemoveFileInfo(FileInfoListPtr list
, FileInfoPtr killMe
)
485 FileInfoPtr nextFileInfo
, prevFileInfo
;
487 nextFileInfo
= killMe
->next
;
488 prevFileInfo
= killMe
->prev
;
489 if (killMe
->lname
!= NULL
) {
490 killMe
->lname
[0] = '\0'; /* Make it useless just in case. */
493 if (killMe
->relname
!= NULL
) {
494 killMe
->relname
[0] = '\0';
495 free(killMe
->relname
);
497 if (killMe
->rname
!= NULL
) {
498 killMe
->rname
[0] = '\0';
501 if (killMe
->rlinkto
!= NULL
) {
502 killMe
->rlinkto
[0] = '\0';
503 free(killMe
->rlinkto
);
505 if (killMe
->plug
!= NULL
) {
506 killMe
->plug
[0] = '\0';
510 if (list
->first
== killMe
)
511 list
->first
= nextFileInfo
;
512 if (list
->last
== killMe
)
513 list
->last
= prevFileInfo
;
515 if (nextFileInfo
!= NULL
)
516 nextFileInfo
->prev
= prevFileInfo
;
517 if (prevFileInfo
!= NULL
)
518 prevFileInfo
->next
= nextFileInfo
;
522 return (nextFileInfo
);
523 } /* RemoveFileInfo */
528 /* Adds a string to the FileInfoList specified. */
530 AddFileInfo(FileInfoListPtr list
, FileInfoPtr src
)
534 lp
= (FileInfoPtr
) malloc(sizeof(FileInfo
));
536 (void) memcpy(lp
, src
, sizeof(FileInfo
));
538 if (list
->first
== NULL
) {
539 list
->first
= list
->last
= lp
;
541 list
->nFileInfos
= 1;
543 lp
->prev
= list
->last
;
544 list
->last
->next
= lp
;
556 ConcatFileInfoList(FileInfoListPtr dst
, FileInfoListPtr src
)
561 for (lp
= src
->first
; lp
!= NULL
; lp
= lp2
) {
564 newfi
.relname
= StrDup(lp
->relname
);
565 newfi
.lname
= StrDup(lp
->lname
);
566 newfi
.rname
= StrDup(lp
->rname
);
567 newfi
.rlinkto
= StrDup(lp
->rlinkto
);
568 newfi
.plug
= StrDup(lp
->plug
);
569 if (AddFileInfo(dst
, &newfi
) == NULL
)
573 } /* ConcatFileInfoList */
579 ComputeRNames(FileInfoListPtr dst
, const char *dstdir
, int pflag
, int nochop
)
588 for (lp
= dst
->first
; lp
!= NULL
; lp
= lp2
) {
593 if ((dstdir
[0] != '\0') && (strcmp(dstdir
, "."))) {
594 if (Dynscat(&buf
, dstdir
, "/", lp
->relname
, 0) == NULL
)
598 /* Init lname to parent dir name of remote dir */
599 cp
= strrchr(dstdir
, '/');
601 cp
= strrchr(dstdir
, '\\');
603 if (Dynscat(&lp
->lname
, cp
+ 1, 0) == NULL
)
605 TVFSPathToLocalPath(lp
->lname
);
609 if (Dynscat(&buf
, lp
->relname
, 0) == NULL
)
613 if ((dstdir
[0] != '\0') && (strcmp(dstdir
, "."))) {
614 cp
= strrchr(lp
->relname
, '/');
616 cp
= strrchr(lp
->relname
, '\\');
622 if (Dynscat(&buf
, dstdir
, "/", cp
, 0) == NULL
)
626 /* Init lname to parent dir name of remote dir */
627 cp
= strrchr(dstdir
, '/');
629 cp
= strrchr(dstdir
, '\\');
631 if (Dynscat(&lp
->lname
, cp
+ 1, 0) == NULL
)
633 TVFSPathToLocalPath(lp
->lname
);
637 cp
= strrchr(lp
->relname
, '/');
639 cp
= strrchr(lp
->relname
, '\\');
645 if (Dynscat(&buf
, cp
, 0) == NULL
)
650 if (lp
->rname
== NULL
) {
654 LocalPathToTVFSPath(lp
->rname
);
657 } /* ComputeRNames */
663 ComputeLNames(FileInfoListPtr dst
, const char *srcdir
, const char *dstdir
, int nochop
)
669 if (srcdir
!= NULL
) {
670 cp
= strrchr(srcdir
, '/');
672 cp
= strrchr(srcdir
, '\\');
679 for (lp
= dst
->first
; lp
!= NULL
; lp
= lp2
) {
684 if ((dstdir
[0] != '\0') && (strcmp(dstdir
, "."))) {
685 if (Dynscat(&buf
, dstdir
, "/", 0) == NULL
)
688 if (lp
->lname
!= NULL
) {
689 if (Dynscat(&buf
, lp
->lname
, "/", 0) == NULL
)
691 } else if (srcdir
!= NULL
) {
692 if (Dynscat(&buf
, srcdir
, "/", 0) == NULL
)
695 if (Dynscat(&buf
, lp
->relname
, 0) == NULL
)
698 if ((dstdir
[0] != '\0') && (strcmp(dstdir
, "."))) {
699 cp
= strrchr(lp
->relname
, '/');
701 cp
= strrchr(lp
->relname
, '\\');
707 if (Dynscat(&buf
, dstdir
, "/", cp
, 0) == NULL
)
710 cp
= strrchr(lp
->relname
, '/');
712 cp
= strrchr(lp
->relname
, '\\');
718 if (Dynscat(&buf
, cp
, 0) == NULL
)
726 if (lp
->lname
!= NULL
) {
731 TVFSPathToLocalPath(lp
->lname
);
734 } /* ComputeLNames */
740 ConcatFileToFileInfoList(FileInfoListPtr dst
, char *rfile
)
744 InitFileInfo(&newfi
); /* Use defaults. */
745 newfi
.relname
= StrDup(rfile
);
749 if (AddFileInfo(dst
, &newfi
) == NULL
)
752 } /* ConcatFileToFileInfoList */
758 LineListToFileInfoList(LineListPtr src
, FileInfoListPtr dst
)
762 InitFileInfoList(dst
);
763 for (lp
= src
->first
; lp
!= NULL
; lp
= lp2
) {
765 if (ConcatFileToFileInfoList(dst
, lp
->line
) < 0)
769 } /* LineListToFileList */
775 LineToFileInfoList(LinePtr lp
, FileInfoListPtr dst
)
777 InitFileInfoList(dst
);
778 if (ConcatFileToFileInfoList(dst
, lp
->line
) < 0)
781 } /* LineToFileInfoList */