| [258] | 1 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 2 | // Date     : 01/06/2015 | 
|---|
|  | 3 | // Authors  : Alain Greiner | 
|---|
| [258] | 4 | // Copyright (c) UPMC-LIP6 | 
|---|
|  | 5 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [569] | 6 | // The fat32.h and fat32.c files define a library of access functions | 
|---|
| [587] | 7 | // to a FAT32 disk on a block device. It is intended to be used by both | 
|---|
|  | 8 | // the boot code and the kernel code. | 
|---|
| [258] | 9 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 10 | // Implementation notes: | 
|---|
|  | 11 | // 1. the "lba" (Logical Block Address) is the physical sector index on | 
|---|
|  | 12 | //    the block device. The physical sector size is supposed to be 512 bytes. | 
|---|
|  | 13 | // 2. the "cluster" variable is actually a cluster index. A cluster contains | 
|---|
| [587] | 14 | //    8 sectors (4K bytes) and the cluster index is a 32 bits word. | 
|---|
|  | 15 | // 3. Each file or directory referenced by the software is represented | 
|---|
|  | 16 | //    by an "inode". The set of "inodes" is organised as a tree, that is | 
|---|
|  | 17 | //    a sub-tree of the complete file system existing on the block device. | 
|---|
|  | 18 | // 4. A given file can be referenced by several software tasks, and each task | 
|---|
|  | 19 | //    will use a private handler, called a "file descriptor", allocated by the OS | 
|---|
|  | 20 | //    when the task open the file, that is organised as an indexed array. | 
|---|
|  | 21 | // 5. This FAT32 library implements (N+1) caches : one private "File_ Cache" | 
|---|
|  | 22 | //    for each referenced file or directory, and a specific "Fat_Cache" for | 
|---|
|  | 23 | //    the FAT itself. Each cache contain a variable number of clusters that are | 
|---|
|  | 24 | //    dynamically allocated when they are accessed, and organised as a 64-Tree. | 
|---|
| [258] | 25 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 26 | // General Debug Policy: | 
|---|
|  | 27 | // The global variable GIET_DEBUG_FAT is defined in the giet_config.h file. | 
|---|
|  | 28 | // The debug is activated if (proctime > GIET_DEBUG_FAT) && (GIET_DEBUG_FAT != 0) | 
|---|
|  | 29 | // The GIET_DEBUG_FAT bit 0 defines the level of debug: | 
|---|
|  | 30 | //    if   (GIET_DEBUG_FAT & 0x1)    => detailed debug | 
|---|
|  | 31 | //    else                           => external functions only | 
|---|
|  | 32 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [258] | 33 |  | 
|---|
|  | 34 | #include <giet_config.h> | 
|---|
| [530] | 35 | #include <hard_config.h> | 
|---|
| [258] | 36 | #include <fat32.h> | 
|---|
| [530] | 37 | #include <utils.h> | 
|---|
|  | 38 | #include <vmem.h> | 
|---|
| [587] | 39 | #include <kernel_malloc.h> | 
|---|
| [530] | 40 | #include <bdv_driver.h> | 
|---|
|  | 41 | #include <hba_driver.h> | 
|---|
|  | 42 | #include <sdc_driver.h> | 
|---|
|  | 43 | #include <rdk_driver.h> | 
|---|
|  | 44 | #include <mmc_driver.h> | 
|---|
| [458] | 45 | #include <tty0.h> | 
|---|
| [258] | 46 |  | 
|---|
|  | 47 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 48 | //               Global variables | 
|---|
| [258] | 49 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 50 |  | 
|---|
| [587] | 51 | // Fat-Descriptor | 
|---|
|  | 52 | __attribute__((section(".kdata"))) | 
|---|
|  | 53 | fat_desc_t _fat __attribute__((aligned(64))); | 
|---|
| [258] | 54 |  | 
|---|
| [587] | 55 | // buffer used by boot code as a simple cache when scanning FAT | 
|---|
|  | 56 | __attribute__((section(".kdata"))) | 
|---|
|  | 57 | unsigned char  _fat_buffer_fat[4096] __attribute__((aligned(64))); | 
|---|
| [530] | 58 |  | 
|---|
| [587] | 59 | // buffer used by boot code as a simple cache when scanning a directory in DATA region | 
|---|
|  | 60 | __attribute__((section(".kdata"))) | 
|---|
|  | 61 | unsigned char  _fat_buffer_data[4096] __attribute__((aligned(64))); | 
|---|
| [530] | 62 |  | 
|---|
| [587] | 63 | // lba of cluster in fat_buffer_fat | 
|---|
|  | 64 | __attribute__((section(".kdata"))) | 
|---|
|  | 65 | unsigned int   _fat_buffer_fat_lba; | 
|---|
|  | 66 |  | 
|---|
|  | 67 | // lba of cluster in fat_buffer_data | 
|---|
|  | 68 | __attribute__((section(".kdata"))) | 
|---|
|  | 69 | unsigned int   _fat_buffer_data_lba; | 
|---|
|  | 70 |  | 
|---|
|  | 71 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 72 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 73 | //                  Static functions declaration | 
|---|
|  | 74 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 75 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 76 |  | 
|---|
|  | 77 |  | 
|---|
|  | 78 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 79 | // This debug function displays the content of a 512 bytes buffer "buf", | 
|---|
|  | 80 | // with an identifier defined by the "string" and "block_id" arguments. | 
|---|
|  | 81 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 82 |  | 
|---|
|  | 83 | #if GIET_DEBUG_FAT | 
|---|
|  | 84 | static void _display_one_block( unsigned char* buf, | 
|---|
|  | 85 | char*          string, | 
|---|
|  | 86 | unsigned int   block_id ); | 
|---|
| [530] | 87 | #endif | 
|---|
|  | 88 |  | 
|---|
| [587] | 89 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 90 | // This debug function displays the FAT descriptor. | 
|---|
|  | 91 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [530] | 92 |  | 
|---|
| [587] | 93 | #if GIET_DEBUG_FAT | 
|---|
|  | 94 | static void _display_fat_descriptor(); | 
|---|
| [551] | 95 | #endif | 
|---|
| [530] | 96 |  | 
|---|
| [587] | 97 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 98 | // This debug function displays the sequence of clusters allocated to a | 
|---|
|  | 99 | // file (or directory) identified by the "inode" argument. | 
|---|
|  | 100 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [530] | 101 |  | 
|---|
| [587] | 102 | #if GIET_DEBUG_FAT | 
|---|
|  | 103 | static void _display_clusters_list( fat_inode_t* inode ); | 
|---|
| [530] | 104 | #endif | 
|---|
|  | 105 |  | 
|---|
| [587] | 106 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 107 | // The following function transfers one or several blocks between the device | 
|---|
|  | 108 | // and a memory buffer identified by a virtual address. | 
|---|
|  | 109 | // It computes the memory buffer physical address, and calls the proper | 
|---|
|  | 110 | // IOC driver depending on the subtype (BDV / HBA / SDC / SPI / RDK). | 
|---|
|  | 111 | // The use_irq argument allows to activate the descheduling mode, | 
|---|
|  | 112 | // if it supported by the IOC driver subtype | 
|---|
|  | 113 | // It returns O  in case of success. | 
|---|
|  | 114 | // It returns -1 in case of error. | 
|---|
|  | 115 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [530] | 116 |  | 
|---|
| [587] | 117 | static int _fat_ioc_access( unsigned int use_irq, | 
|---|
|  | 118 | unsigned int to_mem, | 
|---|
|  | 119 | unsigned int lba, | 
|---|
|  | 120 | unsigned int buf_vaddr, | 
|---|
|  | 121 | unsigned int count ); | 
|---|
| [530] | 122 |  | 
|---|
| [258] | 123 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 124 | // The following function returns in the "desc" argument a pointer on a buffer | 
|---|
|  | 125 | // descriptor contained in a File_Cache, or in the Fat_Cache. | 
|---|
|  | 126 | // The searched buffer is idenfified by the "inode" and "cluster_id" arguments. | 
|---|
|  | 127 | // If the "inode" pointer is not NULL, the searched cache is a File-Cache. | 
|---|
|  | 128 | // If the "inode" pointer is NULL, the searched cache is the Fat-Cache, | 
|---|
|  | 129 | // The "cluster_id" argument is the buffer index in the file (or in the FAT). | 
|---|
|  | 130 | // In case of miss, it allocate a 4 Kbytes buffer and a cluster descriptor | 
|---|
|  | 131 | // from the local kernel heap, and calls the _fat_ioc_access() function to load | 
|---|
|  | 132 | // the missing cluster from the block device. | 
|---|
|  | 133 | // It returns O  in case of success. | 
|---|
|  | 134 | // It returns 1 in case of error. | 
|---|
| [258] | 135 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 136 |  | 
|---|
|  | 137 | static unsigned int _get_buffer_from_cache( fat_inode_t*        inode, | 
|---|
|  | 138 | unsigned int        cluster_id, | 
|---|
|  | 139 | fat_cache_desc_t**  desc ); | 
|---|
|  | 140 |  | 
|---|
|  | 141 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 142 | // This function extract a (partial) name from a LFN directory entry. | 
|---|
|  | 143 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 144 |  | 
|---|
|  | 145 | static void _get_name_from_long( unsigned char* buffer, | 
|---|
|  | 146 | char*          name ); | 
|---|
|  | 147 |  | 
|---|
|  | 148 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 149 | // The following function extract a name from a NORMAL directory entry. | 
|---|
|  | 150 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 151 |  | 
|---|
|  | 152 | static void _get_name_from_short( unsigned char* buffer, | 
|---|
|  | 153 | char*          name ); | 
|---|
|  | 154 |  | 
|---|
|  | 155 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 156 | // This function returns the number of levels of a File-Cache (or Fat-Cache) | 
|---|
|  | 157 | // from the size of the file (or FAT). | 
|---|
|  | 158 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 159 |  | 
|---|
|  | 160 | static inline unsigned int _get_levels_from_size( unsigned int size ); | 
|---|
|  | 161 |  | 
|---|
|  | 162 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 163 | // The following function analyses the "pathname" argument, from the character | 
|---|
|  | 164 | // defined by the "nb_read" argument. | 
|---|
|  | 165 | // It copies the found name in the "name" buffer (without '/'), | 
|---|
|  | 166 | // and updates the "nb_read" argument. | 
|---|
|  | 167 | // It returns 0 if success. | 
|---|
|  | 168 | // It returns 1 if one name length > NAME_MAX_SIZE characters | 
|---|
|  | 169 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 170 |  | 
|---|
|  | 171 | static unsigned int _get_name_from_path( char*          pathname, | 
|---|
|  | 172 | char*          name, | 
|---|
|  | 173 | unsigned int*  nb_read ); | 
|---|
|  | 174 |  | 
|---|
|  | 175 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 176 | // The following function scan the "pathname" argument, and copies in the | 
|---|
|  | 177 | // "name" buffer the last name in path (leaf name). | 
|---|
|  | 178 | // It returns 0 if success. | 
|---|
|  | 179 | // It returns 1 if one name length > NAME_MAX_SIZE characters | 
|---|
|  | 180 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 181 | static unsigned int _get_last_name( char*   pathname, | 
|---|
|  | 182 | char*   name ); | 
|---|
|  | 183 |  | 
|---|
|  | 184 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 185 | // The following function access the Fat-Cache and returns in the "value" | 
|---|
|  | 186 | // argument the content of the FAT slot identified by the "cluster" argument. | 
|---|
|  | 187 | // It loads the missing cluster from block device into cache in case of miss. | 
|---|
|  | 188 | // It returns 0 if success. | 
|---|
|  | 189 | // It returns 1 if error. | 
|---|
|  | 190 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 191 |  | 
|---|
|  | 192 | static unsigned int _get_fat_entry( unsigned int  cluster, | 
|---|
|  | 193 | unsigned int* value ); | 
|---|
|  | 194 |  | 
|---|
|  | 195 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 196 | // The following function writes a new "value" in the Fat-Cache, in the slot | 
|---|
|  | 197 | // identified by the "cluster" argument. | 
|---|
|  | 198 | // It loads the missing cluster from block device into cache in case of miss. | 
|---|
|  | 199 | // It returns 0 if success, | 
|---|
|  | 200 | // It returns 1 if error. | 
|---|
|  | 201 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 202 |  | 
|---|
|  | 203 | static unsigned int _set_fat_entry( unsigned int  cluster, | 
|---|
|  | 204 | unsigned int  value ); | 
|---|
|  | 205 |  | 
|---|
|  | 206 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 207 | // The following function introduces the inode identified by the "child" argument, | 
|---|
|  | 208 | // as a new child of the "parent" inode in the Inode-Tree. | 
|---|
|  | 209 | // All checking are supposed to be done by the caller. | 
|---|
|  | 210 | // Nor the File-Cache, neither the block device are modified. | 
|---|
|  | 211 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 212 |  | 
|---|
|  | 213 | static void _add_inode_in_tree( fat_inode_t*  child, | 
|---|
|  | 214 | fat_inode_t*  parent ); | 
|---|
|  | 215 |  | 
|---|
|  | 216 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 217 | // The following function removes one inode identified by the "inode" argument | 
|---|
|  | 218 | // from the Inode-Tree. All checking are supposed to be done by the caller. | 
|---|
|  | 219 | // Nor the File-Cache, neither the block device are modified. | 
|---|
|  | 220 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 221 |  | 
|---|
|  | 222 | static void _remove_inode_from_tree( fat_inode_t* inode ); | 
|---|
|  | 223 |  | 
|---|
|  | 224 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 225 | // This recursive function scan one File-Cache (or Fat-Cache) from root to leaves, | 
|---|
|  | 226 | // to writes all dirty clusters to block device, and reset the dirty bits. | 
|---|
|  | 227 | // The cache is identified by the "root" an "levels" arguments. | 
|---|
|  | 228 | // The "string" argument is only used for debug : inode name or Fat. | 
|---|
|  | 229 | // It returns 0 if success. | 
|---|
|  | 230 | // It returns 1 if error. | 
|---|
|  | 231 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 232 |  | 
|---|
|  | 233 | static unsigned int _update_device_from_cache( unsigned int      levels, | 
|---|
|  | 234 | fat_cache_node_t* root, | 
|---|
|  | 235 | char*             string ); | 
|---|
|  | 236 |  | 
|---|
|  | 237 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 238 | // The following function access directly the FS_INFO block on the block device, | 
|---|
|  | 239 | // to update the "first_free_cluster" and "free_clusters_number" values, | 
|---|
|  | 240 | // using only the Fat-Descriptor single block buffer. | 
|---|
|  | 241 | // It return 0 in case of success. | 
|---|
|  | 242 | // It return 1 in case of error. | 
|---|
|  | 243 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 244 |  | 
|---|
|  | 245 | static unsigned int _update_fs_info(); | 
|---|
|  | 246 |  | 
|---|
|  | 247 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 248 | // The following function read a data field (from one to four bytes) | 
|---|
|  | 249 | // from an unsigned char[] buffer, taking endianness into account. | 
|---|
|  | 250 | // The analysed field is defined by the "offset" and "size" arguments. | 
|---|
|  | 251 | ////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 252 |  | 
|---|
|  | 253 | static unsigned int _read_entry( unsigned int    offset, | 
|---|
|  | 254 | unsigned int    size, | 
|---|
|  | 255 | unsigned char*  buffer, | 
|---|
|  | 256 | unsigned int    little_indian ); | 
|---|
|  | 257 |  | 
|---|
|  | 258 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 259 | // The following function returns the lba of first sector in DATA region | 
|---|
|  | 260 | // from the cluster index. The cluster index must be larger than 2. | 
|---|
|  | 261 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 262 |  | 
|---|
|  | 263 | static unsigned int _cluster_to_lba( unsigned int cluster ); | 
|---|
|  | 264 |  | 
|---|
|  | 265 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 266 | // The following function returns in the "nb_entries" argument the number of files | 
|---|
| [620] | 267 | // (or directories) contained in a directory identified by the "inode " pointer. | 
|---|
| [587] | 268 | // It returns  0 if success. | 
|---|
|  | 269 | // It returns  1 if error. | 
|---|
|  | 270 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 271 |  | 
|---|
|  | 272 | static unsigned int _get_nb_entries( fat_inode_t*   inode, | 
|---|
|  | 273 | unsigned int*  nb_entries ); | 
|---|
|  | 274 |  | 
|---|
|  | 275 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 276 | // The following function search in the directory identified by the "parent" | 
|---|
|  | 277 | // inode pointer a child (file or directory) identified by its "name". | 
|---|
|  | 278 | // It returns in the "inode" argument the searched child inode pointer. | 
|---|
|  | 279 | // If the searched name is not found in the Inode-Tree, the function access | 
|---|
|  | 280 | // the "file_cache" associated to the parent directory. | 
|---|
|  | 281 | // If the child exist on block device, the Inode-Tree is updated, and | 
|---|
|  | 282 | // a success code is returned. | 
|---|
|  | 283 | // If the file/dir does not exist on block device, a error code is returned. | 
|---|
|  | 284 | // It returns 0 if inode found. | 
|---|
|  | 285 | // It returns 1 if inode not found. | 
|---|
|  | 286 | // It returns 2 if error in cache access. | 
|---|
|  | 287 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 288 |  | 
|---|
|  | 289 | static unsigned int _get_child_from_parent( fat_inode_t*   parent, | 
|---|
|  | 290 | char*          name, | 
|---|
|  | 291 | fat_inode_t**  inode ); | 
|---|
|  | 292 |  | 
|---|
|  | 293 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 294 | // For a file (or a directory) identified by the "pathname" argument, the | 
|---|
|  | 295 | // following function returns in the "inode" argument the inode pointer | 
|---|
|  | 296 | // associated to the searched file (or directory), with code (0). | 
|---|
|  | 297 | // If the searched file (or directory) is not found, but the parent directory | 
|---|
|  | 298 | // is found, it returns in the "inode" argument the pointer on the parent inode, | 
|---|
|  | 299 | // with code (1).  Finally, code (2) and code (3) are error codes. | 
|---|
|  | 300 | // Both the Inode-Tree and the involved Cache-Files are updated from the block | 
|---|
|  | 301 | // device in case of miss on one inode during the search in path. | 
|---|
|  | 302 | // Neither the Fat-Cache, nor the block device are updated. | 
|---|
|  | 303 | // It returns 0 if searched inode found | 
|---|
|  | 304 | // It returns 1 if searched inode not found but parent directory found | 
|---|
|  | 305 | // It returns 2 if searched inode not found and parent directory not found | 
|---|
|  | 306 | // It returns 3 if one name too long | 
|---|
|  | 307 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 308 |  | 
|---|
|  | 309 | static unsigned int _get_inode_from_path( char*          pathname, | 
|---|
|  | 310 | fat_inode_t**  inode ); | 
|---|
|  | 311 |  | 
|---|
|  | 312 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [638] | 313 | // The following function checks if node "a" is an ancestor of inode "b". | 
|---|
|  | 314 | // It returns 0 on failure. | 
|---|
|  | 315 | // It returns 1 otherwise. | 
|---|
|  | 316 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 317 |  | 
|---|
|  | 318 | static unsigned int _is_ancestor( fat_inode_t* a, | 
|---|
|  | 319 | fat_inode_t* b); | 
|---|
|  | 320 |  | 
|---|
|  | 321 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 322 | // This function computes the length and the number of LFN entries required | 
|---|
|  | 323 | // to store a node name in the "length" and "nb_lfn" arguments. | 
|---|
|  | 324 | // Short name (less than 13 characters) require 1 LFN entry. | 
|---|
|  | 325 | // Medium names (from 14 to 26 characters require 2 LFN entries. | 
|---|
|  | 326 | // Large names (up to 31 characters) require 3 LFN entries. | 
|---|
|  | 327 | // It returns 0 if success. | 
|---|
|  | 328 | // It returns 1 if length larger than 31 characters. | 
|---|
|  | 329 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 330 |  | 
|---|
|  | 331 | static unsigned int _check_name_length( char* name, | 
|---|
|  | 332 | unsigned int* length, | 
|---|
|  | 333 | unsigned int* nb_lfn ); | 
|---|
|  | 334 |  | 
|---|
|  | 335 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 336 | // For a node identified by the "inode" argument, this function updates the | 
|---|
|  | 337 | // "size" and "cluster" values in the entry of the parent directory File-Cache. | 
|---|
|  | 338 | // It set the dirty bit in the modified buffer of the parent directory File-Cache. | 
|---|
|  | 339 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 340 |  | 
|---|
|  | 341 | static unsigned int _update_dir_entry( fat_inode_t*  inode ); | 
|---|
|  | 342 |  | 
|---|
|  | 343 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 344 | // The following function add new "child" in Cache-File of "parent" directory. | 
|---|
|  | 345 | // It access the File_Cache associated to the parent directory, and scan the | 
|---|
|  | 346 | // clusters allocated to this directory to find the NO_MORE entry. | 
|---|
|  | 347 | // This entry will be the first modified entry in the directory. | 
|---|
|  | 348 | // Regarding the name storage, it uses LFN entries for all names. | 
|---|
|  | 349 | // Therefore, it writes 1, 2, or 3 LFN entries (depending on the child name | 
|---|
|  | 350 | // actual length, it writes one NORMAL entry, and writes the new NOMORE entry. | 
|---|
|  | 351 | // It updates the dentry field in the child inode. | 
|---|
|  | 352 | // It set the dirty bit for all modified File-Cache buffers. | 
|---|
|  | 353 | // The block device is not modified by this function. | 
|---|
|  | 354 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 355 |  | 
|---|
|  | 356 | static unsigned int _add_dir_entry( fat_inode_t* child, | 
|---|
|  | 357 | fat_inode_t* parent ); | 
|---|
|  | 358 |  | 
|---|
|  | 359 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 360 | // The following function invalidates all dir_entries associated to the "inode" | 
|---|
|  | 361 | // argument from its parent directory. | 
|---|
|  | 362 | // It set the dirty bit for all modified buffers in parent directory Cache-File. | 
|---|
|  | 363 | // The inode itself is not modified by this function. | 
|---|
|  | 364 | // The block device is not modified by this function. | 
|---|
|  | 365 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 366 |  | 
|---|
|  | 367 | static unsigned int _remove_dir_entry( fat_inode_t*  inode ); | 
|---|
|  | 368 |  | 
|---|
|  | 369 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 370 | // The following function add the special entries "." and ".." in the File-Cache | 
|---|
|  | 371 | // of the directory identified by the "child" argument. | 
|---|
|  | 372 | // The parent directory is defined by the "parent" argument. | 
|---|
|  | 373 | // The child directory File-Cache is supposed to be empty. | 
|---|
|  | 374 | // We use two NORMAL entries for these "." and ".." entries. | 
|---|
|  | 375 | // The block device is not modified by this function. | 
|---|
|  | 376 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 377 |  | 
|---|
|  | 378 | static void _add_special_directories( fat_inode_t* child, | 
|---|
|  | 379 | fat_inode_t* parent ); | 
|---|
|  | 380 |  | 
|---|
|  | 381 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 382 | // The following function releases all clusters allocated to a file or directory, | 
|---|
|  | 383 | // from the cluster index defined by the "cluster" argument, until the end | 
|---|
|  | 384 | // of the FAT linked list. | 
|---|
|  | 385 | // It calls _get_fat_entry() and _set_fat_entry() functions to scan the FAT, | 
|---|
|  | 386 | // and to update the clusters chaining. | 
|---|
|  | 387 | // The FAT region on block device is updated. | 
|---|
|  | 388 | // It returns 0 if success. | 
|---|
|  | 389 | // It returns 1 if error. | 
|---|
|  | 390 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 391 |  | 
|---|
|  | 392 | static unsigned int _clusters_release( unsigned int cluster ); | 
|---|
|  | 393 |  | 
|---|
|  | 394 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 395 | // This function allocate "nb_clusters_more" new clusters to a file (or directory) | 
|---|
|  | 396 | // identified by the "inode" pointer. It allocates also the associated buffers | 
|---|
|  | 397 | // and buffer descriptors in the Cache-File. | 
|---|
|  | 398 | // It calls _get_fat_entry() and _set_fat_entry() functions to update the | 
|---|
|  | 399 | // clusters chaining in the Cache-Fat. The FAT region on block device is updated. | 
|---|
|  | 400 | // It returns 0 if success. | 
|---|
|  | 401 | // It returns 1 if error. | 
|---|
|  | 402 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 403 |  | 
|---|
|  | 404 | static unsigned int _clusters_allocate( fat_inode_t* inode, | 
|---|
|  | 405 | unsigned int nb_clusters_current, | 
|---|
|  | 406 | unsigned int nb_clusters_more ); | 
|---|
|  | 407 |  | 
|---|
|  | 408 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [651] | 409 | // This recursive function scans one File-Cache (or Fat-Cache) from root to | 
|---|
|  | 410 | // leaves. All memory allocated for 4KB buffers, and buffer descriptors (in | 
|---|
|  | 411 | // leaves) is released, along with the 64-Tree structure (root node is kept). | 
|---|
|  | 412 | // The cache is identified by the "root" and "levels" arguments. | 
|---|
| [587] | 413 | // It should not contain any dirty clusters. | 
|---|
|  | 414 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 415 |  | 
|---|
| [651] | 416 | static void _release_cache_memory( fat_cache_node_t*  root, | 
|---|
|  | 417 | unsigned int       levels ); | 
|---|
| [587] | 418 |  | 
|---|
|  | 419 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [639] | 420 | // The following function allocates and initializes a new Fat-Cache node. | 
|---|
|  | 421 | // Its first child can be specified (used when adding a cache level). | 
|---|
|  | 422 | // The Fat-Cache is initialized as empty: all children set to NULL. | 
|---|
|  | 423 | // It returns a pointer to a new Fat-Cache node. | 
|---|
|  | 424 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 425 |  | 
|---|
|  | 426 | static fat_cache_node_t* _allocate_one_cache_node( fat_cache_node_t* first_child ); | 
|---|
|  | 427 |  | 
|---|
|  | 428 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 429 | // The following function allocates and initializes a new inode, | 
|---|
|  | 430 | // using the values defined by the arguments. | 
|---|
|  | 431 | // If the "cache_allocate" argument is true ans empty cache is allocated. | 
|---|
|  | 432 | // It returns a pointer on the new inode. | 
|---|
|  | 433 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 434 |  | 
|---|
|  | 435 | static fat_inode_t* _allocate_one_inode( char*        name, | 
|---|
|  | 436 | unsigned int is_dir, | 
|---|
|  | 437 | unsigned int cluster, | 
|---|
|  | 438 | unsigned int size, | 
|---|
|  | 439 | unsigned int count, | 
|---|
|  | 440 | unsigned int dentry, | 
|---|
|  | 441 | unsigned int cache_allocate ); | 
|---|
|  | 442 |  | 
|---|
|  | 443 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 444 | // The following function allocates one 4 Kbytes buffer and associated cluster | 
|---|
|  | 445 | // descriptor for the file (or directory) identified by the "inode" argument, | 
|---|
|  | 446 | // and updates the Cache_File slot identified by the "cluster_id" argument. | 
|---|
|  | 447 | // The File-Cache slot must be empty. | 
|---|
|  | 448 | // It updates the cluster descriptor, using the "cluster" argument, that is | 
|---|
|  | 449 | // the cluster index in FAT.  The cluster descriptor dirty field is set. | 
|---|
|  | 450 | // It traverse the 64-tree Cache-file from top to bottom to find the last level. | 
|---|
|  | 451 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 452 |  | 
|---|
|  | 453 | static void _allocate_one_buffer( fat_inode_t*    inode, | 
|---|
|  | 454 | unsigned int    cluster_id, | 
|---|
|  | 455 | unsigned int    cluster ); | 
|---|
|  | 456 |  | 
|---|
|  | 457 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 458 | // The following function allocates one free cluster from the FAT "heap" of free | 
|---|
|  | 459 | // clusters, and returns the cluster index in the "cluster" argument. | 
|---|
|  | 460 | // It updates the FAT slot, and the two FAT global variables: first_free_cluster, | 
|---|
|  | 461 | // and free_clusters_number. | 
|---|
|  | 462 | // It returns O if success. | 
|---|
|  | 463 | // It returns 1 if error. | 
|---|
|  | 464 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 465 |  | 
|---|
|  | 466 | static unsigned int _allocate_one_cluster( unsigned int*  cluster ); | 
|---|
|  | 467 |  | 
|---|
|  | 468 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 469 | // This function remove from the file system a file or a directory | 
|---|
|  | 470 | // identified by the "inode" argument. | 
|---|
|  | 471 | // The remove condition must be checked by the caller. | 
|---|
|  | 472 | // The relevant lock(s) must have been taken by te caller. | 
|---|
|  | 473 | // It returns O if success. | 
|---|
|  | 474 | // It returns 1 if error. | 
|---|
|  | 475 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 476 |  | 
|---|
|  | 477 | static unsigned int _remove_node_from_fs( fat_inode_t* inode ); | 
|---|
|  | 478 |  | 
|---|
|  | 479 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 480 | // This function return the cluster index and the size for a file | 
|---|
|  | 481 | // identified by the "pathname" argument, scanning directly the block | 
|---|
|  | 482 | // device DATA region. | 
|---|
|  | 483 | // It is intended to be called only by the _fat_load_no_cache() function, | 
|---|
|  | 484 | // it does not use the dynamically allocated File Caches, but uses only | 
|---|
|  | 485 | // the 4 Kbytes _fat_buffer_data. | 
|---|
|  | 486 | // It returns 0 if success. | 
|---|
|  | 487 | // It returns 1 if error. | 
|---|
|  | 488 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 489 |  | 
|---|
|  | 490 | static unsigned int _file_info_no_cache( char*          pathname, | 
|---|
|  | 491 | unsigned int*  file_cluster, | 
|---|
|  | 492 | unsigned int*  file_size ); | 
|---|
|  | 493 |  | 
|---|
|  | 494 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 495 | // This function scan directly the FAT region on the block device, | 
|---|
|  | 496 | // and returns in the "next" argument the value stored in the fat slot | 
|---|
|  | 497 | // identified by the "cluster" argument. | 
|---|
|  | 498 | // It is intended to be called only by the _fat_load_no_cache() function, | 
|---|
|  | 499 | // as it does not use the dynamically allocated Fat-Cache, but uses only | 
|---|
|  | 500 | // the 4 Kbytes _fat_buffer_fat. | 
|---|
|  | 501 | // It returns 0 if success. | 
|---|
|  | 502 | // It returns 1 if error. | 
|---|
|  | 503 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 504 |  | 
|---|
|  | 505 | static unsigned int _next_cluster_no_cache( unsigned int   cluster, | 
|---|
|  | 506 | unsigned int*  next ); | 
|---|
|  | 507 |  | 
|---|
|  | 508 |  | 
|---|
|  | 509 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 510 | // The following functions return the length or the size of a FAT field, | 
|---|
|  | 511 | // identified by an (offset,length) mnemonic defined in the fat32.h file. | 
|---|
|  | 512 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 513 |  | 
|---|
|  | 514 | static inline int get_length( int offset , int length ) { return length; } | 
|---|
|  | 515 |  | 
|---|
|  | 516 | static inline int get_offset( int offset , int length ) { return offset; } | 
|---|
|  | 517 |  | 
|---|
|  | 518 |  | 
|---|
|  | 519 |  | 
|---|
|  | 520 |  | 
|---|
|  | 521 |  | 
|---|
|  | 522 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 523 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 524 | //                  Static functions definition | 
|---|
|  | 525 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 526 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 527 |  | 
|---|
|  | 528 | #if GIET_DEBUG_FAT | 
|---|
|  | 529 | /////////////////////////////////////////////////// | 
|---|
|  | 530 | static void _display_one_block( unsigned char* buf, | 
|---|
|  | 531 | char*          string, | 
|---|
|  | 532 | unsigned int   block_id ) | 
|---|
| [258] | 533 | { | 
|---|
|  | 534 | unsigned int line; | 
|---|
|  | 535 | unsigned int word; | 
|---|
|  | 536 |  | 
|---|
| [587] | 537 | _printf("\n***  <%s>  block %x  ***********************************\n", | 
|---|
|  | 538 | string , block_id ); | 
|---|
| [258] | 539 |  | 
|---|
| [417] | 540 | for ( line = 0 ; line < 16 ; line++ ) | 
|---|
| [258] | 541 | { | 
|---|
| [417] | 542 | // display line index | 
|---|
| [587] | 543 | _printf("%x : ", line ); | 
|---|
| [258] | 544 |  | 
|---|
| [417] | 545 | // display 8*4 bytes hexa | 
|---|
| [258] | 546 | for ( word=0 ; word<8 ; word++ ) | 
|---|
|  | 547 | { | 
|---|
|  | 548 | unsigned int byte  = (line<<5) + (word<<2); | 
|---|
| [587] | 549 | unsigned int hexa  = (buf[byte  ]<<24) | | 
|---|
|  | 550 | (buf[byte+1]<<16) | | 
|---|
|  | 551 | (buf[byte+2]<< 8) | | 
|---|
|  | 552 | (buf[byte+3]      ); | 
|---|
|  | 553 | _printf(" %X |", hexa ); | 
|---|
| [258] | 554 | } | 
|---|
| [587] | 555 | _printf("\n"); | 
|---|
| [258] | 556 | } | 
|---|
| [587] | 557 | _printf("*******************************************************************\n"); | 
|---|
|  | 558 | } // end _display_one_block() | 
|---|
| [530] | 559 | #endif | 
|---|
| [291] | 560 |  | 
|---|
| [587] | 561 |  | 
|---|
|  | 562 |  | 
|---|
| [530] | 563 | #if GIET_DEBUG_FAT | 
|---|
| [587] | 564 | ///////////////////////////////////// | 
|---|
|  | 565 | static void _display_fat_descriptor() | 
|---|
| [530] | 566 | { | 
|---|
| [587] | 567 | _printf("\n###############  FAT DESCRIPTOR  ################################" | 
|---|
| [530] | 568 | "\nFAT initialised                  %x" | 
|---|
| [587] | 569 | "\nBlock Size  (bytes)              %x" | 
|---|
|  | 570 | "\nCluster Size  (bytes)            %x" | 
|---|
| [530] | 571 | "\nFAT region first lba             %x" | 
|---|
| [587] | 572 | "\nFAT region size (blocks)         %x" | 
|---|
|  | 573 | "\nDATA region first lba            %x" | 
|---|
|  | 574 | "\nDATA region size (blocks)        %x" | 
|---|
| [530] | 575 | "\nNumber of free clusters          %x" | 
|---|
| [587] | 576 | "\nFirst free cluster index         %x" | 
|---|
|  | 577 | "\nFat_cache_levels                 %d" | 
|---|
| [530] | 578 | "\n#################################################################\n", | 
|---|
|  | 579 | _fat.initialised, | 
|---|
|  | 580 | _fat.sector_size, | 
|---|
| [587] | 581 | _fat.cluster_size, | 
|---|
| [530] | 582 | _fat.fat_lba, | 
|---|
| [587] | 583 | _fat.fat_sectors, | 
|---|
| [530] | 584 | _fat.data_lba, | 
|---|
| [587] | 585 | _fat.data_sectors, | 
|---|
|  | 586 | _fat.free_clusters_number, | 
|---|
|  | 587 | _fat.first_free_cluster, | 
|---|
|  | 588 | _fat.fat_cache_levels ); | 
|---|
|  | 589 |  | 
|---|
|  | 590 | } // end _display_fat_descriptor() | 
|---|
| [530] | 591 | #endif | 
|---|
|  | 592 |  | 
|---|
| [587] | 593 |  | 
|---|
|  | 594 |  | 
|---|
|  | 595 | #if GIET_DEBUG_FAT | 
|---|
|  | 596 | //////////////////////////////////////////////////////// | 
|---|
|  | 597 | static void _display_clusters_list( fat_inode_t* inode ) | 
|---|
| [258] | 598 | { | 
|---|
| [587] | 599 | _printf("\n**************** clusters for <%s> ***********************\n", inode->name ); | 
|---|
|  | 600 | unsigned int next; | 
|---|
|  | 601 | unsigned int n       = 0; | 
|---|
|  | 602 | unsigned int current = inode->cluster; | 
|---|
|  | 603 | while( (current < END_OF_CHAIN_CLUSTER_MIN) && (n < 1024) ) | 
|---|
|  | 604 | { | 
|---|
|  | 605 | _get_fat_entry( current , &next ); | 
|---|
|  | 606 | _printf(" > %X", current ); | 
|---|
|  | 607 | n++; | 
|---|
|  | 608 | if ( (n & 0x7) == 0 ) _printf("\n"); | 
|---|
|  | 609 | current = next; | 
|---|
|  | 610 | } | 
|---|
|  | 611 | _printf("\n"); | 
|---|
|  | 612 | }  // end _display_clusters_list() | 
|---|
|  | 613 | #endif | 
|---|
| [258] | 614 |  | 
|---|
| [587] | 615 |  | 
|---|
|  | 616 |  | 
|---|
|  | 617 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 618 | static int _fat_ioc_access( unsigned int use_irq,       // descheduling if non zero | 
|---|
|  | 619 | unsigned int to_mem,        // read / write | 
|---|
|  | 620 | unsigned int lba,           // first sector on device | 
|---|
|  | 621 | unsigned int buf_vaddr,     // memory buffer vaddr | 
|---|
|  | 622 | unsigned int count )        // number of sectors | 
|---|
| [291] | 623 | { | 
|---|
| [587] | 624 | // compute memory buffer physical address | 
|---|
|  | 625 | unsigned int       flags;         // for _v2p_translate | 
|---|
|  | 626 | unsigned long long buf_paddr;     // buffer physical address | 
|---|
| [291] | 627 |  | 
|---|
| [587] | 628 | if ( ((_get_mmu_mode() & 0x4) == 0 ) || USE_IOC_RDK )  // identity | 
|---|
|  | 629 | { | 
|---|
|  | 630 | buf_paddr = (unsigned long long)buf_vaddr; | 
|---|
|  | 631 | } | 
|---|
|  | 632 | else                                // V2P translation required | 
|---|
| [291] | 633 | { | 
|---|
| [587] | 634 | buf_paddr = _v2p_translate( buf_vaddr , &flags ); | 
|---|
| [291] | 635 | } | 
|---|
| [587] | 636 |  | 
|---|
|  | 637 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 638 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 639 | _printf("\n[DEBUG FAT] _fat_ioc_access() : enters at cycle %d\n" | 
|---|
|  | 640 | "  to_mem = %d / vaddr = %x / paddr = %l / sectors = %d / lba = %x\n", | 
|---|
|  | 641 | _get_proctime(), to_mem, buf_vaddr, buf_paddr, count, lba ); | 
|---|
|  | 642 | #endif | 
|---|
|  | 643 |  | 
|---|
|  | 644 |  | 
|---|
|  | 645 | #if GIET_NO_HARD_CC     // L1 cache inval (virtual addresses) | 
|---|
|  | 646 | if ( to_mem ) _dcache_buf_invalidate( buf_vaddr, count<<9 ); | 
|---|
|  | 647 | #endif | 
|---|
|  | 648 |  | 
|---|
|  | 649 |  | 
|---|
|  | 650 | #if   ( USE_IOC_BDV )   // call the proper driver | 
|---|
|  | 651 | return( _bdv_access( use_irq , to_mem , lba , buf_paddr , count ) ); | 
|---|
|  | 652 | #elif ( USE_IOC_HBA ) | 
|---|
|  | 653 | return( _hba_access( use_irq , to_mem , lba , buf_paddr , count ) ); | 
|---|
|  | 654 | #elif ( USE_IOC_SDC ) | 
|---|
|  | 655 | return( _sdc_access( use_irq , to_mem , lba , buf_paddr , count ) ); | 
|---|
|  | 656 | #elif ( USE_IOC_SPI ) | 
|---|
|  | 657 | return( _spi_access( use_irq , to_mem , lba , buf_paddr , count ) ); | 
|---|
|  | 658 | #elif ( USE_IOC_RDK ) | 
|---|
|  | 659 | return( _rdk_access( use_irq , to_mem , lba , buf_paddr , count ) ); | 
|---|
|  | 660 | #else | 
|---|
|  | 661 | _printf("\n[FAT ERROR] in _fat_ioc_access() : no IOC driver\n"); | 
|---|
|  | 662 | _exit(); | 
|---|
|  | 663 | #endif | 
|---|
|  | 664 |  | 
|---|
|  | 665 | }  // end _fat_ioc_access() | 
|---|
|  | 666 |  | 
|---|
|  | 667 |  | 
|---|
|  | 668 |  | 
|---|
|  | 669 |  | 
|---|
|  | 670 | ///////////////////////////////////////////////////////////////////// | 
|---|
|  | 671 | static inline unsigned int _get_levels_from_size( unsigned int size ) | 
|---|
|  | 672 | { | 
|---|
|  | 673 | if      ( size <= (1<<18) ) return 1;     // 64 clusters == 256 Kbytes | 
|---|
|  | 674 | else if ( size <= (1<<24) ) return 2;     // 64 * 64 clusters => 16 Mbytes | 
|---|
|  | 675 | else if ( size <= (1<<30) ) return 3;     // 64 * 64 * 64 cluster => 1 Gbytes | 
|---|
|  | 676 | else                        return 4;     // 64 * 64 * 64 * 64 clusters | 
|---|
| [291] | 677 | } | 
|---|
|  | 678 |  | 
|---|
| [587] | 679 |  | 
|---|
|  | 680 |  | 
|---|
|  | 681 | //////////////////////////////////////////////////////// | 
|---|
|  | 682 | static unsigned int _read_entry( unsigned int    offset, | 
|---|
|  | 683 | unsigned int    size, | 
|---|
|  | 684 | unsigned char*  buffer, | 
|---|
|  | 685 | unsigned int    little_endian ) | 
|---|
| [258] | 686 | { | 
|---|
| [587] | 687 | unsigned int n; | 
|---|
| [258] | 688 | unsigned int res  = 0; | 
|---|
|  | 689 |  | 
|---|
| [587] | 690 | if ( little_endian) | 
|---|
| [258] | 691 | { | 
|---|
| [587] | 692 | for( n = size ; n > 0 ; n-- ) res = (res<<8) | buffer[offset+n-1]; | 
|---|
| [258] | 693 | } | 
|---|
|  | 694 | else | 
|---|
|  | 695 | { | 
|---|
| [587] | 696 | for( n = 0 ; n < size ; n++ ) res = (res<<8) | buffer[offset+n]; | 
|---|
| [258] | 697 | } | 
|---|
|  | 698 | return res; | 
|---|
|  | 699 |  | 
|---|
| [587] | 700 | }  // end _read_entry | 
|---|
| [258] | 701 |  | 
|---|
|  | 702 |  | 
|---|
|  | 703 |  | 
|---|
| [587] | 704 | ////////////////////////////////////////////////////////////////// | 
|---|
|  | 705 | static inline unsigned int _cluster_to_lba( unsigned int cluster ) | 
|---|
| [258] | 706 | { | 
|---|
| [587] | 707 | if ( cluster < 2 ) | 
|---|
|  | 708 | { | 
|---|
|  | 709 | _printf("\n[FAT ERROR] in _cluster_to_lba() cluster smaller than 2\n"); | 
|---|
|  | 710 | _exit(); | 
|---|
| [530] | 711 | } | 
|---|
| [258] | 712 |  | 
|---|
| [587] | 713 | return  ((cluster - 2) << 3) + _fat.data_lba; | 
|---|
| [258] | 714 | } | 
|---|
|  | 715 |  | 
|---|
| [587] | 716 |  | 
|---|
| [258] | 717 | ////////////////////////////////////////////////////// | 
|---|
| [596] | 718 | static inline unsigned char _to_lower(unsigned char c) | 
|---|
|  | 719 | { | 
|---|
|  | 720 | if (c >= 'A' && c <= 'Z') return (c | 0x20); | 
|---|
|  | 721 | else                      return c; | 
|---|
|  | 722 | } | 
|---|
|  | 723 |  | 
|---|
|  | 724 |  | 
|---|
|  | 725 | ////////////////////////////////////////////////////// | 
|---|
| [587] | 726 | static inline unsigned char _to_upper(unsigned char c) | 
|---|
| [258] | 727 | { | 
|---|
|  | 728 | if (c >= 'a' && c <= 'z') return (c & ~(0x20)); | 
|---|
|  | 729 | else                      return c; | 
|---|
|  | 730 | } | 
|---|
|  | 731 |  | 
|---|
|  | 732 |  | 
|---|
|  | 733 |  | 
|---|
| [587] | 734 | /////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 735 | static unsigned int _get_name_from_path( char*          pathname,  // input | 
|---|
|  | 736 | char*          name,      // output | 
|---|
|  | 737 | unsigned int*  nb_read )  // input & output | 
|---|
| [291] | 738 | { | 
|---|
| [587] | 739 | // skip leading "/" character | 
|---|
|  | 740 | if ( pathname[*nb_read] == '/' ) *nb_read = *nb_read + 1; | 
|---|
| [291] | 741 |  | 
|---|
| [587] | 742 | // initialises current indexes | 
|---|
|  | 743 | unsigned int i = *nb_read; | 
|---|
|  | 744 | unsigned int j = 0; | 
|---|
| [291] | 745 |  | 
|---|
| [587] | 746 | while ( (pathname[i] != '/') && (pathname[i] != 0) ) | 
|---|
| [291] | 747 | { | 
|---|
| [587] | 748 | name[j++] = pathname[i++]; | 
|---|
|  | 749 | if ( j > NAME_MAX_SIZE ) return 1; | 
|---|
| [291] | 750 | } | 
|---|
| [587] | 751 |  | 
|---|
|  | 752 | // set end of string | 
|---|
| [291] | 753 | name[j] = 0; | 
|---|
|  | 754 |  | 
|---|
| [587] | 755 | // skip trailing "/" character | 
|---|
| [291] | 756 | if ( pathname[i] == '/' ) *nb_read += j+1; | 
|---|
|  | 757 | else                      *nb_read += j; | 
|---|
|  | 758 |  | 
|---|
| [587] | 759 | return 0; | 
|---|
| [291] | 760 | } | 
|---|
|  | 761 |  | 
|---|
| [587] | 762 |  | 
|---|
|  | 763 |  | 
|---|
|  | 764 | //////////////////////////////////////////////////////////////////// | 
|---|
|  | 765 | static unsigned int _get_last_name( char*   pathname,       // input | 
|---|
|  | 766 | char*   name )          // output | 
|---|
|  | 767 | { | 
|---|
|  | 768 | unsigned int nb_read = 0; | 
|---|
|  | 769 | while ( pathname[nb_read] != 0 ) | 
|---|
|  | 770 | { | 
|---|
|  | 771 | if ( _get_name_from_path( pathname, name, &nb_read ) ) return 1; | 
|---|
|  | 772 | } | 
|---|
|  | 773 |  | 
|---|
|  | 774 | return 0; | 
|---|
|  | 775 | }   // end _get_last_name() | 
|---|
|  | 776 |  | 
|---|
|  | 777 |  | 
|---|
|  | 778 |  | 
|---|
| [258] | 779 | //////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 780 | static void _get_name_from_short( unsigned char* buffer,  // input:  SFN dir_entry | 
|---|
|  | 781 | char*          name )   // output: name | 
|---|
| [258] | 782 | { | 
|---|
| [596] | 783 | unsigned int i; | 
|---|
|  | 784 | unsigned int j = 0; | 
|---|
| [258] | 785 |  | 
|---|
| [596] | 786 | // get name | 
|---|
|  | 787 | for ( i = 0; i < 8 && buffer[i] != ' '; i++ ) | 
|---|
| [258] | 788 | { | 
|---|
| [596] | 789 | name[j] = _to_lower( buffer[i] ); | 
|---|
|  | 790 | j++; | 
|---|
| [258] | 791 | } | 
|---|
| [596] | 792 |  | 
|---|
|  | 793 | // get extension | 
|---|
|  | 794 | for ( i = 8; i < 8 + 3 && buffer[i] != ' '; i++ ) | 
|---|
|  | 795 | { | 
|---|
|  | 796 | // we entered the loop so there is an extension. add the dot | 
|---|
|  | 797 | if ( i == 8 ) | 
|---|
|  | 798 | { | 
|---|
|  | 799 | name[j] = '.'; | 
|---|
|  | 800 | j++; | 
|---|
|  | 801 | } | 
|---|
|  | 802 |  | 
|---|
|  | 803 | name[j] = _to_lower( buffer[i] ); | 
|---|
|  | 804 | j++; | 
|---|
|  | 805 | } | 
|---|
|  | 806 |  | 
|---|
|  | 807 | name[j] = '\0'; | 
|---|
| [258] | 808 | } | 
|---|
| [291] | 809 |  | 
|---|
| [258] | 810 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 811 | static void _get_name_from_long( unsigned char*  buffer, // input : LFN dir_entry | 
|---|
|  | 812 | char*           name )  // output : name | 
|---|
| [258] | 813 | { | 
|---|
| [587] | 814 | unsigned int   name_offset         = 0; | 
|---|
|  | 815 | unsigned int   buffer_offset       = get_length(LDIR_ORD); | 
|---|
| [258] | 816 | unsigned int   l_name_1            = get_length(LDIR_NAME_1); | 
|---|
|  | 817 | unsigned int   l_name_2            = get_length(LDIR_NAME_2); | 
|---|
|  | 818 | unsigned int   l_name_3            = get_length(LDIR_NAME_3); | 
|---|
|  | 819 | unsigned int   l_attr              = get_length(LDIR_ATTR); | 
|---|
|  | 820 | unsigned int   l_type              = get_length(LDIR_TYPE); | 
|---|
|  | 821 | unsigned int   l_chksum            = get_length(LDIR_CHKSUM); | 
|---|
|  | 822 | unsigned int   l_rsvd              = get_length(LDIR_RSVD); | 
|---|
|  | 823 |  | 
|---|
|  | 824 | unsigned int j            = 0; | 
|---|
|  | 825 | unsigned int eof          = 0; | 
|---|
|  | 826 |  | 
|---|
| [587] | 827 | while ( (buffer_offset != DIR_ENTRY_SIZE)  && (!eof) ) | 
|---|
| [258] | 828 | { | 
|---|
|  | 829 | while (j != l_name_1 && !eof ) | 
|---|
|  | 830 | { | 
|---|
| [587] | 831 | if ( (buffer[buffer_offset] == 0x00) || | 
|---|
|  | 832 | (buffer[buffer_offset] == 0xFF) ) | 
|---|
| [258] | 833 | { | 
|---|
|  | 834 | eof = 1; | 
|---|
|  | 835 | continue; | 
|---|
|  | 836 | } | 
|---|
| [587] | 837 | name[name_offset] = buffer[buffer_offset]; | 
|---|
|  | 838 | buffer_offset += 2; | 
|---|
| [258] | 839 | j += 2; | 
|---|
| [587] | 840 | name_offset++; | 
|---|
| [258] | 841 | } | 
|---|
|  | 842 |  | 
|---|
| [587] | 843 | buffer_offset += (l_attr + l_type + l_chksum); | 
|---|
| [258] | 844 | j = 0; | 
|---|
|  | 845 |  | 
|---|
|  | 846 | while (j != l_name_2 && !eof ) | 
|---|
|  | 847 | { | 
|---|
| [587] | 848 | if ( (buffer[buffer_offset] == 0x00) || | 
|---|
|  | 849 | (buffer[buffer_offset] == 0xFF) ) | 
|---|
| [258] | 850 | { | 
|---|
|  | 851 | eof = 1; | 
|---|
|  | 852 | continue; | 
|---|
|  | 853 | } | 
|---|
| [587] | 854 | name[name_offset] = buffer[buffer_offset]; | 
|---|
|  | 855 | buffer_offset += 2; | 
|---|
| [258] | 856 | j += 2; | 
|---|
| [587] | 857 | name_offset++; | 
|---|
| [258] | 858 | } | 
|---|
|  | 859 |  | 
|---|
| [587] | 860 | buffer_offset += l_rsvd; | 
|---|
| [258] | 861 | j = 0; | 
|---|
|  | 862 |  | 
|---|
|  | 863 | while (j != l_name_3 && !eof ) | 
|---|
|  | 864 | { | 
|---|
| [587] | 865 | if ( (buffer[buffer_offset] == 0x00) || | 
|---|
|  | 866 | (buffer[buffer_offset] == 0xFF) ) | 
|---|
| [258] | 867 | { | 
|---|
|  | 868 | eof = 1; | 
|---|
|  | 869 | continue; | 
|---|
|  | 870 | } | 
|---|
| [587] | 871 | name[name_offset] = buffer[buffer_offset]; | 
|---|
|  | 872 | buffer_offset += 2; | 
|---|
| [258] | 873 | j += 2; | 
|---|
| [587] | 874 | name_offset++; | 
|---|
| [258] | 875 | } | 
|---|
|  | 876 | } | 
|---|
| [587] | 877 | name[name_offset] = 0; | 
|---|
| [258] | 878 | } // end get_name_from_long() | 
|---|
|  | 879 |  | 
|---|
| [587] | 880 |  | 
|---|
|  | 881 |  | 
|---|
| [639] | 882 | //////////////////////////////////////////////////////////// | 
|---|
|  | 883 | static fat_cache_node_t* _allocate_one_cache_node( fat_cache_node_t* first_child ) | 
|---|
|  | 884 | { | 
|---|
|  | 885 | fat_cache_node_t* cnode; | 
|---|
|  | 886 | unsigned int i; | 
|---|
| [587] | 887 |  | 
|---|
| [639] | 888 | cnode = _malloc( sizeof(fat_cache_node_t) ); | 
|---|
|  | 889 |  | 
|---|
|  | 890 | cnode->children[0] = first_child; | 
|---|
|  | 891 | for ( i = 1 ; i < 64 ; i++ ) | 
|---|
|  | 892 | cnode->children[i] = NULL; | 
|---|
|  | 893 |  | 
|---|
|  | 894 | return cnode; | 
|---|
|  | 895 | }   // end _allocate_one_cache_node() | 
|---|
|  | 896 |  | 
|---|
|  | 897 |  | 
|---|
|  | 898 |  | 
|---|
| [587] | 899 | //////////////////////////////////////////////////////////// | 
|---|
|  | 900 | static fat_inode_t* _allocate_one_inode( char*        name, | 
|---|
|  | 901 | unsigned int is_dir, | 
|---|
|  | 902 | unsigned int cluster, | 
|---|
|  | 903 | unsigned int size, | 
|---|
|  | 904 | unsigned int count, | 
|---|
|  | 905 | unsigned int dentry, | 
|---|
|  | 906 | unsigned int cache_allocate ) | 
|---|
| [291] | 907 | { | 
|---|
| [587] | 908 | fat_inode_t* new_inode  = _malloc( sizeof(fat_inode_t) ); | 
|---|
| [291] | 909 |  | 
|---|
| [587] | 910 | new_inode->parent   = NULL;                 // set by _add_inode_in_tree() | 
|---|
|  | 911 | new_inode->next     = NULL;                 // set by _add_inode_in_tree() | 
|---|
|  | 912 | new_inode->child    = NULL;                 // set by _add_inode_in_tree() | 
|---|
|  | 913 | new_inode->cluster  = cluster; | 
|---|
|  | 914 | new_inode->size     = size; | 
|---|
|  | 915 | new_inode->cache    = NULL; | 
|---|
|  | 916 | new_inode->levels   = 0; | 
|---|
|  | 917 | new_inode->count    = count; | 
|---|
|  | 918 | new_inode->is_dir   = (is_dir != 0); | 
|---|
|  | 919 | new_inode->dentry   = dentry; | 
|---|
| [291] | 920 |  | 
|---|
| [587] | 921 | _strcpy( new_inode->name , name ); | 
|---|
|  | 922 |  | 
|---|
|  | 923 | if ( cache_allocate ) | 
|---|
| [291] | 924 | { | 
|---|
| [639] | 925 | new_inode->cache    = _allocate_one_cache_node( NULL ); | 
|---|
| [587] | 926 | new_inode->levels   = _get_levels_from_size( size ); | 
|---|
| [291] | 927 | } | 
|---|
|  | 928 |  | 
|---|
| [587] | 929 | return new_inode; | 
|---|
|  | 930 | }   // end _allocate_one_inode() | 
|---|
| [291] | 931 |  | 
|---|
| [587] | 932 |  | 
|---|
|  | 933 |  | 
|---|
|  | 934 |  | 
|---|
|  | 935 | //////////////////////////////////////////////////// | 
|---|
|  | 936 | static void _add_inode_in_tree( fat_inode_t*  child, | 
|---|
|  | 937 | fat_inode_t*  parent ) | 
|---|
|  | 938 | { | 
|---|
|  | 939 | child->parent = parent; | 
|---|
|  | 940 | child->next   = parent->child; | 
|---|
|  | 941 | parent->child = child; | 
|---|
|  | 942 | }   // end _add_inode-in_tree() | 
|---|
|  | 943 |  | 
|---|
|  | 944 |  | 
|---|
|  | 945 |  | 
|---|
|  | 946 |  | 
|---|
|  | 947 | ////////////////////////////////////////////////////////// | 
|---|
|  | 948 | static void _remove_inode_from_tree( fat_inode_t*  inode ) | 
|---|
|  | 949 | { | 
|---|
|  | 950 | fat_inode_t*  current; | 
|---|
|  | 951 | fat_inode_t*  prev = inode->parent->child; | 
|---|
|  | 952 |  | 
|---|
|  | 953 | if ( inode == prev )  // removed inode is first in its linked list | 
|---|
| [291] | 954 | { | 
|---|
| [587] | 955 | inode->parent->child = inode->next; | 
|---|
| [291] | 956 | } | 
|---|
| [587] | 957 | else                  // removed inode is not the first | 
|---|
| [291] | 958 | { | 
|---|
| [587] | 959 | for( current = prev->next ; current ; current = current->next ) | 
|---|
| [291] | 960 | { | 
|---|
| [587] | 961 | if ( current == inode ) | 
|---|
| [291] | 962 | { | 
|---|
| [587] | 963 | prev->next = current->next; | 
|---|
| [291] | 964 | } | 
|---|
| [587] | 965 | prev = current; | 
|---|
|  | 966 | } | 
|---|
|  | 967 | } | 
|---|
|  | 968 | }  // end _delete_one_inode() | 
|---|
| [291] | 969 |  | 
|---|
|  | 970 |  | 
|---|
| [587] | 971 |  | 
|---|
|  | 972 |  | 
|---|
|  | 973 | ////////////////////////////////////////////////////////////////////// | 
|---|
|  | 974 | static unsigned int _get_buffer_from_cache( fat_inode_t*        inode, | 
|---|
|  | 975 | unsigned int        cluster_id, | 
|---|
|  | 976 | fat_cache_desc_t**  desc ) | 
|---|
|  | 977 | { | 
|---|
|  | 978 | // get cache pointer and levels | 
|---|
|  | 979 | fat_cache_node_t*   node;         // pointer on a 64-tree node | 
|---|
|  | 980 | unsigned int        level;        // cache level | 
|---|
|  | 981 |  | 
|---|
|  | 982 | if ( inode == NULL )   // searched cache is the Fat-Cache | 
|---|
|  | 983 | { | 
|---|
|  | 984 | node   = _fat.fat_cache_root; | 
|---|
|  | 985 | level  = _fat.fat_cache_levels; | 
|---|
|  | 986 |  | 
|---|
|  | 987 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 988 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 989 | _printf("\n[DEBUG FAT] _get_buffer_from_cache() : enters in FAT-Cache" | 
|---|
|  | 990 | " for cluster_id = %d\n", cluster_id ); | 
|---|
|  | 991 | #endif | 
|---|
|  | 992 |  | 
|---|
|  | 993 | } | 
|---|
|  | 994 | else                   // searched cache is a File-Cache | 
|---|
|  | 995 | { | 
|---|
|  | 996 | node   = inode->cache; | 
|---|
|  | 997 | level  = inode->levels; | 
|---|
|  | 998 |  | 
|---|
|  | 999 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1000 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1001 | _printf("\n[DEBUG FAT] _get_buffer_from_cache() : enters in File-Cache <%s>" | 
|---|
|  | 1002 | " for cluster_id = %d\n", inode->name , cluster_id ); | 
|---|
|  | 1003 | #endif | 
|---|
|  | 1004 |  | 
|---|
|  | 1005 | } | 
|---|
|  | 1006 |  | 
|---|
|  | 1007 | // search the 64-tree cache from top to bottom | 
|---|
|  | 1008 | while ( level ) | 
|---|
|  | 1009 | { | 
|---|
|  | 1010 | // compute child index at each level | 
|---|
|  | 1011 | unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F; | 
|---|
|  | 1012 |  | 
|---|
|  | 1013 | if ( level == 1 )        // last level => children are cluster descriptors | 
|---|
| [291] | 1014 | { | 
|---|
| [587] | 1015 | fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; | 
|---|
| [291] | 1016 |  | 
|---|
| [587] | 1017 | if ( pdesc == NULL )      // miss | 
|---|
| [291] | 1018 | { | 
|---|
| [587] | 1019 | // allocate one cluster descriptor and one 4K buffer | 
|---|
|  | 1020 | unsigned char* buf = _malloc( 4096 ); | 
|---|
|  | 1021 | pdesc              = _malloc( sizeof(fat_cache_desc_t) ); | 
|---|
| [291] | 1022 |  | 
|---|
| [587] | 1023 | // get missing cluster index lba | 
|---|
|  | 1024 | unsigned int lba; | 
|---|
|  | 1025 | unsigned int next; | 
|---|
|  | 1026 | unsigned int current = inode->cluster; | 
|---|
|  | 1027 | unsigned int count   = cluster_id; | 
|---|
|  | 1028 |  | 
|---|
|  | 1029 | if ( inode == NULL )      // searched cache is the Fat-Cache | 
|---|
| [291] | 1030 | { | 
|---|
| [587] | 1031 |  | 
|---|
|  | 1032 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1033 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1034 | _printf("\n[DEBUG FAT] _get_buffer_from_cache() : miss in FAT-Cache for cluster_id %d\n", | 
|---|
|  | 1035 | cluster_id ); | 
|---|
|  | 1036 | #endif | 
|---|
|  | 1037 | lba = _fat.fat_lba + (cluster_id << 3); | 
|---|
| [291] | 1038 | } | 
|---|
| [587] | 1039 | else                      // searched cache is a File-Cache | 
|---|
|  | 1040 | { | 
|---|
|  | 1041 |  | 
|---|
|  | 1042 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1043 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1044 | _printf("\n[DEBUG FAT] _get_buffer_from_cache() : miss in File-Cache <%s> " | 
|---|
|  | 1045 | "for cluster_id %d\n", inode->name, cluster_id ); | 
|---|
|  | 1046 | #endif | 
|---|
|  | 1047 | while ( count ) | 
|---|
|  | 1048 | { | 
|---|
|  | 1049 | if ( _get_fat_entry( current , &next ) ) return 1; | 
|---|
|  | 1050 | current = next; | 
|---|
|  | 1051 | count--; | 
|---|
|  | 1052 | } | 
|---|
|  | 1053 | lba = _cluster_to_lba( current ); | 
|---|
|  | 1054 | } | 
|---|
|  | 1055 |  | 
|---|
|  | 1056 | // load one cluster (8 blocks) from block device | 
|---|
|  | 1057 | if ( _fat_ioc_access( 1,         // descheduling | 
|---|
|  | 1058 | 1,         // to memory | 
|---|
|  | 1059 | lba, | 
|---|
|  | 1060 | (unsigned int)buf, | 
|---|
|  | 1061 | 8 ) ) | 
|---|
|  | 1062 | { | 
|---|
|  | 1063 | _printf("\n[FAT ERROR] in _get_buffer_from_cache()" | 
|---|
|  | 1064 | " : cannot access block device for lba = %x\n", lba ); | 
|---|
|  | 1065 | return 1; | 
|---|
|  | 1066 | } | 
|---|
|  | 1067 |  | 
|---|
|  | 1068 | // update cache and buffer descriptor | 
|---|
|  | 1069 | node->children[index] = pdesc; | 
|---|
|  | 1070 | pdesc->lba     = lba; | 
|---|
|  | 1071 | pdesc->buffer  = buf; | 
|---|
|  | 1072 | pdesc->dirty   = 0; | 
|---|
|  | 1073 |  | 
|---|
|  | 1074 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1075 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1076 | _printf("\n[DEBUG FAT] _get_buffer_from_cache() : buffer loaded from device" | 
|---|
|  | 1077 | " at vaddr = %x\n", (unsigned int)buf ); | 
|---|
|  | 1078 | #endif | 
|---|
| [291] | 1079 | } | 
|---|
| [587] | 1080 |  | 
|---|
|  | 1081 | // return pdesc pointer | 
|---|
|  | 1082 | *desc = pdesc; | 
|---|
|  | 1083 |  | 
|---|
|  | 1084 | // prepare next iteration | 
|---|
|  | 1085 | level--; | 
|---|
|  | 1086 | } | 
|---|
|  | 1087 | else                      // not last level => children are 64-tree nodes | 
|---|
|  | 1088 | { | 
|---|
|  | 1089 | fat_cache_node_t* child = (fat_cache_node_t*)node->children[index]; | 
|---|
|  | 1090 | if ( child == NULL )  // miss | 
|---|
| [291] | 1091 | { | 
|---|
| [587] | 1092 | // allocate a cache node if miss | 
|---|
| [650] | 1093 | child = _allocate_one_cache_node( NULL ); | 
|---|
| [587] | 1094 | node->children[index] = child; | 
|---|
| [291] | 1095 | } | 
|---|
| [587] | 1096 |  | 
|---|
|  | 1097 | // prepare next iteration | 
|---|
|  | 1098 | node = child; | 
|---|
|  | 1099 | level--; | 
|---|
| [291] | 1100 | } | 
|---|
| [587] | 1101 | } // end while | 
|---|
| [291] | 1102 |  | 
|---|
| [530] | 1103 | return 0; | 
|---|
| [587] | 1104 | }  // end _get_buffer_from_cache() | 
|---|
| [530] | 1105 |  | 
|---|
|  | 1106 |  | 
|---|
| [291] | 1107 |  | 
|---|
|  | 1108 |  | 
|---|
| [587] | 1109 | ///////////////////////////////////// | 
|---|
|  | 1110 | static unsigned int _update_fs_info() | 
|---|
|  | 1111 | { | 
|---|
|  | 1112 | // update buffer if miss | 
|---|
|  | 1113 | if ( _fat.fs_info_lba != _fat.block_buffer_lba ) | 
|---|
| [291] | 1114 | { | 
|---|
| [587] | 1115 | if ( _fat_ioc_access( 1,                 // descheduling | 
|---|
| [530] | 1116 | 1,                 // read | 
|---|
| [587] | 1117 | _fat.fs_info_lba, | 
|---|
|  | 1118 | (unsigned int)_fat.block_buffer, | 
|---|
|  | 1119 | 1 ) )              // one block | 
|---|
| [291] | 1120 | { | 
|---|
| [530] | 1121 | _printf("\n[FAT_ERROR] in _update_fs_info() cannot read block\n"); | 
|---|
| [291] | 1122 | return 1; | 
|---|
|  | 1123 | } | 
|---|
| [587] | 1124 | _fat.block_buffer_lba = _fat.fs_info_lba; | 
|---|
| [291] | 1125 | } | 
|---|
|  | 1126 |  | 
|---|
| [587] | 1127 | // update FAT buffer | 
|---|
|  | 1128 | unsigned int* ptr; | 
|---|
|  | 1129 | ptr  = (unsigned int*)(_fat.block_buffer + get_offset(FS_FREE_CLUSTERS) ); | 
|---|
|  | 1130 | *ptr = _fat.free_clusters_number; | 
|---|
|  | 1131 |  | 
|---|
|  | 1132 | ptr  = (unsigned int*)(_fat.block_buffer + get_offset(FS_FREE_CLUSTER_HINT) ); | 
|---|
|  | 1133 | *ptr = _fat.first_free_cluster; | 
|---|
| [530] | 1134 |  | 
|---|
|  | 1135 | // write bloc to FAT | 
|---|
| [587] | 1136 | if ( _fat_ioc_access( 1,                // descheduling | 
|---|
| [530] | 1137 | 0,                // write | 
|---|
| [587] | 1138 | _fat.fs_info_lba, | 
|---|
|  | 1139 | (unsigned int)_fat.block_buffer, | 
|---|
|  | 1140 | 1 ) )             // one block | 
|---|
| [530] | 1141 | { | 
|---|
|  | 1142 | _printf("\n[FAT_ERROR] in _update_fs_info() cannot write block\n"); | 
|---|
|  | 1143 | return 1; | 
|---|
|  | 1144 | } | 
|---|
|  | 1145 |  | 
|---|
| [587] | 1146 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1147 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1148 | _printf("\n[DEBUG FAT] _update_fs_info() : nb_free = %x / first_free = %x\n", | 
|---|
|  | 1149 | _fat.free_clusters_number , _fat.first_free_cluster ); | 
|---|
|  | 1150 | #endif | 
|---|
|  | 1151 |  | 
|---|
| [530] | 1152 | return 0; | 
|---|
|  | 1153 | }  // end _update_fs_info() | 
|---|
|  | 1154 |  | 
|---|
| [587] | 1155 |  | 
|---|
|  | 1156 |  | 
|---|
|  | 1157 | ///////////////////////////////////////////////////////////////// | 
|---|
|  | 1158 | static inline unsigned int _get_fat_entry( unsigned int  cluster, | 
|---|
|  | 1159 | unsigned int* value ) | 
|---|
| [291] | 1160 | { | 
|---|
| [587] | 1161 | // compute cluster_id & entry_id in FAT | 
|---|
|  | 1162 | // a FAT cluster is an array of 1024 unsigned int entries | 
|---|
|  | 1163 | unsigned int       cluster_id = cluster >> 10; | 
|---|
|  | 1164 | unsigned int       entry_id   = cluster & 0x3FF; | 
|---|
| [291] | 1165 |  | 
|---|
| [587] | 1166 | // get pointer on the relevant cluster descriptor in FAT cache | 
|---|
|  | 1167 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 1168 | unsigned int*      buffer; | 
|---|
|  | 1169 | if ( _get_buffer_from_cache( NULL,               // Fat-Cache | 
|---|
|  | 1170 | cluster_id, | 
|---|
|  | 1171 | &pdesc ) ) return 1; | 
|---|
|  | 1172 |  | 
|---|
|  | 1173 | // get value from FAT slot | 
|---|
|  | 1174 | buffer = (unsigned int*)pdesc->buffer; | 
|---|
|  | 1175 | *value = buffer[entry_id]; | 
|---|
|  | 1176 |  | 
|---|
|  | 1177 | return 0; | 
|---|
|  | 1178 | }  // end _get_fat_entry() | 
|---|
|  | 1179 |  | 
|---|
|  | 1180 |  | 
|---|
|  | 1181 |  | 
|---|
|  | 1182 | //////////////////////////////////////////////////////////////// | 
|---|
|  | 1183 | static inline unsigned int _set_fat_entry( unsigned int cluster, | 
|---|
|  | 1184 | unsigned int value  ) | 
|---|
|  | 1185 | { | 
|---|
|  | 1186 | // compute cluster_id & entry_id in FAT | 
|---|
|  | 1187 | // a FAT cluster is an array of 1024 unsigned int entries | 
|---|
|  | 1188 | unsigned int cluster_id = cluster >> 10; | 
|---|
|  | 1189 | unsigned int entry_id   = cluster & 0x3FF; | 
|---|
|  | 1190 |  | 
|---|
|  | 1191 | // get pointer on the relevant cluster descriptor in FAT cache | 
|---|
|  | 1192 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 1193 | unsigned int*      buffer; | 
|---|
|  | 1194 | if ( _get_buffer_from_cache( NULL,               // Fat-Cache | 
|---|
|  | 1195 | cluster_id, | 
|---|
|  | 1196 | &pdesc ) )  return 1; | 
|---|
|  | 1197 |  | 
|---|
|  | 1198 | // set value into FAT slot | 
|---|
|  | 1199 | buffer           = (unsigned int*)pdesc->buffer; | 
|---|
|  | 1200 | buffer[entry_id] = value; | 
|---|
|  | 1201 | pdesc->dirty     = 1; | 
|---|
|  | 1202 |  | 
|---|
|  | 1203 | return 0; | 
|---|
|  | 1204 | } // end _set_fat_entry() | 
|---|
|  | 1205 |  | 
|---|
|  | 1206 |  | 
|---|
|  | 1207 |  | 
|---|
|  | 1208 | ////////////////////////////////////////////////////// | 
|---|
|  | 1209 | static void _allocate_one_buffer( fat_inode_t*  inode, | 
|---|
|  | 1210 | unsigned int  cluster_id, | 
|---|
|  | 1211 | unsigned int  cluster ) | 
|---|
|  | 1212 | { | 
|---|
| [639] | 1213 | // add cache levels if needed | 
|---|
|  | 1214 | while ( _get_levels_from_size( (cluster_id + 1) * 4096 ) > inode->levels ) | 
|---|
|  | 1215 | { | 
|---|
|  | 1216 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1217 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1218 | _printf("\n[DEBUG FAT] _allocate_one_buffer() : adding a cache level\n" ); | 
|---|
|  | 1219 | #endif | 
|---|
|  | 1220 |  | 
|---|
|  | 1221 | inode->cache = _allocate_one_cache_node( inode->cache ); | 
|---|
|  | 1222 | inode->levels++; | 
|---|
|  | 1223 | } | 
|---|
|  | 1224 |  | 
|---|
| [587] | 1225 | // search the 64-tree cache from top to bottom | 
|---|
|  | 1226 | fat_cache_node_t*  node   = inode->cache; | 
|---|
|  | 1227 | unsigned int       level  = inode->levels; | 
|---|
|  | 1228 |  | 
|---|
|  | 1229 | while ( level ) | 
|---|
|  | 1230 | { | 
|---|
|  | 1231 | // compute child index | 
|---|
|  | 1232 | unsigned int index = (cluster_id >> (6*(level-1))) & 0x3F; | 
|---|
|  | 1233 |  | 
|---|
|  | 1234 | if ( level == 1 )        // last level => children are cluster descriptors | 
|---|
|  | 1235 | { | 
|---|
|  | 1236 | fat_cache_desc_t* pdesc = (fat_cache_desc_t*)node->children[index]; | 
|---|
|  | 1237 | if ( pdesc != NULL )      // slot not empty!!! | 
|---|
|  | 1238 | { | 
|---|
|  | 1239 | _printf("\n[FAT ERROR] in allocate_one buffer() : slot not empty " | 
|---|
|  | 1240 | "in File-Cache <%s> / cluster_id = %d\n", inode->name , cluster_id ); | 
|---|
|  | 1241 | _exit(); | 
|---|
|  | 1242 | } | 
|---|
|  | 1243 |  | 
|---|
|  | 1244 | // allocate a cluster descriptor and a 4K buffer | 
|---|
|  | 1245 | pdesc = _malloc( sizeof(fat_cache_desc_t) ); | 
|---|
|  | 1246 | unsigned char* buffer = _malloc( 4096 ); | 
|---|
|  | 1247 |  | 
|---|
|  | 1248 | #if (GIET_DEBUG_FAT & 1) | 
|---|
| [569] | 1249 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 1250 | _printf("\n[DEBUG FAT] _allocate_one_buffer() : buffer allocated to <%s> for cluster_id %d\n", | 
|---|
|  | 1251 | inode->name, cluster_id ); | 
|---|
| [291] | 1252 | #endif | 
|---|
|  | 1253 |  | 
|---|
| [587] | 1254 | // update cache and pdesc | 
|---|
|  | 1255 | node->children[index] = pdesc; | 
|---|
|  | 1256 | pdesc->lba     = _cluster_to_lba( cluster ); | 
|---|
|  | 1257 | pdesc->buffer  = buffer; | 
|---|
|  | 1258 | pdesc->dirty   = 1; | 
|---|
|  | 1259 |  | 
|---|
|  | 1260 | // prepare next iteration | 
|---|
|  | 1261 | level--; | 
|---|
|  | 1262 | } | 
|---|
|  | 1263 | else                      // not last level => children are 64-tree nodes | 
|---|
| [291] | 1264 | { | 
|---|
| [587] | 1265 | fat_cache_node_t* child = (fat_cache_node_t*)node->children[index]; | 
|---|
|  | 1266 | if ( child == NULL )  // miss | 
|---|
|  | 1267 | { | 
|---|
|  | 1268 | // allocate a cache node if miss | 
|---|
| [650] | 1269 | child = _allocate_one_cache_node( NULL ); | 
|---|
| [587] | 1270 | node->children[index] = child; | 
|---|
|  | 1271 | } | 
|---|
|  | 1272 |  | 
|---|
|  | 1273 | // prepare next iteration | 
|---|
|  | 1274 | node  = child; | 
|---|
|  | 1275 | level--; | 
|---|
| [291] | 1276 | } | 
|---|
| [587] | 1277 | } // end while | 
|---|
|  | 1278 | } // end _allocate_one_buffer | 
|---|
| [530] | 1279 |  | 
|---|
|  | 1280 |  | 
|---|
| [587] | 1281 |  | 
|---|
|  | 1282 |  | 
|---|
|  | 1283 | /////////////////////////////////////////////////////////////////// | 
|---|
|  | 1284 | static unsigned int _allocate_one_cluster( unsigned int*  cluster ) | 
|---|
|  | 1285 | { | 
|---|
|  | 1286 | unsigned int nb_free = _fat.free_clusters_number; | 
|---|
|  | 1287 | unsigned int free    = _fat.first_free_cluster; | 
|---|
|  | 1288 |  | 
|---|
|  | 1289 | // scan FAT to get next free cluster index | 
|---|
|  | 1290 | unsigned int current = free; | 
|---|
|  | 1291 | unsigned int found   = 0; | 
|---|
|  | 1292 | unsigned int max     = (_fat.data_sectors >> 3); | 
|---|
|  | 1293 | unsigned int value; | 
|---|
|  | 1294 | do | 
|---|
| [530] | 1295 | { | 
|---|
| [587] | 1296 | // increment current | 
|---|
|  | 1297 | current++; | 
|---|
|  | 1298 |  | 
|---|
|  | 1299 | // get FAT entry indexed by current | 
|---|
|  | 1300 | if ( _get_fat_entry( current , &value ) ) return 1; | 
|---|
|  | 1301 | // test if free | 
|---|
|  | 1302 | if ( value == FREE_CLUSTER ) found = 1; | 
|---|
|  | 1303 | } | 
|---|
|  | 1304 | while ( (current < max) && (found == 0) ); | 
|---|
|  | 1305 |  | 
|---|
|  | 1306 | // check found | 
|---|
|  | 1307 | if ( found == 0 ) | 
|---|
|  | 1308 | { | 
|---|
|  | 1309 | _printf("\n[FAT_ERROR] in _allocate_one_cluster() : unconsistent FAT state"); | 
|---|
| [530] | 1310 | return 1; | 
|---|
|  | 1311 | } | 
|---|
|  | 1312 |  | 
|---|
| [587] | 1313 | // update allocated FAT slot | 
|---|
|  | 1314 | if ( _set_fat_entry( free , END_OF_CHAIN_CLUSTER_MAX ) ) return 1; | 
|---|
|  | 1315 |  | 
|---|
|  | 1316 | // update FAT descriptor global variables | 
|---|
|  | 1317 | _fat.free_clusters_number = nb_free - 1; | 
|---|
|  | 1318 | _fat.first_free_cluster   = current; | 
|---|
|  | 1319 |  | 
|---|
|  | 1320 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1321 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1322 | _printf("\n[DEBUG FAT] _allocate_one_cluster() : cluster = %x / first_free = %x\n", | 
|---|
|  | 1323 | free , current ); | 
|---|
|  | 1324 | #endif | 
|---|
|  | 1325 |  | 
|---|
|  | 1326 | // returns free cluster index | 
|---|
|  | 1327 | *cluster = free; | 
|---|
| [530] | 1328 | return 0; | 
|---|
| [291] | 1329 |  | 
|---|
| [587] | 1330 | }  // end _allocate_one_cluster() | 
|---|
|  | 1331 |  | 
|---|
|  | 1332 |  | 
|---|
|  | 1333 |  | 
|---|
|  | 1334 |  | 
|---|
|  | 1335 | ////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 1336 | static unsigned int _update_device_from_cache( unsigned int        levels, | 
|---|
|  | 1337 | fat_cache_node_t*   root, | 
|---|
|  | 1338 | char*               string ) | 
|---|
| [291] | 1339 | { | 
|---|
| [587] | 1340 | unsigned int index; | 
|---|
|  | 1341 | unsigned int ret = 0; | 
|---|
| [291] | 1342 |  | 
|---|
| [587] | 1343 | if ( levels == 1 )  // last level => children are cluster descriptors | 
|---|
| [291] | 1344 | { | 
|---|
| [587] | 1345 | for( index = 0 ; index < 64 ; index++ ) | 
|---|
|  | 1346 | { | 
|---|
|  | 1347 | fat_cache_desc_t* pdesc = root->children[index]; | 
|---|
|  | 1348 | if ( pdesc != NULL ) | 
|---|
|  | 1349 | { | 
|---|
|  | 1350 | // update cluster on device if dirty | 
|---|
|  | 1351 | if ( pdesc->dirty ) | 
|---|
|  | 1352 | { | 
|---|
|  | 1353 | if ( _fat_ioc_access( 1,           // descheduling | 
|---|
|  | 1354 | 0,           // to block device | 
|---|
|  | 1355 | pdesc->lba, | 
|---|
|  | 1356 | (unsigned int)pdesc->buffer, | 
|---|
|  | 1357 | 8 ) ) | 
|---|
|  | 1358 | { | 
|---|
|  | 1359 | _printf("\n[FAT_ERROR] in _update_device from_cache() : " | 
|---|
|  | 1360 | " cannot access lba = %x\n", pdesc->lba ); | 
|---|
|  | 1361 | ret = 1; | 
|---|
|  | 1362 | } | 
|---|
|  | 1363 | else | 
|---|
|  | 1364 | { | 
|---|
|  | 1365 | pdesc->dirty = 0; | 
|---|
|  | 1366 |  | 
|---|
|  | 1367 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1368 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1369 | _printf("\n[DEBUG FAT] _update_device_from_cache() : cluster_id = %d for <%s>\n", | 
|---|
|  | 1370 | index , string ); | 
|---|
|  | 1371 | #endif | 
|---|
|  | 1372 |  | 
|---|
|  | 1373 | } | 
|---|
|  | 1374 | } | 
|---|
|  | 1375 | } | 
|---|
|  | 1376 | } | 
|---|
| [291] | 1377 | } | 
|---|
| [587] | 1378 | else               // not the last level = recursive call on each children | 
|---|
| [291] | 1379 | { | 
|---|
| [587] | 1380 | for( index = 0 ; index < 64 ; index++ ) | 
|---|
|  | 1381 | { | 
|---|
|  | 1382 | fat_cache_node_t* pnode = root->children[index]; | 
|---|
|  | 1383 | if ( pnode != NULL ) | 
|---|
|  | 1384 | { | 
|---|
|  | 1385 | if ( _update_device_from_cache( levels - 1, | 
|---|
|  | 1386 | root->children[index], | 
|---|
|  | 1387 | string ) ) ret = 1; | 
|---|
|  | 1388 | } | 
|---|
|  | 1389 | } | 
|---|
| [291] | 1390 | } | 
|---|
| [587] | 1391 | return ret; | 
|---|
|  | 1392 | }  // end _update_device_from_cache() | 
|---|
| [291] | 1393 |  | 
|---|
|  | 1394 |  | 
|---|
| [587] | 1395 |  | 
|---|
|  | 1396 | /////////////////////////////////////////////////////////////////// | 
|---|
| [651] | 1397 | static void _release_cache_memory( fat_cache_node_t*  root, | 
|---|
|  | 1398 | unsigned int       levels ) | 
|---|
| [587] | 1399 | { | 
|---|
| [651] | 1400 | unsigned int i; | 
|---|
| [587] | 1401 |  | 
|---|
|  | 1402 | if ( levels == 1 )  // last level => children are cluster descriptors | 
|---|
| [503] | 1403 | { | 
|---|
| [651] | 1404 | for( i = 0 ; i < 64 ; i++ ) | 
|---|
| [587] | 1405 | { | 
|---|
| [651] | 1406 | fat_cache_desc_t* pdesc = root->children[i]; | 
|---|
| [587] | 1407 |  | 
|---|
|  | 1408 | if ( pdesc != NULL ) | 
|---|
|  | 1409 | { | 
|---|
|  | 1410 | // check dirty | 
|---|
|  | 1411 | if ( pdesc->dirty ) | 
|---|
| [651] | 1412 | _printf("\n[FAT ERROR] in _release_cache_memory() : dirty cluster\n"); | 
|---|
|  | 1413 |  | 
|---|
|  | 1414 | _free( pdesc->buffer ); | 
|---|
|  | 1415 | _free( pdesc ); | 
|---|
|  | 1416 | root->children[i] = NULL; | 
|---|
| [587] | 1417 | } | 
|---|
|  | 1418 | } | 
|---|
| [503] | 1419 | } | 
|---|
| [587] | 1420 | else               // not the last level = recursive call on each children | 
|---|
|  | 1421 | { | 
|---|
| [651] | 1422 | for( i = 0 ; i < 64 ; i++ ) | 
|---|
| [587] | 1423 | { | 
|---|
| [651] | 1424 | fat_cache_node_t* cnode = root->children[i]; | 
|---|
| [291] | 1425 |  | 
|---|
| [651] | 1426 | if ( cnode != NULL ) | 
|---|
|  | 1427 | { | 
|---|
|  | 1428 | _release_cache_memory( cnode, levels - 1 ); | 
|---|
|  | 1429 | _free( cnode ); | 
|---|
|  | 1430 | root->children[i] = NULL; | 
|---|
|  | 1431 | } | 
|---|
| [587] | 1432 | } | 
|---|
|  | 1433 | } | 
|---|
|  | 1434 | }  // end _release_cache_memory() | 
|---|
|  | 1435 |  | 
|---|
|  | 1436 |  | 
|---|
|  | 1437 |  | 
|---|
|  | 1438 |  | 
|---|
|  | 1439 |  | 
|---|
|  | 1440 | ///////////////////////////////////////////////////////////// | 
|---|
|  | 1441 | static unsigned int _clusters_allocate( fat_inode_t* inode, | 
|---|
|  | 1442 | unsigned int nb_current_clusters, | 
|---|
|  | 1443 | unsigned int nb_required_clusters ) | 
|---|
|  | 1444 | { | 
|---|
|  | 1445 | // Check if FAT contains enough free clusters | 
|---|
|  | 1446 | if ( nb_required_clusters > _fat.free_clusters_number ) | 
|---|
| [291] | 1447 | { | 
|---|
| [587] | 1448 | _printf("\n[FAT ERROR] in _clusters_allocate() : required_clusters = %d" | 
|---|
|  | 1449 | " / free_clusters = %d\n", nb_required_clusters , _fat.free_clusters_number ); | 
|---|
|  | 1450 | return 1; | 
|---|
|  | 1451 | } | 
|---|
| [291] | 1452 |  | 
|---|
| [587] | 1453 | #if (GIET_DEBUG_FAT & 1) | 
|---|
| [569] | 1454 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 1455 | _printf("\n[DEBUG FAT] _clusters_allocate() : enters for <%s> / nb_current_clusters = %d " | 
|---|
|  | 1456 | "/ nb_required_clusters = %d\n", | 
|---|
|  | 1457 | inode->name , nb_current_clusters , nb_required_clusters ); | 
|---|
| [291] | 1458 | #endif | 
|---|
| [587] | 1459 |  | 
|---|
|  | 1460 | // compute last allocated cluster index when (nb_current_clusters > 0) | 
|---|
|  | 1461 | unsigned int current = inode->cluster; | 
|---|
|  | 1462 | unsigned int next; | 
|---|
|  | 1463 | unsigned int last; | 
|---|
|  | 1464 | if ( nb_current_clusters )   // clusters allocated => search last | 
|---|
|  | 1465 | { | 
|---|
|  | 1466 | while ( current < END_OF_CHAIN_CLUSTER_MIN ) | 
|---|
| [291] | 1467 | { | 
|---|
| [587] | 1468 | // get next cluster | 
|---|
|  | 1469 | if ( _get_fat_entry( current , &next ) )  return 1; | 
|---|
|  | 1470 | last    = current; | 
|---|
|  | 1471 | current = next; | 
|---|
| [291] | 1472 | } | 
|---|
| [587] | 1473 | } | 
|---|
| [291] | 1474 |  | 
|---|
| [587] | 1475 | // Loop on the new clusters to be allocated | 
|---|
|  | 1476 | // if (nb_current_clusters == 0) the first new cluster index must | 
|---|
|  | 1477 | //                               be written in inode->cluster field | 
|---|
|  | 1478 | // if (nb_current_clusters >  0) the first new cluster index must | 
|---|
|  | 1479 | //                               be written in FAT[last] | 
|---|
|  | 1480 | unsigned int      cluster_id; | 
|---|
|  | 1481 | unsigned int      new; | 
|---|
|  | 1482 | for ( cluster_id = nb_current_clusters ; | 
|---|
|  | 1483 | cluster_id < (nb_current_clusters + nb_required_clusters) ; | 
|---|
|  | 1484 | cluster_id ++ ) | 
|---|
|  | 1485 | { | 
|---|
|  | 1486 | // allocate one cluster on block device | 
|---|
|  | 1487 | if ( _allocate_one_cluster( &new ) ) return 1; | 
|---|
| [291] | 1488 |  | 
|---|
| [587] | 1489 | // allocate one 4K buffer to File-Cache | 
|---|
|  | 1490 | _allocate_one_buffer( inode, | 
|---|
|  | 1491 | cluster_id, | 
|---|
|  | 1492 | new ); | 
|---|
|  | 1493 |  | 
|---|
|  | 1494 | if ( cluster_id == 0 )  // update inode | 
|---|
| [291] | 1495 | { | 
|---|
| [587] | 1496 | inode->cluster = new; | 
|---|
| [291] | 1497 | } | 
|---|
| [587] | 1498 | else                    // update FAT | 
|---|
| [291] | 1499 | { | 
|---|
| [587] | 1500 | if ( _set_fat_entry( last , new ) ) return 1; | 
|---|
| [291] | 1501 | } | 
|---|
|  | 1502 |  | 
|---|
| [587] | 1503 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1504 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1505 | _printf("\n[DEBUG FAT] _clusters_allocate() : done for cluster_id = %d / cluster = %x\n", | 
|---|
|  | 1506 | cluster_id , new ); | 
|---|
|  | 1507 | #endif | 
|---|
| [291] | 1508 |  | 
|---|
| [587] | 1509 | // update loop variables | 
|---|
|  | 1510 | last = new; | 
|---|
|  | 1511 |  | 
|---|
|  | 1512 | } // end for loop | 
|---|
|  | 1513 |  | 
|---|
|  | 1514 | // update FAT : last slot should contain END_OF_CHAIN_CLUSTER_MAX | 
|---|
|  | 1515 | if ( _set_fat_entry( last , END_OF_CHAIN_CLUSTER_MAX ) )  return 1; | 
|---|
|  | 1516 |  | 
|---|
|  | 1517 | // update the FAT on block device | 
|---|
|  | 1518 | if ( _update_device_from_cache( _fat.fat_cache_levels, | 
|---|
|  | 1519 | _fat.fat_cache_root, | 
|---|
|  | 1520 | "FAT" ) )              return 1; | 
|---|
|  | 1521 | return 0; | 
|---|
|  | 1522 | }  // end _clusters_allocate() | 
|---|
|  | 1523 |  | 
|---|
|  | 1524 |  | 
|---|
|  | 1525 |  | 
|---|
|  | 1526 | ////////////////////////////////////////////////////////////// | 
|---|
|  | 1527 | static unsigned int _clusters_release( unsigned int cluster ) | 
|---|
|  | 1528 | { | 
|---|
|  | 1529 | // scan the FAT | 
|---|
|  | 1530 | unsigned int current = cluster; | 
|---|
|  | 1531 | unsigned int next; | 
|---|
|  | 1532 | do | 
|---|
|  | 1533 | { | 
|---|
|  | 1534 | // get next_cluster index | 
|---|
|  | 1535 | if ( _get_fat_entry( current , &next ) )  return 1; | 
|---|
|  | 1536 |  | 
|---|
|  | 1537 | // release current_cluster | 
|---|
|  | 1538 | if ( _set_fat_entry( current , FREE_CLUSTER ) )   return 1; | 
|---|
|  | 1539 |  | 
|---|
|  | 1540 | // update first_free_cluster and free_clusters_number in FAT descriptor | 
|---|
|  | 1541 | _fat.free_clusters_number = _fat.free_clusters_number + 1; | 
|---|
|  | 1542 | if ( _fat.first_free_cluster > current ) _fat.first_free_cluster = current; | 
|---|
|  | 1543 |  | 
|---|
|  | 1544 | // update loop variable | 
|---|
|  | 1545 | current = next; | 
|---|
| [291] | 1546 | } | 
|---|
| [587] | 1547 | while ( next < END_OF_CHAIN_CLUSTER_MIN ); | 
|---|
| [291] | 1548 |  | 
|---|
| [587] | 1549 | // update the FAT on block device | 
|---|
|  | 1550 | if ( _update_device_from_cache( _fat.fat_cache_levels, | 
|---|
|  | 1551 | _fat.fat_cache_root, | 
|---|
|  | 1552 | "FAT" ) )                return 1; | 
|---|
| [291] | 1553 | return 0; | 
|---|
| [587] | 1554 | }  // end _clusters_release() | 
|---|
| [291] | 1555 |  | 
|---|
| [587] | 1556 |  | 
|---|
|  | 1557 |  | 
|---|
|  | 1558 | /////////////////////////////////////////////////////////// | 
|---|
|  | 1559 | static void _add_special_directories( fat_inode_t*  child, | 
|---|
|  | 1560 | fat_inode_t*  parent ) | 
|---|
| [258] | 1561 | { | 
|---|
| [587] | 1562 | // get first File-Cache buffer for child | 
|---|
|  | 1563 | fat_cache_desc_t*   pdesc  = (fat_cache_desc_t*)child->cache->children[0]; | 
|---|
|  | 1564 | unsigned char*      entry; | 
|---|
| [258] | 1565 |  | 
|---|
| [587] | 1566 | unsigned int i; | 
|---|
|  | 1567 | unsigned int cluster; | 
|---|
|  | 1568 | unsigned int size; | 
|---|
| [417] | 1569 |  | 
|---|
| [587] | 1570 | // set "." entry (32 bytes) | 
|---|
|  | 1571 | cluster = child->cluster; | 
|---|
|  | 1572 | size    = child->size; | 
|---|
|  | 1573 | entry   = pdesc->buffer; | 
|---|
|  | 1574 |  | 
|---|
|  | 1575 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
|  | 1576 | { | 
|---|
|  | 1577 | if      (i == 0 )     entry[i] = 0x2E;          // SFN | 
|---|
|  | 1578 | else if (i <  11)     entry[i] = 0x20;          // SFN | 
|---|
|  | 1579 | else if (i == 11)     entry[i] = 0x10;          // ATTR == dir | 
|---|
|  | 1580 | else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2 | 
|---|
|  | 1581 | else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3 | 
|---|
|  | 1582 | else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0 | 
|---|
|  | 1583 | else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1 | 
|---|
|  | 1584 | else if (i == 28)     entry[i] = size>>0;       // size.B0 | 
|---|
|  | 1585 | else if (i == 29)     entry[i] = size>>8;       // size.B1 | 
|---|
|  | 1586 | else if (i == 30)     entry[i] = size>>16;      // size.B2 | 
|---|
|  | 1587 | else if (i == 31)     entry[i] = size>>24;      // size.B3 | 
|---|
|  | 1588 | else                  entry[i] = 0x00; | 
|---|
|  | 1589 | } | 
|---|
| [258] | 1590 |  | 
|---|
| [587] | 1591 | // set ".." entry (32 bytes) | 
|---|
|  | 1592 | cluster = parent->cluster; | 
|---|
|  | 1593 | size    = parent->size; | 
|---|
|  | 1594 | entry   = pdesc->buffer + 32; | 
|---|
| [258] | 1595 |  | 
|---|
| [587] | 1596 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
| [258] | 1597 | { | 
|---|
| [587] | 1598 | if      (i <  2 )     entry[i] = 0x2E;          // SFN | 
|---|
|  | 1599 | else if (i <  11)     entry[i] = 0x20;          // SFN | 
|---|
|  | 1600 | else if (i == 11)     entry[i] = 0x10;          // ATTR == dir | 
|---|
|  | 1601 | else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2 | 
|---|
|  | 1602 | else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3 | 
|---|
|  | 1603 | else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0 | 
|---|
|  | 1604 | else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1 | 
|---|
|  | 1605 | else if (i == 28)     entry[i] = size>>0;       // size.B0 | 
|---|
|  | 1606 | else if (i == 29)     entry[i] = size>>8;       // size.B1 | 
|---|
|  | 1607 | else if (i == 30)     entry[i] = size>>16;      // size.B2 | 
|---|
|  | 1608 | else if (i == 31)     entry[i] = size>>24;      // size.B3 | 
|---|
|  | 1609 | else                  entry[i] = 0x00; | 
|---|
| [258] | 1610 | } | 
|---|
| [587] | 1611 | }  // end _add_special_directories | 
|---|
| [258] | 1612 |  | 
|---|
| [358] | 1613 |  | 
|---|
| [587] | 1614 |  | 
|---|
|  | 1615 | //////////////////////////////////////////////////////////// | 
|---|
| [638] | 1616 | static unsigned int _is_ancestor( fat_inode_t* a, | 
|---|
|  | 1617 | fat_inode_t* b ) | 
|---|
|  | 1618 | { | 
|---|
|  | 1619 | while ( b ) | 
|---|
|  | 1620 | { | 
|---|
|  | 1621 | if ( a == b ) | 
|---|
|  | 1622 | return 1; | 
|---|
|  | 1623 |  | 
|---|
|  | 1624 | b = b->parent; | 
|---|
|  | 1625 | } | 
|---|
|  | 1626 |  | 
|---|
|  | 1627 | return 0; | 
|---|
|  | 1628 | } // _is_ancestor() | 
|---|
|  | 1629 |  | 
|---|
|  | 1630 |  | 
|---|
|  | 1631 |  | 
|---|
|  | 1632 | //////////////////////////////////////////////////////////// | 
|---|
| [587] | 1633 | static unsigned int _check_name_length( char* name, | 
|---|
|  | 1634 | unsigned int* length, | 
|---|
|  | 1635 | unsigned int* nb_lfn ) | 
|---|
|  | 1636 | { | 
|---|
|  | 1637 | unsigned int len = _strlen( name ); | 
|---|
|  | 1638 | if      ( len <= 13 ) | 
|---|
| [258] | 1639 | { | 
|---|
| [587] | 1640 | *length  = len; | 
|---|
|  | 1641 | *nb_lfn  = 1; | 
|---|
|  | 1642 | return 0; | 
|---|
|  | 1643 | } | 
|---|
|  | 1644 | else if ( len <= 26 ) | 
|---|
|  | 1645 | { | 
|---|
|  | 1646 | *length  = len; | 
|---|
|  | 1647 | *nb_lfn  = 2; | 
|---|
|  | 1648 | return 0; | 
|---|
|  | 1649 | } | 
|---|
|  | 1650 | else if ( len <= 31 ) | 
|---|
|  | 1651 | { | 
|---|
|  | 1652 | *length  = len; | 
|---|
|  | 1653 | *nb_lfn  = 3; | 
|---|
|  | 1654 | return 0; | 
|---|
|  | 1655 | } | 
|---|
|  | 1656 | else | 
|---|
|  | 1657 | { | 
|---|
|  | 1658 | return 1; | 
|---|
|  | 1659 | } | 
|---|
|  | 1660 | }  // _check_name_length() | 
|---|
|  | 1661 |  | 
|---|
|  | 1662 |  | 
|---|
|  | 1663 |  | 
|---|
|  | 1664 |  | 
|---|
|  | 1665 | /////////////////////////////////////////////////////////// | 
|---|
|  | 1666 | static unsigned int _get_nb_entries( fat_inode_t*   inode, | 
|---|
|  | 1667 | unsigned int*  nb_entries ) | 
|---|
|  | 1668 | { | 
|---|
|  | 1669 | // scan directory until "end of directory" with two embedded loops: | 
|---|
|  | 1670 | // - scan the clusters allocated to this directory | 
|---|
|  | 1671 | // - scan the entries to find NO_MORE_ENTRY | 
|---|
|  | 1672 | fat_cache_desc_t*  pdesc;                      // pointer on buffer descriptor | 
|---|
|  | 1673 | unsigned char*     buffer;                     // 4 Kbytes buffer (one cluster) | 
|---|
|  | 1674 | unsigned int       ord;                        // ORD field in directory entry | 
|---|
|  | 1675 | unsigned int       attr;                       // ATTR field in directory entry | 
|---|
|  | 1676 | unsigned int       cluster_id = 0;             // cluster index in directory | 
|---|
|  | 1677 | unsigned int       offset     = 0;             // position in scanned buffer | 
|---|
|  | 1678 | unsigned int       found      = 0;             // NO_MORE_ENTRY found | 
|---|
|  | 1679 | unsigned int       count      = 0;             // number of valid NORMAL entries | 
|---|
|  | 1680 |  | 
|---|
|  | 1681 | // loop on clusters allocated to directory | 
|---|
|  | 1682 | while ( found == 0 ) | 
|---|
|  | 1683 | { | 
|---|
|  | 1684 | // get one 4 Kytes buffer from File_Cache | 
|---|
|  | 1685 | if ( _get_buffer_from_cache( inode, | 
|---|
|  | 1686 | cluster_id, | 
|---|
|  | 1687 | &pdesc ) )   return 1; | 
|---|
|  | 1688 | buffer = pdesc->buffer; | 
|---|
|  | 1689 |  | 
|---|
|  | 1690 | // loop on directory entries in buffer | 
|---|
|  | 1691 | while ( (offset < 4096) && (found == 0) ) | 
|---|
| [258] | 1692 | { | 
|---|
| [587] | 1693 | attr = _read_entry( DIR_ATTR , buffer + offset , 0 ); | 
|---|
|  | 1694 | ord  = _read_entry( LDIR_ORD , buffer + offset , 0 ); | 
|---|
|  | 1695 |  | 
|---|
|  | 1696 | if ( ord == NO_MORE_ENTRY ) | 
|---|
| [258] | 1697 | { | 
|---|
| [587] | 1698 | found = 1; | 
|---|
|  | 1699 | } | 
|---|
|  | 1700 | else if ( ord == FREE_ENTRY )             // free entry => skip | 
|---|
|  | 1701 | { | 
|---|
|  | 1702 | offset = offset + 32; | 
|---|
| [258] | 1703 | } | 
|---|
| [587] | 1704 | else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => skip | 
|---|
| [258] | 1705 | { | 
|---|
| [587] | 1706 | offset = offset + 32; | 
|---|
|  | 1707 | } | 
|---|
|  | 1708 | else                                      // NORMAL entry | 
|---|
|  | 1709 | { | 
|---|
| [620] | 1710 | offset = offset + 32; | 
|---|
| [587] | 1711 | count++; | 
|---|
|  | 1712 | } | 
|---|
|  | 1713 | }  // end loop on directory entries | 
|---|
|  | 1714 |  | 
|---|
|  | 1715 | cluster_id++; | 
|---|
|  | 1716 | offset = 0; | 
|---|
|  | 1717 |  | 
|---|
|  | 1718 | }  // end loop on clusters | 
|---|
|  | 1719 |  | 
|---|
|  | 1720 | // return nb_entries | 
|---|
|  | 1721 | *nb_entries = count; | 
|---|
|  | 1722 |  | 
|---|
|  | 1723 | return 0; | 
|---|
|  | 1724 | }  // end dir_not_empty() | 
|---|
|  | 1725 |  | 
|---|
|  | 1726 |  | 
|---|
|  | 1727 |  | 
|---|
|  | 1728 | /////////////////////////////////////////////////////////// | 
|---|
|  | 1729 | static unsigned int _add_dir_entry( fat_inode_t*   child, | 
|---|
|  | 1730 | fat_inode_t*   parent ) | 
|---|
|  | 1731 | { | 
|---|
|  | 1732 | // get child attributes | 
|---|
|  | 1733 | unsigned int      is_dir  = child->is_dir; | 
|---|
|  | 1734 | unsigned int      size    = child->size; | 
|---|
|  | 1735 | unsigned int      cluster = child->cluster; | 
|---|
|  | 1736 |  | 
|---|
|  | 1737 | // compute number of required entries to store child->name | 
|---|
|  | 1738 | // - Short name (less than 13 characters) require 3 entries: | 
|---|
|  | 1739 | //   one LFN entry / one NORMAL entry / one NO_MORE_ENTRY entry. | 
|---|
|  | 1740 | // - Longer names (up to 31 characters) can require 4 or 5 entries: | 
|---|
|  | 1741 | //   2 or 3 LFN entries / one NORMAL entry / one NO_MORE entry. | 
|---|
|  | 1742 | unsigned int length; | 
|---|
|  | 1743 | unsigned int nb_lfn; | 
|---|
|  | 1744 | if ( _check_name_length( child->name, | 
|---|
|  | 1745 | &length, | 
|---|
|  | 1746 | &nb_lfn ) )  return 1; | 
|---|
|  | 1747 |  | 
|---|
|  | 1748 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1749 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1750 | _printf("\n[DEBUG FAT] _add_dir_entry() : try to add <%s> in <%s> / nb_lfn = %d\n", | 
|---|
|  | 1751 | child->name , parent->name, nb_lfn ); | 
|---|
|  | 1752 | #endif | 
|---|
|  | 1753 |  | 
|---|
|  | 1754 | // Find end of directory : two embedded loops: | 
|---|
|  | 1755 | // - scan the clusters allocated to this directory | 
|---|
|  | 1756 | // - scan the entries to find NO_MORE_ENTRY | 
|---|
|  | 1757 | fat_cache_desc_t*  pdesc;                      // pointer on buffer descriptor | 
|---|
|  | 1758 | unsigned char*     buffer;                     // 4 Kbytes buffer (one cluster) | 
|---|
|  | 1759 | unsigned int       cluster_id = 0;             // cluster index in directory | 
|---|
|  | 1760 | unsigned int       offset     = 0;             // position in scanned buffer | 
|---|
|  | 1761 | unsigned int       found      = 0;             // NO_MORE_ENTRY found | 
|---|
|  | 1762 |  | 
|---|
|  | 1763 | // loop on clusters allocated to directory | 
|---|
|  | 1764 | while ( found == 0 ) | 
|---|
|  | 1765 | { | 
|---|
|  | 1766 | // get one 4 Kytes buffer from File_Cache | 
|---|
|  | 1767 | if ( _get_buffer_from_cache( parent, | 
|---|
|  | 1768 | cluster_id, | 
|---|
|  | 1769 | &pdesc ) )   return 1; | 
|---|
|  | 1770 |  | 
|---|
|  | 1771 | buffer = pdesc->buffer; | 
|---|
|  | 1772 |  | 
|---|
|  | 1773 | // loop on directory entries in buffer | 
|---|
|  | 1774 | while ( (offset < 4096) && (found == 0) ) | 
|---|
|  | 1775 | { | 
|---|
|  | 1776 | if ( _read_entry( LDIR_ORD , buffer + offset , 0 ) == NO_MORE_ENTRY ) | 
|---|
| [258] | 1777 | { | 
|---|
| [587] | 1778 | found        = 1; | 
|---|
|  | 1779 | pdesc->dirty = 1; | 
|---|
|  | 1780 | } | 
|---|
|  | 1781 | else | 
|---|
|  | 1782 | { | 
|---|
|  | 1783 | offset = offset + 32; | 
|---|
| [258] | 1784 | } | 
|---|
| [587] | 1785 | }  // end loop on entries | 
|---|
|  | 1786 | if ( found == 0 ) | 
|---|
|  | 1787 | { | 
|---|
|  | 1788 | cluster_id++; | 
|---|
|  | 1789 | offset = 0; | 
|---|
| [258] | 1790 | } | 
|---|
| [587] | 1791 | }  // end loop on clusters | 
|---|
| [258] | 1792 |  | 
|---|
| [587] | 1793 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1794 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1795 | _printf("\n[DEBUG FAT] _add_dir_entry() : get NO_MORE directory entry : " | 
|---|
|  | 1796 | " buffer = %x / offset = %x / cluster_id = %d\n", | 
|---|
|  | 1797 | (unsigned int)buffer , offset , cluster_id ); | 
|---|
|  | 1798 | #endif | 
|---|
| [258] | 1799 |  | 
|---|
| [587] | 1800 | // enter FSM : | 
|---|
|  | 1801 | // The new child requires to write 3, 4, or 5 directory entries. | 
|---|
|  | 1802 | // To actually register the new child, we use a 5 steps FSM | 
|---|
|  | 1803 | // (one state per entry to be written), that is traversed as: | 
|---|
|  | 1804 | //    LFN3 -> LFN2 -> LFN1 -> NORMAL -> NOMORE | 
|---|
|  | 1805 | // The buffer and first directory entry to be  written are identified | 
|---|
|  | 1806 | // by the variables : buffer / cluster_id / offset | 
|---|
| [417] | 1807 |  | 
|---|
| [587] | 1808 | unsigned char* name  = (unsigned char*)child->name; | 
|---|
|  | 1809 |  | 
|---|
|  | 1810 | unsigned int step;          // FSM state | 
|---|
|  | 1811 |  | 
|---|
|  | 1812 | if      ( nb_lfn == 1 ) step = 3; | 
|---|
|  | 1813 | else if ( nb_lfn == 2 ) step = 4; | 
|---|
|  | 1814 | else if ( nb_lfn == 3 ) step = 5; | 
|---|
|  | 1815 |  | 
|---|
|  | 1816 | unsigned int   i;           // byte index in 32 bytes directory | 
|---|
|  | 1817 | unsigned int   c;           // character index in name | 
|---|
|  | 1818 | unsigned char* entry;       // buffer + offset; | 
|---|
|  | 1819 |  | 
|---|
|  | 1820 | while ( step ) | 
|---|
|  | 1821 | { | 
|---|
|  | 1822 | // get another buffer if required | 
|---|
|  | 1823 | if ( offset >= 4096 )  // new buffer required | 
|---|
| [417] | 1824 | { | 
|---|
| [587] | 1825 | if ( cluster_id == 63 )   // we need to increase depth of File-Cache | 
|---|
| [258] | 1826 | { | 
|---|
| [587] | 1827 | _printf("\n[FAT ERROR] in add_dir_entry() File Cache depth extension " | 
|---|
|  | 1828 | " not implemented\n" ); | 
|---|
|  | 1829 | _exit();  // TODO | 
|---|
| [258] | 1830 | } | 
|---|
| [587] | 1831 | else | 
|---|
| [258] | 1832 | { | 
|---|
| [587] | 1833 | if ( _get_buffer_from_cache( parent, | 
|---|
|  | 1834 | cluster_id + 1, | 
|---|
|  | 1835 | &pdesc ) )      return 1; | 
|---|
|  | 1836 | buffer       = pdesc->buffer; | 
|---|
|  | 1837 | pdesc->dirty = 1; | 
|---|
|  | 1838 | offset       = 0; | 
|---|
|  | 1839 | } | 
|---|
|  | 1840 | } | 
|---|
| [417] | 1841 |  | 
|---|
| [587] | 1842 | // compute directory entry address | 
|---|
|  | 1843 | entry = buffer + offset; | 
|---|
| [417] | 1844 |  | 
|---|
| [587] | 1845 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1846 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1847 | _printf("\n[DEBUG FAT] _add_dir_entry() : FSM step = %d /" | 
|---|
|  | 1848 | " offset = %x / nb_lfn = %d\n", step, offset, nb_lfn ); | 
|---|
|  | 1849 | #endif | 
|---|
|  | 1850 |  | 
|---|
|  | 1851 | // write one 32 bytes directory entry per iteration | 
|---|
|  | 1852 | switch ( step ) | 
|---|
|  | 1853 | { | 
|---|
|  | 1854 | case 5:   // write LFN3 entry | 
|---|
|  | 1855 | { | 
|---|
|  | 1856 | c = 26; | 
|---|
|  | 1857 | // scan the 32 bytes in dir_entry | 
|---|
|  | 1858 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
| [258] | 1859 | { | 
|---|
| [587] | 1860 | if (i == 0) | 
|---|
|  | 1861 | { | 
|---|
|  | 1862 | if ( nb_lfn == 3) entry[i] = 0x43; | 
|---|
|  | 1863 | else              entry[i] = 0x03; | 
|---|
|  | 1864 | } | 
|---|
|  | 1865 | else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   || | 
|---|
|  | 1866 | ((i >= 14) && (i<=25) && ((i&1)==0))   || | 
|---|
|  | 1867 | ((i >= 28) && (i<=31) && ((i&1)==0)) ) && | 
|---|
|  | 1868 | ( c < length ) ) | 
|---|
|  | 1869 | { | 
|---|
|  | 1870 | entry[i] = name[c]; | 
|---|
|  | 1871 | c++; | 
|---|
|  | 1872 | } | 
|---|
|  | 1873 | else if (i == 11)     entry[i] = 0x0F; | 
|---|
|  | 1874 | else if (i == 12)     entry[i] = 0xCA; | 
|---|
|  | 1875 | else                  entry[i] = 0x00; | 
|---|
| [258] | 1876 | } | 
|---|
| [587] | 1877 | step--; | 
|---|
|  | 1878 | break; | 
|---|
|  | 1879 | } | 
|---|
|  | 1880 | case 4:   // write LFN2 entry | 
|---|
|  | 1881 | { | 
|---|
|  | 1882 | c = 13; | 
|---|
|  | 1883 | // scan the 32 bytes in dir_entry | 
|---|
|  | 1884 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
| [258] | 1885 | { | 
|---|
| [587] | 1886 | if (i == 0) | 
|---|
|  | 1887 | { | 
|---|
|  | 1888 | if ( nb_lfn == 2) entry[i] = 0x42; | 
|---|
|  | 1889 | else              entry[i] = 0x02; | 
|---|
|  | 1890 | } | 
|---|
|  | 1891 | else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   || | 
|---|
|  | 1892 | ((i >= 14) && (i<=25) && ((i&1)==0))   || | 
|---|
|  | 1893 | ((i >= 28) && (i<=31) && ((i&1)==0)) ) && | 
|---|
|  | 1894 | ( c < length ) ) | 
|---|
|  | 1895 | { | 
|---|
|  | 1896 | entry[i] = name[c]; | 
|---|
|  | 1897 | c++; | 
|---|
|  | 1898 | } | 
|---|
|  | 1899 | else if (i == 11)     entry[i] = 0x0F; | 
|---|
|  | 1900 | else if (i == 12)     entry[i] = 0xCA; | 
|---|
|  | 1901 | else                  entry[i] = 0x00; | 
|---|
| [258] | 1902 | } | 
|---|
| [587] | 1903 | step--; | 
|---|
|  | 1904 | break; | 
|---|
| [258] | 1905 | } | 
|---|
| [587] | 1906 | case 3:   // Write LFN1 entry | 
|---|
| [258] | 1907 | { | 
|---|
| [587] | 1908 | c = 0; | 
|---|
|  | 1909 | // scan the 32 bytes in dir_entry | 
|---|
|  | 1910 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
|  | 1911 | { | 
|---|
|  | 1912 | if (i == 0) | 
|---|
|  | 1913 | { | 
|---|
|  | 1914 | if ( nb_lfn == 1) entry[i] = 0x41; | 
|---|
|  | 1915 | else              entry[i] = 0x01; | 
|---|
|  | 1916 | } | 
|---|
|  | 1917 | else if ( ( ((i >= 1 ) && (i<=10) && ((i&1)==1))   || | 
|---|
|  | 1918 | ((i >= 14) && (i<=25) && ((i&1)==0))   || | 
|---|
|  | 1919 | ((i >= 28) && (i<=31) && ((i&1)==0)) ) && | 
|---|
|  | 1920 | ( c < length ) ) | 
|---|
|  | 1921 | { | 
|---|
|  | 1922 | entry[i] = name[c]; | 
|---|
|  | 1923 | c++; | 
|---|
|  | 1924 | } | 
|---|
|  | 1925 | else if (i == 11)     entry[i] = 0x0F; | 
|---|
|  | 1926 | else if (i == 12)     entry[i] = 0xCA; | 
|---|
|  | 1927 | else                  entry[i] = 0x00; | 
|---|
|  | 1928 | } | 
|---|
|  | 1929 | step--; | 
|---|
|  | 1930 | break; | 
|---|
| [258] | 1931 | } | 
|---|
| [587] | 1932 | case 2:   // write NORMAL entry | 
|---|
| [258] | 1933 | { | 
|---|
| [587] | 1934 | c = 0; | 
|---|
|  | 1935 | // scan the 32 bytes in dir_entry | 
|---|
|  | 1936 | for ( i = 0 ; i < 32 ; i++ ) | 
|---|
| [258] | 1937 | { | 
|---|
| [587] | 1938 | if      ( (i < 8) && (c < length) )             // SFN | 
|---|
| [417] | 1939 | { | 
|---|
| [587] | 1940 | entry[i] = _to_upper( name[c] ); | 
|---|
|  | 1941 | c++; | 
|---|
| [417] | 1942 | } | 
|---|
| [587] | 1943 | else if (i <  11)     entry[i] = 0x20;          // EXT | 
|---|
|  | 1944 | else if (i == 11)                               // ATTR | 
|---|
|  | 1945 | { | 
|---|
|  | 1946 | if (is_dir)       entry[i] = 0x10; | 
|---|
|  | 1947 | else              entry[i] = 0x20; | 
|---|
|  | 1948 | } | 
|---|
|  | 1949 | else if (i == 20)     entry[i] = cluster>>16;   // cluster.B2 | 
|---|
|  | 1950 | else if (i == 21)     entry[i] = cluster>>24;   // cluster.B3 | 
|---|
|  | 1951 | else if (i == 26)     entry[i] = cluster>>0;    // cluster.B0 | 
|---|
|  | 1952 | else if (i == 27)     entry[i] = cluster>>8;    // cluster.B1 | 
|---|
|  | 1953 | else if (i == 28)     entry[i] = size>>0;       // size.B0 | 
|---|
|  | 1954 | else if (i == 29)     entry[i] = size>>8;       // size.B1 | 
|---|
|  | 1955 | else if (i == 30)     entry[i] = size>>16;      // size.B2 | 
|---|
|  | 1956 | else if (i == 31)     entry[i] = size>>24;      // size.B3 | 
|---|
|  | 1957 | else                  entry[i] = 0x00; | 
|---|
| [258] | 1958 | } | 
|---|
| [587] | 1959 |  | 
|---|
|  | 1960 | // update the dentry field in child inode | 
|---|
|  | 1961 | child->dentry = ((cluster_id<<12) + offset)>>5; | 
|---|
|  | 1962 |  | 
|---|
|  | 1963 | step--; | 
|---|
|  | 1964 | break; | 
|---|
| [417] | 1965 | } | 
|---|
| [587] | 1966 | case 1:   // write NOMORE entry | 
|---|
| [417] | 1967 | { | 
|---|
| [587] | 1968 | step--; | 
|---|
|  | 1969 | entry [0] = 0x00; | 
|---|
|  | 1970 | break; | 
|---|
|  | 1971 | } | 
|---|
|  | 1972 | } // end switch step | 
|---|
|  | 1973 | offset += 32; | 
|---|
|  | 1974 | } // exit while => exit FSM | 
|---|
|  | 1975 |  | 
|---|
|  | 1976 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 1977 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 1978 | { | 
|---|
|  | 1979 | _printf("\n[DEBUG FAT] _add_dir_entry() : <%s> successfully added in <%s>\n", | 
|---|
|  | 1980 | child->name , parent->name ); | 
|---|
|  | 1981 | } | 
|---|
|  | 1982 | #endif | 
|---|
|  | 1983 |  | 
|---|
|  | 1984 | return 0; | 
|---|
|  | 1985 | } // end _add_dir_entry | 
|---|
|  | 1986 |  | 
|---|
|  | 1987 |  | 
|---|
|  | 1988 |  | 
|---|
|  | 1989 | //////////////////////////////////////////////////////////// | 
|---|
|  | 1990 | static unsigned int _remove_dir_entry( fat_inode_t*  inode ) | 
|---|
|  | 1991 | { | 
|---|
|  | 1992 | // compute number of LFN entries | 
|---|
|  | 1993 | unsigned int length; | 
|---|
|  | 1994 | unsigned int nb_lfn; | 
|---|
|  | 1995 | if ( _check_name_length( inode->name, | 
|---|
|  | 1996 | &length, | 
|---|
|  | 1997 | &nb_lfn ) )  return 1; | 
|---|
|  | 1998 |  | 
|---|
|  | 1999 | // get cluster_id and offset in parent directory cache | 
|---|
|  | 2000 | unsigned int  dentry     = inode->dentry; | 
|---|
|  | 2001 | unsigned int  cluster_id = dentry >> 7; | 
|---|
|  | 2002 | unsigned int  offset     = (dentry & 0x7F)<<5; | 
|---|
|  | 2003 |  | 
|---|
|  | 2004 | // get buffer from parent directory cache | 
|---|
|  | 2005 | unsigned char*     buffer; | 
|---|
|  | 2006 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 2007 |  | 
|---|
|  | 2008 | if ( _get_buffer_from_cache( inode->parent, | 
|---|
|  | 2009 | cluster_id, | 
|---|
|  | 2010 | &pdesc ) ) return 1; | 
|---|
|  | 2011 | buffer       = pdesc->buffer; | 
|---|
|  | 2012 | pdesc->dirty = 1; | 
|---|
|  | 2013 |  | 
|---|
|  | 2014 | // invalidate NORMAL entry in directory cache | 
|---|
|  | 2015 | buffer[offset] = 0xE5; | 
|---|
|  | 2016 |  | 
|---|
|  | 2017 | // invalidate LFN entries | 
|---|
|  | 2018 | while ( nb_lfn ) | 
|---|
|  | 2019 | { | 
|---|
| [616] | 2020 | if (offset == 0)  // we must load buffer for (cluster_id - 1) | 
|---|
| [587] | 2021 | { | 
|---|
| [636] | 2022 | if ( cluster_id == 0 ) | 
|---|
|  | 2023 | break; | 
|---|
|  | 2024 |  | 
|---|
| [587] | 2025 | if ( _get_buffer_from_cache( inode->parent, | 
|---|
|  | 2026 | cluster_id - 1, | 
|---|
|  | 2027 | &pdesc ) )   return 1; | 
|---|
|  | 2028 | buffer       = pdesc->buffer; | 
|---|
|  | 2029 | pdesc->dirty = 1; | 
|---|
| [616] | 2030 | offset       = 4096; | 
|---|
| [587] | 2031 | } | 
|---|
|  | 2032 |  | 
|---|
| [616] | 2033 | offset = offset - 32; | 
|---|
|  | 2034 |  | 
|---|
|  | 2035 | // check for LFN entry | 
|---|
|  | 2036 | if ( _read_entry( DIR_ATTR , buffer + offset , 0 ) != ATTR_LONG_NAME_MASK ) | 
|---|
|  | 2037 | break; | 
|---|
|  | 2038 |  | 
|---|
| [587] | 2039 | // invalidate LFN entry | 
|---|
|  | 2040 | buffer[offset] = 0xE5; | 
|---|
|  | 2041 |  | 
|---|
|  | 2042 | nb_lfn--; | 
|---|
|  | 2043 | } | 
|---|
|  | 2044 |  | 
|---|
|  | 2045 | return 0; | 
|---|
|  | 2046 | }  // end _remove_dir_entry | 
|---|
|  | 2047 |  | 
|---|
|  | 2048 |  | 
|---|
|  | 2049 |  | 
|---|
|  | 2050 |  | 
|---|
|  | 2051 | //////////////////////////////////////////////////////////// | 
|---|
|  | 2052 | static unsigned int _update_dir_entry( fat_inode_t*  inode ) | 
|---|
|  | 2053 | { | 
|---|
|  | 2054 | // get Cache-File buffer containing the parent directory entry | 
|---|
|  | 2055 | // 128 directories entries in one 4 Kbytes buffer | 
|---|
|  | 2056 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 2057 | unsigned char*     buffer; | 
|---|
|  | 2058 | unsigned int       cluster_id = inode->dentry>>7; | 
|---|
| [626] | 2059 | unsigned int       offset     = (inode->dentry & 0x7F)<<5; | 
|---|
| [587] | 2060 |  | 
|---|
|  | 2061 | if ( _get_buffer_from_cache( inode->parent, | 
|---|
|  | 2062 | cluster_id, | 
|---|
|  | 2063 | &pdesc ) )    return 1; | 
|---|
|  | 2064 | buffer       = pdesc->buffer; | 
|---|
|  | 2065 | pdesc->dirty = 1; | 
|---|
|  | 2066 |  | 
|---|
|  | 2067 | // update size field | 
|---|
|  | 2068 | buffer[offset + 28] = inode->size>>0;       // size.B0 | 
|---|
|  | 2069 | buffer[offset + 29] = inode->size>>8;       // size.B1 | 
|---|
|  | 2070 | buffer[offset + 30] = inode->size>>16;      // size.B2 | 
|---|
|  | 2071 | buffer[offset + 31] = inode->size>>24;      // size.B3 | 
|---|
|  | 2072 |  | 
|---|
|  | 2073 | // update cluster field | 
|---|
|  | 2074 | buffer[offset + 26] = inode->cluster>>0;    // cluster.B0 | 
|---|
|  | 2075 | buffer[offset + 27] = inode->cluster>>8;    // cluster.B1 | 
|---|
|  | 2076 | buffer[offset + 20] = inode->cluster>>16;   // cluster.B2 | 
|---|
|  | 2077 | buffer[offset + 21] = inode->cluster>>24;   // cluster.B3 | 
|---|
|  | 2078 |  | 
|---|
|  | 2079 | return 0; | 
|---|
|  | 2080 | } // end _update_dir_entry() | 
|---|
|  | 2081 |  | 
|---|
|  | 2082 |  | 
|---|
|  | 2083 |  | 
|---|
|  | 2084 |  | 
|---|
|  | 2085 | ////////////////////////////////////////////////////////////////// | 
|---|
|  | 2086 | static unsigned int _get_child_from_parent( fat_inode_t*   parent, | 
|---|
|  | 2087 | char*          name, | 
|---|
|  | 2088 | fat_inode_t**  inode ) | 
|---|
|  | 2089 | { | 
|---|
|  | 2090 | fat_inode_t*   current; | 
|---|
|  | 2091 |  | 
|---|
|  | 2092 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2093 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2094 | _printf("\n[DEBUG FAT] _get_child_from_parent() : search <%s> in directory <%s>\n", | 
|---|
|  | 2095 | name , parent->name ); | 
|---|
|  | 2096 | #endif | 
|---|
|  | 2097 |  | 
|---|
|  | 2098 | // scan inodes in the parent directory | 
|---|
|  | 2099 | for ( current = parent->child ; current ; current = current->next ) | 
|---|
|  | 2100 | { | 
|---|
| [619] | 2101 | if ( _strcmp( name , current->name ) == 0 ) | 
|---|
| [587] | 2102 | { | 
|---|
|  | 2103 |  | 
|---|
|  | 2104 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2105 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2106 | _printf("\n[DEBUG FAT] _get_child_from_parent() : found inode <%s> in directory <%s>\n", | 
|---|
|  | 2107 | name , parent->name ); | 
|---|
|  | 2108 | #endif | 
|---|
|  | 2109 | *inode = current; | 
|---|
|  | 2110 | return 0;           // name found | 
|---|
|  | 2111 | } | 
|---|
|  | 2112 | } | 
|---|
|  | 2113 |  | 
|---|
|  | 2114 | // not found in Inode-Tree => access the parent directory | 
|---|
|  | 2115 | // file_cache.  Two embedded loops: | 
|---|
|  | 2116 | // - scan the clusters allocated to this directory | 
|---|
|  | 2117 | // - scan the directory entries in each 4 Kbytes buffer | 
|---|
|  | 2118 |  | 
|---|
|  | 2119 | unsigned char*    buffer;           // pointer on one cache buffer | 
|---|
|  | 2120 | char              cname[32];        // buffer for one full entry name | 
|---|
|  | 2121 | char              lfn1[16];         // buffer for one partial name | 
|---|
|  | 2122 | char              lfn2[16];         // buffer for one partial name | 
|---|
|  | 2123 | char              lfn3[16];         // buffer for one partial name | 
|---|
|  | 2124 | unsigned int      size;             // searched file/dir size (bytes) | 
|---|
|  | 2125 | unsigned int      cluster;          // searched file/dir cluster index | 
|---|
|  | 2126 | unsigned int      is_dir;           // searched file/dir type | 
|---|
|  | 2127 | unsigned int      attr;             // directory entry ATTR field | 
|---|
|  | 2128 | unsigned int      ord;              // directory entry ORD field | 
|---|
| [597] | 2129 | unsigned int      lfn = 0;          // LFN entries number | 
|---|
| [587] | 2130 | unsigned int      dentry;           // directory entry index | 
|---|
|  | 2131 | unsigned int      offset     = 0;   // byte offset in buffer | 
|---|
|  | 2132 | unsigned int      cluster_id = 0;   // cluster index in directory | 
|---|
|  | 2133 | int               found      = 0;   // not found (0) / name found (1) / end of dir (-1) | 
|---|
|  | 2134 |  | 
|---|
|  | 2135 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2136 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2137 | _printf("\n[DEBUG FAT] _get_child_from_parent() : does not found inode <%s>" | 
|---|
|  | 2138 | " in directory <%s> => search in cache\n", name , parent->name ); | 
|---|
|  | 2139 | #endif | 
|---|
|  | 2140 |  | 
|---|
|  | 2141 | // scan the clusters allocated to parent directory | 
|---|
|  | 2142 | while ( found == 0 ) | 
|---|
|  | 2143 | { | 
|---|
|  | 2144 | // get one 4 Kytes buffer from parent File_Cache | 
|---|
|  | 2145 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 2146 | if ( _get_buffer_from_cache( parent, | 
|---|
|  | 2147 | cluster_id, | 
|---|
|  | 2148 | &pdesc ) )    return 2; | 
|---|
|  | 2149 | buffer = pdesc->buffer; | 
|---|
|  | 2150 |  | 
|---|
|  | 2151 | // scan this buffer until end of directory, end of buffer, or name found | 
|---|
|  | 2152 | while( (offset < 4096) && (found == 0) ) | 
|---|
|  | 2153 | { | 
|---|
|  | 2154 |  | 
|---|
|  | 2155 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2156 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2157 | _printf("\n[DEBUG FAT] _get_child_from_parent() : scan buffer %d for <%s>\n", | 
|---|
|  | 2158 | cluster_id , name ); | 
|---|
|  | 2159 | #endif | 
|---|
|  | 2160 | attr = _read_entry( DIR_ATTR , buffer + offset , 0 ); | 
|---|
|  | 2161 | ord  = _read_entry( LDIR_ORD , buffer + offset , 0 ); | 
|---|
|  | 2162 |  | 
|---|
|  | 2163 | if (ord == NO_MORE_ENTRY)                 // no more entry in directory => break | 
|---|
|  | 2164 | { | 
|---|
|  | 2165 | found = -1; | 
|---|
|  | 2166 | } | 
|---|
|  | 2167 | else if ( ord == FREE_ENTRY )             // free entry => skip | 
|---|
|  | 2168 | { | 
|---|
|  | 2169 | offset = offset + 32; | 
|---|
|  | 2170 | } | 
|---|
|  | 2171 | else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial name | 
|---|
|  | 2172 | { | 
|---|
|  | 2173 | unsigned int seq = ord & 0x3; | 
|---|
|  | 2174 | lfn = (seq > lfn) ? seq : lfn; | 
|---|
|  | 2175 | if      ( seq == 1 ) _get_name_from_long( buffer + offset, lfn1 ); | 
|---|
|  | 2176 | else if ( seq == 2 ) _get_name_from_long( buffer + offset, lfn2 ); | 
|---|
|  | 2177 | else if ( seq == 3 ) _get_name_from_long( buffer + offset, lfn3 ); | 
|---|
|  | 2178 | offset = offset + 32; | 
|---|
|  | 2179 | } | 
|---|
|  | 2180 | else                                 // NORMAL entry | 
|---|
|  | 2181 | { | 
|---|
|  | 2182 | // build the extracted name | 
|---|
|  | 2183 | if      ( lfn == 0 ) | 
|---|
| [258] | 2184 | { | 
|---|
| [587] | 2185 | _get_name_from_short( buffer + offset , cname ); | 
|---|
| [258] | 2186 | } | 
|---|
| [587] | 2187 | else if ( lfn == 1 ) | 
|---|
| [417] | 2188 | { | 
|---|
| [587] | 2189 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2190 | } | 
|---|
|  | 2191 | else if ( lfn == 2 ) | 
|---|
|  | 2192 | { | 
|---|
|  | 2193 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2194 | _strcpy( cname + 13 , lfn2 ); | 
|---|
| [417] | 2195 | } | 
|---|
| [587] | 2196 | else if ( lfn == 3 ) | 
|---|
|  | 2197 | { | 
|---|
|  | 2198 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2199 | _strcpy( cname + 13 , lfn2 ); | 
|---|
|  | 2200 | _strcpy( cname + 26 , lfn3 ); | 
|---|
|  | 2201 | } | 
|---|
|  | 2202 |  | 
|---|
|  | 2203 | // test if extracted name == searched name | 
|---|
| [619] | 2204 | if ( _strcmp( name , cname ) == 0 ) | 
|---|
| [587] | 2205 | { | 
|---|
|  | 2206 | cluster = (_read_entry( DIR_FST_CLUS_HI , buffer + offset , 1 ) << 16) | | 
|---|
|  | 2207 | (_read_entry( DIR_FST_CLUS_LO , buffer + offset , 1 )      ) ; | 
|---|
|  | 2208 | dentry  = ((cluster_id<<12) + offset)>>5; | 
|---|
|  | 2209 | is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY); | 
|---|
|  | 2210 | size    = _read_entry( DIR_FILE_SIZE , buffer + offset , 1 ); | 
|---|
|  | 2211 | found   = 1; | 
|---|
|  | 2212 | } | 
|---|
|  | 2213 | offset = offset + 32; | 
|---|
|  | 2214 | lfn    = 0; | 
|---|
| [258] | 2215 | } | 
|---|
| [587] | 2216 | }  // end loop on directory entries | 
|---|
|  | 2217 | cluster_id++; | 
|---|
|  | 2218 | offset = 0; | 
|---|
|  | 2219 | }  // end loop on buffers | 
|---|
|  | 2220 |  | 
|---|
|  | 2221 | if ( found == -1 )  // found end of directory in parent directory | 
|---|
|  | 2222 | { | 
|---|
|  | 2223 |  | 
|---|
|  | 2224 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2225 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2226 | _printf("\n[DEBUG FAT] _get_child_from_parent() : found end of directory in <%s>\n", | 
|---|
|  | 2227 | parent->name ); | 
|---|
|  | 2228 | #endif | 
|---|
|  | 2229 | *inode = NULL; | 
|---|
|  | 2230 | return 1; | 
|---|
|  | 2231 | } | 
|---|
|  | 2232 | else               // found searched name in parent directory | 
|---|
|  | 2233 | { | 
|---|
|  | 2234 | // allocate a new inode and an empty Cache-File | 
|---|
|  | 2235 | *inode = _allocate_one_inode( name, | 
|---|
|  | 2236 | is_dir, | 
|---|
|  | 2237 | cluster, | 
|---|
|  | 2238 | size, | 
|---|
|  | 2239 | 0,             // count | 
|---|
|  | 2240 | dentry, | 
|---|
|  | 2241 | 1 );           // cache_allocate | 
|---|
|  | 2242 |  | 
|---|
|  | 2243 | // introduce it in Inode-Tree | 
|---|
|  | 2244 | _add_inode_in_tree( *inode , parent ); | 
|---|
|  | 2245 |  | 
|---|
|  | 2246 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2247 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2248 | _printf("\n[DEBUG FAT] _get_child_from_parent() : found <%s> on device\n", name ); | 
|---|
|  | 2249 | #endif | 
|---|
|  | 2250 | return 0; | 
|---|
|  | 2251 | } | 
|---|
|  | 2252 | }  // end _get_child_from_parent() | 
|---|
|  | 2253 |  | 
|---|
|  | 2254 |  | 
|---|
|  | 2255 |  | 
|---|
|  | 2256 |  | 
|---|
|  | 2257 | ////////////////////////////////////////////////////////////////// | 
|---|
|  | 2258 | static unsigned int _get_inode_from_path( char*          pathname, | 
|---|
|  | 2259 | fat_inode_t**  inode ) | 
|---|
|  | 2260 | { | 
|---|
|  | 2261 | char                 name[32];         // buffer for one name in pathname | 
|---|
|  | 2262 | unsigned int         nb_read;              // number of characters written in name[] | 
|---|
|  | 2263 | fat_inode_t*         parent;           // parent inode | 
|---|
|  | 2264 | fat_inode_t*         child;            // child inode | 
|---|
|  | 2265 | unsigned int         last;             // while exit condition | 
|---|
|  | 2266 | unsigned int         code;             // return value | 
|---|
|  | 2267 |  | 
|---|
|  | 2268 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2269 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2270 | _printf("\n[DEBUG FAT] _get_inode_from_path() : enters for path <%s>\n", pathname ); | 
|---|
|  | 2271 | #endif | 
|---|
|  | 2272 |  | 
|---|
|  | 2273 | // handle root directory case | 
|---|
| [619] | 2274 | if ( _strcmp( pathname , "/" ) == 0 ) | 
|---|
| [587] | 2275 | { | 
|---|
|  | 2276 |  | 
|---|
|  | 2277 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2278 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2279 | _printf("\n[DEBUG FAT] _get_inode_from_path() : found root inode for <%s>\n", | 
|---|
|  | 2280 | pathname ); | 
|---|
|  | 2281 | #endif | 
|---|
|  | 2282 | *inode  = _fat.inode_tree_root; | 
|---|
|  | 2283 | return 0; | 
|---|
|  | 2284 | } | 
|---|
|  | 2285 |  | 
|---|
|  | 2286 | // If the pathname is not "/", we traverse the inode tree from the root. | 
|---|
|  | 2287 | // We use _get_name_from_path() to scan pathname and extract inode names. | 
|---|
|  | 2288 | // We use _get_child_from_parent() to scan each directory in the path. | 
|---|
|  | 2289 |  | 
|---|
|  | 2290 | last       = 0; | 
|---|
|  | 2291 | nb_read    = 0;                      // number of characters analysed in path | 
|---|
|  | 2292 | parent     = _fat.inode_tree_root;   // Inode-Tree root | 
|---|
|  | 2293 |  | 
|---|
| [617] | 2294 | while ( !last ) | 
|---|
| [587] | 2295 | { | 
|---|
|  | 2296 | // get searched file/dir name | 
|---|
|  | 2297 | if ( _get_name_from_path( pathname, name, &nb_read ) ) | 
|---|
|  | 2298 | { | 
|---|
|  | 2299 | return 3;   // error : name too long | 
|---|
| [258] | 2300 | } | 
|---|
|  | 2301 |  | 
|---|
| [587] | 2302 | // compute last iteration condition | 
|---|
|  | 2303 | last = (pathname[nb_read] == 0); | 
|---|
| [258] | 2304 |  | 
|---|
| [587] | 2305 | #if (GIET_DEBUG_FAT & 1) | 
|---|
| [569] | 2306 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2307 | _printf("\n[DEBUG FAT] _get_inode_from_path() : got name <%s>\n", name ); | 
|---|
| [417] | 2308 | #endif | 
|---|
|  | 2309 |  | 
|---|
| [619] | 2310 | if ( _strcmp( name, ".." ) == 0) | 
|---|
| [587] | 2311 | { | 
|---|
| [617] | 2312 | // found special name "..", try to go up | 
|---|
|  | 2313 | code = 0; | 
|---|
|  | 2314 | if ( parent->parent ) | 
|---|
|  | 2315 | child = parent->parent; | 
|---|
|  | 2316 | else | 
|---|
|  | 2317 | child = parent; | 
|---|
|  | 2318 | } | 
|---|
| [619] | 2319 | else if ( _strcmp( name, "." ) == 0 ) | 
|---|
| [617] | 2320 | { | 
|---|
|  | 2321 | // found special name ".", stay on the same level | 
|---|
|  | 2322 | code = 0; | 
|---|
|  | 2323 | child = parent; | 
|---|
|  | 2324 | } | 
|---|
|  | 2325 | else | 
|---|
|  | 2326 | { | 
|---|
|  | 2327 | // get child inode from parent directory | 
|---|
|  | 2328 | code = _get_child_from_parent( parent, | 
|---|
|  | 2329 | name, | 
|---|
|  | 2330 | &child ); | 
|---|
| [417] | 2331 |  | 
|---|
| [617] | 2332 | // we need to find the child inode for all non terminal names | 
|---|
|  | 2333 | if ( (code == 2) || ((code == 1 ) && !last) ) | 
|---|
|  | 2334 | { | 
|---|
|  | 2335 |  | 
|---|
|  | 2336 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2337 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2338 | _printf("\n[DEBUG FAT] _get_inode_from_path() : neither parent, nor child found for <%s>\n", | 
|---|
|  | 2339 | pathname ); | 
|---|
|  | 2340 | #endif | 
|---|
|  | 2341 | return 2;  // error : parent inode not found | 
|---|
|  | 2342 | } | 
|---|
| [587] | 2343 | } | 
|---|
| [617] | 2344 |  | 
|---|
| [587] | 2345 | // update parent if not the last iteration | 
|---|
| [617] | 2346 | if ( !last ) | 
|---|
|  | 2347 | parent = child; | 
|---|
| [587] | 2348 | } // end while | 
|---|
|  | 2349 |  | 
|---|
|  | 2350 | // returns inode pointer | 
|---|
|  | 2351 | if (code == 0 ) | 
|---|
|  | 2352 | { | 
|---|
|  | 2353 |  | 
|---|
|  | 2354 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2355 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2356 | _printf("\n[DEBUG FAT] _get_inode_from_path() : found inode for <%s>\n", | 
|---|
|  | 2357 | pathname ); | 
|---|
|  | 2358 | #endif | 
|---|
|  | 2359 | *inode  = child; | 
|---|
|  | 2360 | } | 
|---|
|  | 2361 | else | 
|---|
|  | 2362 | { | 
|---|
|  | 2363 |  | 
|---|
|  | 2364 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2365 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2366 | _printf("\n[DEBUG FAT] _get_inode_from_path() : found only parent inode for <%s>\n", | 
|---|
|  | 2367 | pathname ); | 
|---|
|  | 2368 | #endif | 
|---|
|  | 2369 | *inode  = parent; | 
|---|
|  | 2370 | } | 
|---|
|  | 2371 |  | 
|---|
|  | 2372 | return code;                 // can be 0 (found) or 1 (not found) | 
|---|
|  | 2373 |  | 
|---|
|  | 2374 | }  // end _get_inode_from_path() | 
|---|
|  | 2375 |  | 
|---|
|  | 2376 |  | 
|---|
|  | 2377 |  | 
|---|
|  | 2378 |  | 
|---|
|  | 2379 | ////////////////////////////////////////////////////////////// | 
|---|
|  | 2380 | static unsigned int _remove_node_from_fs( fat_inode_t* inode ) | 
|---|
| [258] | 2381 | { | 
|---|
| [637] | 2382 | // check for root node | 
|---|
|  | 2383 | if ( !inode->parent ) return 1; | 
|---|
|  | 2384 |  | 
|---|
| [587] | 2385 | // remove entry in parent directory | 
|---|
|  | 2386 | if ( _remove_dir_entry( inode ) ) return 1; | 
|---|
|  | 2387 |  | 
|---|
|  | 2388 | // update parent directory on device | 
|---|
|  | 2389 | if ( _update_device_from_cache( inode->parent->levels, | 
|---|
|  | 2390 | inode->parent->cache, | 
|---|
|  | 2391 | inode->parent->name ) ) return 1; | 
|---|
|  | 2392 |  | 
|---|
|  | 2393 | // release clusters allocated to file/dir in DATA region | 
|---|
|  | 2394 | if ( _clusters_release( inode->cluster ) ) return 1; | 
|---|
|  | 2395 |  | 
|---|
|  | 2396 | // release File-Cache | 
|---|
| [651] | 2397 | _release_cache_memory( inode->cache, inode->levels ); | 
|---|
|  | 2398 | _free ( inode->cache ); | 
|---|
| [587] | 2399 |  | 
|---|
|  | 2400 | // remove inode from Inode-Tree | 
|---|
|  | 2401 | _remove_inode_from_tree( inode ); | 
|---|
|  | 2402 |  | 
|---|
|  | 2403 | // release inode | 
|---|
|  | 2404 | _free ( inode ); | 
|---|
|  | 2405 |  | 
|---|
| [258] | 2406 | return 0; | 
|---|
| [587] | 2407 | }  // end _remove_node_from_fs() | 
|---|
| [258] | 2408 |  | 
|---|
|  | 2409 |  | 
|---|
| [587] | 2410 | ////////////////////////////////////////////////////////////////// | 
|---|
|  | 2411 | static unsigned int _next_cluster_no_cache( unsigned int   cluster, | 
|---|
|  | 2412 | unsigned int*  next ) | 
|---|
|  | 2413 | { | 
|---|
|  | 2414 | // compute cluster_id and slot_id | 
|---|
|  | 2415 | // each cluster contains 1024 slots (4 bytes per slot) | 
|---|
|  | 2416 | unsigned int cluster_id  = cluster >> 10; | 
|---|
|  | 2417 | unsigned int slot_id     = cluster & 0x3FF; | 
|---|
| [258] | 2418 |  | 
|---|
| [587] | 2419 | // compute lba of cluster identified by cluster_id | 
|---|
|  | 2420 | unsigned int lba = _fat.fat_lba + (cluster_id << 3); | 
|---|
| [258] | 2421 |  | 
|---|
| [587] | 2422 | // get cluster containing the adressed FAT slot in FAT buffer | 
|---|
|  | 2423 | if ( _fat_buffer_fat_lba != lba ) | 
|---|
|  | 2424 | { | 
|---|
|  | 2425 | if ( _fat_ioc_access( 0,         // no descheduling | 
|---|
|  | 2426 | 1,         // read | 
|---|
|  | 2427 | lba, | 
|---|
|  | 2428 | (unsigned int)_fat_buffer_fat, | 
|---|
|  | 2429 | 8 ) ) | 
|---|
|  | 2430 | { | 
|---|
|  | 2431 | _printf("\n[FAT ERROR] in _next_cluster_no_cache() : " | 
|---|
|  | 2432 | "cannot load lba = %x into fat_buffer\n", lba ); | 
|---|
|  | 2433 | return 1; | 
|---|
|  | 2434 | } | 
|---|
|  | 2435 |  | 
|---|
|  | 2436 | _fat_buffer_fat_lba = lba; | 
|---|
|  | 2437 | } | 
|---|
|  | 2438 |  | 
|---|
|  | 2439 | // return next cluster index | 
|---|
|  | 2440 | unsigned int* buf = (unsigned int*)_fat_buffer_fat; | 
|---|
|  | 2441 | *next = buf[slot_id]; | 
|---|
|  | 2442 | return 0; | 
|---|
|  | 2443 |  | 
|---|
|  | 2444 | }  // end _next_cluster_no_cache() | 
|---|
|  | 2445 |  | 
|---|
|  | 2446 |  | 
|---|
|  | 2447 |  | 
|---|
|  | 2448 |  | 
|---|
|  | 2449 | ///////////////////////////////////////////////////////////////// | 
|---|
|  | 2450 | static unsigned int _file_info_no_cache( char*          pathname, | 
|---|
|  | 2451 | unsigned int*  file_cluster, | 
|---|
|  | 2452 | unsigned int*  file_size ) | 
|---|
| [258] | 2453 | { | 
|---|
| [587] | 2454 |  | 
|---|
|  | 2455 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2456 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2457 | _printf("\n[DEBUG FAT] _file_info_no_cache() : enters for path <%s>\n", pathname ); | 
|---|
|  | 2458 | #endif | 
|---|
| [258] | 2459 |  | 
|---|
| [587] | 2460 | char            name[32];             // buffer for one name in the analysed pathname | 
|---|
|  | 2461 | char            lfn1[16];             // buffer for a partial name in LFN entry | 
|---|
|  | 2462 | char            lfn2[16];             // buffer for a partial name in LFN entry | 
|---|
|  | 2463 | char            lfn3[16];             // buffer for a partial name in LFN entry | 
|---|
|  | 2464 | char            cname[32];            // buffer for a full name in a directory entry | 
|---|
|  | 2465 | unsigned int    nb_read;              // number of characters analysed in path | 
|---|
|  | 2466 | unsigned int    parent_cluster;       // cluster index for the parent directory | 
|---|
| [597] | 2467 | unsigned int    child_cluster = 0;    // cluster index for the searched file/dir | 
|---|
|  | 2468 | unsigned int    child_size = 0;       // size of the searched file/dir | 
|---|
| [587] | 2469 | unsigned int    child_is_dir;         // type of the searched file/dir | 
|---|
|  | 2470 | unsigned int    offset;               // offset in a 4 Kbytes buffer | 
|---|
|  | 2471 | unsigned int    ord;                  // ORD field in a directory entry | 
|---|
|  | 2472 | unsigned int    attr;                 // ATTR field in a directory entry | 
|---|
| [597] | 2473 | unsigned int    lfn = 0;              // number of lfn entries | 
|---|
| [587] | 2474 | unsigned char*  buf;                  // pointer on a 4 Kbytes buffer | 
|---|
|  | 2475 | unsigned int    found;                // name found in current directory entry | 
|---|
|  | 2476 |  | 
|---|
|  | 2477 | // Three embedded loops: | 
|---|
|  | 2478 | // - scan pathname to extract file/dir names, | 
|---|
|  | 2479 | // - for each name, scan the clusters of the parent directory | 
|---|
|  | 2480 | // - for each cluster, scan the 4 Kbytes buffer to find the file/dir name | 
|---|
|  | 2481 | // The starting point is the root directory (cluster 2) | 
|---|
|  | 2482 |  | 
|---|
|  | 2483 | nb_read        = 0; | 
|---|
|  | 2484 | parent_cluster = 2; | 
|---|
|  | 2485 |  | 
|---|
|  | 2486 | // scan pathname | 
|---|
|  | 2487 | while ( pathname[nb_read] != 0 ) | 
|---|
|  | 2488 | { | 
|---|
|  | 2489 | // get searched file/dir name | 
|---|
|  | 2490 | if ( _get_name_from_path( pathname, name, &nb_read ) ) return 1; | 
|---|
|  | 2491 |  | 
|---|
|  | 2492 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2493 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2494 | _printf("\n[DEBUG FAT] _file_info_no_cache() : search name <%s>" | 
|---|
|  | 2495 | " in cluster %x\n", name , parent_cluster ); | 
|---|
|  | 2496 | #endif | 
|---|
|  | 2497 | found  = 0; | 
|---|
|  | 2498 |  | 
|---|
|  | 2499 | // scan clusters containing the parent directory | 
|---|
|  | 2500 | while ( found == 0 ) | 
|---|
|  | 2501 | { | 
|---|
|  | 2502 | // compute lba | 
|---|
|  | 2503 | unsigned int lba = _cluster_to_lba( parent_cluster ); | 
|---|
|  | 2504 |  | 
|---|
|  | 2505 | // load one cluster of the parent directory into data_buffer | 
|---|
|  | 2506 | if ( _fat_buffer_data_lba != lba ) | 
|---|
|  | 2507 | { | 
|---|
|  | 2508 | if ( _fat_ioc_access( 0,         // no descheduling | 
|---|
|  | 2509 | 1,         // read | 
|---|
|  | 2510 | lba, | 
|---|
|  | 2511 | (unsigned int)_fat_buffer_data, | 
|---|
|  | 2512 | 8 ) ) | 
|---|
|  | 2513 | { | 
|---|
|  | 2514 | _printf("\n[FAT ERROR] in _file_info_no_cache() : " | 
|---|
|  | 2515 | "cannot load lba = %x into data_buffer\n", lba ); | 
|---|
|  | 2516 | return 1; | 
|---|
|  | 2517 | } | 
|---|
|  | 2518 |  | 
|---|
|  | 2519 | _fat_buffer_data_lba = lba; | 
|---|
|  | 2520 | } | 
|---|
|  | 2521 |  | 
|---|
|  | 2522 | offset = 0; | 
|---|
|  | 2523 |  | 
|---|
|  | 2524 | // scan this 4 Kbytes buffer | 
|---|
|  | 2525 | while ( (offset < 4096) && (found == 0) ) | 
|---|
|  | 2526 | { | 
|---|
|  | 2527 | buf  = _fat_buffer_data + offset; | 
|---|
|  | 2528 | attr = _read_entry( DIR_ATTR , buf , 0 ); | 
|---|
|  | 2529 | ord  = _read_entry( LDIR_ORD , buf , 0 ); | 
|---|
|  | 2530 |  | 
|---|
|  | 2531 | if (ord == NO_MORE_ENTRY)               // no more entry => break | 
|---|
|  | 2532 | { | 
|---|
|  | 2533 | found = 2; | 
|---|
|  | 2534 | } | 
|---|
|  | 2535 | else if ( ord == FREE_ENTRY )           // free entry => skip | 
|---|
|  | 2536 | { | 
|---|
|  | 2537 | offset = offset + 32; | 
|---|
|  | 2538 | } | 
|---|
|  | 2539 | else if ( attr == ATTR_LONG_NAME_MASK ) // LFN entry => get partial name | 
|---|
|  | 2540 | { | 
|---|
|  | 2541 | unsigned int seq = ord & 0x3; | 
|---|
|  | 2542 | lfn = (seq > lfn) ? seq : lfn; | 
|---|
|  | 2543 | if      ( seq == 1 ) _get_name_from_long( buf, lfn1 ); | 
|---|
|  | 2544 | else if ( seq == 2 ) _get_name_from_long( buf, lfn2 ); | 
|---|
|  | 2545 | else if ( seq == 3 ) _get_name_from_long( buf, lfn3 ); | 
|---|
|  | 2546 | offset = offset + 32; | 
|---|
|  | 2547 | } | 
|---|
|  | 2548 | else                                    // NORMAL entry | 
|---|
|  | 2549 | { | 
|---|
|  | 2550 | // build the full mame for current directory entry | 
|---|
|  | 2551 | if      ( lfn == 0 ) | 
|---|
|  | 2552 | { | 
|---|
|  | 2553 | _get_name_from_short( buf , cname ); | 
|---|
|  | 2554 | } | 
|---|
|  | 2555 | else if ( lfn == 1 ) | 
|---|
|  | 2556 | { | 
|---|
|  | 2557 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2558 | } | 
|---|
|  | 2559 | else if ( lfn == 2 ) | 
|---|
|  | 2560 | { | 
|---|
|  | 2561 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2562 | _strcpy( cname + 13 , lfn2 ); | 
|---|
|  | 2563 | } | 
|---|
|  | 2564 | else if ( lfn == 3 ) | 
|---|
|  | 2565 | { | 
|---|
|  | 2566 | _strcpy( cname      , lfn1 ); | 
|---|
|  | 2567 | _strcpy( cname + 13 , lfn2 ); | 
|---|
|  | 2568 | _strcpy( cname + 26 , lfn3 ); | 
|---|
|  | 2569 | } | 
|---|
|  | 2570 |  | 
|---|
|  | 2571 | // test if extracted name == searched name | 
|---|
| [619] | 2572 | if ( _strcmp( name , cname ) == 0 ) | 
|---|
| [587] | 2573 | { | 
|---|
|  | 2574 | child_cluster = (_read_entry( DIR_FST_CLUS_HI , buf , 1 ) << 16) | | 
|---|
|  | 2575 | (_read_entry( DIR_FST_CLUS_LO , buf , 1 )      ) ; | 
|---|
|  | 2576 | child_is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY); | 
|---|
|  | 2577 | child_size    = _read_entry( DIR_FILE_SIZE , buf , 1 ); | 
|---|
|  | 2578 | found         = 1; | 
|---|
|  | 2579 | } | 
|---|
|  | 2580 | offset = offset + 32; | 
|---|
|  | 2581 | lfn = 0; | 
|---|
|  | 2582 | } | 
|---|
|  | 2583 | }  // en loop on directory entries | 
|---|
|  | 2584 |  | 
|---|
|  | 2585 | // compute next cluster index | 
|---|
|  | 2586 | unsigned int next; | 
|---|
|  | 2587 | if ( _next_cluster_no_cache ( parent_cluster , &next ) ) return 1; | 
|---|
|  | 2588 | parent_cluster = next; | 
|---|
|  | 2589 | } // end loop on clusters | 
|---|
|  | 2590 |  | 
|---|
|  | 2591 | if ( found == 2 )  // found end of directory => error | 
|---|
|  | 2592 | { | 
|---|
|  | 2593 | _printf("\n[FAT ERROR] in _file_info_no_cache() : <%s> not found\n", | 
|---|
|  | 2594 | name ); | 
|---|
|  | 2595 | return 1; | 
|---|
|  | 2596 | } | 
|---|
|  | 2597 |  | 
|---|
|  | 2598 | // check type | 
|---|
|  | 2599 | if ( ((pathname[nb_read] == 0) && (child_is_dir != 0)) || | 
|---|
|  | 2600 | ((pathname[nb_read] != 0) && (child_is_dir == 0)) ) | 
|---|
|  | 2601 | { | 
|---|
|  | 2602 | _printf("\n[FAT ERROR] in _file_info_no_cache() : illegal type for <%s>\n", name ); | 
|---|
|  | 2603 | return 1; | 
|---|
|  | 2604 | } | 
|---|
|  | 2605 |  | 
|---|
|  | 2606 | // update parent_cluster for next name | 
|---|
|  | 2607 | parent_cluster = child_cluster; | 
|---|
|  | 2608 |  | 
|---|
|  | 2609 | }  // end loop on names | 
|---|
|  | 2610 |  | 
|---|
|  | 2611 | #if (GIET_DEBUG_FAT & 1) | 
|---|
|  | 2612 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2613 | _printf("\n[DEBUG FAT] _file_info_no_cache() : success for <%s> / " | 
|---|
|  | 2614 | "file_size = %x / file_cluster = %x\n", pathname, child_size, child_cluster ); | 
|---|
|  | 2615 | #endif | 
|---|
|  | 2616 |  | 
|---|
|  | 2617 | // return file cluster and size | 
|---|
|  | 2618 | *file_size    = child_size; | 
|---|
|  | 2619 | *file_cluster = child_cluster; | 
|---|
|  | 2620 | return 0; | 
|---|
|  | 2621 |  | 
|---|
|  | 2622 | }  // end _file_info_no_cache() | 
|---|
|  | 2623 |  | 
|---|
|  | 2624 |  | 
|---|
|  | 2625 |  | 
|---|
|  | 2626 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2627 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2628 | //             Extern functions | 
|---|
|  | 2629 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2630 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2631 |  | 
|---|
|  | 2632 |  | 
|---|
|  | 2633 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2634 | // This function initializes the FAT structures. | 
|---|
|  | 2635 | // - The Fat-Descriptor is always initialised. | 
|---|
|  | 2636 | // - The dynamically allocated structures (the Inode-Tre, the Fat_Cache, | 
|---|
|  | 2637 | //   and the File-Cache for the root directory) are only allocated | 
|---|
|  | 2638 | //   and initialised if the "kernel_mode" argument is set. | 
|---|
|  | 2639 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2640 | // Implementation note: | 
|---|
|  | 2641 | // This function is called twice, by the boot-loader, and by the kernel_init. | 
|---|
|  | 2642 | // It does not use dynamic memory allocation from the distributed heap. | 
|---|
|  | 2643 | // It use informations found in the boot sector and FS-INFO sector. | 
|---|
|  | 2644 | // that are loaded in the Fat-Descriptor temporary block_buffer. | 
|---|
|  | 2645 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2646 | // Returns 0 if success. | 
|---|
|  | 2647 | // Returns -1 if error. | 
|---|
|  | 2648 | ///////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2649 | int _fat_init( unsigned int kernel_mode ) | 
|---|
|  | 2650 | { | 
|---|
|  | 2651 |  | 
|---|
| [258] | 2652 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2653 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2654 | _printf("\n[DEBUG FAT] _fat_init() : enters at cycle %d\n", _get_proctime() ); | 
|---|
| [258] | 2655 | #endif | 
|---|
| [458] | 2656 |  | 
|---|
|  | 2657 | // FAT initialisation should be done only once | 
|---|
| [530] | 2658 | if ( _fat.initialised == FAT_INITIALISED ) | 
|---|
| [458] | 2659 | { | 
|---|
| [587] | 2660 | _printf("\n[FAT ERROR] in _fat_init() : FAT already initialised\n"); | 
|---|
|  | 2661 | return -1; | 
|---|
| [458] | 2662 | } | 
|---|
|  | 2663 |  | 
|---|
| [587] | 2664 | // load Boot sector (VBR) into FAT buffer | 
|---|
|  | 2665 | if ( _fat_ioc_access( 0,                                  // no descheduling | 
|---|
|  | 2666 | 1,                                  // read | 
|---|
|  | 2667 | 0,                                  // block index | 
|---|
|  | 2668 | (unsigned int)_fat.block_buffer, | 
|---|
|  | 2669 | 1 ) )                               // one block | 
|---|
| [258] | 2670 | { | 
|---|
| [503] | 2671 | _printf("\n[FAT ERROR] in _fat_init() cannot load VBR\n"); | 
|---|
| [587] | 2672 | return -1; | 
|---|
| [258] | 2673 | } | 
|---|
|  | 2674 |  | 
|---|
| [587] | 2675 | _fat.block_buffer_lba = 0; | 
|---|
|  | 2676 |  | 
|---|
|  | 2677 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2678 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2679 | { | 
|---|
|  | 2680 | _printf("\n[DEBUG FAT] _fat_init() : Boot sector loaded\n"); | 
|---|
|  | 2681 | _display_one_block( _fat.block_buffer, "block device", _fat.block_buffer_lba ); | 
|---|
|  | 2682 | } | 
|---|
| [258] | 2683 | #endif | 
|---|
|  | 2684 |  | 
|---|
|  | 2685 | // checking various FAT32 assuptions from boot sector | 
|---|
| [587] | 2686 | if( _read_entry( BPB_BYTSPERSEC, _fat.block_buffer, 1 ) != 512 ) | 
|---|
| [258] | 2687 | { | 
|---|
| [503] | 2688 | _printf("\n[FAT ERROR] The sector size must be 512 bytes\n"); | 
|---|
| [587] | 2689 | return -1; | 
|---|
| [258] | 2690 | } | 
|---|
| [587] | 2691 | if( _read_entry( BPB_SECPERCLUS, _fat.block_buffer, 1 ) != 8 ) | 
|---|
| [258] | 2692 | { | 
|---|
| [587] | 2693 | _printf("\n[FAT ERROR] The cluster size must be 8 blocks\n"); | 
|---|
|  | 2694 | return -1; | 
|---|
|  | 2695 | } | 
|---|
|  | 2696 | if( _read_entry( BPB_NUMFATS, _fat.block_buffer, 1 ) != 1 ) | 
|---|
|  | 2697 | { | 
|---|
| [503] | 2698 | _printf("\n[FAT ERROR] The number of FAT copies in FAT region must be 1\n"); | 
|---|
| [587] | 2699 | return -1; | 
|---|
| [258] | 2700 | } | 
|---|
| [587] | 2701 | if( (_read_entry( BPB_FAT32_FATSZ32, _fat.block_buffer, 1 ) & 0xF) != 0 ) | 
|---|
| [258] | 2702 | { | 
|---|
| [587] | 2703 | _printf("\n[FAT ERROR] The FAT region must be multiple of 16 sectors\n"); | 
|---|
|  | 2704 | return -1; | 
|---|
| [258] | 2705 | } | 
|---|
| [587] | 2706 | if( _read_entry( BPB_FAT32_ROOTCLUS, _fat.block_buffer, 1 ) != 2 ) | 
|---|
| [258] | 2707 | { | 
|---|
| [587] | 2708 | _printf("\n[FAT ERROR] The root directory must be at cluster 2\n"); | 
|---|
|  | 2709 | return -1; | 
|---|
| [258] | 2710 | } | 
|---|
|  | 2711 |  | 
|---|
| [587] | 2712 | // initialise Fat-Descriptor from VBR | 
|---|
|  | 2713 | _fat.sector_size         = 512; | 
|---|
|  | 2714 | _fat.cluster_size        = 4096; | 
|---|
|  | 2715 | _fat.fat_sectors         = _read_entry( BPB_FAT32_FATSZ32 , _fat.block_buffer , 1 ); | 
|---|
|  | 2716 | _fat.fat_lba             = _read_entry( BPB_RSVDSECCNT , _fat.block_buffer , 1 ); | 
|---|
|  | 2717 | _fat.data_sectors        = _fat.fat_sectors << 10; | 
|---|
| [530] | 2718 | _fat.data_lba            = _fat.fat_lba + _fat.fat_sectors; | 
|---|
| [587] | 2719 | _fat.fs_info_lba         = _read_entry( BPB_FAT32_FSINFO , _fat.block_buffer , 1 ); | 
|---|
|  | 2720 | _fat_buffer_fat_lba      = 0xFFFFFFFF; | 
|---|
|  | 2721 | _fat_buffer_data_lba     = 0xFFFFFFFF; | 
|---|
| [530] | 2722 | _fat.initialised         = FAT_INITIALISED; | 
|---|
| [258] | 2723 |  | 
|---|
| [587] | 2724 | // load FS_INFO sector into FAT buffer | 
|---|
|  | 2725 | if ( _fat_ioc_access( 0,                                // no descheduling | 
|---|
|  | 2726 | 1,                                // read | 
|---|
|  | 2727 | _fat.fs_info_lba,                 // lba | 
|---|
|  | 2728 | (unsigned int)_fat.block_buffer, | 
|---|
|  | 2729 | 1 ) )                             // one block | 
|---|
|  | 2730 | { | 
|---|
|  | 2731 | _printf("\n[FAT ERROR] in _fat_init() cannot load FS_INFO Sector\n"); | 
|---|
|  | 2732 | return -1; | 
|---|
|  | 2733 | } | 
|---|
| [458] | 2734 |  | 
|---|
| [587] | 2735 | _fat.block_buffer_lba = _fat.fs_info_lba; | 
|---|
| [258] | 2736 |  | 
|---|
| [291] | 2737 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2738 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2739 | { | 
|---|
|  | 2740 | _printf("\n[DEBUG FAT] _fat_init() : FS-INFO sector loaded\n"); | 
|---|
|  | 2741 | _display_one_block( _fat.block_buffer, "block device", _fat.block_buffer_lba ); | 
|---|
|  | 2742 | } | 
|---|
| [291] | 2743 | #endif | 
|---|
|  | 2744 |  | 
|---|
| [587] | 2745 | // initialise Fat-Descriptor from FS_INFO | 
|---|
|  | 2746 | _fat.free_clusters_number   = _read_entry( FS_FREE_CLUSTERS    , _fat.block_buffer, 1); | 
|---|
|  | 2747 | _fat.first_free_cluster     = _read_entry( FS_FREE_CLUSTER_HINT, _fat.block_buffer, 1); | 
|---|
| [291] | 2748 |  | 
|---|
| [587] | 2749 | // This is done only when the _fat_init() is called in kernel mode | 
|---|
| [291] | 2750 |  | 
|---|
| [587] | 2751 | if ( kernel_mode ) | 
|---|
|  | 2752 | { | 
|---|
|  | 2753 | unsigned int   n; | 
|---|
|  | 2754 |  | 
|---|
|  | 2755 | // allocate and initialise the Inode-Tree root | 
|---|
|  | 2756 | fat_inode_t*      inode  = _malloc( sizeof(fat_inode_t) ); | 
|---|
| [650] | 2757 | fat_cache_node_t* cache  = _allocate_one_cache_node( NULL ); | 
|---|
| [587] | 2758 |  | 
|---|
|  | 2759 | inode->parent   = NULL;        // no parent | 
|---|
|  | 2760 | inode->next     = NULL;        // no brother | 
|---|
|  | 2761 | inode->child    = NULL;        // children come later | 
|---|
|  | 2762 | inode->cache    = cache;       // empty cache | 
|---|
|  | 2763 | inode->cluster  = 2;           // forced value | 
|---|
|  | 2764 | inode->size     = 0;           // no size for a directory | 
|---|
|  | 2765 | inode->count    = 0;           // children come later | 
|---|
|  | 2766 | inode->dentry   = 0;           // no parent => no dentry | 
|---|
|  | 2767 | inode->levels   = 1;           // one level cache | 
|---|
|  | 2768 | inode->is_dir   = 1;           // it's a directory | 
|---|
| [650] | 2769 | _strcpy( inode->name , "/" ); | 
|---|
| [587] | 2770 |  | 
|---|
|  | 2771 | _fat.inode_tree_root = inode; | 
|---|
|  | 2772 |  | 
|---|
|  | 2773 | // initialise the lock | 
|---|
|  | 2774 | _spin_lock_init( &_fat.fat_lock ); | 
|---|
|  | 2775 |  | 
|---|
|  | 2776 | // initialise File Descriptor Array | 
|---|
|  | 2777 | for( n = 0 ; n < GIET_OPEN_FILES_MAX ; n++ ) _fat.fd[n].allocated = 0; | 
|---|
|  | 2778 |  | 
|---|
|  | 2779 | // initialise fat_cache root | 
|---|
| [650] | 2780 | _fat.fat_cache_root   = _allocate_one_cache_node( NULL ); | 
|---|
| [587] | 2781 | _fat.fat_cache_levels = _get_levels_from_size( _fat.fat_sectors << 9 ); | 
|---|
|  | 2782 | }  // end if kernel_mode | 
|---|
|  | 2783 |  | 
|---|
| [291] | 2784 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2785 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2786 | _display_fat_descriptor(); | 
|---|
| [291] | 2787 | #endif | 
|---|
|  | 2788 |  | 
|---|
| [258] | 2789 | return 0; | 
|---|
|  | 2790 | }  // end _fat_init() | 
|---|
|  | 2791 |  | 
|---|
| [587] | 2792 |  | 
|---|
|  | 2793 |  | 
|---|
|  | 2794 |  | 
|---|
| [258] | 2795 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 2796 | // This function implements the giet_fat_open() system call. | 
|---|
|  | 2797 | // The semantic is similar to the UNIX open() function, but only the O_CREATE | 
|---|
|  | 2798 | // and O_RDONLY flags are supported. The UNIX access rights are not supported. | 
|---|
|  | 2799 | // If the file does not exist in the specified directory, it is created. | 
|---|
|  | 2800 | // If the specified directory does not exist, an error is returned. | 
|---|
|  | 2801 | // It allocates a file descriptor to the calling task, for the file identified | 
|---|
|  | 2802 | // by "pathname". If several tasks try to open the same file, each task | 
|---|
|  | 2803 | // obtains a private file descriptor. | 
|---|
|  | 2804 | // A node name (file or directory) cannot be larger than 31 characters. | 
|---|
| [258] | 2805 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 2806 | // Returns file descriptor index if success | 
|---|
|  | 2807 | // Returns a negative value if error: | 
|---|
|  | 2808 | //   -1  :  "fat not initialised" | 
|---|
|  | 2809 | //   -2  :  "path to parent not found" | 
|---|
|  | 2810 | //   -3  :  "one name in path too long" | 
|---|
|  | 2811 | //   -4  :  "file not found" | 
|---|
|  | 2812 | //   -5  :  "Cannot update parent directory" | 
|---|
|  | 2813 | //   -6  :  "Cannot update DATA region" | 
|---|
|  | 2814 | //   -7  :  "Cannot update FAT region" | 
|---|
|  | 2815 | //   -8  :  "Cannot update FS_INFO sector" | 
|---|
|  | 2816 | //   -9  :  "file descriptor array full" | 
|---|
| [258] | 2817 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 2818 | int _fat_open( char*        pathname,     // absolute path from root | 
|---|
|  | 2819 | unsigned int flags )       // O_CREATE and O_RDONLY | 
|---|
| [258] | 2820 | { | 
|---|
| [587] | 2821 | unsigned int         fd_id;            // index in File-Descriptor-Array | 
|---|
|  | 2822 | unsigned int         code;             // error code | 
|---|
|  | 2823 | fat_inode_t*         inode;            // anonymous inode pointer | 
|---|
|  | 2824 | fat_inode_t*         child;            // pointer on searched file inode | 
|---|
|  | 2825 | fat_inode_t*         parent;           // pointer on parent directory inode | 
|---|
| [258] | 2826 |  | 
|---|
| [587] | 2827 | // get flags | 
|---|
|  | 2828 | unsigned int create    = ((flags & O_CREATE) != 0); | 
|---|
|  | 2829 | unsigned int read_only = ((flags & O_RDONLY) != 0); | 
|---|
|  | 2830 |  | 
|---|
| [258] | 2831 | #if GIET_DEBUG_FAT | 
|---|
| [295] | 2832 | unsigned int procid  = _get_procid(); | 
|---|
| [429] | 2833 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 2834 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 2835 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
| [569] | 2836 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2837 | _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] enters for path <%s> / " | 
|---|
|  | 2838 | " create = %d / read_only = %d\n", | 
|---|
|  | 2839 | x, y, p, pathname , create , read_only ); | 
|---|
| [258] | 2840 | #endif | 
|---|
|  | 2841 |  | 
|---|
| [458] | 2842 | // checking FAT initialised | 
|---|
| [530] | 2843 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [458] | 2844 | { | 
|---|
| [503] | 2845 | _printf("\n[FAT ERROR] in _fat_open() : FAT not initialised\n"); | 
|---|
| [458] | 2846 | return -1; | 
|---|
|  | 2847 | } | 
|---|
| [587] | 2848 |  | 
|---|
|  | 2849 | // takes the lock | 
|---|
| [530] | 2850 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
| [295] | 2851 |  | 
|---|
| [587] | 2852 | // get inode pointer | 
|---|
|  | 2853 | code = _get_inode_from_path( pathname , &inode ); | 
|---|
|  | 2854 |  | 
|---|
|  | 2855 | if ( code == 2 ) | 
|---|
| [258] | 2856 | { | 
|---|
| [587] | 2857 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2858 | _printf("\n[FAT ERROR] in _fat_open() : path to parent not found" | 
|---|
|  | 2859 | " for file <%s>\n", pathname ); | 
|---|
|  | 2860 | return -2; | 
|---|
|  | 2861 | } | 
|---|
|  | 2862 | else if ( code == 3 ) | 
|---|
|  | 2863 | { | 
|---|
|  | 2864 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2865 | _printf("\n[FAT ERROR] in _fat_open() : one name in path too long" | 
|---|
|  | 2866 | " for file <%s>\n", pathname ); | 
|---|
|  | 2867 | return -3; | 
|---|
|  | 2868 | } | 
|---|
|  | 2869 | else if ( (code == 1) && (create == 0) ) | 
|---|
|  | 2870 | { | 
|---|
|  | 2871 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2872 | _printf("\n[FAT ERROR] in _fat_open() : file not found" | 
|---|
|  | 2873 | " for file <%s>\n", pathname ); | 
|---|
|  | 2874 | return -4; | 
|---|
|  | 2875 | } | 
|---|
|  | 2876 | else if ( (code == 1) && (create != 0) )   // file name not found => create | 
|---|
|  | 2877 | { | 
|---|
|  | 2878 | // set parent inode pointer | 
|---|
|  | 2879 | parent = inode; | 
|---|
| [258] | 2880 |  | 
|---|
|  | 2881 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2882 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2883 | _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] create a new file <%s>\n", | 
|---|
|  | 2884 | x , y , p , pathname ); | 
|---|
| [258] | 2885 | #endif | 
|---|
| [291] | 2886 |  | 
|---|
| [587] | 2887 | // get new file name / error check already done by _get_inode_from_path() | 
|---|
|  | 2888 | char name[32]; | 
|---|
|  | 2889 | _get_last_name( pathname , name ); | 
|---|
|  | 2890 |  | 
|---|
|  | 2891 | // allocate a new inode and an empty Cache-File | 
|---|
|  | 2892 | child = _allocate_one_inode( name, | 
|---|
|  | 2893 | 0,                         // not a directory | 
|---|
|  | 2894 | END_OF_CHAIN_CLUSTER_MAX,  // no cluster allocated | 
|---|
|  | 2895 | 0,                         // size : new file is empty | 
|---|
|  | 2896 | 0,                         // count incremented later | 
|---|
|  | 2897 | 0,                         // dentry set by add_dir_entry | 
|---|
|  | 2898 | 1 );                       // cache_allocate | 
|---|
|  | 2899 |  | 
|---|
|  | 2900 | // introduce inode into Inode-Tree | 
|---|
|  | 2901 | _add_inode_in_tree( child , parent ); | 
|---|
|  | 2902 |  | 
|---|
|  | 2903 | // add an entry in the parent directory Cache_file | 
|---|
|  | 2904 | if ( _add_dir_entry( child , parent ) ) | 
|---|
| [258] | 2905 | { | 
|---|
| [587] | 2906 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2907 | _printf("\n[FAT ERROR] in _fat_open() : cannot update parent directory" | 
|---|
|  | 2908 | " for file <%s>\n" , pathname ); | 
|---|
|  | 2909 | return -5; | 
|---|
|  | 2910 | } | 
|---|
|  | 2911 |  | 
|---|
|  | 2912 | // update DATA region on block device for parent directory | 
|---|
|  | 2913 | if ( _update_device_from_cache( parent->levels, | 
|---|
|  | 2914 | parent->cache, | 
|---|
|  | 2915 | parent->name ) ) | 
|---|
|  | 2916 | { | 
|---|
|  | 2917 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2918 | _printf("\n[FAT ERROR] in _fat_open() : cannot update DATA region " | 
|---|
|  | 2919 | " for parent of file <%s>\n", pathname ); | 
|---|
|  | 2920 | return -6; | 
|---|
| [258] | 2921 | } | 
|---|
|  | 2922 |  | 
|---|
| [587] | 2923 | // update FAT region on block device | 
|---|
|  | 2924 | if ( _update_device_from_cache( _fat.fat_cache_levels, | 
|---|
|  | 2925 | _fat.fat_cache_root, | 
|---|
|  | 2926 | "FAT" ) ) | 
|---|
| [258] | 2927 | { | 
|---|
| [587] | 2928 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2929 | _printf("\n[FAT ERROR] in _fat_open() : cannot update FAT region" | 
|---|
|  | 2930 | " for file <%s>\n", pathname ); | 
|---|
|  | 2931 | return -7; | 
|---|
| [258] | 2932 | } | 
|---|
| [587] | 2933 |  | 
|---|
|  | 2934 | // update FS_INFO sector | 
|---|
|  | 2935 | if ( _update_fs_info() ) | 
|---|
| [258] | 2936 | { | 
|---|
| [530] | 2937 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
| [587] | 2938 | _printf("\n[FAT ERROR] in _fat_open() : cannot update FS-INFO" | 
|---|
|  | 2939 | " for file <%s>\n", pathname ); | 
|---|
|  | 2940 | return -8; | 
|---|
| [258] | 2941 | } | 
|---|
|  | 2942 | } | 
|---|
| [587] | 2943 | else // code == 0 | 
|---|
|  | 2944 | { | 
|---|
|  | 2945 | // set searched file inode pointer | 
|---|
|  | 2946 | child = inode; | 
|---|
| [258] | 2947 |  | 
|---|
| [417] | 2948 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 2949 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 2950 | _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] found file <%s> on device : inode = %x\n", | 
|---|
|  | 2951 | x , y , p , pathname , child ); | 
|---|
| [417] | 2952 | #endif | 
|---|
|  | 2953 |  | 
|---|
| [587] | 2954 | } | 
|---|
| [258] | 2955 |  | 
|---|
| [587] | 2956 | // Search an empty slot in file descriptors array | 
|---|
|  | 2957 | fd_id = 0; | 
|---|
|  | 2958 | while ( (_fat.fd[fd_id].allocated) != 0 && (fd_id < GIET_OPEN_FILES_MAX) ) | 
|---|
| [258] | 2959 | { | 
|---|
| [587] | 2960 | fd_id++; | 
|---|
|  | 2961 | } | 
|---|
|  | 2962 |  | 
|---|
|  | 2963 | // set file descriptor if an empty slot has been found | 
|---|
|  | 2964 | if ( fd_id < GIET_OPEN_FILES_MAX ) | 
|---|
|  | 2965 | { | 
|---|
|  | 2966 | // update file descriptor | 
|---|
|  | 2967 | _fat.fd[fd_id].allocated  = 1; | 
|---|
|  | 2968 | _fat.fd[fd_id].seek       = 0; | 
|---|
|  | 2969 | _fat.fd[fd_id].read_only  = read_only; | 
|---|
|  | 2970 | _fat.fd[fd_id].inode      = child; | 
|---|
|  | 2971 |  | 
|---|
|  | 2972 | // increment the refcount | 
|---|
|  | 2973 | child->count = child->count + 1; | 
|---|
|  | 2974 |  | 
|---|
|  | 2975 | // releases the lock | 
|---|
|  | 2976 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2977 |  | 
|---|
|  | 2978 | #if GIET_DEBUG_FAT | 
|---|
|  | 2979 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 2980 | _printf("\n[DEBUG FAT] _fat_open() : P[%d,%d,%d] got fd = %d for <%s> / " | 
|---|
|  | 2981 | "read_only = %d\n", | 
|---|
|  | 2982 | x , y , p , fd_id , pathname , read_only ); | 
|---|
|  | 2983 | #endif | 
|---|
|  | 2984 | return fd_id; | 
|---|
|  | 2985 | } | 
|---|
|  | 2986 | else | 
|---|
|  | 2987 | { | 
|---|
|  | 2988 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 2989 | _printf("\n[FAT ERROR] in _fat_open() : File-Descriptors-Array full\n"); | 
|---|
|  | 2990 | return -9; | 
|---|
|  | 2991 | } | 
|---|
|  | 2992 | } // end _fat_open() | 
|---|
|  | 2993 |  | 
|---|
|  | 2994 |  | 
|---|
|  | 2995 |  | 
|---|
|  | 2996 |  | 
|---|
|  | 2997 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2998 | // This function implements the "giet_fat_close()" system call. | 
|---|
|  | 2999 | // It decrements the inode reference count, and release the fd_id entry | 
|---|
|  | 3000 | // in the file descriptors array. | 
|---|
|  | 3001 | // If the reference count is zero, it writes all dirty clusters on block device, | 
|---|
| [651] | 3002 | // and releases the memory allocated to the File_Cache. | 
|---|
| [587] | 3003 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3004 | // Returns 0 on success. | 
|---|
|  | 3005 | // Returns negative value if error: | 
|---|
|  | 3006 | //  -1  : "FAT not initialised" | 
|---|
|  | 3007 | //  -2  : "Illegal file descriptor" | 
|---|
| [625] | 3008 | //  -3  : "File not open" | 
|---|
|  | 3009 | //  -4  : "Cannot update DATA regions" | 
|---|
| [587] | 3010 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3011 | int _fat_close( unsigned int fd_id ) | 
|---|
|  | 3012 | { | 
|---|
|  | 3013 | // checking FAT initialised | 
|---|
|  | 3014 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
|  | 3015 | { | 
|---|
|  | 3016 | _printf("\n[FAT ERROR] in _fat_close() : FAT not initialised\n"); | 
|---|
|  | 3017 | return -1; | 
|---|
|  | 3018 | } | 
|---|
|  | 3019 |  | 
|---|
|  | 3020 | if( (fd_id >= GIET_OPEN_FILES_MAX) ) | 
|---|
|  | 3021 | { | 
|---|
|  | 3022 | _printf("\n[FAT ERROR] in _fat_close() : illegal file descriptor index\n"); | 
|---|
|  | 3023 | return -2; | 
|---|
|  | 3024 | } | 
|---|
|  | 3025 |  | 
|---|
|  | 3026 | // takes lock | 
|---|
|  | 3027 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
|  | 3028 |  | 
|---|
| [625] | 3029 | if( _fat.fd[fd_id].allocated == 0 ) | 
|---|
|  | 3030 | { | 
|---|
|  | 3031 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3032 | _printf("\n[FAT ERROR] in _fat_close() : file not open\n"); | 
|---|
|  | 3033 | return -3; | 
|---|
|  | 3034 | } | 
|---|
|  | 3035 |  | 
|---|
| [587] | 3036 | // get the inode pointer | 
|---|
|  | 3037 | fat_inode_t*  inode = _fat.fd[fd_id].inode; | 
|---|
|  | 3038 |  | 
|---|
|  | 3039 | // decrement reference count | 
|---|
|  | 3040 | inode->count = inode->count - 1; | 
|---|
|  | 3041 |  | 
|---|
|  | 3042 | #if GIET_DEBUG_FAT | 
|---|
|  | 3043 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3044 | _printf("\n[FAT DEBUG] _fat_close() for file <%s> : refcount = %d\n", | 
|---|
|  | 3045 | inode->name , inode->count ); | 
|---|
|  | 3046 | #endif | 
|---|
|  | 3047 |  | 
|---|
|  | 3048 | // update block device and release File-Cache if no more references | 
|---|
|  | 3049 | if ( inode->count == 0 ) | 
|---|
|  | 3050 | { | 
|---|
|  | 3051 | // update all dirty clusters for closed file | 
|---|
|  | 3052 | if ( _update_device_from_cache( inode->levels, | 
|---|
|  | 3053 | inode->cache, | 
|---|
|  | 3054 | inode->name ) ) | 
|---|
| [258] | 3055 | { | 
|---|
| [587] | 3056 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3057 | _printf("\n[FAT ERROR] in _fat_close() : cannot write dirty clusters " | 
|---|
|  | 3058 | "for file <%s>\n", inode->name ); | 
|---|
| [625] | 3059 | return -4; | 
|---|
| [258] | 3060 | } | 
|---|
|  | 3061 |  | 
|---|
| [587] | 3062 | #if GIET_DEBUG_FAT | 
|---|
|  | 3063 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3064 | _printf("\n[FAT DEBUG] _fat_close() update device for file <%s>\n", inode->name ); | 
|---|
|  | 3065 | #endif | 
|---|
|  | 3066 |  | 
|---|
|  | 3067 | // update directory dirty clusters for parent directory | 
|---|
| [624] | 3068 | if ( inode->parent && | 
|---|
|  | 3069 | _update_device_from_cache( inode->parent->levels, | 
|---|
| [587] | 3070 | inode->parent->cache, | 
|---|
| [624] | 3071 | inode->parent->name ) ) | 
|---|
| [258] | 3072 | { | 
|---|
| [587] | 3073 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3074 | _printf("\n[FAT ERROR] in _fat_close() : cannot write dirty clusters " | 
|---|
|  | 3075 | "for directory <%s>\n", inode->parent->name ); | 
|---|
|  | 3076 | return -4; | 
|---|
|  | 3077 | } | 
|---|
| [258] | 3078 |  | 
|---|
|  | 3079 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 3080 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3081 | _printf("\n[FAT DEBUG] _fat_close() update device for parent directory <%s>\n", | 
|---|
|  | 3082 | inode->parent->name ); | 
|---|
| [258] | 3083 | #endif | 
|---|
|  | 3084 |  | 
|---|
| [651] | 3085 | // release memory allocated to File-Cache (keep cache root node) | 
|---|
|  | 3086 | _release_cache_memory( inode->cache, inode->levels ); | 
|---|
| [587] | 3087 |  | 
|---|
|  | 3088 | #if GIET_DEBUG_FAT | 
|---|
|  | 3089 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3090 | _printf("\n[FAT DEBUG] _fat_close() release memory for File-Cache <%s>\n", | 
|---|
|  | 3091 | inode->name ); | 
|---|
|  | 3092 | #endif | 
|---|
|  | 3093 |  | 
|---|
| [258] | 3094 | } | 
|---|
| [587] | 3095 |  | 
|---|
|  | 3096 | // release fd_id entry in file descriptor array | 
|---|
|  | 3097 | _fat.fd[fd_id].allocated = 0; | 
|---|
|  | 3098 |  | 
|---|
|  | 3099 | // release lock | 
|---|
|  | 3100 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3101 |  | 
|---|
|  | 3102 | return 0; | 
|---|
|  | 3103 | } // end fat_close() | 
|---|
|  | 3104 |  | 
|---|
|  | 3105 |  | 
|---|
|  | 3106 |  | 
|---|
|  | 3107 |  | 
|---|
|  | 3108 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3109 | // This function implements the giet_fat_file_info() system call. | 
|---|
| [623] | 3110 | // It returns the size, the current offset and the directory info for a file | 
|---|
|  | 3111 | // identified by the "fd_id" argument. | 
|---|
| [587] | 3112 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3113 | // Returns  0 if success. | 
|---|
|  | 3114 | // Returns negative value if error. | 
|---|
|  | 3115 | //  -1  : "FAT not initialised" | 
|---|
|  | 3116 | //  -2  : "Illegal file descriptor" | 
|---|
|  | 3117 | //  -3  : "File not open" | 
|---|
|  | 3118 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [623] | 3119 | int _fat_file_info( unsigned int            fd_id, | 
|---|
|  | 3120 | struct fat_file_info_s* info ) | 
|---|
| [587] | 3121 | { | 
|---|
| [623] | 3122 | if ( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [258] | 3123 | { | 
|---|
| [587] | 3124 | _printf("\n[FAT ERROR] in _fat_file_info() : FAT not initialised\n"); | 
|---|
| [258] | 3125 | return -1; | 
|---|
|  | 3126 | } | 
|---|
|  | 3127 |  | 
|---|
| [623] | 3128 | if ( fd_id >= GIET_OPEN_FILES_MAX ) | 
|---|
| [587] | 3129 | { | 
|---|
|  | 3130 | _printf("\n[FAT ERROR] in _fat_file_info() : illegal file descriptor index\n"); | 
|---|
|  | 3131 | return -2; | 
|---|
|  | 3132 | } | 
|---|
| [258] | 3133 |  | 
|---|
| [587] | 3134 | if ( _fat.fd[fd_id].allocated == 0 ) | 
|---|
|  | 3135 | { | 
|---|
| [625] | 3136 | _printf("\n[FAT ERROR] in _fat_file_info() : file not open\n"); | 
|---|
| [587] | 3137 | return -3; | 
|---|
| [258] | 3138 | } | 
|---|
| [587] | 3139 |  | 
|---|
| [623] | 3140 | info->size   = _fat.fd[fd_id].inode->size; | 
|---|
|  | 3141 | info->offset = _fat.fd[fd_id].seek; | 
|---|
|  | 3142 | info->is_dir = _fat.fd[fd_id].inode->is_dir; | 
|---|
|  | 3143 |  | 
|---|
| [587] | 3144 | return 0; | 
|---|
|  | 3145 | } // end _fat_file_info() | 
|---|
|  | 3146 |  | 
|---|
|  | 3147 |  | 
|---|
|  | 3148 |  | 
|---|
|  | 3149 |  | 
|---|
|  | 3150 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3151 | // The following function implements the "giet_fat_read()" system call. | 
|---|
|  | 3152 | // It transfers "count" bytes from the File_Cache associated to the file | 
|---|
|  | 3153 | // identified by "fd_id", to the user "buffer", from the current file offset. | 
|---|
|  | 3154 | // In case of miss in the File_Cache, it loads all involved clusters into cache. | 
|---|
|  | 3155 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3156 | // Returns number of bytes actually transfered if success . | 
|---|
|  | 3157 | // Returns 0 if EOF encountered (offset + count > file_size). | 
|---|
|  | 3158 | // Returns a negative value if error: | 
|---|
|  | 3159 | //   -1 :  "fat not initialised" | 
|---|
| [634] | 3160 | //   -2 :  "illegal file descriptor" | 
|---|
| [587] | 3161 | //   -2 :  "file not open" | 
|---|
|  | 3162 | //   -3 :  "cannot load file from device" | 
|---|
|  | 3163 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3164 | int _fat_read( unsigned int fd_id,     // file descriptor index | 
|---|
|  | 3165 | void*        buffer,    // destination buffer | 
|---|
|  | 3166 | unsigned int count )    // number of bytes to read | 
|---|
|  | 3167 | { | 
|---|
|  | 3168 | // checking FAT initialised | 
|---|
|  | 3169 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [258] | 3170 | { | 
|---|
| [587] | 3171 | _printf("\n[FAT ERROR] in _fat_write() : FAT not initialised\n"); | 
|---|
| [258] | 3172 | return -1; | 
|---|
|  | 3173 | } | 
|---|
| [587] | 3174 |  | 
|---|
|  | 3175 | // check fd_id overflow | 
|---|
|  | 3176 | if ( fd_id >= GIET_OPEN_FILES_MAX ) | 
|---|
| [258] | 3177 | { | 
|---|
| [587] | 3178 | _printf("\n[FAT ERROR] in _fat_read() : illegal file descriptor\n"); | 
|---|
| [634] | 3179 | return -2; | 
|---|
| [258] | 3180 | } | 
|---|
| [358] | 3181 |  | 
|---|
| [587] | 3182 | // check file is open | 
|---|
|  | 3183 | if ( _fat.fd[fd_id].allocated == 0 ) | 
|---|
|  | 3184 | { | 
|---|
|  | 3185 | _printf("\n[FAT ERROR] in _fat_read() : file not open\n"); | 
|---|
| [634] | 3186 | return -3; | 
|---|
| [587] | 3187 | } | 
|---|
| [358] | 3188 |  | 
|---|
| [587] | 3189 | // takes lock | 
|---|
|  | 3190 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
|  | 3191 |  | 
|---|
|  | 3192 | // get file inode pointer and offset | 
|---|
|  | 3193 | fat_inode_t* inode  = _fat.fd[fd_id].inode; | 
|---|
|  | 3194 | unsigned int seek   = _fat.fd[fd_id].seek; | 
|---|
|  | 3195 |  | 
|---|
|  | 3196 | // check count & seek versus file size | 
|---|
|  | 3197 | if ( count + seek > inode->size ) | 
|---|
| [258] | 3198 | { | 
|---|
| [587] | 3199 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3200 | _printf("\n[FAT ERROR] in _fat_read() : file too small" | 
|---|
|  | 3201 | " / seek = %x / count = %x / file_size = %x\n", | 
|---|
|  | 3202 | seek , count , inode->size ); | 
|---|
|  | 3203 | return 0; | 
|---|
| [258] | 3204 | } | 
|---|
|  | 3205 |  | 
|---|
| [587] | 3206 | // compute first_cluster_id and first_byte_to_move | 
|---|
|  | 3207 | unsigned int first_cluster_id   = seek >> 12; | 
|---|
|  | 3208 | unsigned int first_byte_to_move = seek & 0xFFF; | 
|---|
| [258] | 3209 |  | 
|---|
| [587] | 3210 | // compute last_cluster and last_byte_to_move | 
|---|
|  | 3211 | unsigned int last_cluster_id   = (seek + count - 1) >> 12; | 
|---|
|  | 3212 | unsigned int last_byte_to_move = (seek + count - 1) & 0xFFF; | 
|---|
| [258] | 3213 |  | 
|---|
|  | 3214 | #if GIET_DEBUG_FAT | 
|---|
| [354] | 3215 | unsigned int procid  = _get_procid(); | 
|---|
| [429] | 3216 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 3217 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 3218 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
| [569] | 3219 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3220 | _printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] enters for file <%s> " | 
|---|
|  | 3221 | " / bytes = %x / offset = %x\n" | 
|---|
|  | 3222 | "first_cluster_id = %x / first_byte_to_move = %x" | 
|---|
|  | 3223 | " / last_cluster_id = %x / last_byte_to_move = %x\n", | 
|---|
|  | 3224 | x , y , p , inode->name , count , seek , | 
|---|
|  | 3225 | first_cluster_id , first_byte_to_move , last_cluster_id , last_byte_to_move ); | 
|---|
| [258] | 3226 | #endif | 
|---|
|  | 3227 |  | 
|---|
| [587] | 3228 | // loop on all cluster covering the requested transfer | 
|---|
|  | 3229 | unsigned int cluster_id; | 
|---|
|  | 3230 | unsigned int done = 0; | 
|---|
|  | 3231 | for ( cluster_id = first_cluster_id ; cluster_id <= last_cluster_id ; cluster_id++ ) | 
|---|
| [258] | 3232 | { | 
|---|
| [587] | 3233 | // get pointer on the cluster_id buffer in cache | 
|---|
|  | 3234 | unsigned char*     cbuf; | 
|---|
|  | 3235 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 3236 | if ( _get_buffer_from_cache( inode, | 
|---|
|  | 3237 | cluster_id, | 
|---|
|  | 3238 | &pdesc ) ) | 
|---|
|  | 3239 | { | 
|---|
|  | 3240 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3241 | _printf("\n[FAT ERROR] in _fat_read() : cannot load file <%s>\n", | 
|---|
|  | 3242 | inode->name ); | 
|---|
| [634] | 3243 | return -4; | 
|---|
| [587] | 3244 | } | 
|---|
|  | 3245 | cbuf = pdesc->buffer; | 
|---|
|  | 3246 |  | 
|---|
|  | 3247 | #if GIET_DEBUG_FAT | 
|---|
|  | 3248 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3249 | _printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] moves cluster_id %d from Cache-File <%s>\n", | 
|---|
|  | 3250 | x , y , p , cluster_id, inode->name ); | 
|---|
|  | 3251 | #endif | 
|---|
|  | 3252 |  | 
|---|
|  | 3253 | // compute memcpy arguments | 
|---|
|  | 3254 | unsigned char*  source; | 
|---|
|  | 3255 | unsigned int    nbytes; | 
|---|
|  | 3256 | unsigned char*  dest = (unsigned char*)buffer + done; | 
|---|
|  | 3257 | if ( (cluster_id == first_cluster_id) && (cluster_id == last_cluster_id) ) | 
|---|
|  | 3258 | { | 
|---|
|  | 3259 | source = cbuf + first_byte_to_move; | 
|---|
|  | 3260 | nbytes = last_byte_to_move - first_byte_to_move + 1; | 
|---|
|  | 3261 | } | 
|---|
|  | 3262 | else if ( cluster_id == first_cluster_id ) | 
|---|
|  | 3263 | { | 
|---|
|  | 3264 | source = cbuf + first_byte_to_move; | 
|---|
|  | 3265 | nbytes = 4096 - first_byte_to_move; | 
|---|
|  | 3266 | } | 
|---|
|  | 3267 | else if ( cluster_id == last_cluster_id ) | 
|---|
|  | 3268 | { | 
|---|
|  | 3269 | source = cbuf; | 
|---|
|  | 3270 | nbytes = last_byte_to_move + 1; | 
|---|
|  | 3271 | } | 
|---|
|  | 3272 | else  // not first / not last | 
|---|
|  | 3273 | { | 
|---|
|  | 3274 | source = cbuf; | 
|---|
|  | 3275 | nbytes = 4096; | 
|---|
|  | 3276 | } | 
|---|
|  | 3277 |  | 
|---|
|  | 3278 | // move data | 
|---|
|  | 3279 | memcpy( dest , source , nbytes ); | 
|---|
|  | 3280 | done = done + nbytes; | 
|---|
| [258] | 3281 | } | 
|---|
|  | 3282 |  | 
|---|
| [587] | 3283 | #if GIET_DEBUG_FAT | 
|---|
|  | 3284 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3285 | _printf("\n[DEBUG FAT] _fat_read() : P[%d,%d,%d] loaded file <%s> from Cache-File\n", | 
|---|
|  | 3286 | x , y , p , inode->name ); | 
|---|
|  | 3287 | #endif | 
|---|
| [258] | 3288 |  | 
|---|
| [587] | 3289 | // update seek | 
|---|
|  | 3290 | _fat.fd[fd_id].seek += done; | 
|---|
| [258] | 3291 |  | 
|---|
| [587] | 3292 | // release lock | 
|---|
|  | 3293 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3294 |  | 
|---|
|  | 3295 | return done; | 
|---|
|  | 3296 | } // end _fat_read() | 
|---|
|  | 3297 |  | 
|---|
|  | 3298 |  | 
|---|
|  | 3299 |  | 
|---|
|  | 3300 |  | 
|---|
|  | 3301 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3302 | // The following function implements the "giet_fat_write()" system call. | 
|---|
|  | 3303 | // It transfers "count" bytes to the fat_cache associated to the file | 
|---|
|  | 3304 | // identified by "fd_id", from the user "buffer", using the current file offset. | 
|---|
|  | 3305 | // It increases the file size and allocate new clusters if (count + offset) | 
|---|
|  | 3306 | // is larger than the current file size. Then it loads and updates all | 
|---|
|  | 3307 | // involved clusters in the cache. | 
|---|
|  | 3308 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3309 | // Returns number of bytes actually written if success. | 
|---|
|  | 3310 | // Returns a negative value if error: | 
|---|
|  | 3311 | //   -1 :  "FAT not initialised" | 
|---|
|  | 3312 | //   -2 :  "Illegal file descriptor" | 
|---|
|  | 3313 | //   -3 :  "File not open" | 
|---|
|  | 3314 | //   -4 :  "File not writable" | 
|---|
|  | 3315 | //   -5 :  "No free clusters" | 
|---|
|  | 3316 | //   -6 :  "Cannot update parent directory entry" | 
|---|
|  | 3317 | //   -7 :  "Cannot access File-Cache" | 
|---|
|  | 3318 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3319 | int _fat_write( unsigned int fd_id,    // file descriptor index | 
|---|
|  | 3320 | void*        buffer,   // source buffer | 
|---|
|  | 3321 | unsigned int count )   // number of bytes to write | 
|---|
|  | 3322 | { | 
|---|
|  | 3323 | // checking FAT initialised | 
|---|
|  | 3324 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [258] | 3325 | { | 
|---|
| [587] | 3326 | _printf("\n[FAT ERROR] in _fat_write() : FAT not initialised\n"); | 
|---|
|  | 3327 | return -1; | 
|---|
|  | 3328 | } | 
|---|
| [258] | 3329 |  | 
|---|
| [587] | 3330 | // takes lock | 
|---|
|  | 3331 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
|  | 3332 |  | 
|---|
|  | 3333 | // check fd_id overflow | 
|---|
|  | 3334 | if ( fd_id >= GIET_OPEN_FILES_MAX ) | 
|---|
|  | 3335 | { | 
|---|
|  | 3336 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3337 | _printf("\n[FAT ERROR] in _fat_write() : illegal file descriptor\n"); | 
|---|
|  | 3338 | return -2; | 
|---|
|  | 3339 | } | 
|---|
|  | 3340 |  | 
|---|
|  | 3341 | // check file open | 
|---|
|  | 3342 | if ( _fat.fd[fd_id].allocated == 0 ) | 
|---|
|  | 3343 | { | 
|---|
|  | 3344 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3345 | _printf("\n[FAT ERROR] in _fat_write() : file not open\n" ); | 
|---|
|  | 3346 | return -3; | 
|---|
|  | 3347 | } | 
|---|
|  | 3348 |  | 
|---|
|  | 3349 | // check file writable | 
|---|
|  | 3350 | if ( _fat.fd[fd_id].read_only ) | 
|---|
|  | 3351 | { | 
|---|
|  | 3352 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3353 | _printf("\n[FAT ERROR] in _fat_write() : file <%s> is read-only\n", | 
|---|
|  | 3354 | _fat.fd[fd_id].inode->name ); | 
|---|
|  | 3355 | return -4; | 
|---|
|  | 3356 | } | 
|---|
|  | 3357 |  | 
|---|
|  | 3358 | // get file inode pointer and seek | 
|---|
|  | 3359 | fat_inode_t* inode  = _fat.fd[fd_id].inode; | 
|---|
|  | 3360 | unsigned int seek   = _fat.fd[fd_id].seek; | 
|---|
|  | 3361 |  | 
|---|
| [258] | 3362 | #if GIET_DEBUG_FAT | 
|---|
| [587] | 3363 | unsigned int procid  = _get_procid(); | 
|---|
|  | 3364 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 3365 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 3366 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
| [569] | 3367 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3368 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] enters for file <%s> " | 
|---|
|  | 3369 | " / bytes = %x / seek = %x\n", | 
|---|
|  | 3370 | x , y , p , inode->name , count , seek ); | 
|---|
| [258] | 3371 | #endif | 
|---|
|  | 3372 |  | 
|---|
| [587] | 3373 | // chek if file size must be incremented | 
|---|
|  | 3374 | // and allocate new clusters from FAT if required | 
|---|
|  | 3375 | unsigned int old_size = inode->size; | 
|---|
|  | 3376 | unsigned int new_size = seek + count; | 
|---|
|  | 3377 | if ( new_size > old_size ) | 
|---|
|  | 3378 | { | 
|---|
|  | 3379 | // update size in inode | 
|---|
|  | 3380 | inode->size = new_size; | 
|---|
|  | 3381 |  | 
|---|
|  | 3382 | // compute current and required numbers of clusters | 
|---|
|  | 3383 | unsigned old_clusters = old_size >> 12; | 
|---|
|  | 3384 | if ( old_size & 0xFFF ) old_clusters++; | 
|---|
|  | 3385 |  | 
|---|
|  | 3386 | unsigned new_clusters = new_size >> 12; | 
|---|
|  | 3387 | if ( new_size & 0xFFF ) new_clusters++; | 
|---|
|  | 3388 |  | 
|---|
|  | 3389 | // allocate new clusters from FAT if required | 
|---|
|  | 3390 | if ( new_clusters > old_clusters ) | 
|---|
| [258] | 3391 | { | 
|---|
| [587] | 3392 |  | 
|---|
|  | 3393 | #if GIET_DEBUG_FAT | 
|---|
|  | 3394 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3395 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] allocates new clusters for file <%s>" | 
|---|
|  | 3396 | " / current = %d / required = %d\n", | 
|---|
|  | 3397 | x , y , p , inode->name , old_clusters , new_clusters ); | 
|---|
|  | 3398 | #endif | 
|---|
|  | 3399 | // allocate missing clusters | 
|---|
|  | 3400 | if ( _clusters_allocate( inode, | 
|---|
|  | 3401 | old_clusters, | 
|---|
|  | 3402 | new_clusters - old_clusters ) ) | 
|---|
|  | 3403 | { | 
|---|
|  | 3404 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3405 | _printf("\n[FAT ERROR] in _fat_write() : no free clusters" | 
|---|
|  | 3406 | " for file <%s>\n", _fat.fd[fd_id].inode->name ); | 
|---|
|  | 3407 | return -5; | 
|---|
|  | 3408 | } | 
|---|
| [258] | 3409 | } | 
|---|
|  | 3410 |  | 
|---|
| [587] | 3411 | // update parent directory entry (size an cluster index) | 
|---|
|  | 3412 | if ( _update_dir_entry( inode ) ) | 
|---|
|  | 3413 | { | 
|---|
|  | 3414 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3415 | _printf("\n[FAT ERROR] in _fat_write() : cannot update parent directory entry" | 
|---|
|  | 3416 | " for file <%s>\n", _fat.fd[fd_id].inode->name ); | 
|---|
|  | 3417 | return -6; | 
|---|
|  | 3418 | } | 
|---|
|  | 3419 |  | 
|---|
|  | 3420 |  | 
|---|
|  | 3421 | #if GIET_DEBUG_FAT | 
|---|
|  | 3422 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3423 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] updates size for file <%s> / size = %x\n", | 
|---|
|  | 3424 | x , y , p , inode->name , (new_size - old_size) ); | 
|---|
|  | 3425 | #endif | 
|---|
|  | 3426 |  | 
|---|
| [258] | 3427 | } | 
|---|
|  | 3428 |  | 
|---|
| [587] | 3429 | // compute first_cluster_id and first_byte_to_move | 
|---|
|  | 3430 | unsigned int first_cluster_id   = seek >> 12; | 
|---|
|  | 3431 | unsigned int first_byte_to_move = seek & 0xFFF; | 
|---|
| [258] | 3432 |  | 
|---|
| [587] | 3433 | // compute last_cluster and last_byte_to_move | 
|---|
|  | 3434 | unsigned int last_cluster_id   = (seek + count - 1) >> 12; | 
|---|
|  | 3435 | unsigned int last_byte_to_move = (seek + count - 1) & 0xFFF; | 
|---|
|  | 3436 |  | 
|---|
|  | 3437 | #if GIET_DEBUG_FAT | 
|---|
|  | 3438 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3439 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] starts loop on clusters for file <%s>\n" | 
|---|
|  | 3440 | "  first_cluster_id = %d / first_byte_to_move = %x" | 
|---|
|  | 3441 | " / last_cluster_id = %d / last_byte_to_move = %x\n", | 
|---|
|  | 3442 | x , y , p , inode->name , | 
|---|
|  | 3443 | first_cluster_id , first_byte_to_move , last_cluster_id , last_byte_to_move ); | 
|---|
|  | 3444 | #endif | 
|---|
|  | 3445 |  | 
|---|
|  | 3446 | // loop on all clusters covering the requested transfer | 
|---|
|  | 3447 | unsigned int cluster_id; | 
|---|
|  | 3448 | unsigned int done = 0; | 
|---|
|  | 3449 | for ( cluster_id = first_cluster_id ; cluster_id <= last_cluster_id ; cluster_id++ ) | 
|---|
|  | 3450 | { | 
|---|
|  | 3451 | // get pointer on one 4K buffer in File-Cache | 
|---|
|  | 3452 | unsigned char*     cbuf; | 
|---|
|  | 3453 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 3454 | if ( _get_buffer_from_cache( inode, | 
|---|
|  | 3455 | cluster_id, | 
|---|
|  | 3456 | &pdesc ) ) | 
|---|
|  | 3457 | { | 
|---|
|  | 3458 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3459 | _printf("\n[FAT ERROR] in _fat_write() : cannot load file <%s>\n", | 
|---|
|  | 3460 | inode->name ); | 
|---|
|  | 3461 | return -7; | 
|---|
|  | 3462 | } | 
|---|
|  | 3463 |  | 
|---|
|  | 3464 | cbuf         = pdesc->buffer; | 
|---|
|  | 3465 | pdesc->dirty = 1; | 
|---|
|  | 3466 |  | 
|---|
|  | 3467 | #if GIET_DEBUG_FAT | 
|---|
|  | 3468 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3469 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] move cluster_id %d to Cache-file <%s>\n", | 
|---|
|  | 3470 | x , y , p , cluster_id, inode->name ); | 
|---|
|  | 3471 | #endif | 
|---|
|  | 3472 |  | 
|---|
|  | 3473 | // compute memcpy arguments | 
|---|
|  | 3474 | unsigned char* source = (unsigned char*)buffer + done; | 
|---|
|  | 3475 | unsigned char* dest; | 
|---|
|  | 3476 | unsigned int   nbytes; | 
|---|
|  | 3477 | if ( (cluster_id == first_cluster_id) && (cluster_id == last_cluster_id) ) | 
|---|
|  | 3478 | { | 
|---|
|  | 3479 | dest   = cbuf + first_byte_to_move; | 
|---|
|  | 3480 | nbytes = last_byte_to_move - first_byte_to_move + 1; | 
|---|
|  | 3481 | } | 
|---|
|  | 3482 | else if ( cluster_id == first_cluster_id ) | 
|---|
|  | 3483 | { | 
|---|
|  | 3484 | dest   = cbuf + first_byte_to_move; | 
|---|
|  | 3485 | nbytes = 4096 - first_byte_to_move; | 
|---|
|  | 3486 | } | 
|---|
|  | 3487 | else if ( cluster_id == last_cluster_id ) | 
|---|
|  | 3488 | { | 
|---|
|  | 3489 | dest   = cbuf; | 
|---|
|  | 3490 | nbytes = last_byte_to_move + 1; | 
|---|
|  | 3491 | } | 
|---|
|  | 3492 | else | 
|---|
|  | 3493 | { | 
|---|
|  | 3494 | dest   = cbuf; | 
|---|
|  | 3495 | nbytes = 4096; | 
|---|
|  | 3496 | } | 
|---|
|  | 3497 |  | 
|---|
|  | 3498 | //move date | 
|---|
|  | 3499 | memcpy( dest , source , nbytes ); | 
|---|
|  | 3500 | done = done + nbytes; | 
|---|
|  | 3501 |  | 
|---|
|  | 3502 | } // end for clusters | 
|---|
|  | 3503 |  | 
|---|
|  | 3504 | // update seek | 
|---|
|  | 3505 | _fat.fd[fd_id].seek += done; | 
|---|
|  | 3506 |  | 
|---|
|  | 3507 | #if GIET_DEBUG_FAT | 
|---|
|  | 3508 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3509 | _printf("\n[DEBUG FAT] _fat_write() : P[%d,%d,%d] store file <%s> into Cache-File\n", | 
|---|
|  | 3510 | x , y , p , inode->name ); | 
|---|
|  | 3511 | #endif | 
|---|
|  | 3512 |  | 
|---|
|  | 3513 | // release lock | 
|---|
|  | 3514 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3515 |  | 
|---|
|  | 3516 | return done; | 
|---|
|  | 3517 | } // end _fat_write() | 
|---|
|  | 3518 |  | 
|---|
|  | 3519 |  | 
|---|
|  | 3520 |  | 
|---|
|  | 3521 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3522 | // The following function implements the "giet_fat_lseek()" system call. | 
|---|
|  | 3523 | // It repositions the seek in the file descriptor "fd_id", according to | 
|---|
|  | 3524 | // the "seek" and "whence" arguments. | 
|---|
|  | 3525 | // It has the same semantic as the UNIX lseek() function. | 
|---|
|  | 3526 | // Accepted values for whence are SEEK_SET and SEEK_CUR. | 
|---|
|  | 3527 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3528 | // Returns new seek value (bytes) if success. | 
|---|
|  | 3529 | // Returns negative value if error: | 
|---|
|  | 3530 | //   -1  : "FAT not initialised" | 
|---|
|  | 3531 | //   -2  : "Illegal file descriptor" | 
|---|
|  | 3532 | //   -3  : "File not open" | 
|---|
|  | 3533 | //   -4  : "Illegal whence argument" | 
|---|
|  | 3534 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3535 | int _fat_lseek( unsigned int fd_id, | 
|---|
|  | 3536 | unsigned int seek, | 
|---|
|  | 3537 | unsigned int whence ) | 
|---|
| [258] | 3538 | { | 
|---|
| [587] | 3539 | // checking FAT initialised | 
|---|
|  | 3540 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
|  | 3541 | { | 
|---|
|  | 3542 | _printf("\n[FAT ERROR] in _fat_lseek() : FAT not initialised\n"); | 
|---|
|  | 3543 | return -1; | 
|---|
|  | 3544 | } | 
|---|
| [259] | 3545 |  | 
|---|
| [587] | 3546 | // check fd_id overflow | 
|---|
|  | 3547 | if ( fd_id >= GIET_OPEN_FILES_MAX ) | 
|---|
|  | 3548 | { | 
|---|
|  | 3549 | _printf("\n[FAT ERROR] in _fat_lseek() : illegal file descriptor\n"); | 
|---|
|  | 3550 | return -2; | 
|---|
|  | 3551 | } | 
|---|
| [259] | 3552 |  | 
|---|
| [587] | 3553 | // takes lock | 
|---|
|  | 3554 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
| [259] | 3555 |  | 
|---|
| [587] | 3556 | // check file open | 
|---|
|  | 3557 | if ( _fat.fd[fd_id].allocated == 0 ) | 
|---|
|  | 3558 | { | 
|---|
|  | 3559 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3560 | _printf("\n[FAT ERROR] in _fat_lseek() : file not open\n"); | 
|---|
|  | 3561 | return -3; | 
|---|
|  | 3562 | } | 
|---|
| [259] | 3563 |  | 
|---|
| [587] | 3564 | unsigned int  new_seek; | 
|---|
| [291] | 3565 |  | 
|---|
| [587] | 3566 | // compute new seek | 
|---|
|  | 3567 | if      ( whence == SEEK_CUR ) new_seek = _fat.fd[fd_id].seek + seek; | 
|---|
|  | 3568 | else if ( whence == SEEK_SET ) new_seek = seek; | 
|---|
|  | 3569 | else | 
|---|
|  | 3570 | { | 
|---|
|  | 3571 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3572 | _printf("\n[FAT ERROR] in _fat_user_lseek() : illegal whence valuel\n"); | 
|---|
|  | 3573 | return -4; | 
|---|
|  | 3574 | } | 
|---|
| [291] | 3575 |  | 
|---|
| [587] | 3576 | // update file descriptor offset | 
|---|
|  | 3577 | _fat.fd[fd_id].seek = new_seek; | 
|---|
| [291] | 3578 |  | 
|---|
| [259] | 3579 | #if GIET_DEBUG_FAT | 
|---|
| [295] | 3580 | unsigned int procid  = _get_procid(); | 
|---|
| [429] | 3581 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 3582 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 3583 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
| [569] | 3584 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3585 | _printf("\n[DEBUG FAT] _fat_lseek() : P[%d,%d,%d] set seek = %x for file <%s>\n", | 
|---|
|  | 3586 | x , y , p , new_seek , _fat.fd[fd_id].inode->name ); | 
|---|
| [259] | 3587 | #endif | 
|---|
|  | 3588 |  | 
|---|
| [587] | 3589 | // release lock | 
|---|
|  | 3590 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3591 |  | 
|---|
|  | 3592 | return new_seek; | 
|---|
|  | 3593 | }  // end _fat_lseek() | 
|---|
|  | 3594 |  | 
|---|
|  | 3595 |  | 
|---|
|  | 3596 |  | 
|---|
|  | 3597 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3598 | // The following function implements the giet_fat_remove() system call. | 
|---|
|  | 3599 | // It deletes the file/directory identified by the "pathname" argument from | 
|---|
|  | 3600 | // the file system, if the remove condition is fulfilled (directory empty, | 
|---|
|  | 3601 | // or file not referenced). | 
|---|
|  | 3602 | // All clusters allocated in the block device DATA region are released. | 
|---|
|  | 3603 | // The FAT region is updated on the block device. | 
|---|
|  | 3604 | // The Inode-Tree is updated. | 
|---|
|  | 3605 | // The associated File_Cache is released. | 
|---|
|  | 3606 | // The Fat_Cache is updated. | 
|---|
|  | 3607 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3608 | // Returns 0 if success. | 
|---|
|  | 3609 | // Returns negative value if error | 
|---|
|  | 3610 | //   -1  : "FAT not initialised" | 
|---|
|  | 3611 | //   -2  : "File/Directory not found" | 
|---|
|  | 3612 | //   -3  : "Name too long in path" | 
|---|
|  | 3613 | //   -4  : "Has the wrong type" | 
|---|
|  | 3614 | //   -5  : "File still open" | 
|---|
|  | 3615 | //   -6  : "Cannot scan directory" | 
|---|
|  | 3616 | //   -7  : "Directory not empty" | 
|---|
|  | 3617 | //   -8  : "Cannot remove file/dir from FS" | 
|---|
|  | 3618 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3619 | int _fat_remove( char*        pathname, | 
|---|
|  | 3620 | unsigned int should_be_dir ) | 
|---|
|  | 3621 | { | 
|---|
|  | 3622 | fat_inode_t*  inode;            // searched file inode pointer | 
|---|
|  | 3623 |  | 
|---|
|  | 3624 | #if GIET_DEBUG_FAT | 
|---|
|  | 3625 | unsigned int procid  = _get_procid(); | 
|---|
|  | 3626 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 3627 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 3628 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
|  | 3629 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3630 | _printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] enters for path <%s>\n", | 
|---|
|  | 3631 | x, y, p, pathname ); | 
|---|
|  | 3632 | #endif | 
|---|
|  | 3633 |  | 
|---|
|  | 3634 | // checking FAT initialised | 
|---|
|  | 3635 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
|  | 3636 | { | 
|---|
|  | 3637 | _printf("\n[FAT ERROR] in _fat_remove() : FAT not initialised\n"); | 
|---|
| [259] | 3638 | return -1; | 
|---|
|  | 3639 | } | 
|---|
| [587] | 3640 |  | 
|---|
|  | 3641 | // take the lock | 
|---|
|  | 3642 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
|  | 3643 |  | 
|---|
|  | 3644 | // get searched file inode | 
|---|
|  | 3645 | unsigned int code = _get_inode_from_path( pathname , &inode ); | 
|---|
|  | 3646 |  | 
|---|
|  | 3647 | #if GIET_DEBUG_FAT | 
|---|
|  | 3648 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3649 | _printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] found inode %x for <%s> / code = %d\n", | 
|---|
|  | 3650 | x , y , p , (unsigned int)inode , pathname , code ); | 
|---|
|  | 3651 | #endif | 
|---|
|  | 3652 |  | 
|---|
|  | 3653 | if ( (code == 1) || (code == 2) ) | 
|---|
| [259] | 3654 | { | 
|---|
| [587] | 3655 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3656 | _printf("\n[FAT ERROR] in _fat_remove() : file <%s> not found\n", | 
|---|
|  | 3657 | pathname ); | 
|---|
|  | 3658 | return -2; | 
|---|
| [259] | 3659 | } | 
|---|
| [587] | 3660 | else if ( code == 3 ) | 
|---|
| [259] | 3661 | { | 
|---|
| [587] | 3662 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3663 | _printf("\n[FAT ERROR] in _fat_remove() : name too long in <%s>\n", | 
|---|
|  | 3664 | pathname ); | 
|---|
|  | 3665 | return -3; | 
|---|
| [259] | 3666 | } | 
|---|
|  | 3667 |  | 
|---|
| [587] | 3668 | // check inode type | 
|---|
|  | 3669 | if ( (inode->is_dir != 0) && (should_be_dir == 0) ) | 
|---|
| [291] | 3670 | { | 
|---|
| [587] | 3671 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3672 | _printf("\n[FAT ERROR] in _fat_remove() : <%s> is a directory\n", | 
|---|
|  | 3673 | pathname ); | 
|---|
|  | 3674 | return -4; | 
|---|
|  | 3675 | } | 
|---|
|  | 3676 | if ( (inode->is_dir == 0) && (should_be_dir != 0) ) | 
|---|
|  | 3677 | { | 
|---|
|  | 3678 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3679 | _printf("\n[FAT ERROR] in _fat_remove() : <%s> is not a directory\n", | 
|---|
|  | 3680 | pathname ); | 
|---|
|  | 3681 | return -4; | 
|---|
|  | 3682 | } | 
|---|
|  | 3683 |  | 
|---|
|  | 3684 | #if GIET_DEBUG_FAT | 
|---|
|  | 3685 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3686 | _printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] checked inode type for <%s>\n", | 
|---|
|  | 3687 | x , y , p , pathname ); | 
|---|
|  | 3688 | #endif | 
|---|
|  | 3689 |  | 
|---|
|  | 3690 | // check references count for a file | 
|---|
|  | 3691 | if ( (inode->is_dir == 0) && (inode->count != 0) ) | 
|---|
|  | 3692 | { | 
|---|
|  | 3693 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3694 | _printf("\n[FAT ERROR] in _fat_remove() : file <%s> still referenced\n", | 
|---|
|  | 3695 | pathname ); | 
|---|
|  | 3696 | return -5; | 
|---|
|  | 3697 | } | 
|---|
|  | 3698 |  | 
|---|
|  | 3699 | //  check empty for a directory | 
|---|
|  | 3700 | if ( inode->is_dir ) | 
|---|
|  | 3701 | { | 
|---|
|  | 3702 | unsigned int entries; | 
|---|
|  | 3703 | if ( _get_nb_entries( inode , &entries ) ) | 
|---|
| [291] | 3704 | { | 
|---|
| [587] | 3705 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3706 | _printf("\n[FAT ERROR] in _fat_remove() : cannot scan directory <%s>\n", | 
|---|
|  | 3707 | pathname ); | 
|---|
|  | 3708 | return -6; | 
|---|
| [291] | 3709 | } | 
|---|
| [587] | 3710 | else if ( entries > 2 ) | 
|---|
|  | 3711 | { | 
|---|
|  | 3712 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3713 | _printf("\n[FAT ERROR] in _fat_remove() : directory <%s> not empty\n", | 
|---|
|  | 3714 | pathname ); | 
|---|
|  | 3715 | return -7; | 
|---|
|  | 3716 | } | 
|---|
| [291] | 3717 | } | 
|---|
|  | 3718 |  | 
|---|
| [587] | 3719 | #if GIET_DEBUG_FAT | 
|---|
|  | 3720 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3721 | _printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] checked remove condition OK for <%s>\n", | 
|---|
|  | 3722 | x , y , p , pathname ); | 
|---|
|  | 3723 | #endif | 
|---|
| [259] | 3724 |  | 
|---|
| [587] | 3725 | // remove the file or directory from the file system | 
|---|
|  | 3726 | if ( _remove_node_from_fs( inode ) ) | 
|---|
|  | 3727 | { | 
|---|
|  | 3728 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3729 | _printf("\n[FAT ERROR] in _fat_remove() : cannot remove <%s> from FS\n", | 
|---|
|  | 3730 | pathname ); | 
|---|
|  | 3731 | return -8; | 
|---|
|  | 3732 | } | 
|---|
| [259] | 3733 |  | 
|---|
| [587] | 3734 | // release lock and return success | 
|---|
|  | 3735 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3736 |  | 
|---|
| [259] | 3737 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 3738 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3739 | _printf("\n[DEBUG FAT] _fat_remove() : P[%d,%d,%d] removed  <%s> from FS\n", | 
|---|
|  | 3740 | x, y, p, pathname ); | 
|---|
| [259] | 3741 | #endif | 
|---|
| [587] | 3742 |  | 
|---|
|  | 3743 | return 0; | 
|---|
|  | 3744 |  | 
|---|
|  | 3745 | }  // end _fat_remove() | 
|---|
| [259] | 3746 |  | 
|---|
| [587] | 3747 |  | 
|---|
|  | 3748 |  | 
|---|
|  | 3749 |  | 
|---|
|  | 3750 |  | 
|---|
|  | 3751 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3752 | // This function implements the giet_fat_rename() system call. | 
|---|
|  | 3753 | // It moves an existing file or directory from one node (defined by "old_path" | 
|---|
|  | 3754 | // argument) to another node (defined by "new_path" argument) in the FS tree. | 
|---|
|  | 3755 | // The type (file/directory) and content are not modified. | 
|---|
|  | 3756 | // If the new_path file/dir exist, it is removed from the file system, but only | 
|---|
|  | 3757 | // if the remove condition is respected (directory empty / file not referenced). | 
|---|
|  | 3758 | // The removed entry is only removed after the new entry is actually created. | 
|---|
|  | 3759 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3760 | // Returns 0 if success. | 
|---|
|  | 3761 | // Returns a negative value if error: | 
|---|
|  | 3762 | //  -1  : "FAT not initialised" | 
|---|
|  | 3763 | //  -2  : "old_path not found" | 
|---|
|  | 3764 | //  -3  : "new_path not found" | 
|---|
|  | 3765 | //  -4  : "cannot scan to_remove directory" | 
|---|
|  | 3766 | //  -5  : "to_remove directory not empty" | 
|---|
|  | 3767 | //  -6  : "to_remove file still referenced" | 
|---|
|  | 3768 | //  -7  : "cannot add new node to new_parent directory" | 
|---|
|  | 3769 | //  -8  : "cannot update new_parent directory on device" | 
|---|
|  | 3770 | //  -9  : "cannot remove old node from old_parent directory" | 
|---|
|  | 3771 | //  -10 : "cannot update old_parent directory on device" | 
|---|
|  | 3772 | //  -11 : "cannot remove to_remove node from FS" | 
|---|
| [638] | 3773 | //  -12 : "cannot move into its own subdirectory" | 
|---|
| [587] | 3774 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 3775 | int _fat_rename( char*  old_path, | 
|---|
|  | 3776 | char*  new_path ) | 
|---|
|  | 3777 | { | 
|---|
|  | 3778 | fat_inode_t*  inode;        // anonymous inode pointer | 
|---|
|  | 3779 | fat_inode_t*  old;          // inode identified by old_path      => to be deleted | 
|---|
|  | 3780 | fat_inode_t*  new;          // inode identified by new_path      => to be created | 
|---|
|  | 3781 | fat_inode_t*  old_parent;   // parent inode  in old_path         => to be modified | 
|---|
|  | 3782 | fat_inode_t*  new_parent;   // parent inode  in new_path         => to be modified | 
|---|
|  | 3783 | fat_inode_t*  to_remove;    // previouly identified by new_path  => to be removed | 
|---|
|  | 3784 | unsigned int  code; | 
|---|
|  | 3785 |  | 
|---|
|  | 3786 | #if GIET_DEBUG_FAT | 
|---|
|  | 3787 | unsigned int procid  = _get_procid(); | 
|---|
|  | 3788 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 3789 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 3790 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
|  | 3791 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3792 | _printf("\n[DEBUG FAT] _fat_rename() : P[%d,%d,%d] enters to move <%s> to <%s>\n", | 
|---|
|  | 3793 | x , y , p , old_path , new_path ); | 
|---|
|  | 3794 | #endif | 
|---|
|  | 3795 |  | 
|---|
|  | 3796 | // checking FAT initialised | 
|---|
|  | 3797 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [259] | 3798 | { | 
|---|
| [587] | 3799 | _printf("\n[FAT ERROR] in _fat_rename() : FAT not initialised\n"); | 
|---|
|  | 3800 | return -1; | 
|---|
| [259] | 3801 | } | 
|---|
|  | 3802 |  | 
|---|
| [587] | 3803 | // take the lock | 
|---|
|  | 3804 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
| [259] | 3805 |  | 
|---|
| [587] | 3806 | // get "old" and "old_parent" inode pointers | 
|---|
|  | 3807 | if ( _get_inode_from_path( old_path , &inode ) ) | 
|---|
|  | 3808 | { | 
|---|
|  | 3809 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3810 | _printf("\n[FAT ERROR] in _fat_rename() : <%s> not found\n", old_path ); | 
|---|
|  | 3811 | return -2; | 
|---|
|  | 3812 | } | 
|---|
|  | 3813 | else | 
|---|
|  | 3814 | { | 
|---|
|  | 3815 | old        = inode; | 
|---|
|  | 3816 | old_parent = inode->parent; | 
|---|
|  | 3817 | } | 
|---|
| [259] | 3818 |  | 
|---|
| [587] | 3819 | // get "to_removed" and "new_parent" inode pointers | 
|---|
|  | 3820 | code = _get_inode_from_path( new_path , &inode ); | 
|---|
|  | 3821 |  | 
|---|
|  | 3822 | if ( code == 0 )       // new_path inode already exist | 
|---|
| [259] | 3823 | { | 
|---|
| [621] | 3824 | if ( inode == old )  // the file will replace itself, do nothing | 
|---|
|  | 3825 | { | 
|---|
|  | 3826 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3827 | return 0; | 
|---|
|  | 3828 | } | 
|---|
|  | 3829 |  | 
|---|
| [587] | 3830 | to_remove        = inode; | 
|---|
| [621] | 3831 | new_parent       = inode->parent; | 
|---|
| [587] | 3832 | } | 
|---|
|  | 3833 | else if ( code == 1 )  // to_remove does not exist but parent exist | 
|---|
|  | 3834 | { | 
|---|
|  | 3835 | to_remove        = NULL; | 
|---|
|  | 3836 | new_parent       = inode; | 
|---|
|  | 3837 | } | 
|---|
|  | 3838 | else                   // parent directory in new_path not found | 
|---|
|  | 3839 | { | 
|---|
|  | 3840 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3841 | _printf("\n[FAT ERROR] in _fat_rename() : <%s> not found\n", new_path ); | 
|---|
|  | 3842 | return -3; | 
|---|
|  | 3843 | } | 
|---|
| [259] | 3844 |  | 
|---|
| [638] | 3845 | // check for move into own subdirectory | 
|---|
|  | 3846 | if ( _is_ancestor( old, new_parent ) ) | 
|---|
|  | 3847 | { | 
|---|
|  | 3848 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3849 | _printf("\n[FAT ERROR] in _fat_rename() : can't move %s into its own subdirectory\n", old_path ); | 
|---|
|  | 3850 | return -12; | 
|---|
|  | 3851 | } | 
|---|
|  | 3852 |  | 
|---|
| [259] | 3853 | #if GIET_DEBUG_FAT | 
|---|
| [569] | 3854 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
| [587] | 3855 | { | 
|---|
|  | 3856 | if ( to_remove ) | 
|---|
|  | 3857 | _printf("\n[DEBUG FAT] _fat_rename() : old_parent = %s / old = %s / new_parent = %s " | 
|---|
|  | 3858 | "/ to_remove = %s\n", | 
|---|
|  | 3859 | old_parent->name , old->name , new_parent->name , to_remove->name ); | 
|---|
|  | 3860 | else | 
|---|
|  | 3861 | _printf("\n[DEBUG FAT] _fat_rename() : old_parent = %s / old = %s / new_parent = %s " | 
|---|
|  | 3862 | "/ no remove\n", | 
|---|
|  | 3863 | old_parent->name , old->name , new_parent->name ); | 
|---|
|  | 3864 | } | 
|---|
| [259] | 3865 | #endif | 
|---|
|  | 3866 |  | 
|---|
| [587] | 3867 | // check remove condition for "to_remove" inode | 
|---|
|  | 3868 | if ( to_remove ) | 
|---|
|  | 3869 | { | 
|---|
|  | 3870 | if ( to_remove->is_dir )   // it's a directory | 
|---|
| [259] | 3871 | { | 
|---|
| [587] | 3872 | unsigned int entries; | 
|---|
|  | 3873 | if ( _get_nb_entries( to_remove , &entries ) ) | 
|---|
|  | 3874 | { | 
|---|
|  | 3875 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3876 | _printf("\n[FAT ERROR] in _fat_rename() : cannot scan directory <%s>\n", | 
|---|
|  | 3877 | to_remove->name ); | 
|---|
|  | 3878 | return -4; | 
|---|
|  | 3879 | } | 
|---|
|  | 3880 | else if ( entries > 2 ) | 
|---|
|  | 3881 | { | 
|---|
|  | 3882 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3883 | _printf("\n[FAT ERROR] in _fat_rename() : directory <%s> not empty\n", | 
|---|
|  | 3884 | to_remove->name ); | 
|---|
|  | 3885 | return -5; | 
|---|
|  | 3886 | } | 
|---|
| [259] | 3887 | } | 
|---|
| [587] | 3888 | else                       // it's a file | 
|---|
|  | 3889 | { | 
|---|
|  | 3890 | if ( to_remove->count ) | 
|---|
|  | 3891 | { | 
|---|
|  | 3892 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3893 | _printf("\n[FAT ERROR] in _fat_rename() : file <%s> still referenced\n", | 
|---|
|  | 3894 | to_remove->name ); | 
|---|
|  | 3895 | return -6; | 
|---|
|  | 3896 | } | 
|---|
|  | 3897 | } | 
|---|
| [259] | 3898 | } | 
|---|
| [291] | 3899 |  | 
|---|
| [587] | 3900 | #if GIET_DEBUG_FAT | 
|---|
|  | 3901 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 3902 | _printf("\n[FAT DEBUG] _fat_rename() : P[%d,%d,%d] checked remove condition OK\n", | 
|---|
|  | 3903 | x , y , p ); | 
|---|
|  | 3904 | #endif | 
|---|
|  | 3905 |  | 
|---|
|  | 3906 | // get new last name / error checking already done by _get_inode_from_path() | 
|---|
|  | 3907 | char  new_name[32]; | 
|---|
|  | 3908 | _get_last_name( new_path , new_name ); | 
|---|
|  | 3909 |  | 
|---|
|  | 3910 | // allocate "new" inode | 
|---|
|  | 3911 | new = _allocate_one_inode( new_name, | 
|---|
|  | 3912 | old->is_dir, | 
|---|
|  | 3913 | old->cluster, | 
|---|
|  | 3914 | old->size, | 
|---|
|  | 3915 | 0,              // count | 
|---|
|  | 3916 | 0,              // dentry | 
|---|
|  | 3917 | 0 );            // no cache_allocate | 
|---|
|  | 3918 |  | 
|---|
|  | 3919 | // give the "old" File-Cache to the "new inode | 
|---|
|  | 3920 | new->levels = old->levels; | 
|---|
|  | 3921 | new->cache  = old->cache; | 
|---|
|  | 3922 |  | 
|---|
|  | 3923 | // add "new" to "new_parent" directory File-Cache | 
|---|
|  | 3924 | if ( _add_dir_entry( new , new_parent ) ) | 
|---|
| [291] | 3925 | { | 
|---|
| [587] | 3926 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3927 | _printf("\n[FAT ERROR] in _fat_rename() : cannot add <%s> into <%s>\n", | 
|---|
|  | 3928 | new->name , new_parent->name ); | 
|---|
|  | 3929 | return -7; | 
|---|
| [291] | 3930 | } | 
|---|
|  | 3931 |  | 
|---|
| [587] | 3932 | // add "new" to "new_parent" directory in Inode-Tree | 
|---|
|  | 3933 | _add_inode_in_tree( new , new_parent ); | 
|---|
|  | 3934 |  | 
|---|
|  | 3935 | // updates "new_parent" directory on device | 
|---|
|  | 3936 | if ( _update_device_from_cache( new_parent->levels, | 
|---|
|  | 3937 | new_parent->cache, | 
|---|
|  | 3938 | new_parent->name ) ) | 
|---|
| [291] | 3939 | { | 
|---|
| [587] | 3940 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3941 | _printf("\n[FAT ERROR] in _fat_rename() : cannot update <%s> on device\n", | 
|---|
|  | 3942 | new_parent->name ); | 
|---|
|  | 3943 | return -8; | 
|---|
| [291] | 3944 | } | 
|---|
| [258] | 3945 |  | 
|---|
| [587] | 3946 | // remove "old" from "old_parent" File-Cache | 
|---|
|  | 3947 | if ( _remove_dir_entry( old ) ) | 
|---|
|  | 3948 | { | 
|---|
|  | 3949 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3950 | _printf("\n[FAT ERROR] in _fat_rename() : cannot remove <%s> from <%s>\n", | 
|---|
|  | 3951 | old->name , old_parent->name ); | 
|---|
|  | 3952 | return -9; | 
|---|
|  | 3953 | } | 
|---|
|  | 3954 |  | 
|---|
|  | 3955 | // remove "old" inode from Inode-Tree | 
|---|
|  | 3956 | _remove_inode_from_tree( old ); | 
|---|
|  | 3957 |  | 
|---|
| [622] | 3958 | // release "old" inode | 
|---|
|  | 3959 | _free( old ); | 
|---|
|  | 3960 |  | 
|---|
| [587] | 3961 | // updates "old_parent" directory on device | 
|---|
|  | 3962 | if ( _update_device_from_cache( old_parent->levels, | 
|---|
|  | 3963 | old_parent->cache, | 
|---|
|  | 3964 | old_parent->name ) ) | 
|---|
|  | 3965 | { | 
|---|
|  | 3966 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3967 | _printf("\n[FAT ERROR] in _fat_rename() : cannot update <%s> on device\n", | 
|---|
|  | 3968 | old_parent->name ); | 
|---|
|  | 3969 | return -10; | 
|---|
|  | 3970 | } | 
|---|
|  | 3971 |  | 
|---|
|  | 3972 | // remove "to_remove" from File System (if required) | 
|---|
|  | 3973 | if ( to_remove ) | 
|---|
|  | 3974 | { | 
|---|
|  | 3975 | if ( _remove_node_from_fs( to_remove ) ) | 
|---|
|  | 3976 | { | 
|---|
|  | 3977 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3978 | _printf("\n[FAT ERROR] in _fat_rename() : cannot remove <%s> from FS\n", | 
|---|
|  | 3979 | to_remove->name ); | 
|---|
|  | 3980 | return -11; | 
|---|
|  | 3981 | } | 
|---|
|  | 3982 | } | 
|---|
|  | 3983 |  | 
|---|
|  | 3984 | // release lock | 
|---|
|  | 3985 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 3986 |  | 
|---|
|  | 3987 | return 0; | 
|---|
|  | 3988 | }  // end _fat_rename() | 
|---|
|  | 3989 |  | 
|---|
|  | 3990 |  | 
|---|
|  | 3991 |  | 
|---|
|  | 3992 |  | 
|---|
| [258] | 3993 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 3994 | // The following function implements the giet_fat_mkdir() system call. | 
|---|
|  | 3995 | // It creates in file system the directory specified by the "pathname" argument. | 
|---|
|  | 3996 | // The Inode-Tree is updated. | 
|---|
|  | 3997 | // One cluster is allocated to the new directory. | 
|---|
|  | 3998 | // The associated File-Cache is created. | 
|---|
|  | 3999 | // The FAT region on block device is updated. | 
|---|
|  | 4000 | // The DATA region on block device is updated. | 
|---|
| [260] | 4001 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 4002 | // Returns 0 if success. | 
|---|
|  | 4003 | // Returns a negative value if error: | 
|---|
|  | 4004 | //   -1  : "Fat not initialised" | 
|---|
|  | 4005 | //   -2  : "Path to parent not found" | 
|---|
|  | 4006 | //   -3  : "One name in path too long" | 
|---|
|  | 4007 | //   -4  : "Directory already exist" | 
|---|
|  | 4008 | //   -5  : "No free cluster" | 
|---|
|  | 4009 | //   -6  : "Cannot update parent directory" | 
|---|
|  | 4010 | //   -7  : "Cannot update parent DATA region" | 
|---|
|  | 4011 | //   -8  : "Cannot update FAT region" | 
|---|
|  | 4012 | //   -9  : "Cannot update FS-INFO" | 
|---|
|  | 4013 | //   -10 : "Cannot update directory DATA region" | 
|---|
| [260] | 4014 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 4015 | int _fat_mkdir( char* pathname ) | 
|---|
| [260] | 4016 | { | 
|---|
| [587] | 4017 | fat_inode_t*         inode;            // anonymous inode pointer | 
|---|
|  | 4018 | fat_inode_t*         child;            // searched directory inode pointer | 
|---|
|  | 4019 | fat_inode_t*         parent;           // parent directory inode pointer | 
|---|
| [260] | 4020 |  | 
|---|
| [587] | 4021 | #if GIET_DEBUG_FAT | 
|---|
|  | 4022 | unsigned int procid  = _get_procid(); | 
|---|
|  | 4023 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 4024 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 4025 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
|  | 4026 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4027 | _printf("\n[DEBUG FAT] _fat_mkdir() : P[%d,%d,%d] enters for path <%s>\n", | 
|---|
|  | 4028 | x, y, p, pathname ); | 
|---|
|  | 4029 | #endif | 
|---|
|  | 4030 |  | 
|---|
|  | 4031 | // checking FAT initialised | 
|---|
|  | 4032 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [260] | 4033 | { | 
|---|
| [587] | 4034 | _printf("\n[FAT ERROR] in _fat_mkdir() : FAT not initialised\n"); | 
|---|
|  | 4035 | return -1; | 
|---|
|  | 4036 | } | 
|---|
| [260] | 4037 |  | 
|---|
| [587] | 4038 | // takes the lock | 
|---|
|  | 4039 | _spin_lock_acquire( &_fat.fat_lock ); | 
|---|
|  | 4040 |  | 
|---|
|  | 4041 | // get inode | 
|---|
|  | 4042 | unsigned int code = _get_inode_from_path( pathname , &inode ); | 
|---|
| [260] | 4043 |  | 
|---|
| [587] | 4044 | if ( code == 2 ) | 
|---|
|  | 4045 | { | 
|---|
|  | 4046 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4047 | _printf("\n[FAT ERROR] in _fat_mkdir() : path to parent not found" | 
|---|
|  | 4048 | " for directory <%s>\n", pathname ); | 
|---|
|  | 4049 | return -2; | 
|---|
| [260] | 4050 | } | 
|---|
| [587] | 4051 | else if ( code == 3 ) | 
|---|
| [260] | 4052 | { | 
|---|
| [587] | 4053 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4054 | _printf("\n[FAT ERROR] in _fat_mkdir() : one name in path too long" | 
|---|
|  | 4055 | " for directory  <%s>\n", pathname ); | 
|---|
|  | 4056 | return -3; | 
|---|
|  | 4057 | } | 
|---|
|  | 4058 | else if ( code == 0 ) | 
|---|
|  | 4059 | { | 
|---|
|  | 4060 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4061 | _printf("\n[FAT ERROR] in _fat_mkdir() : directory <%s> already exist\n", | 
|---|
|  | 4062 | pathname ); | 
|---|
|  | 4063 | return -4; | 
|---|
|  | 4064 | } | 
|---|
|  | 4065 | else if ( code == 1 )   // directory not found => create | 
|---|
|  | 4066 | { | 
|---|
|  | 4067 | parent = inode; | 
|---|
| [260] | 4068 |  | 
|---|
| [587] | 4069 | #if GIET_DEBUG_FAT | 
|---|
|  | 4070 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4071 | _printf("\n[DEBUG FAT] _fat_mkdir() : P[%d,%d,%d] create new directory <%s>\n", | 
|---|
|  | 4072 | x , y , p , pathname ); | 
|---|
|  | 4073 | #endif | 
|---|
|  | 4074 |  | 
|---|
|  | 4075 | // get directory name / error check already done by _get_inode_from_path() | 
|---|
|  | 4076 | char name[32]; | 
|---|
|  | 4077 | _get_last_name( pathname , name ); | 
|---|
|  | 4078 |  | 
|---|
|  | 4079 | // allocate one cluster from FAT for the new directory | 
|---|
|  | 4080 | unsigned int cluster; | 
|---|
|  | 4081 | if ( _allocate_one_cluster( &cluster ) ) | 
|---|
|  | 4082 | { | 
|---|
|  | 4083 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4084 | _printf("\n[FAT ERROR] in _fat_mkdir() : no free cluster" | 
|---|
|  | 4085 | " for directory <%s>\n" , pathname ); | 
|---|
|  | 4086 | return -5; | 
|---|
|  | 4087 | } | 
|---|
|  | 4088 |  | 
|---|
|  | 4089 | // allocate a new inode and an empty Cache-File | 
|---|
|  | 4090 | child = _allocate_one_inode( name, | 
|---|
|  | 4091 | 1,           // it's a directory | 
|---|
|  | 4092 | cluster, | 
|---|
|  | 4093 | 0,           // size not defined | 
|---|
|  | 4094 | 0,           // count | 
|---|
|  | 4095 | 0,           // dentry set by _add_dir_entry() | 
|---|
|  | 4096 | 1 );         // cache_allocate | 
|---|
|  | 4097 |  | 
|---|
|  | 4098 | // introduce inode in Inode-Tree | 
|---|
|  | 4099 | _add_inode_in_tree( child , parent ); | 
|---|
|  | 4100 |  | 
|---|
|  | 4101 | // allocate and initialise one 4 Kbytes buffer and associated descriptor | 
|---|
|  | 4102 | _allocate_one_buffer( child, | 
|---|
|  | 4103 | 0,            // cluster_id, | 
|---|
|  | 4104 | cluster ); | 
|---|
|  | 4105 |  | 
|---|
|  | 4106 | _add_special_directories( child, | 
|---|
|  | 4107 | parent ); | 
|---|
|  | 4108 |  | 
|---|
|  | 4109 | // add an entry in the parent directory Cache_file | 
|---|
|  | 4110 | if ( _add_dir_entry( child , parent ) ) | 
|---|
|  | 4111 | { | 
|---|
|  | 4112 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4113 | _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update parent directory" | 
|---|
|  | 4114 | " for directory <%s>\n" , pathname ); | 
|---|
|  | 4115 | return -6; | 
|---|
|  | 4116 | } | 
|---|
|  | 4117 |  | 
|---|
|  | 4118 | // update DATA region on block device for parent directory | 
|---|
|  | 4119 | if ( _update_device_from_cache( parent->levels, | 
|---|
|  | 4120 | parent->cache, | 
|---|
|  | 4121 | parent->name ) ) | 
|---|
|  | 4122 | { | 
|---|
|  | 4123 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4124 | _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update DATA region " | 
|---|
|  | 4125 | " for parent of directory <%s>\n", pathname ); | 
|---|
|  | 4126 | return -7; | 
|---|
|  | 4127 | } | 
|---|
|  | 4128 |  | 
|---|
|  | 4129 | // update FAT region on block device | 
|---|
|  | 4130 | if ( _update_device_from_cache( _fat.fat_cache_levels, | 
|---|
|  | 4131 | _fat.fat_cache_root, | 
|---|
|  | 4132 | "FAT" ) ) | 
|---|
|  | 4133 | { | 
|---|
|  | 4134 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4135 | _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update FAT region" | 
|---|
|  | 4136 | " for directory <%s>\n", pathname ); | 
|---|
|  | 4137 | return -8; | 
|---|
|  | 4138 | } | 
|---|
|  | 4139 |  | 
|---|
|  | 4140 | // update FS_INFO sector | 
|---|
|  | 4141 | if ( _update_fs_info() ) | 
|---|
|  | 4142 | { | 
|---|
|  | 4143 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4144 | _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update FS-INFO" | 
|---|
|  | 4145 | " for directory <%s>\n", pathname ); | 
|---|
|  | 4146 | return -9; | 
|---|
|  | 4147 | } | 
|---|
|  | 4148 |  | 
|---|
|  | 4149 | // update DATA region on block device for the new directory | 
|---|
|  | 4150 | if ( _update_device_from_cache( child->levels, | 
|---|
|  | 4151 | child->cache, | 
|---|
|  | 4152 | child->name ) ) | 
|---|
|  | 4153 | { | 
|---|
|  | 4154 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4155 | _printf("\n[FAT ERROR] in _fat_mkdir() : cannot update DATA region" | 
|---|
|  | 4156 | " for directory <%s>\n", pathname ); | 
|---|
|  | 4157 | return -10; | 
|---|
|  | 4158 | } | 
|---|
|  | 4159 | }  // end create directory | 
|---|
|  | 4160 |  | 
|---|
| [606] | 4161 | // release lock | 
|---|
|  | 4162 | _spin_lock_release( &_fat.fat_lock ); | 
|---|
|  | 4163 |  | 
|---|
| [587] | 4164 | return 0; | 
|---|
|  | 4165 | }  // end _fat_mkdir() | 
|---|
|  | 4166 |  | 
|---|
|  | 4167 |  | 
|---|
|  | 4168 |  | 
|---|
|  | 4169 |  | 
|---|
|  | 4170 |  | 
|---|
| [260] | 4171 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 4172 | // The following function implements the giet_fat_list() system call. | 
|---|
|  | 4173 | // It displays the content of a directory identified by the "pathname" argument. | 
|---|
|  | 4174 | // It returns an error code if the pathname is not a directory. | 
|---|
| [258] | 4175 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 4176 | // Returns 0 if success. | 
|---|
|  | 4177 | // Returns a negative value if error: | 
|---|
|  | 4178 | //   -1  : "FAT not initialised | 
|---|
|  | 4179 | //   -2  : "Directory not found" | 
|---|
|  | 4180 | //   -3  : "Name in path too long | 
|---|
|  | 4181 | //   -4  : "Not a directory" | 
|---|
|  | 4182 | //   -5  : "Cannot access directory" | 
|---|
| [258] | 4183 | ///////////////////////////////////////////////////////////////////////////////// | 
|---|
| [587] | 4184 | int _fat_list( char*  pathname ) | 
|---|
| [258] | 4185 | { | 
|---|
| [587] | 4186 | fat_inode_t*  inode; | 
|---|
|  | 4187 |  | 
|---|
|  | 4188 | // checking FAT initialised | 
|---|
|  | 4189 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
| [258] | 4190 | { | 
|---|
| [587] | 4191 | _printf("\n[FAT ERROR] in _fat_list() : FAT not initialised\n"); | 
|---|
|  | 4192 | return -1; | 
|---|
| [258] | 4193 | } | 
|---|
| [587] | 4194 |  | 
|---|
|  | 4195 | #if GIET_DEBUG_FAT | 
|---|
|  | 4196 | unsigned int procid  = _get_procid(); | 
|---|
|  | 4197 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 4198 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 4199 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
|  | 4200 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4201 | _printf("\n[DEBUG FAT] _fat_list() : P[%d,%d,%d] enters for path <%s>\n", | 
|---|
|  | 4202 | x, y, p, pathname ); | 
|---|
|  | 4203 | #endif | 
|---|
|  | 4204 |  | 
|---|
|  | 4205 | // get inode | 
|---|
|  | 4206 | unsigned int code = _get_inode_from_path( pathname , &inode ); | 
|---|
|  | 4207 |  | 
|---|
|  | 4208 | if ( (code == 1) || (code == 2) ) | 
|---|
| [258] | 4209 | { | 
|---|
| [587] | 4210 | _printf("\n[FAT ERROR] in _fat_list() : directory <%s> not found\n", pathname ); | 
|---|
|  | 4211 | return -2; | 
|---|
|  | 4212 | } | 
|---|
|  | 4213 | if ( code == 3 ) | 
|---|
|  | 4214 | { | 
|---|
|  | 4215 | _printf("\n[FAT ERROR] in _fat_list() : name too long in path <%s>\n", pathname ); | 
|---|
|  | 4216 | return -3; | 
|---|
|  | 4217 | } | 
|---|
| [258] | 4218 |  | 
|---|
| [587] | 4219 | // check found inode is a directory | 
|---|
|  | 4220 | if ( inode->is_dir == 0 ) | 
|---|
|  | 4221 | { | 
|---|
|  | 4222 | _printf("\n[FAT ERROR] in _fat_list() : <%s> is not a directory\n", pathname ); | 
|---|
|  | 4223 | return -4; | 
|---|
|  | 4224 | } | 
|---|
| [258] | 4225 |  | 
|---|
| [587] | 4226 | #if GIET_DEBUG_FAT | 
|---|
|  | 4227 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4228 | _printf("\n[DEBUG FAT] _fat_list() : P[%d,%d,%d] found inode for path <%s>\n", | 
|---|
|  | 4229 | x, y, p, pathname ); | 
|---|
|  | 4230 | #endif | 
|---|
| [258] | 4231 |  | 
|---|
| [587] | 4232 | // scan directory up to end of directory / two embedded loops : | 
|---|
|  | 4233 | // - loop on the clusters allocated to the directory | 
|---|
|  | 4234 | // - loop on the directory entries in each 4 Kbytes buffer | 
|---|
|  | 4235 | unsigned char*     buffer; | 
|---|
|  | 4236 | fat_cache_desc_t*  pdesc; | 
|---|
|  | 4237 | unsigned int       cluster_id = 0;     // cluster index in directory | 
|---|
|  | 4238 | unsigned int       offset     = 0;     // position in scanned buffer | 
|---|
|  | 4239 | unsigned int       lfn        = 0;     // number of lfn entries | 
|---|
|  | 4240 | unsigned int       nb_entries = 0;     // number of directory entries | 
|---|
|  | 4241 | unsigned int       done       = 0;     // end of directory found | 
|---|
|  | 4242 | unsigned int       attr;               // ATTR field value | 
|---|
|  | 4243 | unsigned int       ord;                // ORD field value | 
|---|
|  | 4244 | char               lfn1[16];           // temporary buffer for string in LFN1 | 
|---|
|  | 4245 | char               lfn2[16];           // temporary buffer for string in LFN2 | 
|---|
|  | 4246 | char               lfn3[16];           // temporary buffer for string in LFN3 | 
|---|
|  | 4247 | char               name[36];           // directory entry full name | 
|---|
|  | 4248 | unsigned int       cluster;            // directory entry cluster index | 
|---|
|  | 4249 | unsigned int       size;               // directory entry size | 
|---|
|  | 4250 | unsigned int       is_dir;             // directory entry is a directory | 
|---|
|  | 4251 | unsigned int       is_vid;             // directory entry is volume_id | 
|---|
|  | 4252 |  | 
|---|
|  | 4253 | // TODO : define a method to transfer this information to user mode | 
|---|
|  | 4254 | _printf("\n<%s>   cluster = %x / lba = %x\n", pathname , | 
|---|
|  | 4255 | inode->cluster , _cluster_to_lba( inode->cluster) ); | 
|---|
|  | 4256 |  | 
|---|
|  | 4257 | while ( done == 0 ) | 
|---|
|  | 4258 | { | 
|---|
|  | 4259 | // get one 4 Kytes buffer | 
|---|
|  | 4260 | if ( _get_buffer_from_cache( inode, | 
|---|
|  | 4261 | cluster_id, | 
|---|
|  | 4262 | &pdesc ) ) | 
|---|
|  | 4263 | { | 
|---|
|  | 4264 | _printf("\n[FAT ERROR] in _fat_list() : cannot access <%s>\n", pathname ); | 
|---|
|  | 4265 | return -5; | 
|---|
|  | 4266 | } | 
|---|
|  | 4267 | buffer = pdesc->buffer; | 
|---|
|  | 4268 |  | 
|---|
|  | 4269 | // scan this 4 Kbytes buffer | 
|---|
|  | 4270 | while ( (offset < 4096)  && (done == 0) ) | 
|---|
|  | 4271 | { | 
|---|
|  | 4272 | attr = _read_entry( DIR_ATTR , buffer + offset , 0 ); | 
|---|
|  | 4273 | ord  = _read_entry( LDIR_ORD , buffer + offset , 0 ); | 
|---|
|  | 4274 |  | 
|---|
|  | 4275 | if (ord == NO_MORE_ENTRY)                 // no more entry in directory => break | 
|---|
|  | 4276 | { | 
|---|
|  | 4277 | done = 1; | 
|---|
|  | 4278 | } | 
|---|
|  | 4279 | else if ( ord == FREE_ENTRY )             // free entry => skip | 
|---|
|  | 4280 | { | 
|---|
|  | 4281 | offset = offset + 32; | 
|---|
|  | 4282 | } | 
|---|
|  | 4283 | else if ( attr == ATTR_LONG_NAME_MASK )   // LFN entry => get partial names | 
|---|
|  | 4284 | { | 
|---|
|  | 4285 | unsigned int seq = ord & 0x3; | 
|---|
|  | 4286 | lfn = (seq > lfn) ? seq : lfn; | 
|---|
|  | 4287 | if      ( seq == 1 ) _get_name_from_long( buffer + offset, lfn1 ); | 
|---|
|  | 4288 | else if ( seq == 2 ) _get_name_from_long( buffer + offset, lfn2 ); | 
|---|
|  | 4289 | else if ( seq == 3 ) _get_name_from_long( buffer + offset, lfn3 ); | 
|---|
|  | 4290 | offset = offset + 32; | 
|---|
|  | 4291 | } | 
|---|
|  | 4292 | else                                 // NORMAL entry | 
|---|
|  | 4293 | { | 
|---|
|  | 4294 | if      ( lfn == 0 ) | 
|---|
|  | 4295 | { | 
|---|
|  | 4296 | _get_name_from_short( buffer + offset , name ); | 
|---|
|  | 4297 | } | 
|---|
|  | 4298 | else if ( lfn == 1 ) | 
|---|
|  | 4299 | { | 
|---|
|  | 4300 | _strcpy( name , lfn1 ); | 
|---|
|  | 4301 | } | 
|---|
|  | 4302 | else if ( lfn == 2 ) | 
|---|
|  | 4303 | { | 
|---|
|  | 4304 | _strcpy( name      , lfn1 ); | 
|---|
|  | 4305 | _strcpy( name + 13 , lfn2 ); | 
|---|
|  | 4306 | } | 
|---|
|  | 4307 | else if ( lfn == 3 ) | 
|---|
|  | 4308 | { | 
|---|
|  | 4309 | _strcpy( name      , lfn1 ); | 
|---|
|  | 4310 | _strcpy( name + 13 , lfn2 ); | 
|---|
|  | 4311 | _strcpy( name + 26 , lfn3 ); | 
|---|
|  | 4312 | } | 
|---|
|  | 4313 |  | 
|---|
|  | 4314 | is_dir  = ((attr & ATTR_DIRECTORY) == ATTR_DIRECTORY); | 
|---|
|  | 4315 | is_vid  = ((attr & ATTR_VOLUME_ID) == ATTR_VOLUME_ID); | 
|---|
|  | 4316 | size    = (_read_entry( DIR_FILE_SIZE   , buffer + offset , 1 )      ) ; | 
|---|
|  | 4317 | cluster = (_read_entry( DIR_FST_CLUS_HI , buffer + offset , 1 ) << 16) | | 
|---|
|  | 4318 | (_read_entry( DIR_FST_CLUS_LO , buffer + offset , 1 )      ) ; | 
|---|
|  | 4319 |  | 
|---|
|  | 4320 | if ( is_vid == 0 ) | 
|---|
|  | 4321 | { | 
|---|
|  | 4322 | // TODO : define a method to transfer this information to user mode | 
|---|
|  | 4323 | if (is_dir) _printf("  DIR  | size = %X | cluster = %X | %s\n", | 
|---|
|  | 4324 | size , cluster, name ); | 
|---|
|  | 4325 | else        _printf("  FILE | size = %X | cluster = %X | %s\n", | 
|---|
|  | 4326 | size , cluster, name ); | 
|---|
|  | 4327 | nb_entries++; | 
|---|
|  | 4328 | } | 
|---|
|  | 4329 |  | 
|---|
|  | 4330 | offset = offset + 32; | 
|---|
|  | 4331 | lfn    = 0; | 
|---|
|  | 4332 | } | 
|---|
|  | 4333 | }  // end loop on directory entries | 
|---|
|  | 4334 |  | 
|---|
|  | 4335 | if ( done == 0 ) | 
|---|
|  | 4336 | { | 
|---|
|  | 4337 | cluster_id++; | 
|---|
|  | 4338 | offset = 0; | 
|---|
|  | 4339 | } | 
|---|
|  | 4340 | }  // end loop on buffers | 
|---|
|  | 4341 |  | 
|---|
|  | 4342 | // TODO : define a method to transfer this information to user mode | 
|---|
|  | 4343 | _printf("  total = %d entries\n", nb_entries ); | 
|---|
|  | 4344 |  | 
|---|
|  | 4345 | return 0; | 
|---|
|  | 4346 | } // end _fat_list() | 
|---|
|  | 4347 |  | 
|---|
|  | 4348 |  | 
|---|
|  | 4349 |  | 
|---|
|  | 4350 |  | 
|---|
|  | 4351 |  | 
|---|
|  | 4352 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 4353 | // This functiond load a file identified by the "pathname" argument into the | 
|---|
|  | 4354 | // memory buffer defined by the "buffer_vbase" and "buffer_size" arguments. | 
|---|
|  | 4355 | // It is intended to be called by the boot-loader, as it does not use the | 
|---|
|  | 4356 | // dynamically allocated FAT structures (Inode-Tree, Fat_Cache or File-Cache, | 
|---|
|  | 4357 | // File-Descriptor-Array). | 
|---|
|  | 4358 | // It uses only the 512 bytes buffer defined in the FAT descriptor. | 
|---|
|  | 4359 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 4360 | // Returns  0 if success. | 
|---|
|  | 4361 | // Returns negative value if error: | 
|---|
|  | 4362 | //  -1  : "FAT not initialised" | 
|---|
|  | 4363 | //  -2  : "File not found" | 
|---|
|  | 4364 | //  -3  : "Buffer too small" | 
|---|
|  | 4365 | //  -4  : "Cannot access block device" | 
|---|
|  | 4366 | //  -5  : "Cannot access FAT on block device" | 
|---|
|  | 4367 | /////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 4368 | int _fat_load_no_cache( char*        pathname, | 
|---|
|  | 4369 | unsigned int buffer_vbase, | 
|---|
|  | 4370 | unsigned int buffer_size ) | 
|---|
| [258] | 4371 | { | 
|---|
| [587] | 4372 | // checking FAT initialised | 
|---|
|  | 4373 | if( _fat.initialised != FAT_INITIALISED ) | 
|---|
|  | 4374 | { | 
|---|
|  | 4375 | _printf("\n[FAT ERROR] in _fat_load_no_cache() : FAT not initialised\n"); | 
|---|
|  | 4376 | return -1; | 
|---|
|  | 4377 | } | 
|---|
| [258] | 4378 |  | 
|---|
| [587] | 4379 | unsigned int  file_size; | 
|---|
|  | 4380 | unsigned int  cluster; | 
|---|
|  | 4381 |  | 
|---|
|  | 4382 | #if GIET_DEBUG_FAT | 
|---|
|  | 4383 | unsigned int procid  = _get_procid(); | 
|---|
|  | 4384 | unsigned int x       = procid >> (Y_WIDTH + P_WIDTH); | 
|---|
|  | 4385 | unsigned int y       = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1); | 
|---|
|  | 4386 | unsigned int p       = procid & ((1<<P_WIDTH)-1); | 
|---|
|  | 4387 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4388 | _printf("\n[DEBUG FAT] _fat_load_no_cache() : P[%d,%d,%d] enters for file <%s>\n", | 
|---|
|  | 4389 | x , y , p , pathname ); | 
|---|
|  | 4390 | #endif | 
|---|
|  | 4391 |  | 
|---|
|  | 4392 | // get file size, and cluster index in FAT | 
|---|
|  | 4393 | if ( _file_info_no_cache( pathname, | 
|---|
|  | 4394 | &cluster, | 
|---|
|  | 4395 | &file_size ) ) | 
|---|
|  | 4396 | { | 
|---|
|  | 4397 | _printf("\n[FAT ERROR] in _fat_load_no_cache() : file <%s> not found\n", | 
|---|
|  | 4398 | pathname ); | 
|---|
|  | 4399 | return -2; | 
|---|
|  | 4400 | } | 
|---|
|  | 4401 |  | 
|---|
|  | 4402 | // check buffer size | 
|---|
|  | 4403 | if ( file_size > buffer_size ) | 
|---|
|  | 4404 | { | 
|---|
|  | 4405 | _printf("\n[FAT ERROR] in _fat_load_no_cache() : buffer too small : " | 
|---|
|  | 4406 | "file_size = %x / buffer_size = %x", file_size , buffer_size ); | 
|---|
|  | 4407 | return -3; | 
|---|
|  | 4408 | } | 
|---|
|  | 4409 |  | 
|---|
|  | 4410 | // compute total number of clusters to read | 
|---|
|  | 4411 | unsigned int nb_clusters = file_size >> 12; | 
|---|
|  | 4412 | if ( file_size & 0xFFF ) nb_clusters++; | 
|---|
|  | 4413 |  | 
|---|
|  | 4414 | // initialise buffer address | 
|---|
|  | 4415 | unsigned int dst = buffer_vbase; | 
|---|
|  | 4416 |  | 
|---|
|  | 4417 | // loop on the clusters containing the file | 
|---|
|  | 4418 | while ( nb_clusters > 0 ) | 
|---|
|  | 4419 | { | 
|---|
|  | 4420 | unsigned int lba = _cluster_to_lba( cluster ); | 
|---|
|  | 4421 |  | 
|---|
|  | 4422 | if( _fat_ioc_access( 0,         // no descheduling | 
|---|
|  | 4423 | 1,         // read | 
|---|
|  | 4424 | lba, | 
|---|
|  | 4425 | dst, | 
|---|
|  | 4426 | 8 ) )      // 8 blocks | 
|---|
|  | 4427 | { | 
|---|
|  | 4428 | _printf("\n[FAT ERROR] in _fat_no _cache_read() : cannot load lba %x", lba ); | 
|---|
|  | 4429 | return -4; | 
|---|
|  | 4430 | } | 
|---|
|  | 4431 |  | 
|---|
|  | 4432 |  | 
|---|
|  | 4433 | // compute next cluster index | 
|---|
|  | 4434 | unsigned int next; | 
|---|
|  | 4435 | if ( _next_cluster_no_cache( cluster , &next ) ) | 
|---|
|  | 4436 | { | 
|---|
|  | 4437 | _printf("\n[FAT ERROR] in _fat_no _cache_read() : cannot get next cluster " | 
|---|
|  | 4438 | " for cluster = %x\n", cluster ); | 
|---|
|  | 4439 | return -5; | 
|---|
|  | 4440 | } | 
|---|
|  | 4441 |  | 
|---|
|  | 4442 | // update variables for next iteration | 
|---|
|  | 4443 | nb_clusters = nb_clusters - 1; | 
|---|
|  | 4444 | dst         = dst + 4096; | 
|---|
|  | 4445 | cluster     = next; | 
|---|
|  | 4446 | } | 
|---|
|  | 4447 |  | 
|---|
|  | 4448 | #if GIET_DEBUG_FAT | 
|---|
|  | 4449 | if ( _get_proctime() > GIET_DEBUG_FAT ) | 
|---|
|  | 4450 | _printf("\n[DEBUG FAT] _fat_load_no_cache() : P[%d,%d,%d] loaded <%s> at vaddr = %x" | 
|---|
|  | 4451 | " / size = %x\n", x , y , p , pathname , buffer_vbase , file_size ); | 
|---|
|  | 4452 | #endif | 
|---|
|  | 4453 |  | 
|---|
| [258] | 4454 | return 0; | 
|---|
| [587] | 4455 | }  // end _fat_load_no_cache() | 
|---|
| [258] | 4456 |  | 
|---|
|  | 4457 |  | 
|---|
| [587] | 4458 |  | 
|---|
| [258] | 4459 | // Local Variables: | 
|---|
|  | 4460 | // tab-width: 4 | 
|---|
|  | 4461 | // c-basic-offset: 4 | 
|---|
|  | 4462 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
|  | 4463 | // indent-tabs-mode: nil | 
|---|
|  | 4464 | // End: | 
|---|
|  | 4465 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
|  | 4466 |  | 
|---|