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

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