ls.cpp
上传用户:surprise9
上传日期:2007-01-04
资源大小:426k
文件大小:17k
源码类别:

Ftp客户端

开发平台:

Visual C++

  1. // This is part of the WAR SOFTWARE SERIES initiated by Jarle Aase
  2. // Copyright 1996 by Jarle Aase. All rights reserved.
  3. // See the "War Software Series Licende Agreement" for details concerning 
  4. // use and distribution.
  5. // ---
  6. // This source code, executables and programs containing source code or
  7. // binaries or proprietetary technology from the War Software Series are
  8. // NOT alloed used, viewed or tested by any governmental agencies in
  9. // any countries. This includes the government, departments, police, 
  10. // military etc.
  11. // ---
  12. // This file is intended for use with Tab space = 2
  13. // Created and maintained in MSVC Developer Studio
  14. // ---
  15. // NAME : ls.cpp
  16. // PURPOSE : UNIX ls command for VfSys.dll
  17. // PROGRAM : 
  18. // DATE : Mar 29 1997
  19. // AUTHOR : Jarle Aase
  20. // ---
  21. //
  22. // The best design would be to use the CLs class, and let that call VfSys at
  23. // need, but it is faster to do the job in one go from the VfSys worker thread.
  24. //
  25. // REVISION HISTORY
  26. // 
  27. #include "stdafx.h"
  28. // For now, we don't support non-daemon programs
  29. //#include "WarSoftware.h"
  30. #include "WarDaemon.h"
  31. #include "WarFsys.h"
  32. #include "VfFSys.h"
  33. #ifdef _DEBUG
  34. #define new DEBUG_NEW
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38. CVfSysLs::CVfSysLs()
  39. {
  40. /* Terminal defaults to -Cq, non-terminal defaults to -1. */
  41. termwidth = 80;
  42. blocksize = 0;
  43. f_followLinks = 0;
  44. output = 0;
  45. btotal = 0;
  46. maxsize = 0;
  47. s_block = s_group = s_inode = s_nlink = s_size = s_user = 0;
  48. f_accesstime = 0; /* use time of last access */
  49. f_column = 0; /* columnated format */
  50. f_flags = 0; /* show flags associated with a file */
  51. f_inode = 0; /* print inode */
  52. f_kblocks = 0; /* print size in kilobytes */
  53. f_listdir = 0; /* list actual directory, not contents */
  54. f_listdot = 0; /* list files beginning with . */
  55. f_hidethisandprevdotdir = 1;
  56. f_longform = 0; /* long listing format */
  57. f_newline = 0; /* if precede with newline */
  58. f_nonprint = 0; /* show unprintables as ? */
  59. f_nosort = 0; /* don't sort output */
  60. f_recursive = 0; /* ls subdirectories also */
  61. f_reversesort = 0; /* reverse whatever sort is used */
  62. f_sectime = 0; /* print the real time for all files */
  63. f_singlecol = 1 ; /* use single column output */
  64. f_size = 0; /* list size in short listing */
  65. f_statustime = 0 ; /* use time of last mode change */
  66. f_dirname = 0; /* if precede with directory name */
  67. f_timesort = 0; /* sort by time vice name */
  68. f_type = 0; /* add type character for non-regular files */
  69. f_comment = 0; // Print comments 
  70. f_printdlc = 0; // Print download count
  71. m_CRLF = "rn"; // On binary transferes we will need "n" only..
  72. // Used by getopt()
  73. opterr = 0; /* if error message should be printed */
  74. optind = 0; /* index into parent argv vector */
  75. optopt = 0; /* character checked for validity */
  76. optarg = NULL; /* argument associated with option */
  77. m_Virgin = TRUE;
  78. array = NULL;
  79. lastentries = -1;
  80. }
  81. CVfSysLs::~CVfSysLs()
  82. {
  83. if (array)
  84. free(array);
  85. }
  86. int CVfSysLs::main(int argc, char **argv)
  87. {
  88. static char dot[] = "./", *dotav[] = { dot, NULL };
  89. //struct winsize win;
  90. int ch;
  91. /* Root is -A automatically. */
  92. if (!getuid())
  93. f_listdot = 1;
  94. while ((ch = getopt(argc, argv, "ID1ACFLRTacdfgikloqrstu")) != EOF) {
  95. switch (ch) {
  96. /*
  97.  * The -1, -C and -l options all override each other so shell
  98.  * aliasing works right.
  99.  */
  100. // War Extentions: -D Print dl count + comment, -I Ptint comment
  101. case 'D':
  102. f_printdlc = 1;
  103. // fall trough
  104. case 'I':
  105. f_comment = 1;
  106. break;
  107. // Standatd UNIX ls flags
  108. case '1':
  109. f_singlecol = 1;
  110. f_column = f_longform = 0;
  111. break;
  112. case 'C':
  113. f_column = 1;
  114. f_longform = f_singlecol = 0;
  115. break;
  116. case 'l':
  117. f_longform = 1;
  118. f_column = f_singlecol = 0;
  119. break;
  120. /* The -c and -u options override each other. */
  121. case 'c':
  122. f_statustime = 1;
  123. f_accesstime = 0;
  124. break;
  125. case 'u':
  126. f_accesstime = 1;
  127. f_statustime = 0;
  128. break;
  129. case 'F':
  130. f_type = 1;
  131. break;
  132. case 'L':
  133. m_ShowLinkAsFile = TRUE;
  134. break;
  135. case 'R':
  136. f_recursive = 1;
  137. break;
  138. case 'a':
  139. //fts_options |= FTS_SEEDOT;
  140. f_hidethisandprevdotdir = 0;
  141. /* FALLTHROUGH */
  142. case 'A':
  143. f_listdot = 1;
  144. break;
  145. /* The -d option turns off the -R option. */
  146. case 'd':
  147. f_listdir = 1;
  148. f_recursive = 0;
  149. break;
  150. case 'f':
  151. f_nosort = 1;
  152. break;
  153. case 'g': /* Compatibility with 4.3BSD. */
  154. break;
  155. case 'i':
  156. f_inode = 1;
  157. break;
  158. case 'k':
  159. f_kblocks = 1;
  160. break;
  161. case 'o':
  162. f_flags = 1;
  163. break;
  164. case 'q':
  165. f_nonprint = 1;
  166. break;
  167. case 'r':
  168. f_reversesort = 1;
  169. break;
  170. case 's':
  171. f_size = 1;
  172. break;
  173. case 'T':
  174. f_sectime = 1;
  175. break;
  176. case 't':
  177. f_timesort = 1;
  178. break;
  179. default:
  180. case 'h':
  181. usage();
  182. return 0;
  183. }
  184. }
  185. argc -= optind;
  186. argv += optind;
  187. /*
  188.  * If not -F, -i, -l, -s or -t options, don't require stat
  189.  * information.
  190.  */
  191. /*
  192.  * If not -F, -d or -l options, follow any symbolic links listed on
  193.  * the command line.
  194.  */
  195. if (!f_longform && !f_listdir && !f_type)
  196. f_followLinks = 1;
  197. if (f_singlecol && !f_recursive)
  198. f_dirname = 1;
  199. /* Select a sort function. */
  200. if (f_reversesort) {
  201. if (!f_timesort)
  202. sortfcn = revnamecmp;
  203. else if (f_accesstime)
  204. sortfcn = revacccmp;
  205. else if (f_statustime)
  206. sortfcn = revstatcmp;
  207. else /* Use modification time. */
  208. sortfcn = revmodcmp;
  209. } else {
  210. if (!f_timesort)
  211. sortfcn = namecmp;
  212. else if (f_accesstime)
  213. sortfcn = acccmp;
  214. else if (f_statustime)
  215. sortfcn = statcmp;
  216. else /* Use modification time. */
  217. sortfcn = modcmp;
  218. }
  219. ASSERT(argc >= 0);
  220. int Rval = 0;
  221. if (argc)
  222. Rval = ListDir(argc, argv);
  223. else
  224. Rval = ListDir(1, dotav);
  225. return Rval;
  226. }
  227. int CVfSysLs::ListDir(int argc, char **argv)
  228. {
  229. int argcSave = argc;
  230. char **argvSave = argv;
  231. for(;argc ; argc--, argv++)
  232. {
  233. // Prepere file system
  234. CString Path = *argv;
  235. m_pFsysThread->ParsePath(Path);
  236. m_pFsysThread->ScanPath(Path, FALSE, f_recursive, FALSE);
  237. }
  238. pLock->ReadLock();
  239. int Rval =  _ListDir(argcSave, argvSave);
  240. pLock->UnlockRead();
  241. return Rval;
  242. }
  243. int CVfSysLs::_ListDir(int argc, char **argv)
  244. {
  245. BOOL UsePrint = TRUE;
  246. CString cShowPath, cCurrentPath;
  247. ASSERT(argc >= 1);
  248. for(;argc ; argc--, argv++)
  249. {
  250. CFileList FileList;
  251. CLinkedListItem *Item;
  252. ASSERT(AfxIsValidString(*argv));
  253. if (m_VisitedDirs.Find(*argv))
  254. continue; // Already been here
  255. cCurrentPath = cShowPath = *argv;
  256. m_pFsysThread->BldFileInfoList(FileList, *argv, !f_listdir);
  257. if (!PrintFileList(FileList, cShowPath))
  258. return -1;
  259. if (f_recursive)
  260. {
  261. // Grab subdirs too
  262. int Rval;
  263. m_VisitedDirs.AddHead(*argv);
  264. for(Item = FileList.First(); Item; Item = FileList.Next(Item))
  265. {
  266. FILE_NODE *pNode = (FILE_NODE *)FileList.Ptr(Item);
  267. if ((pNode->Perms & NODE_DIR) 
  268. && strcmp(pNode->Name,".") && strcmp(pNode->Name,".."))
  269. {
  270. CString cBuf;
  271. cBuf.Format("%s/%s", cCurrentPath, pNode->Name);
  272. LPSTR MyArgs[1];
  273. MyArgs[0] = cBuf.GetBuffer(1);
  274. if (Rval = ListDir(1, MyArgs))
  275. return Rval; // Error
  276. }
  277. }
  278. }
  279. }
  280. return 0;
  281. }
  282. BOOL CVfSysLs::PrintFileList(CFileList& FileList, LPCSTR Path)
  283. {
  284. FLEN maxblock, maxinode, maxnlink;
  285. int bcfile, flen, glen, ulen, maxflags, maxgroup, maxuser;
  286. int needstats;
  287. LPCSTR user, group ,flags;
  288. char buf[20]; /* 32 bits == 10 digits */
  289. CPseudoFileInfo Info;
  290. CLinkedListItem *Item;
  291. LPCSTR FileName;
  292. CString cBuf;
  293. if (!f_nosort)
  294. FileList.Sort((int (*)(const void *, const void *))sortfcn);
  295. needstats = f_inode || f_longform || f_size;
  296. flen = 0;
  297. maxblock = maxinode = maxnlink = (FLEN)0;
  298. btotal = maxlen = 0;
  299. bcfile = 0;
  300. maxuser = maxgroup = maxflags = 0;
  301. flags = NULL;
  302. maxsize = 0;
  303. for(Item = FileList.First(), entries = 0; Item; Item = FileList.Next(Item))
  304. {
  305. Info = (FILE_NODE *)FileList.Ptr(Item);
  306. FileName = Info.FileName();
  307. ASSERT(AfxIsValidString(FileName));
  308. if (ISDOT(FileName) && !f_listdot)
  309. {
  310. //Info.Hide(TRUE);
  311. continue;
  312. }
  313. else if (f_hidethisandprevdotdir && (!strcmp(FileName,".") || !strcmp(FileName,"..")))
  314. {
  315. //Info.Hide(TRUE);
  316. continue;
  317. }
  318. if (f_nonprint)
  319. {
  320. Info.MakeFileNameASCII();
  321. }
  322. if (Info.GetFileNameLen() > maxlen)
  323. maxlen = Info.GetFileNameLen() ;
  324. if (needstats) 
  325. {
  326. FLEN NumBlocks = Info.GetFileBlocks();
  327. if (NumBlocks > maxblock)
  328. maxblock = NumBlocks;
  329. if ((FLEN)Info.GetInode() > maxinode)
  330. (FLEN)maxinode = Info.GetInode();
  331. if ((FLEN)Info.GetLinks() > maxnlink)
  332. maxnlink = (FLEN)Info.GetLinks();
  333. if (Info.GetFileLength() > maxsize)
  334. maxsize = Info.GetFileLength();
  335. btotal += NumBlocks;
  336. btotal++;
  337. if (f_longform) 
  338. {
  339. user = Info.GetUserName(cBuf);
  340. if ((ulen = strlen(user)) > maxuser)
  341. maxuser = ulen;
  342. group = Info.GetGroupName(cBuf);
  343. if ((glen = strlen(group)) > maxgroup)
  344. maxgroup = glen;
  345. /*if (f_flags) {
  346. flags = flags_to_string(sp->st_flags, "-");
  347. if ((flen = strlen(flags)) > maxflags)
  348. maxflags = flen;
  349. } else */
  350. flen = 0;
  351. /*if (S_ISCHR(sp->st_mode) ||
  352.     S_ISBLK(sp->st_mode))
  353. bcfile = 1;*/
  354. /*if (f_flags) {
  355. np->flags = &np->data[ulen + glen + 2];
  356.    (void)strcpy(np->flags, flags);
  357. }*/
  358. }
  359. }
  360. ++entries;
  361. }
  362. if (!entries)
  363. return TRUE;
  364. if (needstats) 
  365. {
  366. _snprintf(buf, sizeof(buf), "%lu", maxblock);
  367. s_block = strlen(buf);
  368. _snprintf(buf, sizeof(buf), "%lu", maxinode);
  369. s_inode = strlen(buf);
  370. _snprintf(buf, sizeof(buf), "%lu", maxnlink);
  371. s_nlink = strlen(buf);
  372. _snprintf(buf, sizeof(buf), "%lu", maxsize);
  373. s_size = strlen(buf);
  374. s_user = maxuser;
  375. }
  376. /*
  377.  * If already output something, put out a newline as
  378.  * a separator.  If multiple arguments, precede each
  379.  * directory with its name.
  380. */
  381. if (output)
  382. printf("n%s:n", Path);
  383. /* Select a print function. */
  384. if (f_singlecol)
  385. printscol(FileList, Path);
  386. else if (f_longform)
  387. printlong(FileList, Path);
  388. else
  389. printcol(FileList, Path);
  390. output = 1;
  391. return TRUE;
  392. }
  393. void CVfSysLs::printscol(CFileList& FileList, LPCSTR Path)
  394. {
  395. CPseudoFileInfo Info;
  396. CLinkedListItem *Item;
  397. for(Item = FileList.First(), entries = 0; Item; Item = FileList.Next(Item))
  398. {
  399. Info = (FILE_NODE *)FileList.Ptr(Item);
  400. if (Info.Hide(-1))
  401. continue;
  402. printaname(Info, Path);
  403. putchar('n');
  404. }
  405. }
  406. /*
  407.  * print [inode] [size] name
  408.  * return # of characters printed, no trailing characters.
  409.  */
  410. int CVfSysLs::printaname(CPseudoFileInfo& Info, LPCSTR Path)
  411. {
  412. int chcnt = 0;
  413. if (f_inode)
  414. chcnt += printf("%*lu ", s_inode, Info.GetInode());
  415. if (f_size)
  416. chcnt += printf("%*I64d ", s_size, Info.GetFileLength());
  417. if (f_dirname && Path && *Path)
  418. {
  419. int ofs = 0;
  420. if ((Path[0] == '.') && (Path[1] == '/'))
  421. ofs = 2;
  422. if (Path[ofs])
  423. chcnt += printf("%s/", Path + ofs);
  424. }
  425. chcnt += printf("%s", Info.FileName());
  426. if (f_type)
  427. chcnt += printtype(Info);
  428. if (f_comment)
  429. chcnt += printcomment(Info);
  430. return (chcnt);
  431. }
  432. int CVfSysLs::printcomment(CPseudoFileInfo& Info)
  433. {
  434. int chcnt = 0;
  435. if (f_printdlc)
  436. chcnt += printf(" %u", Info.GetDLC());
  437. chcnt += printf(" %s", Info.GetComment());
  438. return chcnt;
  439. }
  440. int CVfSysLs::printtype(CPseudoFileInfo& Info)
  441. {
  442. if (Info.IsDirectory())
  443. {
  444. putchar('/');
  445. return 1;
  446. }
  447. //case S_IFIFO:
  448. // (void)putchar('|');
  449. // return (1);
  450. if (Info.IsLink())
  451. {
  452. putchar('@');
  453. return 1;
  454. }
  455. //case S_IFSOCK:
  456. // (void)putchar('=');
  457. // return (1);
  458. //}
  459. /*
  460. if (IS_EXEC(Info))
  461. {
  462. putchar('*');
  463. return 1;
  464. }
  465. */
  466. return 0;
  467. }
  468. void CVfSysLs::printlong(CFileList& FileList, LPCSTR Path)
  469. {
  470. char buf[20];
  471. CPseudoFileInfo Info;
  472. CLinkedListItem *Item;
  473. CString cBuf, cBuf2;
  474. if (m_Virgin && (f_longform || f_size))
  475. {
  476. printf("total %I64d%s", btotal, m_CRLF);
  477. m_Virgin = FALSE;
  478. }
  479. for(Item = FileList.First(); Item; Item = FileList.Next(Item))
  480. {
  481. Info = (FILE_NODE *)FileList.Ptr(Item);
  482. if (Info.Hide(-1))
  483. continue;
  484. if (f_inode)
  485. printf("%*lu ", s_inode, Info.GetInode());
  486. if (f_size)
  487. printf("%*I64d ", s_size, Info.GetFileBlocks());
  488. strmode(Info, buf);
  489. printf("%s %*u %-*s  %-*s  ", buf, s_nlink,
  490.     Info.GetLinks(), s_user, Info.GetUserName(cBuf), s_group,
  491.     Info.GetGroupName(cBuf2));
  492. printf("%*I64d ", s_size, Info.GetFileLength());
  493. if (f_accesstime)
  494. printtime(Info.GetAccessTime());
  495. else if (f_statustime)
  496. printtime(Info.GetLastModeTime());
  497. else
  498. printtime(Info.GetModifyTime());
  499. printf("%s", Info.FileName());
  500. if (f_comment)
  501. printcomment(Info);
  502. if (f_type)
  503. printtype(Info);
  504. //if (S_ISLNK(sp->st_mode))
  505. // printlink(p);
  506. putchar('n');
  507. }
  508. }
  509. static const char *Months[] = {{"Jan"}, {"Feb"}, {"Mar"}, {"Apr"}, {"May"}, {"Jun"}, 
  510. {"Jul"}, {"Aug"}, {"Sep"}, {"Oct"}, {"Nov"}, {"Dec"}};
  511. void CVfSysLs::printtime(LPFILETIME ftime)
  512. {
  513. ASSERT(AfxIsValidAddress(ftime,sizeof(FILETIME)));
  514. FILETIME lt;
  515. SYSTEMTIME st, tn;
  516. FileTimeToLocalFileTime(ftime,&lt);
  517. FileTimeToSystemTime(&lt,&st);
  518. GetSystemTime(&tn);
  519. if ((st.wMonth <= 0) || (st.wMonth > 12))
  520. st.wMonth = 1;
  521. if ((st.wDay < 0) || (st.wDay >= 32))
  522. st.wDay = 1;
  523. printf("%s %2d ", SafeStringIndex(Months,st.wMonth -1, 12), st.wDay);
  524. if (st.wYear && (tn.wYear == st.wYear))
  525. printf("%02d:%02d ", st.wHour, st.wMinute);
  526. else
  527. printf(" %04d ", (st.wYear > 1970) ? st.wYear : 1990);
  528. }
  529. #ifdef TAB
  530. #undef TAB
  531. #endif
  532. #define TAB 8
  533. void CVfSysLs::printcol(CFileList& FileList, LPCSTR Path)
  534. {
  535. int base, chcnt, cnt, col, colwidth, num;
  536. int endcol, numcols, numrows, row;
  537. CPseudoFileInfo Info;
  538. CLinkedListItem *Item;
  539. /*
  540.  * Have to do random access in the linked list -- build a table
  541.  * of pointers.
  542.  */
  543. if (entries > lastentries) 
  544. {
  545. lastentries = entries;
  546. if (array)
  547. {
  548. if ((array = (FILE_NODE **)realloc(array, entries * sizeof(CFileInfo *))) == NULL) 
  549. {
  550. printscol(FileList, Path);
  551. return;
  552. }
  553. }
  554. else
  555. {
  556. if ((array = (FILE_NODE **)malloc(entries * sizeof(CFileInfo *))) == NULL)
  557. {
  558. printscol(FileList, Path);
  559. return;
  560. }
  561. }
  562. }
  563. for(Item = FileList.First(), num = 0; Item; Item = FileList.Next(Item))
  564. {
  565. Info = (FILE_NODE *)FileList.Ptr(Item);
  566. if (!Info.Hide(-1))
  567. array[num++] = Info;
  568. }
  569. colwidth = maxlen;
  570. if (f_inode)
  571. colwidth += s_inode + 1;
  572. if (f_size)
  573. colwidth += s_block + 1;
  574. if (f_type)
  575. colwidth += 1;
  576. colwidth = (colwidth + TAB) & ~(TAB - 1);
  577. if (termwidth < 2 * colwidth) 
  578. {
  579. printscol(FileList, Path);
  580. return;
  581. }
  582. numcols = termwidth / colwidth;
  583. numrows = num / numcols;
  584. if (num % numcols)
  585. ++numrows;
  586. if (m_Virgin && (f_longform || f_size))
  587. {
  588. printf("total %I64d%s", btotal, m_CRLF);
  589. m_Virgin = FALSE;
  590. }
  591. for (row = 0; row < numrows; ++row) 
  592. {
  593. endcol = colwidth;
  594. for (base = row, chcnt = col = 0; col < numcols; ++col) 
  595. {
  596. Info = array[base];
  597. chcnt += printaname(Info, Path);
  598. if ((base += numrows) >= num)
  599. break;
  600. while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol)
  601. {
  602. putchar('t');
  603. chcnt = cnt;
  604. }
  605. endcol += colwidth;
  606. }
  607. putchar('n');
  608. }
  609. }
  610. void CVfSysLs::usage()
  611. {
  612. fprintf(m_stdio, "usage: ls [-1ACFLRTacdfiklqrstu] [file ...]n");
  613. return;
  614. }
  615. int CVfSysLs::namecmp(const CLinkedListItem **a, const CLinkedListItem **b)
  616. {
  617. //CFileInfo *Infoa = ((CFileInfo *)(a[0]->m_Ptr));
  618. //CFileInfo *Infob = ((CFileInfo *)(b[0]->m_Ptr));
  619. return strcmp(((LPCFILE_NODE)(a[0]->m_Ptr))->Name,((LPCFILE_NODE )(b[0]->m_Ptr))->Name);
  620. }
  621. int CVfSysLs::revnamecmp(const CLinkedListItem **a, const CLinkedListItem **b)
  622. {
  623. return strcmp(((LPCFILE_NODE )(b[0]->m_Ptr))->Name,((LPCFILE_NODE)(a[0]->m_Ptr))->Name);
  624. }
  625. int CVfSysLs::modcmp(const CLinkedListItem **a, const CLinkedListItem **b)
  626. {
  627. return CompareFileTime(((CFileInfo *)(a[0]->m_Ptr))->GetModifyTime(),((CFileInfo *)(b[0]->m_Ptr))->GetModifyTime());
  628. }
  629. int CVfSysLs::revmodcmp(const CLinkedListItem **a, const CLinkedListItem **b)
  630. {
  631. return CompareFileTime(((CFileInfo *)(b[0]->m_Ptr))->GetModifyTime(),((CFileInfo *)(a[0]->m_Ptr))->GetModifyTime());
  632. }
  633. int CVfSysLs::acccmp(const CLinkedListItem **a, const CLinkedListItem **b)
  634. {
  635. return CompareFileTime(((CFileInfo *)(a[0]->m_Ptr))->GetAccessTime(),((CFileInfo *)(b[0]->m_Ptr))->GetAccessTime());
  636. }
  637. int CVfSysLs::revacccmp(const CLinkedListItem **a, const CLinkedListItem **b)
  638. {
  639. return CompareFileTime(((CFileInfo *)(b[0]->m_Ptr))->GetAccessTime(),((CFileInfo *)(a[0]->m_Ptr))->GetAccessTime());
  640. }
  641. int CVfSysLs::statcmp(const CLinkedListItem **a, const CLinkedListItem **b)
  642. {
  643. return CompareFileTime(((CFileInfo *)(a[0]->m_Ptr))->GetLastModeTime(),((CFileInfo *)(b[0]->m_Ptr))->GetLastModeTime());
  644. }
  645. int CVfSysLs::revstatcmp(const CLinkedListItem **a, const CLinkedListItem **b)
  646. {
  647. return CompareFileTime(((CFileInfo *)(b[0]->m_Ptr))->GetLastModeTime(),((CFileInfo *)(a[0]->m_Ptr))->GetLastModeTime());
  648. }