fat_open.c
上传用户:yj_qqy
上传日期:2017-01-28
资源大小:2911k
文件大小:35k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. **********************************************************************
  3. *                          Micrium, Inc.
  4. *                      949 Crestview Circle
  5. *                     Weston,  FL 33327-1848
  6. *
  7. *                            uC/FS
  8. *
  9. *             (c) Copyright 2001 - 2003, Micrium, Inc.
  10. *                      All rights reserved.
  11. *
  12. ***********************************************************************
  13. ----------------------------------------------------------------------
  14. File        : fat_open.c
  15. Purpose     : FAT routines for open/delete files
  16. ----------------------------------------------------------------------
  17. Known problems or limitations with current version
  18. ----------------------------------------------------------------------
  19. None.
  20. ---------------------------END-OF-HEADER------------------------------
  21. */
  22. /*********************************************************************
  23. *
  24. *             #include Section
  25. *
  26. **********************************************************************
  27. */
  28. #include "fs_conf.h"
  29. #include "fs_port.h"
  30. #ifndef FS_FARCHARPTR
  31. #define FS_FARCHARPTR char *
  32. #endif
  33. #include "fs_dev.h"
  34. #include "fs_api.h"
  35. #include "fs_fsl.h"
  36. #include "fs_int.h"
  37. #include "fs_os.h"
  38. #include "fs_lbl.h"
  39. #include "fs_fat.h"
  40. #include "fs_clib.h"
  41. /*********************************************************************
  42. *
  43. *             #define constants
  44. *
  45. **********************************************************************
  46. */
  47. #ifndef FS_FAT_NOFAT32
  48.   #define FS_FAT_NOFAT32        0
  49. #endif /* FS_FAT_NOFAT32 */
  50. /*********************************************************************
  51. *
  52. *             Local functions
  53. *
  54. **********************************************************************
  55. */
  56. /*********************************************************************
  57. *
  58. *             _FS_fat_find_file
  59. *
  60.   Description:
  61.   FS internal function. Find the file with name pFileName in directory
  62.   DirStart. Copy its directory entry to pDirEntry.
  63.   
  64.   Parameters:
  65.   Idx         - Index of device in the device information table 
  66.                 referred by FS__pDevInfo.
  67.   Unit        - Unit number.
  68.   pFileName   - File name. 
  69.   pDirEntry   - Pointer to an FS__fat_dentry_type data structure.
  70.   DirStart    - 1st cluster of the directory.
  71.   DirSize     - Sector (not cluster) size of the directory.
  72.  
  73.   Return value:
  74.   >=0         - File found. Value is the first cluster of the file.
  75.   <0          - An error has occured.
  76. */
  77. static FS_i32 _FS_fat_find_file(int Idx, FS_u32 Unit, const char *pFileName,
  78.                                     FS__fat_dentry_type *pDirEntry,
  79.                                     FS_u32 DirStart, FS_u32 DirSize) {
  80.   FS__fat_dentry_type *s;
  81.   FS_u32 i;
  82.   FS_u32 dsec;
  83.   int len;
  84.   int err; 
  85.   int c;
  86.   char *buffer;
  87.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  88.   if (!buffer) {
  89.     return -1;
  90.   }
  91.   len = FS__CLIB_strlen(pFileName);
  92.   if (len > 11) {
  93.     len = 11;
  94.   }
  95.   /* Read directory */
  96.   for (i = 0; i < DirSize; i++) {
  97.     dsec = FS__fat_dir_realsec(Idx, Unit, DirStart, i);
  98.     if (dsec == 0) {
  99.       FS__fat_free(buffer);
  100.       return -1;
  101.     }
  102.     err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  103.     if (err < 0) {
  104.       FS__fat_free(buffer);
  105.       return -1;
  106.     }
  107.     s = (FS__fat_dentry_type*)buffer;
  108.     while (1) {
  109.       if (s >= (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  110.         break;  /* End of sector reached */
  111.       }
  112.       c = FS__CLIB_strncmp((char*)s->data, pFileName, len);
  113.       if (c == 0) {  /* Name does match */
  114.         if (s->data[11] & FS_FAT_ATTR_ARCHIVE) {
  115.           break;  /* Entry found */
  116.         }
  117.       }
  118.       s++;
  119.     }
  120.     if (s < (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  121.       /* Entry found. Return number of 1st block of the file */
  122.       if (pDirEntry) {
  123.         FS__CLIB_memcpy(pDirEntry, s, sizeof(FS__fat_dentry_type));
  124.       }
  125.       FS__fat_free(buffer);
  126.       dsec  = (FS_u32)s->data[26];
  127.       dsec += (FS_u32)s->data[27] * 0x100UL;
  128.       dsec += (FS_u32)s->data[20] * 0x10000UL;
  129.       dsec += (FS_u32)s->data[21] * 0x1000000UL;
  130.       return ((FS_i32)dsec);
  131.     }
  132.   }
  133.   FS__fat_free(buffer);
  134.   return -1;
  135. }
  136. /*********************************************************************
  137. *
  138. *             _FS_fat_IncDir
  139. *
  140.   Description:
  141.   FS internal function. Increase directory starting at DirStart.
  142.   
  143.   Parameters:
  144.   Idx         - Index of device in the device information table 
  145.                 referred by FS__pDevInfo.
  146.   Unit        - Unit number.
  147.   DirStart    - 1st cluster of the directory.
  148.   pDirSize    - Pointer to an FS_u32, which is used to return the new 
  149.                 sector (not cluster) size of the directory.
  150.  
  151.   Return value:
  152.   ==1         - Success.
  153.   ==-1        - An error has occured.
  154. */
  155. static int _FS_fat_IncDir(int Idx, FS_u32 Unit, FS_u32 DirStart, FS_u32 *pDirSize) {
  156.   FS_u32 i;
  157.   FS_u32 dsec;
  158.   FS_i32 last;
  159.   char *buffer;
  160.   int err;
  161.   if (DirStart == 0) { 
  162.     /* Increase root directory only, if not FAT12/16  */
  163.     i = FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt;
  164.     if (i != 0) {
  165.       return -1;  /* Not FAT32 */
  166.     }
  167.   }
  168.   last = FS__fat_FAT_find_eof(Idx, Unit, DirStart, 0);
  169.   if (last < 0) {
  170.     return -1;  /* No EOF marker found */
  171.   }
  172.   last = FS__fat_FAT_alloc(Idx, Unit, last);  /* Allocate new cluster */
  173.   if (last < 0) {
  174.     return -1;
  175.   }
  176.   *pDirSize = *pDirSize + FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  177.   /* Clean new directory cluster */
  178.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  179.   if (!buffer) {
  180.     return -1;
  181.   }
  182.   FS__CLIB_memset(buffer, 0x00, (FS_size_t)FS_FAT_SEC_SIZE);
  183.   for (i = *pDirSize - FS__FAT_aBPBUnit[Idx][Unit].SecPerClus; i < *pDirSize; i++) {
  184.     dsec = FS__fat_dir_realsec(Idx, Unit, DirStart, i);
  185.     if (dsec == 0) {
  186.       FS__fat_free(buffer);
  187.       return -1;
  188.     }
  189.     err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  190.     if (err < 0) {
  191.       FS__fat_free(buffer);
  192.       return -1;
  193.     }
  194.   }
  195.   FS__fat_free(buffer);
  196.   return 1;
  197. }
  198. /*********************************************************************
  199. *
  200. *             _FS_fat_create_file
  201. *
  202.   Description:
  203.   FS internal function. Create a file in the directory specified
  204.   with DirStart. Do not call, if you have not checked before for 
  205.   existing file with name pFileName.
  206.   Parameters:
  207.   Idx         - Index of device in the device information table 
  208.                 referred by FS__pDevInfo.
  209.   Unit        - Unit number, which is passed to the device driver.
  210.   pFileName   - File name. 
  211.   DirStart    - Start of directory, where to create pDirName.
  212.   DirSize     - Sector size of the directory starting at DirStart.
  213.   
  214.   Return value:
  215.   >=0         - 1st cluster of the new file.
  216.   ==-1        - An error has occured.
  217.   ==-2        - Cannot create, because directory is full.
  218. */
  219. static FS_i32 _FS_fat_create_file(int Idx, FS_u32 Unit,  const char *pFileName,
  220.                                     FS_u32 DirStart, FS_u32 DirSize) {
  221.   FS__fat_dentry_type *s;
  222.   FS_u32 i;
  223.   FS_u32 dsec;
  224.   FS_i32 cluster;
  225.   int len;
  226.   int err;
  227.   FS_u16 val;
  228.   char *buffer;
  229.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  230.   if (!buffer) {
  231.     return -1;
  232.   }
  233.   len = FS__CLIB_strlen(pFileName);
  234.   if (len > 11) {
  235.     len = 11;
  236.   }
  237.   /* Read directory */
  238.   for (i = 0; i < DirSize; i++) {
  239.     dsec = FS__fat_dir_realsec(Idx, Unit, DirStart, i);
  240.     if (dsec == 0) {
  241.       FS__fat_free(buffer);
  242.       return -1;
  243.     }
  244.     err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  245.     if (err < 0) {
  246.       FS__fat_free(buffer);
  247.       return -1;
  248.     }
  249.     s = (FS__fat_dentry_type*)buffer;
  250.     while (1) {
  251.       if (s >= (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  252.         break;  /* End of sector reached */
  253.       }
  254.       if (s->data[0] == 0x00) {
  255.         break;  /* Empty entry found */
  256.       }
  257.       if (s->data[0] == (unsigned char)0xe5) {
  258.         break;  /* Deleted entry found */
  259.       }
  260.       s++;
  261.     }
  262.     if (s < (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  263.       /* Free entry found. Make entry and return 1st block of the file */
  264.       FS__CLIB_strncpy((char*)s->data, pFileName, len);
  265.       s->data[11] = FS_FAT_ATTR_ARCHIVE;
  266.       /* Alloc block in FAT */
  267.       cluster = FS__fat_FAT_alloc(Idx, Unit, -1);
  268.       if (cluster >= 0) {
  269.         s->data[12]     = 0x00;                           /* Res */
  270.         s->data[13]     = 0x00;                           /* CrtTimeTenth (optional, not supported) */
  271.         s->data[14]     = 0x00;                           /* CrtTime (optional, not supported) */
  272.         s->data[15]     = 0x00;
  273.         s->data[16]     = 0x00;                           /* CrtDate (optional, not supported) */
  274.         s->data[17]     = 0x00;
  275.         s->data[18]     = 0x00;                           /* LstAccDate (optional, not supported) */
  276.         s->data[19]     = 0x00;
  277.         val             = FS_X_OS_GetTime();
  278.         s->data[22]     = (unsigned char)(val & 0xff);   /* WrtTime */
  279.         s->data[23]     = (unsigned char)(val / 256);
  280.         val             = FS_X_OS_GetDate();
  281.         s->data[24]     = (unsigned char)(val & 0xff);   /* WrtDate */
  282.         s->data[25]     = (unsigned char)(val / 256);
  283.         s->data[26]     = (unsigned char)(cluster & 0xff);    /* FstClusLo / FstClusHi */ 
  284.         s->data[27]     = (unsigned char)((cluster / 256) & 0xff);
  285.         s->data[20]     = (unsigned char)((cluster / 0x10000L) & 0xff);
  286.         s->data[21]     = (unsigned char)((cluster / 0x1000000L) & 0xff);
  287.         s->data[28]     = 0x00;                           /* FileSize */
  288.         s->data[29]     = 0x00;
  289.         s->data[30]     = 0x00;
  290.         s->data[31]     = 0x00;
  291.         err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  292.         if (err < 0) {
  293.           FS__fat_free(buffer);
  294.           return -1;
  295.         }
  296.       }
  297.       FS__fat_free(buffer);
  298.       return cluster;
  299.     }
  300.   }
  301.   FS__fat_free(buffer);
  302.   return -2;      /* Directory is full */
  303. }
  304. /*********************************************************************
  305. *
  306. *             Global functions section 1
  307. *
  308. **********************************************************************
  309.   Functions in this section are global, but are used inside the FAT
  310.   File System Layer only.
  311.   
  312. */
  313. /*********************************************************************
  314. *
  315. *             FS__fat_DeleteFileOrDir
  316. *
  317.   Description:
  318.   FS internal function. Delete a file or directory.
  319.   
  320.   Parameters:
  321.   Idx         - Index of device in the device information table 
  322.                 referred by FS__pDevInfo.
  323.   Unit        - Unit number, which is passed to the device driver.
  324.   pName       - File or directory name. 
  325.   DirStart    - Start of directory, where to create pDirName.
  326.   DirSize     - Sector size of the directory starting at DirStart.
  327.   RmFile      - 1 => remove a file
  328.                 0 => remove a directory
  329.   
  330.   Return value:
  331.   >=0         - Success. 
  332.   <0          - An error has occured.
  333. */
  334. FS_i32 FS__fat_DeleteFileOrDir(int Idx, FS_u32 Unit,  const char *pName,
  335.                                     FS_u32 DirStart, FS_u32 DirSize, char RmFile) {
  336.   FS__fat_dentry_type *s;
  337.   FS_u32 dsec;
  338.   FS_u32 i;
  339.   FS_u32 value;
  340.   FS_u32 fatsize;
  341.   FS_u32 filesize;
  342.   FS_i32 len;
  343.   FS_i32 bytespersec;
  344.   FS_i32 fatindex;
  345.   FS_i32 fatsec;
  346.   FS_i32 fatoffs;
  347.   FS_i32 lastsec;
  348.   FS_i32 curclst = 0;
  349.   FS_i32 todo;
  350.   char *buffer;
  351.   int fattype;
  352.   int err;
  353.   int err2;
  354.   int lexp;
  355.   int x;
  356.   unsigned char a;
  357.   unsigned char b;
  358. #if (FS_FAT_NOFAT32==0)
  359.   unsigned char c;
  360.   unsigned char d;
  361. #endif /* FS_FAT_NOFAT32==0 */
  362.   buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  363.   if (!buffer) {
  364.     return 0;
  365.   }
  366.   fattype = FS__fat_which_type(Idx, Unit);
  367. #if (FS_FAT_NOFAT32!=0)
  368.   if (fattype == 2) {
  369.     FS__fat_free(buffer);
  370.     return -1;
  371.   }
  372. #endif  /* FS_FAT_NOFAT32!=0 */
  373.   fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  374.   if (fatsize == 0) {
  375.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  376.   }
  377.   bytespersec = (FS_i32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec;
  378.   len = FS__CLIB_strlen(pName);
  379.   if (len > 11) {
  380.     len = 11;
  381.   }
  382.   /* Read directory */
  383.   for (i = 0; i < DirSize; i++) {
  384.     curclst = -1;
  385.     dsec = FS__fat_dir_realsec(Idx, Unit, DirStart, i);
  386.     if (dsec == 0) {
  387.       FS__fat_free(buffer);
  388.       return -1;
  389.     }
  390.     err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  391.     if (err < 0) {
  392.       FS__fat_free(buffer);
  393.       return -1;
  394.     }
  395.     /* Scan for pName in the directory sector */
  396.     s = (FS__fat_dentry_type*) buffer;
  397.     while (1) {
  398.       if (s >= (FS__fat_dentry_type*)(buffer + bytespersec)) {
  399.         break;  /* End of sector reached */
  400.       }
  401.       x = FS__CLIB_strncmp((char*)s->data, pName, len);
  402.       if (x == 0) { /* Name does match */
  403.         if (s->data[11] != 0) {
  404.           break;  /* Entry found */
  405.         }
  406.       }
  407.       s++;
  408.     }
  409.     if (s < (FS__fat_dentry_type*)(buffer + bytespersec)) {
  410.       /* Entry has been found, delete directory entry */
  411.       s->data[0]  = 0xe5;
  412.       s->data[11] = 0;
  413.       err = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  414.       if (err < 0) {
  415.         FS__fat_free(buffer);
  416.         return -1;
  417.       }
  418.       /* Free blocks in FAT */
  419.       /*
  420.          For normal files, there are no more clusters freed than the entrie's filesize
  421.          does indicate. That avoids corruption of the complete media in case there is
  422.          no EOF mark found for the file (FAT is corrupt!!!). 
  423.          If the function should remove a directory, filesize if always 0 and cannot
  424.          be used for that purpose. To avoid running into endless loop, todo is set
  425.          to 0x0ffffff8L, which is the maximum number of clusters for FAT32.
  426.       */
  427.       if (RmFile) {
  428.         filesize  = s->data[28] + 0x100UL * s->data[29] + 0x10000UL * s->data[30] + 0x1000000UL * s->data[31];
  429.         todo      = filesize / (FS__FAT_aBPBUnit[Idx][Unit].SecPerClus * bytespersec);
  430.         value     = filesize % (FS__FAT_aBPBUnit[Idx][Unit].SecPerClus * bytespersec);
  431.         if (value != 0) {
  432.           todo++;
  433.         }
  434.       } 
  435.       else {
  436.         todo = (FS_i32)0x0ffffff8L;
  437.       }
  438.       curclst = s->data[26] + 0x100L * s->data[27] + 0x10000L * s->data[20] + 0x1000000L * s->data[21];
  439.       lastsec = -1;
  440.       /* Free cluster loop */
  441.       while (todo) {
  442.         if (fattype == 1) {
  443.           fatindex = curclst + (curclst / 2);    /* FAT12 */
  444.         }
  445. #if (FS_FAT_NOFAT32==0)
  446.         else if (fattype == 2) {
  447.           fatindex = curclst * 4;               /* FAT32 */
  448.         }
  449. #endif  /* FS_FAT_NOFAT32==0 */
  450.         else {
  451.           fatindex = curclst * 2;               /* FAT16 */
  452.         }
  453.         fatsec = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + (fatindex / bytespersec);
  454.         fatoffs = fatindex % bytespersec;
  455.         if (fatsec != lastsec) {
  456.           err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  457.           if (err < 0) {
  458.             err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  459.             if (err < 0) {
  460.               FS__fat_free(buffer);
  461.               return -1;
  462.             }
  463.             /* Try to repair original FAT sector with contents of copy */
  464.             FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  465.           }
  466.           lastsec = fatsec;
  467.         }
  468.         if (fattype == 1) {
  469.           if (fatoffs == (bytespersec - 1)) {
  470.             a = buffer[fatoffs];
  471.             if (curclst & 1) {
  472.               buffer[fatoffs] &= 0x0f;
  473.             }
  474.             else {
  475.               buffer[fatoffs]  = 0x00;
  476.             }
  477.             err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  478.             err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  479.             lexp = (err < 0);
  480.             lexp = lexp || (err2 < 0);
  481.             if (lexp) {
  482.               FS__fat_free(buffer);
  483.               return -1;
  484.             }
  485.             err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  486.             if (err < 0) {
  487.               err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
  488.               if (err < 0) {
  489.                 FS__fat_free(buffer);
  490.                 return -1;
  491.               }
  492.               /* Try to repair original FAT sector with contents of copy */
  493.               FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  494.             }
  495.             lastsec = fatsec + 1;
  496.             b = buffer[0];
  497.             if (curclst & 1) {
  498.               buffer[0]  = 0x00;;
  499.             }
  500.             else {
  501.               buffer[0] &= 0xf0;
  502.             }
  503.             err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec + 1, (void*)buffer);
  504.             err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec + 1, (void*)buffer);
  505.             lexp = (err < 0);
  506.             lexp = lexp || (err2 < 0);
  507.             if (lexp) {
  508.               FS__fat_free(buffer);
  509.               return -1;
  510.             }
  511.           }
  512.           else {
  513.             a = buffer[fatoffs];
  514.             b = buffer[fatoffs + 1];
  515.             if (curclst & 1) {
  516.               buffer[fatoffs]     &= 0x0f;
  517.               buffer[fatoffs + 1]  = 0x00;
  518.             }
  519.             else {
  520.               buffer[fatoffs]      = 0x00;
  521.               buffer[fatoffs + 1] &= 0xf0;
  522.             }
  523.             err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  524.             err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  525.             lexp = (err < 0);
  526.             lexp = lexp || (err2 < 0);
  527.             if (lexp) {
  528.               FS__fat_free(buffer);
  529.               return -1;
  530.             }
  531.           }
  532.           if (curclst & 1) {
  533.             curclst = ((a & 0xf0) >> 4) + 16 * b;
  534.           }
  535.           else {
  536.             curclst = a + 256 * (b & 0x0f);
  537.           }
  538.           curclst &= 0x0fff;
  539.           if (curclst >= 0x0ff8) {
  540.             FS__fat_free(buffer);
  541.             return 0;
  542.           }
  543.         }
  544. #if (FS_FAT_NOFAT32==0)
  545.         else if (fattype == 2) { /* FAT32 */
  546.           a = buffer[fatoffs];
  547.           b = buffer[fatoffs + 1];
  548.           c = buffer[fatoffs + 2];
  549.           d = buffer[fatoffs + 3] & 0x0f;
  550.           buffer[fatoffs]      = 0x00;
  551.           buffer[fatoffs + 1]  = 0x00;
  552.           buffer[fatoffs + 2]  = 0x00;
  553.           buffer[fatoffs + 3]  = 0x00;
  554.           err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  555.           err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  556.           lexp = (err < 0);
  557.           lexp = lexp || (err2 < 0);
  558.           if (lexp) {
  559.             FS__fat_free(buffer);
  560.             return -1;
  561.           }
  562.           curclst = a + 0x100 * b + 0x10000L * c + 0x1000000L * d;
  563.           curclst &= 0x0fffffffL;
  564.           if (curclst >= (FS_i32)0x0ffffff8L) {
  565.             FS__fat_free(buffer);
  566.             return 0;
  567.           }
  568.         }
  569. #endif /* FS_FAT_NOFAT32==0 */
  570.         else {
  571.           a = buffer[fatoffs];
  572.           b = buffer[fatoffs + 1];
  573.           buffer[fatoffs]     = 0x00;
  574.           buffer[fatoffs + 1] = 0x00;
  575.           err  = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsec, (void*)buffer);
  576.           err2 = FS__lb_write(FS__pDevInfo[Idx].devdriver, Unit, fatsize + fatsec, (void*)buffer);
  577.           lexp = (err < 0);
  578.           lexp = lexp || (err2 < 0);
  579.           if (lexp) {
  580.             FS__fat_free(buffer);
  581.             return -1;
  582.           }
  583.           curclst  = a + 256 * b;
  584.           curclst &= 0xffff;
  585.           if (curclst >= (FS_i32)0xfff8) {
  586.             FS__fat_free(buffer);
  587.             return 0;
  588.           }
  589.         }
  590.         todo--;
  591.       } /* Free cluster loop */
  592.     } /*  Delete entry */
  593.     if (curclst > 0) {
  594.       FS__fat_free(buffer);
  595.       return curclst;
  596.     }
  597.   } /* for */
  598.   FS__fat_free(buffer);
  599.   return curclst;
  600. }
  601. /*********************************************************************
  602. *
  603. *             FS__fat_make_realname
  604. *
  605.   Description:
  606.   FS internal function. Convert a given name to the format, which is
  607.   used in the FAT directory.
  608.   
  609.   Parameters:
  610.   pOrgName    - Pointer to name to be translated
  611.   pEntryName  - Pointer to a buffer for storing the real name used
  612.                 in a directory.
  613.   Return value:
  614.   None.
  615. */
  616. void FS__fat_make_realname(char *pEntryName, const char *pOrgName) {
  617.   FS_FARCHARPTR ext;
  618.   FS_FARCHARPTR s;
  619.   int i;
  620.   s = (FS_FARCHARPTR)pOrgName;
  621.   ext = (FS_FARCHARPTR) FS__CLIB_strchr(s, '.');
  622.   if (!ext) {
  623.     ext = &s[FS__CLIB_strlen(s)];
  624.   }
  625.   i=0;
  626.   while (1) {
  627.     if (s >= ext) {
  628.       break;  /* '.' reached */
  629.     }
  630.     if (i >= 8) {
  631.       break;  /* If there is no '.', this is the end of the name */
  632.     }
  633.     if (*s == (char)0xe5) {
  634.       pEntryName[i] = 0x05;
  635.     }
  636.     else {
  637.       pEntryName[i] = (char)FS__CLIB_toupper(*s);
  638.     }
  639.     i++;
  640.     s++;
  641.   }
  642.   while (i < 8) {
  643.     /* Fill name with spaces*/
  644.     pEntryName[i] = ' ';
  645.     i++;
  646.   }
  647.   if (*s == '.') {
  648.     s++;
  649.   }
  650.   while (i < 11) {
  651.     if (*s != 0) {
  652.       if (*s == (char)0xe5) {
  653.         pEntryName[i] = 0x05;
  654.       }
  655.       else {
  656.         pEntryName[i] = (char)FS__CLIB_toupper(*s);
  657.       }
  658.       s++;
  659.     }
  660.     else {
  661.       pEntryName[i] = ' ';
  662.     }
  663.     i++;
  664.   }
  665.   pEntryName[11]=0;
  666. }
  667. /*********************************************************************
  668. *
  669. *             FS__fat_find_dir
  670. *
  671.   Description:
  672.   FS internal function. Find the directory with name pDirName in directory
  673.   DirStart.
  674.   
  675.   Parameters:
  676.   Idx         - Index of device in the device information table 
  677.                 referred by FS__pDevInfo.
  678.   Unit        - Unit number.
  679.   pDirName    - Directory name; if zero, return the root directory.
  680.   DirStart    - 1st cluster of the directory.
  681.   DirSize     - Sector (not cluster) size of the directory.
  682.  
  683.   Return value:
  684.   >0          - Directory found. Value is the first cluster of the file.
  685.   ==0         - An error has occured.
  686. */
  687. FS_u32 FS__fat_find_dir(int Idx, FS_u32 Unit, char *pDirName, FS_u32 DirStart, 
  688.                         FS_u32 DirSize) {
  689.   FS__fat_dentry_type *s;
  690.   FS_u32 dstart;
  691.   FS_u32 i;
  692.   FS_u32 dsec;
  693.   FS_u32 fatsize;
  694.   int len;
  695.   int err;
  696.   int c;
  697.   char *buffer;
  698.   if (pDirName == 0) {
  699.     /* Return root directory */
  700.     if (FS__FAT_aBPBUnit[Idx][Unit].FATSz16) {
  701.       fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  702.       dstart  = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + FS__FAT_aBPBUnit[Idx][Unit].NumFATs * fatsize;
  703.     }
  704.     else {
  705.       fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  706.       dstart  = FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + FS__FAT_aBPBUnit[Idx][Unit].NumFATs * fatsize
  707.                 + (FS__FAT_aBPBUnit[Idx][Unit].RootClus - 2) * FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  708.     }
  709.   }
  710.   else {
  711.     /* Find directory */
  712.     buffer = FS__fat_malloc(FS_FAT_SEC_SIZE);
  713.     if (!buffer) {
  714.       return 0;
  715.     }
  716.     len = FS__CLIB_strlen(pDirName);
  717.     if (len > 11) {
  718.       len = 11;
  719.     }
  720.     /* Read directory */
  721.     for (i = 0; i < DirSize; i++) {
  722.       dsec = FS__fat_dir_realsec(Idx, Unit, DirStart, i);
  723.       if (dsec == 0) {
  724.         FS__fat_free(buffer);
  725.         return 0;
  726.       }
  727.       err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, dsec, (void*)buffer);
  728.       if (err < 0) {
  729.         FS__fat_free(buffer);
  730.         return 0;
  731.       }
  732.       s = (FS__fat_dentry_type*)buffer;
  733.       while (1) {
  734.         if (s >= (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  735.           break;  /* End of sector reached */
  736.         }
  737.         c = FS__CLIB_strncmp((char*)s->data, pDirName, len);
  738.         if (c == 0) { /* Name does match */
  739.           if (s->data[11] & FS_FAT_ATTR_DIRECTORY) {
  740.             break;  /* Entry found */
  741.           }
  742.         }
  743.         s++;
  744.       }
  745.       if (s < (FS__fat_dentry_type*)(buffer + FS_FAT_SEC_SIZE)) {
  746.         /* Entry found. Return number of 1st block of the directory */
  747.         FS__fat_free(buffer);
  748.         dstart  = (FS_u32)s->data[26];
  749.         dstart += (FS_u32)0x100UL * s->data[27];
  750.         dstart += (FS_u32)0x10000UL * s->data[20];
  751.         dstart += (FS_u32)0x1000000UL * s->data[21];
  752.         return dstart;
  753.       }
  754.     }
  755.     dstart = 0;
  756.     FS__fat_free(buffer);
  757.   }
  758.   return dstart;
  759. }
  760. /*********************************************************************
  761. *
  762. *             FS__fat_dir_realsec
  763. *
  764.   Description:
  765.   FS internal function. Translate a directory relative sector number
  766.   to a real sector number on the media.
  767.   
  768.   Parameters:
  769.   Idx         - Index of device in the device information table 
  770.                 referred by FS__pDevInfo.
  771.   Unit        - Unit number.
  772.   DirStart    - 1st cluster of the directory. This is zero to address 
  773.                 the root directory. 
  774.   DirSec      - Sector in the directory.
  775.  
  776.   Return value:
  777.   >0          - Directory found. Value is the sector number on the media.
  778.   ==0         - An error has occured.
  779. */
  780. FS_u32 FS__fat_dir_realsec(int Idx, FS_u32 Unit, FS_u32 DirStart, FS_u32 DirSec) {
  781.   FS_u32 rootdir;
  782.   FS_u32 rsec;
  783.   FS_u32 dclust;
  784.   FS_u32 fatsize;
  785.   int fattype;
  786.   int lexp;
  787.   unsigned char secperclus;
  788.   fattype = FS__fat_which_type(Idx, Unit);
  789.   lexp = (0 == DirStart);
  790.   lexp = lexp && (fattype != 2);
  791.   if (lexp) {
  792.     /* Sector in FAT12/FAT16 root directory */
  793.     rootdir = FS__fat_find_dir(Idx, Unit, 0, 0, 0);
  794.     rsec = rootdir + DirSec;
  795.   }
  796.   else {
  797.     fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz16;
  798.     if (fatsize == 0) {
  799.       fatsize = FS__FAT_aBPBUnit[Idx][Unit].FATSz32;
  800.     }
  801.     secperclus = FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  802.     dclust = DirSec / secperclus;
  803.     if (0 == DirStart) {
  804.       /* FAT32 root directory */
  805.       rsec = FS__FAT_aBPBUnit[Idx][Unit].RootClus;
  806.     } 
  807.     else {
  808.       rsec = FS__fat_diskclust(Idx, Unit, DirStart, dclust);
  809.       if (rsec == 0) {
  810.         return 0;
  811.       }
  812.     }
  813.     rsec -= 2;
  814.     rsec *= secperclus;
  815.     rsec += FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt + FS__FAT_aBPBUnit[Idx][Unit].NumFATs * fatsize;
  816.     rsec += ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt) * FS_FAT_DENTRY_SIZE) / FS_FAT_SEC_SIZE;
  817.     rsec += (DirSec % secperclus);
  818.   }
  819.   return rsec;
  820. }
  821. /*********************************************************************
  822. *
  823. *             FS__fat_dirsize
  824. *
  825.   Description:
  826.   FS internal function. Return the sector size of the directory 
  827.   starting at DirStart.
  828.   
  829.   Parameters:
  830.   Idx         - Index of device in the device information table 
  831.                 referred by FS__pDevInfo.
  832.   Unit        - Unit number.
  833.   DirStart    - 1st cluster of the directory. This is zero to address 
  834.                 the root directory. 
  835.  
  836.   Return value:
  837.   >0          - Sector (not cluster) size of the directory.
  838.   ==0         - An error has occured.
  839. */
  840. FS_u32 FS__fat_dir_size(int Idx, FS_u32 Unit, FS_u32 DirStart) {
  841.   FS_u32 dsize;
  842.   FS_i32 value;
  843.   if (DirStart == 0) {
  844.     /* For FAT12/FAT16 root directory, the size can be found in BPB */
  845.     dsize = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt)
  846.             * FS_FAT_DENTRY_SIZE) / ((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec);
  847.     if (dsize == 0) {
  848.       /* Size in BPB is 0, so it is a FAT32 (FAT32 does not have a real root dir) */
  849.       value = FS__fat_FAT_find_eof(Idx, Unit, FS__FAT_aBPBUnit[Idx][Unit].RootClus, &dsize);
  850.       if (value < 0) {
  851.         dsize = 0;
  852.       }
  853.       else {
  854.         dsize *= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  855.       }
  856.     }
  857.   }
  858.   else {
  859.     /* Calc size of a sub-dir */
  860.     value = FS__fat_FAT_find_eof(Idx, Unit, DirStart, &dsize);
  861.     if (value < 0) {
  862.       dsize = 0;
  863.     }
  864.     else {
  865.       dsize *= FS__FAT_aBPBUnit[Idx][Unit].SecPerClus;
  866.     }
  867.   }
  868.   return dsize;
  869. }
  870. /*********************************************************************
  871. *
  872. *             FS__fat_findpath
  873. *
  874.   Description:
  875.   FS internal function. Return start cluster and size of the directory
  876.   of the file name in pFileName.
  877.   
  878.   Parameters:
  879.   Idx         - Index of device in the device information table 
  880.                 referred by FS__pDevInfo.
  881.   pFullName   - Fully qualified file name w/o device name.
  882.   pFileName   - Pointer to a pointer, which is modified to point to the
  883.                 file name part of pFullName.
  884.   pUnit       - Pointer to an FS_u32 for returning the unit number.
  885.   pDirStart   - Pointer to an FS_u32 for returning the start cluster of
  886.                 the directory.
  887.   Return value:
  888.   >0          - Sector (not cluster) size of the directory.
  889.   ==0         - An error has occured.
  890. */
  891. FS_u32 FS__fat_findpath(int Idx, const char *pFullName, FS_FARCHARPTR *pFileName, 
  892.                         FS_u32 *pUnit, FS_u32 *pDirStart) {
  893.   FS_u32 dsize;
  894.   FS_i32 i;
  895.   FS_i32 j;
  896.   FS_FARCHARPTR dname_start;
  897.   FS_FARCHARPTR dname_stop;
  898.   FS_FARCHARPTR chprt;
  899.   int x;
  900.   char dname[12];
  901.   char realname[12];
  902.   /* Find correct unit (unit:name) */
  903.   *pFileName = (FS_FARCHARPTR)FS__CLIB_strchr(pFullName, ':');
  904.   if (*pFileName) {
  905.     /* Scan for unit number */
  906.     *pUnit = FS__CLIB_atoi(pFullName);
  907.     (*pFileName)++;
  908.   }
  909.   else {
  910.     /* Use 1st unit as default */
  911.     *pUnit = 0;
  912.     *pFileName = (FS_FARCHARPTR) pFullName;
  913.   }
  914.   /* Check volume */
  915.   x = !FS__fat_checkunit(Idx, *pUnit);
  916.   if (x) {
  917.     return 0;
  918.   }
  919.   /* Setup pDirStart/dsize for root directory */
  920.   *pDirStart = 0;
  921.   dsize      = FS__fat_dir_size(Idx, *pUnit, 0);
  922.   /* Find correct directory */
  923.   do {
  924.     dname_start = (FS_FARCHARPTR)FS__CLIB_strchr(*pFileName, '\');
  925.     if (dname_start) {
  926.       dname_start++;
  927.       *pFileName = dname_start;
  928.       dname_stop = (FS_FARCHARPTR)FS__CLIB_strchr(dname_start, '\');
  929.     }
  930.     else {
  931.       dname_stop = 0;
  932.     }
  933.     if (dname_stop) {
  934.       i = dname_stop-dname_start;
  935.       if (i >= 12) {
  936.         j = 0;
  937.         for (chprt = dname_start; chprt < dname_stop; chprt++) {
  938.           if (*chprt == '.') {
  939.             i--;
  940.           }
  941.           else if (j < 12) {
  942.             realname[j] = *chprt;
  943.             j++;
  944.           }
  945.         }
  946.         if (i >= 12) {
  947.           return 0;
  948.         }
  949.       }
  950.       else {
  951.         FS__CLIB_strncpy(realname, dname_start, i);
  952.       }
  953.       realname[i] = 0;
  954.       FS__fat_make_realname(dname, realname);
  955.       *pDirStart =  FS__fat_find_dir(Idx, *pUnit, dname, *pDirStart, dsize);
  956.       if (*pDirStart) {
  957.         dsize  =  FS__fat_dir_size(Idx, *pUnit, *pDirStart);
  958.       }
  959.       else {
  960.         dsize = 0;    /* Directory NOT found */
  961.       }
  962.     }
  963.   } while (dname_start);
  964.   return dsize;
  965. }
  966. /*********************************************************************
  967. *
  968. *             Global functions section 2
  969. *
  970. **********************************************************************
  971.   These are real global functions, which are used by the API Layer
  972.   of the file system.
  973.   
  974. */
  975. /*********************************************************************
  976. *
  977. *             FS__fat_fopen
  978. *
  979.   Description:
  980.   FS internal function. Open an existing file or create a new one.
  981.   Parameters:
  982.   pFileName   - File name. 
  983.   pMode       - Mode for opening the file.
  984.   pFile       - Pointer to an FS_FILE data structure.
  985.   
  986.   Return value:
  987.   ==0         - Unable to open the file.
  988.   !=0         - Address of the FS_FILE data structure.
  989. */
  990. FS_FILE *FS__fat_fopen(const char *pFileName, const char *pMode, FS_FILE *pFile) {
  991.   FS_u32 unit;
  992.   FS_u32 dstart;
  993.   FS_u32 dsize;
  994.   FS_i32 i;
  995.   FS_FARCHARPTR fname;
  996.   FS__fat_dentry_type s;
  997.   char realname[12];
  998.   int lexp_a;
  999.   int lexp_b;
  1000.   
  1001.   if (!pFile) {
  1002.     return 0;  /* Not a valid pointer to an FS_FILE structure*/
  1003.   }
  1004.   dsize = FS__fat_findpath(pFile->dev_index, pFileName, &fname, &unit, &dstart);
  1005.   if (dsize == 0) {
  1006.     return 0;  /* Directory not found */
  1007.   }
  1008.   FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_INC_BUSYCNT, 0, (void*)0);  /* Turn on busy signal */
  1009.   FS__fat_make_realname(realname, fname);  /* Convert name to FAT real name */
  1010.   /* FileSize = 0 */
  1011.   s.data[28] = 0x00;      
  1012.   s.data[29] = 0x00;
  1013.   s.data[30] = 0x00;
  1014.   s.data[31] = 0x00;
  1015.   i = _FS_fat_find_file(pFile->dev_index, unit, realname, &s, dstart, dsize);
  1016.   /* Delete file */
  1017.   lexp_b = (FS__CLIB_strcmp(pMode, "del") == 0);    /* Delete file request */
  1018.   lexp_a = lexp_b && (i >= 0);                      /* File does exist */
  1019.   if (lexp_a) {
  1020.     i = FS__fat_DeleteFileOrDir(pFile->dev_index, unit, realname, dstart, dsize, 1);
  1021.     if (i != 0) {
  1022.       pFile->error = -1;
  1023.     }
  1024.     else {
  1025.       pFile->error = 0;
  1026.     }
  1027.     FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, pFile->fileid_lo, FS_CMD_FLUSH_CACHE, 2, (void*)0);
  1028.     FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  1029.     return 0;
  1030.   }
  1031.   else if (lexp_b) {
  1032.     FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  1033.     pFile->error = -1;
  1034.     return 0;
  1035.   }
  1036.   /* Check read only */
  1037.   lexp_a = ((i >= 0) && ((s.data[11] & FS_FAT_ATTR_READ_ONLY) != 0)) &&
  1038.           ((pFile->mode_w) || (pFile->mode_a) || (pFile->mode_c));
  1039.   if (lexp_a) {
  1040.     /* Files is RO and we try to create, write or append */
  1041.     FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  1042.     return 0;
  1043.   }
  1044.   lexp_a = ( i>= 0) && (!pFile->mode_a) && (((pFile->mode_w) && (!pFile->mode_r)) || 
  1045.           ((pFile->mode_w) && (pFile->mode_c) && (pFile->mode_r)) );
  1046.   if (lexp_a) {
  1047.     /* Delete old file */
  1048.     i = FS__fat_DeleteFileOrDir(pFile->dev_index, unit, realname, dstart, dsize, 1);
  1049.     /* FileSize = 0 */
  1050.     s.data[28] = 0x00;      
  1051.     s.data[29] = 0x00;
  1052.     s.data[30] = 0x00;
  1053.     s.data[31] = 0x00;
  1054.     i=-1;
  1055.   }
  1056.   if ((!pFile->mode_c) && (i < 0)) {
  1057.     /* File does not exist and we must not create */
  1058.     FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  1059.     return 0;
  1060.   }
  1061.   else if ((pFile->mode_c) && (i < 0)) {
  1062.     /* Create new file */
  1063.     i = _FS_fat_create_file(pFile->dev_index, unit, realname, dstart, dsize);
  1064.     if (i < 0) {
  1065.       /* Could not create file */
  1066.       if (i == -2) {
  1067.         /* Directory is full, try to increase */
  1068.         i = _FS_fat_IncDir(pFile->dev_index, unit, dstart, &dsize);
  1069.         if (i > 0) {
  1070.           i = _FS_fat_create_file(pFile->dev_index, unit, realname, dstart, dsize);
  1071.         }
  1072.       }
  1073.       if (i < 0) {
  1074.         FS__lb_ioctl(FS__pDevInfo[pFile->dev_index].devdriver, unit, FS_CMD_DEC_BUSYCNT, 0, (void*)0);  /* Turn off busy signal */
  1075.         return 0;
  1076.       }
  1077.     }
  1078.   }
  1079.   pFile->fileid_lo  = unit;
  1080.   pFile->fileid_hi  = i;
  1081.   pFile->fileid_ex  = dstart;
  1082.   pFile->EOFClust   = -1;
  1083.   pFile->CurClust   = 0;
  1084.   pFile->error      = 0;
  1085.   pFile->size       = (FS_u32)s.data[28];   /* FileSize */
  1086.   pFile->size      += (FS_u32)0x100UL * s.data[29];
  1087.   pFile->size      += (FS_u32)0x10000UL * s.data[30];
  1088.   pFile->size      += (FS_u32)0x1000000UL * s.data[31];
  1089.   if (pFile->mode_a) {
  1090.     pFile->filepos   = pFile->size;
  1091.   }
  1092.   else {
  1093.     pFile->filepos   = 0;
  1094.   }
  1095.   pFile->inuse     = 1;
  1096.   return pFile;
  1097. }