home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / CMDS / mtools_3.6.src.lzh / MTOOLS_3.6 / mdir.c < prev    next >
Text File  |  1997-11-12  |  9KB  |  410 lines

  1. /*
  2.  * mdir.c:
  3.  * Display an MSDOS directory
  4.  */
  5.  
  6. #include "sysincludes.h"
  7. #include "msdos.h"
  8. #include "vfat.h"
  9. #include "mtools.h"
  10. #include "file.h"
  11. #include "mainloop.h"
  12. #include "fs.h"
  13. #include "codepage.h"
  14.  
  15. static int concise;
  16. static char newpath[MAX_PATH];
  17. static char drive;
  18.  
  19. struct recurs_ptr {
  20.     struct recurs_ptr *next;
  21.     char *value;
  22. } *recurs_ptr, **tail_ptr;
  23.  
  24.  
  25. /*
  26.  * Print an MSDOS directory date stamp.
  27.  */
  28. static inline void print_date(struct directory *dir)
  29. {
  30.     printf("%02d-%02d-%02d", DOS_MONTH(dir), DOS_DAY(dir), DOS_YEAR(dir));
  31. }
  32.  
  33. /*
  34.  * Print an MSDOS directory time stamp.
  35.  */
  36. static inline void print_time(struct directory *dir)
  37. {
  38.     char am_pm;
  39.     int hour = DOS_HOUR(dir);
  40.        
  41.     am_pm = (hour >= 12) ? 'p' : 'a';
  42.     if (hour > 12)
  43.         hour = hour - 12;
  44.     if (hour == 0)
  45.         hour = 12;
  46.  
  47.     printf("%2d:%02d%c", hour, DOS_MINUTE(dir), am_pm);
  48. }
  49.  
  50. /*
  51.  * Return a number in dotted notation
  52.  */
  53. static const char *dotted_num(unsigned long num, int width, char **buf)
  54. {
  55.     int      len;
  56.     register char *srcp, *dstp;
  57.     int size;
  58.  
  59.     size = width + width;
  60.     *buf = malloc(size+1);
  61.  
  62.     if (*buf == NULL)
  63.         return "";
  64.     
  65.     /* Create the number in maximum width; make sure that the string
  66.      * length is not exceeded (in %6ld, the result can be longer than 6!)
  67.      */
  68.     sprintf(*buf, "%.*ld", size, num);
  69.  
  70.     for (srcp=*buf; srcp[1] != '\0'; ++srcp)
  71.         if (srcp[0] == '0')
  72.             srcp[0] = ' ';
  73.         else
  74.             break;
  75.     
  76.     len = strlen(*buf);
  77.     srcp = (*buf)+len;
  78.     dstp = (*buf)+len+1;
  79.  
  80.     for ( ; dstp >= (*buf)+4 && isdigit (srcp[-1]); ) {
  81.         srcp -= 3;  /* from here we copy three digits */
  82.         dstp -= 4;  /* that's where we put these 3 digits */
  83.     }
  84.  
  85.     /* now finally copy the 3-byte blocks to their new place */
  86.     while (dstp < (*buf) + len) {
  87.         dstp[0] = srcp[0];
  88.         dstp[1] = srcp[1];
  89.         dstp[2] = srcp[2];
  90.         if (dstp + 3 < (*buf) + len)
  91.             /* use spaces instead of dots: they place both
  92.              * Americans and Europeans */
  93.             dstp[3] = ' ';        
  94.         srcp += 3;
  95.         dstp += 4;
  96.     }
  97.  
  98.     return (*buf) + len-width;
  99. }
  100.  
  101. static inline void print_volume_label(Stream_t *Dir, char drive)
  102. {
  103.     Stream_t *Stream = GetFs(Dir);
  104.     DeclareThis(FsPublic_t);
  105.     Stream_t *RootDir;
  106.     int entry;
  107.     struct directory dir;
  108.     char shortname[13];
  109.     char longname[VBUFSIZE];
  110.  
  111.     if(concise)
  112.         return;
  113.     
  114.     /* find the volume label */
  115.     RootDir = open_root(Stream);
  116.     entry = 0;
  117.     if(vfat_lookup(RootDir, &dir, &entry, 0, 0,
  118.                ACCEPT_LABEL | MATCH_ANY,
  119.                NULL, shortname, longname) )
  120.         printf(" Volume in drive %c has no label\n", drive);
  121.     else if (*longname)
  122.         printf(" Volume in drive %c is %s (abbr=%s)\n",
  123.                drive, longname, shortname);
  124.     else
  125.         printf(" Volume in drive %c is %s\n",
  126.                drive, shortname);
  127.     if(This->serialized)
  128.         printf(" Volume Serial Number is %04lX-%04lX\n",
  129.                (This->serial_number >> 16) & 0xffff, 
  130.                This->serial_number & 0xffff);
  131.     FREE(&RootDir);
  132. }
  133.  
  134.  
  135. static inline int list_directory(Stream_t *Dir, char *newname, 
  136.                  int wide, int all,
  137.                  size_t *tot_size)
  138. {
  139.     int entry;
  140.     struct directory dir;
  141.     int files;
  142.     size_t size;
  143.     char shortname[13];
  144.     char longname[VBUFSIZE];
  145.     char outname[VBUFSIZE];
  146.     int i;
  147.     int Case;
  148.  
  149.     entry = 0;
  150.     files = 0;
  151.  
  152.     if(!wide && !concise)
  153.         printf("\n");
  154.  
  155.     while(vfat_lookup(Dir, &dir, &entry, 0, newname,
  156.               ACCEPT_DIR | ACCEPT_PLAIN,
  157.               outname, shortname, longname) == 0){
  158.         if(!all && (dir.attr & 0x6))
  159.             continue;
  160.         if (wide) {
  161.             if(files % 5)
  162.                 putchar(' ');                
  163.             else
  164.                 putchar('\n');
  165.         }
  166.         files++;
  167.  
  168.         if(dir.attr & 0x10){
  169.             size = 0;
  170.         } else
  171.             size = FILE_SIZE(&dir);
  172.  
  173.         Case = dir.Case;
  174.         if(!(Case & (BASECASE | EXTCASE)) && mtools_ignore_short_case)
  175.             Case |= BASECASE | EXTCASE;
  176.  
  177.         if(Case & EXTCASE){
  178.             for(i=0; i<3;i++)
  179.                 dir.ext[i] = tolower(dir.ext[i]);
  180.         }
  181.         to_unix(dir.ext,3);
  182.         if(Case & BASECASE){
  183.             for(i=0; i<8;i++)
  184.                 dir.name[i] = tolower(dir.name[i]);
  185.         }
  186.         to_unix(dir.name,8);
  187.         if(wide){
  188.             if(dir.attr & 0x10)
  189.                 printf("[%s]%*s", shortname,
  190.                     (int) (15 - 2 - strlen(shortname)), "");
  191.             else
  192.                 printf("%-15s", shortname);
  193.         } else if(!concise) {                
  194.             /* is a subdirectory */
  195.             printf("%-8.8s %-3.3s ",dir.name, dir.ext);
  196.             if(dir.attr & 0x10)
  197.                 printf("<DIR>    ");
  198.             else
  199.                 printf(" %8ld", (long) size);
  200.             printf(" ");
  201.             print_date(&dir);
  202.             printf("  ");
  203.             print_time(&dir);
  204.  
  205.             if(*longname)
  206.                 printf(" %s", longname);
  207.             printf("\n");
  208.         } else {
  209.             if(!strcmp(outname,".") || !strcmp(outname,".."))
  210.                 continue;
  211.             if(newpath[0] && newpath[strlen(newpath)-1] == '/')
  212.                 printf("%c:%s%s", drive, newpath, outname);
  213.             else
  214.                 printf("%c:%s/%s", drive, newpath, outname);
  215.             if(dir.attr & 0x10) {
  216.                 (*tail_ptr) = New(struct recurs_ptr);
  217.                 (*tail_ptr)->next = 0;
  218.                 (*tail_ptr)->value = 
  219.                     malloc(strlen(newpath)+
  220.                            strlen(outname)+4);
  221.                 (*tail_ptr)->value[0]=drive;
  222.                 (*tail_ptr)->value[1]=':';
  223.                 strcpy((*tail_ptr)->value+2,newpath);
  224.                 strcat((*tail_ptr)->value,"/");
  225.                 strcat((*tail_ptr)->value,outname);
  226.                 tail_ptr = &(*tail_ptr)->next;
  227.                 putchar('/');
  228.             }
  229.             putchar('\n');
  230.             
  231.  
  232.         }
  233.         *tot_size += size;
  234.     }
  235.  
  236.     if(wide)
  237.         putchar('\n');
  238.     return files;
  239. }
  240.  
  241. static inline void print_footer(char *drive, char *newname, int files,
  242.              size_t tot_size, size_t blocks)
  243. {    
  244.     char *s1,*s2;
  245.  
  246.     if(concise)
  247.         return;
  248.  
  249.     if (*drive != '\0') {
  250.         if (!files)
  251.             printf("File \"%s\" not found\n"
  252.                    "                     %s bytes free\n\n",
  253.                    newname, dotted_num(blocks,13, &s1));
  254.         else {
  255.             printf("      %3d file(s)     %s bytes\n"
  256.                    "                      %s bytes free\n\n",
  257.                    files, dotted_num(tot_size,13, &s1),
  258.                    dotted_num(blocks,13, &s2));
  259.             if(s2)
  260.                 free(s2);
  261.         }
  262.         if(s1)
  263.             free(s1);
  264.     }
  265.     *drive = '\0'; /* ensure the footer is only printed once */
  266. }
  267.  
  268.  
  269. static void usage(void)
  270. {
  271.         fprintf(stderr, "Mtools version %s, dated %s\n",
  272.             mversion, mdate);
  273.         fprintf(stderr, "Usage: %s: [-V] [-w] [-a] msdosdirectory\n",
  274.             progname);
  275.         fprintf(stderr,
  276.             "       %s: [-V] [-w] [-a] msdosfile [msdosfiles...]\n",
  277.             progname);
  278.         exit(1);
  279. }
  280.  
  281. void mdir(int argc, char **argv, int type)
  282. {
  283.     const char *arg;
  284.     MainParam_t mp;
  285.     int i, files, wide, all, faked;
  286.     size_t blocks, tot_size=0;
  287.     char last_drive;
  288.     char newname[13];
  289.     Stream_t *SubDir;
  290.     Stream_t *Dir;
  291.     int c;
  292.     int fast=0;
  293.     
  294.     concise = 0;
  295.     wide = all = files = blocks = 0;
  296.                     /* first argument */
  297.     while ((c = getopt(argc, argv, "waXf")) != EOF) {
  298.         switch(c) {
  299.             case 'w':
  300.                 wide = 1;
  301.                 break;
  302.             case 'a':
  303.                 all = 1;
  304.                 break;
  305.             case 'X':
  306.                 concise = 1;
  307.                 break;
  308.             case 'f':
  309.                 fast = 1;
  310.                 break;
  311.             default:
  312.                 usage();
  313.         }
  314.     }
  315.  
  316.     /* fake an argument */
  317.     faked = 0;
  318.     if (optind == argc) {
  319.         faked++;
  320.         argc++;
  321.     }
  322.  
  323.     tail_ptr = &recurs_ptr;
  324.  
  325.     init_mp(&mp);
  326.     last_drive = '\0';
  327.     for (i = optind; i < argc || recurs_ptr ; i++) {
  328.         char *free_arg=0;
  329.         if(i>=argc) {
  330.             struct recurs_ptr *old;
  331.             old = recurs_ptr;
  332.             free_arg = recurs_ptr->value;
  333.             arg = free_arg;
  334.             recurs_ptr = recurs_ptr->next;
  335.             if(!recurs_ptr)
  336.                 tail_ptr = &recurs_ptr;
  337.             free(old);
  338.         } else if (faked)
  339.             arg="";
  340.         else 
  341.             arg = argv[i];
  342.         Dir = open_subdir(&mp, arg, O_RDONLY, 0, 0);
  343.         if(!Dir)
  344.             continue;
  345.         drive = mp.drivename;
  346.         /* is this a new device? */
  347.         if (drive != last_drive) {
  348.             print_footer(&last_drive, newname, files, tot_size,
  349.                      blocks);
  350.             if(fast)
  351.                 blocks = 0;
  352.             else
  353.                 blocks = getfree(Dir);
  354.             files = 0;
  355.             tot_size = 0;
  356.             print_volume_label(Dir, drive);
  357.         }
  358.         last_drive = drive;
  359.  
  360.         /*
  361.          * Under MSDOS, wildcards that match directories don't
  362.          * display the contents of that directory.  So I guess I'll
  363.          * do that too.
  364.          */
  365.         get_path(arg,newpath,mp.mcwd,  0);
  366.         if (strpbrk(mp.filename, "*[?") == NULL &&
  367.             ((SubDir = descend(Dir, mp.filename, 0, 0, 0) )) ) {
  368.             static char tmppath[MAX_PATH+5];
  369.  
  370.             /* Subdirectory */
  371.             FREE(&Dir);
  372.             Dir = SubDir;
  373. #if 0
  374.             if(*mp.filename){
  375.                 if (newpath[strlen(newpath) -1 ] != '/')
  376.                     strcat(newpath, "/");
  377.                 strcat(newpath, mp.filename);
  378.             }
  379. #endif
  380.             strncpy(tmppath, arg, MAX_PATH+2);
  381.             if(tmppath[0] != '\0' &&
  382.                (tmppath[1] !=':' || tmppath[2] != '\0'))
  383.                 strcat(tmppath,"/");
  384.             get_path(tmppath,newpath,mp.mcwd,  0);           
  385.             *mp.filename='\0';
  386.         }        
  387.         
  388.         if(concise && i<argc){
  389.             printf("%c:%s",drive,newpath);
  390.             if(newpath[0] != '/' || newpath[1])
  391.                 putchar('/');
  392.             putchar('\n');
  393.         }
  394.  
  395.         if(mp.filename[0]=='\0')
  396.             strcpy(newname, "*");
  397.         else
  398.             strcpy(newname, mp.filename);
  399.  
  400.         if(!concise)
  401.             printf(" Directory for %c:%s\n", drive, newpath);
  402.         files += list_directory(Dir, newname, wide, all, &tot_size);
  403.         FREE(&Dir);
  404.         if(i>=argc)
  405.             free(free_arg);
  406.     }
  407.     print_footer(&last_drive, newname, files, tot_size, blocks);
  408.     exit(0);
  409. }
  410.