home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol144 / ucsdir.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-04-29  |  9.5 KB  |  297 lines

  1. /*      ------------------------------------------------------- 
  2.         *** Template for Procedure Heading *** 
  3.  
  4.         Name: 
  5.         Result: 
  6.         Errors: 
  7.         Globals: 
  8.         Macros: 
  9.         Procedures: 
  10.  
  11.         Action: 
  12.  
  13.         ------------------------------------------------------- */ 
  14.  
  15. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  16.         ucsdir -- List the  directory of a UCSD Pascal diskette 
  17.  
  18.                 H.Moran 10/27/79 
  19.  
  20.                 column labels added 2/13/80 
  21.                 quick and dirty sort added 2/14/80 
  22.  
  23.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  24.  
  25.  
  26.  
  27.  
  28. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  29.         Constants 
  30.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  31.  
  32. #define SEL_DSK 14              /* bdos function number */ 
  33. #define SET_DMA 26              /* bdos function number */ 
  34.  
  35. #define SET_TRK 10              /* bios index number (was 9 c.u.) */ 
  36. #define SET_SEC 11              /* bios index number (was 10 c.u) */ 
  37. #define READ    13              /* bios index number (was 12 c.u) */ 
  38.  
  39. #define DUMMY   0               /* dummy parameter for bios routine */ 
  40.  
  41. #define D_ENT_SZ 26             /* UCSD directory entry size */ 
  42. #define D_TITLE 6               /* offset to entry title */ 
  43. #define UCSD_NAM_SZ 17          /* size of the name part of ucsd dir entry */ 
  44. #define UCSD_DIR_SZ 2048        /* size of UCSD directory in bytes */ 
  45.  
  46. #define SECT_SIZE 128           /* bytes per physical sector */ 
  47. #define BLOK_SIZE 512           /* bytes per UCSD logical block */ 
  48. #define SECT_PER_BLOK 4         /* physical sectors per logical block */ 
  49.  
  50.  
  51. /*      : : : : : : : : : : : : : : : : : : : : : : : : : : : : 
  52.         Globals -- these would be static if it were available 
  53.         : : : : : : : : : : : : : : : : : : : : : : : : : : : : */ 
  54.  
  55. int lsn;                /* logical sector number */ 
  56. int lstlsn;             /* last logical sector number */ 
  57. int nbytes;             /* number of bytes remaining in ucsd file buffer */ 
  58. char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd directory */ 
  59. char *ptr;              /* pointer to current byte in ucsd buffer */ 
  60.  
  61. /*     ------------------------------------------------------- 
  62.  
  63.         Name:           main(argc,argv) 
  64.         Result:         --- 
  65.         Errors:         --- 
  66.         Globals:        lsn,lstlsn,nbytes,ptr,ucsdbuf[] 
  67.         Macros:         --- 
  68.         Procedures:     printf(),exit(),ucsdir() 
  69.  
  70.         Action:         Handle invocation errors 
  71.                         Call ucsdir() to list from drive B 
  72.                         a UCSD formatted directory 
  73.  
  74.         ------------------------------------------------------- */ 
  75.  
  76.  
  77. main(argc,argv) 
  78.         int argc; 
  79.         char *argv[]; 
  80.         { 
  81.  
  82.         lsn = lstlsn = nbytes = 0;      /* init globals */ 
  83.         ptr = ucsdbuf; 
  84.  
  85.         if( argc != 1 ) { 
  86.           printf("Proper invocation form is:\n\n"); 
  87.           printf("ucsdir\n"); 
  88.           printf("Will list the directory of the UCSD disk on drive B\n"); 
  89.           exit(1); 
  90.           } 
  91.         ucsdir(); 
  92.         exit(0); 
  93.         } 
  94.  
  95.  
  96.  
  97.  
  98. /*      ------------------------------------------------------- 
  99.  
  100.         Name:           ucsdir() 
  101.         Result:         --- 
  102.         Errors:         sector read error (aborts) 
  103.         Globals:        lsn,lstlsn 
  104.         Macros:         D_TITLE,UCSD_NAM_SZ,UCSD_NAM_SZ 
  105.                         D_ENT_SZ,SECT_PER_BLOK 
  106.         Procedures:     read_ucsd(),putchar(),puts() 
  107.  
  108.         Action:         Read from the diskette on drive B 
  109.                         and print on the console 
  110.                         the directory of a presumed 
  111.                         UCSD Pascal formatted disk 
  112.  
  113.         ------------------------------------------------------- */ 
  114.  
  115.  
  116. ucsdir() 
  117.         { 
  118.         char ucsd_dir[UCSD_DIR_SZ]; 
  119.         char *dir,*saved_dir; 
  120.         int name_len,colct,entries,dunno; 
  121.         int cmpare(),i; 
  122.  
  123.         read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4); /* get entire directory */ 
  124.  
  125.         dir = &ucsd_dir[D_TITLE];               /* print volume label */ 
  126.         puts("\nDirectory of : "); 
  127.         name_len  = *dir++; 
  128.         while ( name_len-- ) 
  129.           putchar(*dir++); 
  130.         puts("\n\n"); 
  131.  
  132.         dir = &ucsd_dir[(D_TITLE + D_ENT_SZ)];  /* point to 1'st entry */ 
  133.         i = 0; 
  134.         while( *(dir+i) != 0 && (dir+i) < &ucsd_dir[UCSD_DIR_SZ] ) 
  135.          i += D_ENT_SZ; 
  136.         qsort((dir-D_TITLE),(i)/D_ENT_SZ,D_ENT_SZ,&cmpare); 
  137.         entries = 0; 
  138.         puts("\nFilename         locn len  type"); 
  139.         puts("  Filename         locn len  type"); 
  140.         puts("\n---------------- ---- ---- ----"); 
  141.         puts("  ---------------- ---- ---- ----\n"); 
  142.         while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) {/* print directory entries */ 
  143.           saved_dir = dir; 
  144.           colct = 1; 
  145.           name_len = *dir++; 
  146.           if( name_len <= 0 || name_len > (UCSD_NAM_SZ-1) ) 
  147.             break; 
  148.           while( name_len-- ) {         /* print the file name */ 
  149.             putchar(*dir++); 
  150.             colct++; 
  151.             } 
  152.           while( colct++ <UCSD_NAM_SZ ) /* print spaces to max name length */ 
  153.             putchar(' '); 
  154.  
  155.           dir = saved_dir - D_TITLE;    /* point to begin of entry */ 
  156.                                         /* i.e. block alloc. indicators */ 
  157.  
  158.           lsn = *dir++ + ( *dir++ << 8);/* lsn = starting logical block # */ 
  159.           lstlsn= *dir++ +(*dir++ << 8);/* lstlsn = ending logical block # */ 
  160.           dunno = *dir++ + (*dir++ <<8);/* file type */ 
  161.  
  162.  
  163.           printf(" %4d %4d %4d",lsn,lstlsn-lsn,dunno); 
  164.           dir = saved_dir + D_ENT_SZ;   /* dir = pointer to next entry */ 
  165.           entries & 1 ? puts("\n") : puts("  "); 
  166.           entries++; 
  167.           } 
  168.         return; 
  169.         } 
  170.  
  171. /*     ------------------------------------------------------- 
  172.  
  173.         Name:           read_ucsd(buf,rn,count) 
  174.         Result:         result of selecting drive A 
  175.         Errors:         sector read error (exit to CP/M) 
  176.         Globals:        --- 
  177.         Macros:         SEL_DSK,SET_DMA,SET_TRK,SET_SEC 
  178.                         READ,DUMMY,SECT_SIZE,SEL_DSK 
  179.  
  180.         Procedures:     bdos(),bios(),printf(),exit() 
  181.                         track(),sector() 
  182.  
  183.         Action:         Read count UCSD sized blocks from drive B 
  184.                         into buf[] starting at logical record number 
  185.                         rn using the UCSD Pascal logical record 
  186.                         number to physical sector mapping 
  187.  
  188.         ------------------------------------------------------- */ 
  189.  
  190.  
  191. read_ucsd(buf,rn,count) 
  192.         char *buf; 
  193.         int rn; 
  194.         int count; 
  195.         { 
  196.     char bios();
  197.         int seccnt; seccnt = count*4; 
  198.  
  199.         bdos(SEL_DSK,1); 
  200.         while( seccnt-- ) { 
  201.           bdos(SET_DMA,buf); 
  202.           bios(SET_TRK,track(rn)); 
  203.           bios(SET_SEC,sector(rn)); 
  204.           if( bios(READ,DUMMY) ) { 
  205.            printf("read error @ track %2d sector %2d\n",track(rn),sector(rn)); 
  206.           /*  exit(1); */ 
  207.             } 
  208.           buf += SECT_SIZE; 
  209.           rn++; 
  210.           } 
  211.         return bdos(SEL_DSK,0); 
  212.         } 
  213.  
  214. /*     ------------------------------------------------------- 
  215.  
  216.         Name:           sector(rn) 
  217.         Result:         physical sector number 
  218.         Errors:         --- 
  219.         Globals:        --- 
  220.         Macros:         --- 
  221.         Procedures:     --- 
  222.  
  223.         Action:         This code maps logical sectors to physical 
  224.                         sectors by selecting every second sector 
  225.                         in order (accounting for the modulo 26 
  226.                         process) on the diskette except that at a 
  227.                         track switchover point there is an additional 
  228.                         'gap' of 6 sectors (total of 7) to allow 
  229.                         for the drive to seek. This is UCSD's 
  230.                         attempt to minimize disk access time. 
  231.  
  232.         ------------------------------------------------------- */ 
  233.  
  234.  
  235. sector(rn) 
  236.         unsigned rn; 
  237.         { 
  238.         unsigned t1,t2,trk,t3,sect; 
  239.  
  240.         t1 = rn % 26; 
  241.         t2 = t1 << 1; 
  242.         if(t1 > 12) 
  243.           t2++; 
  244.         trk = rn/26;            /* zero based absolute track */ 
  245.         t3 = t2 + 6*trk;        /* new logical sector number */ 
  246.         sect = t3 % 26;         /* new zero based absolute sector */ 
  247.         return ++sect;          /* one based absolute sector */ 
  248.         } 
  249.  
  250. /*      ------------------------------------------------------- 
  251.  
  252.         Name:           track(rn) 
  253.         Result:         physical track number 
  254.         Errors:         --- 
  255.         Globals:        --- 
  256.         Macros:         --- 
  257.         Procedures:     --- 
  258.  
  259.         Action:         convert logical sector number to 
  260.                         absolute track number. This is simply 
  261.                         the modulo 26 process except that 
  262.                         track 0 is not considered part of the 
  263.                         logical sector space. 
  264.  
  265.         ------------------------------------------------------- */ 
  266.  
  267.  
  268. track(rn) 
  269.         unsigned rn; 
  270.         { 
  271.         return rn/26 + 1; 
  272.         } 
  273.  
  274.  
  275. /* tacked on compare of filenames */ 
  276.  
  277.  
  278. cmpare(x,y) 
  279.         char *x,*y; 
  280.         { 
  281.         int i,j,k; 
  282.  
  283.         x += D_TITLE; 
  284.         y += D_TITLE; 
  285.         for( i = *x++, j = *y++; j & i; i--, j--, x++, y++ ) { 
  286.           if( *x > *y ) 
  287.             return -1; 
  288.           if( *x < *y ) 
  289.             return 1; 
  290.           } 
  291.         if( i && ! j ) 
  292.           return 1; 
  293.         if( j && ! i ) 
  294.           return -1; 
  295.         return 0; 
  296.         } 
  297.