smartfs_utils.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523
  1. /****************************************************************************
  2. * fs/smartfs/smartfs_utils.c
  3. *
  4. * Copyright (C) 2013-2014 Ken Pettit. All rights reserved.
  5. * Author: Ken Pettit <pettitkd@gmail.com>
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in
  15. * the documentation and/or other materials provided with the
  16. * distribution.
  17. * 3. Neither the name NuttX nor the names of its contributors may be
  18. * used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  24. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  25. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  26. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  27. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  28. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  29. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *
  34. ****************************************************************************/
  35. /****************************************************************************
  36. * Included Files
  37. ****************************************************************************/
  38. #include <nuttx/config.h>
  39. #include <sys/types.h>
  40. #include <stdint.h>
  41. #include <stdbool.h>
  42. #include <stdlib.h>
  43. #include <string.h>
  44. #include <time.h>
  45. #include <semaphore.h>
  46. #include <assert.h>
  47. #include <errno.h>
  48. #include <debug.h>
  49. #include <nuttx/kmalloc.h>
  50. #include <nuttx/fs/fs.h>
  51. #include <nuttx/fs/ioctl.h>
  52. #include "smartfs.h"
  53. /****************************************************************************
  54. * Private Data
  55. ****************************************************************************/
  56. #if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS) || \
  57. (defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS))
  58. static struct smartfs_mountpt_s *g_mounthead = NULL;
  59. #endif
  60. /****************************************************************************
  61. * Public Functions
  62. ****************************************************************************/
  63. /****************************************************************************
  64. * Name: smartfs_semtake
  65. ****************************************************************************/
  66. void smartfs_semtake(struct smartfs_mountpt_s *fs)
  67. {
  68. /* Take the semaphore (perhaps waiting) */
  69. while (sem_wait(fs->fs_sem) != 0)
  70. {
  71. /* The only case that an error should occur here is if
  72. * the wait was awakened by a signal.
  73. */
  74. ASSERT(*get_errno_ptr() == EINTR);
  75. }
  76. }
  77. /****************************************************************************
  78. * Name: smartfs_semgive
  79. ****************************************************************************/
  80. void smartfs_semgive(struct smartfs_mountpt_s *fs)
  81. {
  82. sem_post(fs->fs_sem);
  83. }
  84. /****************************************************************************
  85. * Name: smartfs_rdle16
  86. *
  87. * Description:
  88. * Get a (possibly unaligned) 16-bit little endian value.
  89. *
  90. * Input Parameters:
  91. * val - A pointer to the first byte of the little endian value.
  92. *
  93. * Returned Value:
  94. * A uint16_t representing the whole 16-bit integer value
  95. *
  96. ****************************************************************************/
  97. uint16_t smartfs_rdle16(FAR const void *val)
  98. {
  99. return (uint16_t)((FAR const uint8_t *)val)[1] << 8 |
  100. (uint16_t)((FAR const uint8_t *)val)[0];
  101. }
  102. /****************************************************************************
  103. * Name: smartfs_wrle16
  104. *
  105. * Description:
  106. * Put a (possibly unaligned) 16-bit little endian value.
  107. *
  108. * Input Parameters:
  109. * dest - A pointer to the first byte to save the little endian value.
  110. * val - The 16-bit value to be saved.
  111. *
  112. * Returned Value:
  113. * None
  114. *
  115. ****************************************************************************/
  116. void smartfs_wrle16(FAR void *dest, uint16_t val)
  117. {
  118. ((FAR uint8_t *) dest)[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
  119. ((FAR uint8_t *) dest)[1] = val >> 8;
  120. }
  121. /****************************************************************************
  122. * Name: smartfs_rdle32
  123. *
  124. * Description:
  125. * Get a (possibly unaligned) 32-bit little endian value.
  126. *
  127. * Input Parameters:
  128. * val - A pointer to the first byte of the little endian value.
  129. *
  130. * Returned Value:
  131. * A uint32_t representing the whole 32-bit integer value
  132. *
  133. ****************************************************************************/
  134. uint32_t smartfs_rdle32(FAR const void *val)
  135. {
  136. /* Little endian means LS halfword first in byte stream */
  137. return (uint32_t)smartfs_rdle16(&((FAR const uint8_t *)val)[2]) << 16 |
  138. (uint32_t)smartfs_rdle16(val);
  139. }
  140. /****************************************************************************
  141. * Name: smartfs_wrle32
  142. *
  143. * Description:
  144. * Put a (possibly unaligned) 32-bit little endian value.
  145. *
  146. * Input Parameters:
  147. * dest - A pointer to the first byte to save the little endian value.
  148. * val - The 32-bit value to be saved.
  149. *
  150. * Returned Value:
  151. * None
  152. *
  153. ****************************************************************************/
  154. void smartfs_wrle32(uint8_t *dest, uint32_t val)
  155. {
  156. /* Little endian means LS halfword first in byte stream */
  157. smartfs_wrle16(dest, (uint16_t)(val & 0xffff));
  158. smartfs_wrle16(dest+2, (uint16_t)(val >> 16));
  159. }
  160. /****************************************************************************
  161. * Name: smartfs_mount
  162. *
  163. * Desciption: This function is called only when the mountpoint is first
  164. * established. It initializes the mountpoint structure and verifies
  165. * that a valid SMART filesystem is provided by the block driver.
  166. *
  167. * The caller should hold the mountpoint semaphore
  168. *
  169. ****************************************************************************/
  170. int smartfs_mount(struct smartfs_mountpt_s *fs, bool writeable)
  171. {
  172. FAR struct inode *inode;
  173. struct geometry geo;
  174. int ret = OK;
  175. #if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS)
  176. struct smartfs_mountpt_s *nextfs;
  177. #endif
  178. /* Assume that the mount is not successful */
  179. fs->fs_mounted = false;
  180. /* Check if there is media available */
  181. inode = fs->fs_blkdriver;
  182. if (!inode || !inode->u.i_bops || !inode->u.i_bops->geometry ||
  183. inode->u.i_bops->geometry(inode, &geo) != OK || !geo.geo_available)
  184. {
  185. ret = -ENODEV;
  186. goto errout;
  187. }
  188. /* Make sure that that the media is write-able (if write access is needed) */
  189. if (writeable && !geo.geo_writeenabled)
  190. {
  191. ret = -EACCES;
  192. goto errout;
  193. }
  194. /* Get the SMART low-level format information to validate the device has been
  195. * formatted and scan properly for logical to physical sector mapping.
  196. */
  197. ret = FS_IOCTL(fs, BIOC_GETFORMAT, (unsigned long) &fs->fs_llformat);
  198. if (ret != OK)
  199. {
  200. ferr("ERROR: Error getting device low level format: %d\n", ret);
  201. goto errout;
  202. }
  203. /* Validate the low-level format is valid */
  204. if (!(fs->fs_llformat.flags & SMART_FMT_ISFORMATTED))
  205. {
  206. ferr("ERROR: No low-level format found\n");
  207. ret = -ENODEV;
  208. goto errout;
  209. }
  210. /* Allocate a read/write buffer */
  211. #ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
  212. /* Scan linked list of mounted file systems to find another FS with
  213. * the same blockdriver. We will reuse the buffers.
  214. */
  215. nextfs = g_mounthead;
  216. while (nextfs != NULL)
  217. {
  218. /* Test if this FS uses the same block driver */
  219. if (nextfs->fs_blkdriver == fs->fs_blkdriver)
  220. {
  221. /* Yep, it's the same block driver. Reuse the buffers.
  222. * we can do this because we are protected by the same
  223. * semaphore.
  224. */
  225. fs->fs_rwbuffer = nextfs->fs_rwbuffer;
  226. fs->fs_workbuffer = nextfs->fs_workbuffer;
  227. break;
  228. }
  229. /* Advance to next FS */
  230. nextfs = nextfs->fs_next;
  231. }
  232. /* If we didn't find a FS above, then allocate some buffers */
  233. if (nextfs == NULL)
  234. {
  235. fs->fs_rwbuffer = (char *) kmm_malloc(fs->fs_llformat.availbytes);
  236. fs->fs_workbuffer = (char *) kmm_malloc(256);
  237. }
  238. /* Now add ourselves to the linked list of SMART mounts */
  239. fs->fs_next = g_mounthead;
  240. g_mounthead = fs;
  241. /* Set our root directory sector based on the directory entry
  242. * reported by the block driver (based on which device is
  243. * associated with this mount.
  244. */
  245. fs->fs_rootsector = SMARTFS_ROOT_DIR_SECTOR + fs->fs_llformat.rootdirnum;
  246. #else /* CONFIG_SMARTFS_MULTI_ROOT_DIRS */
  247. #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
  248. /* Now add ourselves to the linked list of SMART mounts */
  249. fs->fs_next = g_mounthead;
  250. g_mounthead = fs;
  251. #endif
  252. #endif /* CONFIG_SMARTFS_MULTI_ROOT_DIRS */
  253. fs->fs_rwbuffer = (char *) kmm_malloc(fs->fs_llformat.availbytes);
  254. fs->fs_workbuffer = (char *) kmm_malloc(256);
  255. fs->fs_rootsector = SMARTFS_ROOT_DIR_SECTOR;
  256. /* We did it! */
  257. fs->fs_mounted = TRUE;
  258. finfo("SMARTFS:\n");
  259. finfo("\t Sector size: %d\n", fs->fs_llformat.sectorsize);
  260. finfo("\t Bytes/sector %d\n", fs->fs_llformat.availbytes);
  261. finfo("\t Num sectors: %d\n", fs->fs_llformat.nsectors);
  262. finfo("\t Free sectors: %d\n", fs->fs_llformat.nfreesectors);
  263. finfo("\t Max filename: %d\n", CONFIG_SMARTFS_MAXNAMLEN);
  264. #ifdef CONFIG_SMARTFS_MULTI_ROOT_DIRS
  265. finfo("\t RootDirEntries: %d\n", fs->fs_llformat.nrootdirentries);
  266. #endif
  267. finfo("\t RootDirSector: %d\n", fs->fs_rootsector);
  268. errout:
  269. return ret;
  270. }
  271. /****************************************************************************
  272. * Name: smartfs_unmount
  273. *
  274. * Desciption: This function is called only when the mountpoint is being
  275. * unbound. If we are serving multiple directories, then we have to
  276. * remove ourselves from the mount linked list, and potentially free
  277. * the shared buffers.
  278. *
  279. * The caller should hold the mountpoint semaphore
  280. *
  281. ****************************************************************************/
  282. int smartfs_unmount(struct smartfs_mountpt_s *fs)
  283. {
  284. int ret = OK;
  285. struct inode *inode;
  286. #if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS) || \
  287. (defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS))
  288. struct smartfs_mountpt_s *nextfs;
  289. struct smartfs_mountpt_s *prevfs;
  290. int count = 0;
  291. int found = FALSE;
  292. #endif
  293. #if defined(CONFIG_SMARTFS_MULTI_ROOT_DIRS) || \
  294. (defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS))
  295. /* Start at the head of the mounts and search for our entry. Also
  296. * count the number of entries that match our blkdriver.
  297. */
  298. nextfs = g_mounthead;
  299. prevfs = NULL;
  300. while (nextfs != NULL)
  301. {
  302. /* Test if this FS's blkdriver matches ours (it could be us) */
  303. if (nextfs->fs_blkdriver == fs->fs_blkdriver)
  304. count++;
  305. /* Test if this entry is our's */
  306. if (nextfs == fs)
  307. {
  308. found = TRUE;
  309. }
  310. /* Keep track of the previous entry until our's is found */
  311. if (!found)
  312. {
  313. /* Save this entry as the previous entry */
  314. prevfs = nextfs;
  315. }
  316. /* Advance to the next entry */
  317. nextfs = nextfs->fs_next;
  318. }
  319. /* Ensure we found our FS */
  320. if (!found)
  321. {
  322. /* Our entry not found! Invalid unmount or bug somewhere */
  323. return -EINVAL;
  324. }
  325. /* If the count is only one, then we need to delete the shared
  326. * buffers because we are the last ones.
  327. */
  328. if (count == 1)
  329. {
  330. /* Close the block driver */
  331. if (fs->fs_blkdriver)
  332. {
  333. inode = fs->fs_blkdriver;
  334. if (inode)
  335. {
  336. if (inode->u.i_bops && inode->u.i_bops->close)
  337. {
  338. (void)inode->u.i_bops->close(inode);
  339. }
  340. }
  341. }
  342. /* Free the buffers */
  343. kmm_free(fs->fs_rwbuffer);
  344. kmm_free(fs->fs_workbuffer);
  345. /* Set the buffer's to invalid value to catch program bugs */
  346. fs->fs_rwbuffer = (char *) 0xDEADBEEF;
  347. fs->fs_workbuffer = (char *) 0xDEADBEEF;
  348. }
  349. /* Now removed ourselves from the linked list */
  350. if (fs == g_mounthead)
  351. {
  352. /* We were the first ones. Set a new head */
  353. g_mounthead = fs->fs_next;
  354. }
  355. else
  356. {
  357. /* Remove from the middle of the list somewhere */
  358. prevfs->fs_next = fs->fs_next;
  359. }
  360. #else
  361. if (fs->fs_blkdriver)
  362. {
  363. inode = fs->fs_blkdriver;
  364. if (inode)
  365. {
  366. if (inode->u.i_bops && inode->u.i_bops->close)
  367. {
  368. (void)inode->u.i_bops->close(inode);
  369. }
  370. }
  371. }
  372. /* Release the mountpoint private data */
  373. kmm_free(fs->fs_rwbuffer);
  374. kmm_free(fs->fs_workbuffer);
  375. #endif
  376. return ret;
  377. }
  378. /****************************************************************************
  379. * Name: smartfs_finddirentry
  380. *
  381. * Description: Finds an entry in the filesystem as specified by relpath.
  382. * If found, the direntry will be populated with information
  383. * for accessing the entry.
  384. *
  385. * If the final directory segment of relpath just before the
  386. * last segment (the target file/dir) is valid, then the
  387. * parentdirsector will indicate the logical sector number of
  388. * the parent directory where a new entry should be created,
  389. * and the filename pointer will point to the final segment
  390. * (i.e. the "filename").
  391. *
  392. ****************************************************************************/
  393. int smartfs_finddirentry(struct smartfs_mountpt_s *fs,
  394. struct smartfs_entry_s *direntry, const char *relpath,
  395. uint16_t *parentdirsector, const char **filename)
  396. {
  397. int ret = -ENOENT;
  398. const char *segment;
  399. const char *ptr;
  400. uint16_t seglen;
  401. uint16_t depth = 0;
  402. uint16_t dirstack[CONFIG_SMARTFS_DIRDEPTH];
  403. uint16_t dirsector;
  404. uint16_t entrysize;
  405. uint16_t offset;
  406. struct smartfs_chain_header_s *header;
  407. struct smart_read_write_s readwrite;
  408. struct smartfs_entry_header_s *entry;
  409. /* Initialize directory level zero as the root sector */
  410. dirstack[0] = fs->fs_rootsector;
  411. entrysize = sizeof(struct smartfs_entry_header_s) + fs->fs_llformat.namesize;
  412. /* Test if this is a request for the root directory */
  413. if (*relpath == '\0')
  414. {
  415. direntry->firstsector = fs->fs_rootsector;
  416. direntry->flags = SMARTFS_DIRENT_TYPE_DIR | 0777;
  417. direntry->utc = 0;
  418. direntry->dsector = 0;
  419. direntry->doffset = 0;
  420. direntry->dfirst = fs->fs_rootsector;
  421. direntry->name = NULL;
  422. direntry->datlen = 0;
  423. *parentdirsector = 0; /* Our parent is the format sector I guess */
  424. return OK;
  425. }
  426. /* Parse through each segment of relpath */
  427. segment = relpath;
  428. while (segment != NULL && *segment != '\0')
  429. {
  430. /* Find the end of this segment. It will be '/' or NULL. */
  431. ptr = segment;
  432. seglen = 0;
  433. while (*ptr != '/' && *ptr != '\0')
  434. {
  435. seglen++;
  436. ptr++;
  437. }
  438. strncpy(fs->fs_workbuffer, segment, seglen);
  439. fs->fs_workbuffer[seglen] = '\0';
  440. /* Search for "." and ".." as segment names */
  441. if (strcmp(fs->fs_workbuffer, ".") == 0)
  442. {
  443. /* Just ignore this segment. Advance ptr if not on NULL */
  444. if (*ptr == '/')
  445. {
  446. ptr++;
  447. }
  448. segment = ptr;
  449. continue;
  450. }
  451. else if (strcmp(fs->fs_workbuffer, "..") == 0)
  452. {
  453. /* Up one level */
  454. if (depth == 0)
  455. {
  456. /* We went up one level past our mount point! */
  457. goto errout;
  458. }
  459. /* "Pop" to the previous directory level */
  460. depth--;
  461. if (*ptr == '/')
  462. {
  463. ptr++;
  464. }
  465. segment = ptr;
  466. continue;
  467. }
  468. else
  469. {
  470. /* Search for the entry in the current directory */
  471. dirsector = dirstack[depth];
  472. /* Read the directory */
  473. offset = 0xFFFF;
  474. #if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
  475. while (dirsector != 0xFFFF)
  476. #else
  477. while (dirsector != 0)
  478. #endif
  479. {
  480. /* Read the next directory in the chain */
  481. readwrite.logsector = dirsector;
  482. readwrite.count = fs->fs_llformat.availbytes;
  483. readwrite.buffer = (uint8_t *)fs->fs_rwbuffer;
  484. readwrite.offset = 0;
  485. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  486. if (ret < 0)
  487. {
  488. goto errout;
  489. }
  490. /* Point to next sector in chain */
  491. header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
  492. dirsector = SMARTFS_NEXTSECTOR(header);
  493. /* Search for the entry */
  494. offset = sizeof(struct smartfs_chain_header_s);
  495. entry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  496. while (offset < readwrite.count)
  497. {
  498. /* Test if this entry is valid and active */
  499. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  500. if (((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_EMPTY) ==
  501. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
  502. ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_ACTIVE) !=
  503. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  504. #else
  505. if (((entry->flags & SMARTFS_DIRENT_EMPTY) ==
  506. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) ||
  507. ((entry->flags & SMARTFS_DIRENT_ACTIVE) !=
  508. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  509. #endif
  510. {
  511. /* This entry isn't valid, skip it */
  512. offset += entrysize;
  513. entry = (struct smartfs_entry_header_s *)
  514. &fs->fs_rwbuffer[offset];
  515. continue;
  516. }
  517. /* Test if the name matches */
  518. if (strncmp(entry->name, fs->fs_workbuffer,
  519. fs->fs_llformat.namesize) == 0)
  520. {
  521. /* We found it! If this is the last segment entry,
  522. * then report the entry. If it isn't the last
  523. * entry, then validate it is a directory entry and
  524. * open it and continue searching.
  525. */
  526. if (*ptr == '\0')
  527. {
  528. /* We are at the last segment. Report the entry */
  529. /* Fill in the entry */
  530. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  531. direntry->firstsector = smartfs_rdle16(&entry->firstsector);
  532. direntry->flags = smartfs_rdle16(&entry->flags);
  533. direntry->utc = smartfs_rdle32(&entry->utc);
  534. #else
  535. direntry->firstsector = entry->firstsector;
  536. direntry->flags = entry->flags;
  537. direntry->utc = entry->utc;
  538. #endif
  539. direntry->dsector = readwrite.logsector;
  540. direntry->doffset = offset;
  541. direntry->dfirst = dirstack[depth];
  542. if (direntry->name == NULL)
  543. {
  544. direntry->name = (char *) kmm_malloc(fs->fs_llformat.namesize+1);
  545. }
  546. memset(direntry->name, 0, fs->fs_llformat.namesize + 1);
  547. strncpy(direntry->name, entry->name, fs->fs_llformat.namesize);
  548. direntry->datlen = 0;
  549. /* Scan the file's sectors to calculate the length and perform
  550. * a rudimentary check.
  551. */
  552. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  553. if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) ==
  554. SMARTFS_DIRENT_TYPE_FILE)
  555. {
  556. dirsector = smartfs_rdle16(&entry->firstsector);
  557. #else
  558. if ((entry->flags & SMARTFS_DIRENT_TYPE) ==
  559. SMARTFS_DIRENT_TYPE_FILE)
  560. {
  561. dirsector = entry->firstsector;
  562. #endif
  563. readwrite.count = sizeof(struct smartfs_chain_header_s);
  564. readwrite.buffer = (uint8_t *)fs->fs_rwbuffer;
  565. readwrite.offset = 0;
  566. while (dirsector != SMARTFS_ERASEDSTATE_16BIT)
  567. {
  568. /* Read the next sector of the file */
  569. readwrite.logsector = dirsector;
  570. ret = FS_IOCTL(fs, BIOC_READSECT,
  571. (unsigned long) &readwrite);
  572. if (ret < 0)
  573. {
  574. ferr("ERROR: Error in sector chain at %d!\n",
  575. dirsector);
  576. break;
  577. }
  578. /* Add used bytes to the total and point to next sector */
  579. if (*((uint16_t *) header->used) != SMARTFS_ERASEDSTATE_16BIT)
  580. {
  581. direntry->datlen += *((uint16_t *) header->used);
  582. }
  583. dirsector = SMARTFS_NEXTSECTOR(header);
  584. }
  585. }
  586. *parentdirsector = dirstack[depth];
  587. *filename = segment;
  588. ret = OK;
  589. goto errout;
  590. }
  591. else
  592. {
  593. /* Validate it's a directory */
  594. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  595. if ((smartfs_rdle16(&entry->flags) & SMARTFS_DIRENT_TYPE) !=
  596. SMARTFS_DIRENT_TYPE_DIR)
  597. #else
  598. if ((entry->flags & SMARTFS_DIRENT_TYPE) !=
  599. SMARTFS_DIRENT_TYPE_DIR)
  600. #endif
  601. {
  602. /* Not a directory! Report the error */
  603. ret = -ENOTDIR;
  604. goto errout;
  605. }
  606. /* "Push" the directory and continue searching */
  607. if (depth >= CONFIG_SMARTFS_DIRDEPTH - 1)
  608. {
  609. /* Directory depth too big */
  610. ret = -ENAMETOOLONG;
  611. goto errout;
  612. }
  613. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  614. dirstack[++depth] = smartfs_rdle16(&entry->firstsector);
  615. #else
  616. dirstack[++depth] = entry->firstsector;
  617. #endif
  618. segment = ptr + 1;
  619. break;
  620. }
  621. }
  622. /* Not this entry. Skip to the next one */
  623. offset += entrysize;
  624. entry = (struct smartfs_entry_header_s *)
  625. &fs->fs_rwbuffer[offset];
  626. }
  627. /* Test if a directory entry was found and break if it was */
  628. if (offset < readwrite.count)
  629. {
  630. break;
  631. }
  632. }
  633. /* If we found a dir entry, then continue searching */
  634. if (offset < readwrite.count)
  635. {
  636. /* Update the segment pointer */
  637. if (*ptr != '\0')
  638. {
  639. ptr++;
  640. }
  641. segment = ptr;
  642. continue;
  643. }
  644. /* Entry not found! Report the error. Also, if this is the last
  645. * segment, then report the parent directory sector.
  646. */
  647. if (*ptr == '\0')
  648. {
  649. *parentdirsector = dirstack[depth];
  650. *filename = segment;
  651. }
  652. else
  653. {
  654. *parentdirsector = 0xFFFF;
  655. *filename = NULL;
  656. }
  657. ret = -ENOENT;
  658. goto errout;
  659. }
  660. }
  661. errout:
  662. return ret;
  663. }
  664. /****************************************************************************
  665. * Name: smartfs_createentry
  666. *
  667. * Description: Creates a new entry in the specified parent directory, using
  668. * the specified type and name. If the given sectorno is
  669. * 0xFFFF, then a new sector is allocated for the new entry,
  670. * otherwise the supplied sectorno is used.
  671. *
  672. ****************************************************************************/
  673. int smartfs_createentry(FAR struct smartfs_mountpt_s *fs,
  674. uint16_t parentdirsector, FAR const char *filename,
  675. uint16_t type, mode_t mode,
  676. FAR struct smartfs_entry_s *direntry,
  677. uint16_t sectorno, FAR struct smartfs_ofile_s *sf)
  678. {
  679. struct smart_read_write_s readwrite;
  680. int ret;
  681. uint16_t psector;
  682. uint16_t nextsector;
  683. uint16_t offset;
  684. uint16_t found;
  685. uint16_t entrysize;
  686. struct smartfs_entry_header_s *entry;
  687. struct smartfs_chain_header_s *chainheader;
  688. /* Start at the 1st sector in the parent directory */
  689. psector = parentdirsector;
  690. found = FALSE;
  691. entrysize = sizeof(struct smartfs_entry_header_s) +
  692. fs->fs_llformat.namesize;
  693. /* Validate the name isn't too long */
  694. if (strlen(filename) > fs->fs_llformat.namesize)
  695. {
  696. return -ENAMETOOLONG;
  697. }
  698. /* Read the parent directory sector and find a place to insert
  699. * the new entry.
  700. */
  701. while (1)
  702. {
  703. /* Read the next sector */
  704. readwrite.logsector = psector;
  705. readwrite.count = fs->fs_llformat.availbytes;
  706. readwrite.offset = 0;
  707. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  708. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  709. if (ret < 0)
  710. {
  711. goto errout;
  712. }
  713. /* Get the next chained sector */
  714. chainheader = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
  715. nextsector = SMARTFS_NEXTSECTOR(chainheader);
  716. /* Search for an empty entry in this sector */
  717. offset = sizeof(struct smartfs_chain_header_s);
  718. entry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  719. while (offset + entrysize < readwrite.count)
  720. {
  721. /* Check if this entry is available */
  722. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  723. if ((smartfs_rdle16(&entry->flags) == SMARTFS_ERASEDSTATE_16BIT) ||
  724. ((smartfs_rdle16(&entry->flags) &
  725. #else
  726. if ((entry->flags == SMARTFS_ERASEDSTATE_16BIT) ||
  727. ((entry->flags &
  728. #endif
  729. (SMARTFS_DIRENT_EMPTY | SMARTFS_DIRENT_ACTIVE)) ==
  730. (~SMARTFS_ERASEDSTATE_16BIT &
  731. (SMARTFS_DIRENT_EMPTY | SMARTFS_DIRENT_ACTIVE))))
  732. {
  733. /* We found an empty entry. Use it. */
  734. found = TRUE;
  735. break;
  736. }
  737. /* Not available. Skip to next entry */
  738. offset += entrysize;
  739. entry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  740. }
  741. /* If we found an entry, stop the search */
  742. if (found)
  743. {
  744. break;
  745. }
  746. /* If there are no more sectors, then we need to add one to make
  747. * room for the new entry.
  748. */
  749. if (nextsector == SMARTFS_ERASEDSTATE_16BIT)
  750. {
  751. /* Allocate a new sector and chain it to the last one */
  752. ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF);
  753. if (ret < 0)
  754. {
  755. goto errout;
  756. }
  757. nextsector = (uint16_t) ret;
  758. /* Chain the next sector into this sector sector */
  759. *((uint16_t *) chainheader->nextsector) = nextsector;
  760. readwrite.offset = offsetof(struct smartfs_chain_header_s,
  761. nextsector);
  762. readwrite.count = sizeof(uint16_t);
  763. readwrite.buffer = chainheader->nextsector;
  764. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  765. if (ret < 0)
  766. {
  767. ferr("ERROR: Error chaining sector %d\n", nextsector);
  768. goto errout;
  769. }
  770. }
  771. /* Now update to the next sector */
  772. psector = nextsector;
  773. }
  774. /* We found an insertion point. Create the entry at sector,offset */
  775. #if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
  776. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  777. smartfs_wrle16(&entry->flags, (uint16_t) (SMARTFS_DIRENT_ACTIVE |
  778. SMARTFS_DIRENT_DELETING | SMARTFS_DIRENT_RESERVED | type | (mode &
  779. SMARTFS_DIRENT_MODE)));
  780. #else
  781. entry->flags = (uint16_t) (SMARTFS_DIRENT_ACTIVE |
  782. SMARTFS_DIRENT_DELETING | SMARTFS_DIRENT_RESERVED | type | (mode &
  783. SMARTFS_DIRENT_MODE));
  784. #endif
  785. #else /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */
  786. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  787. smartfs_wrle16(&entry->flags, (uint16_t) (SMARTFS_DIRENT_EMPTY | type |
  788. (mode & SMARTFS_DIRENT_MODE)));
  789. #else
  790. entry->flags = (uint16_t) (SMARTFS_DIRENT_EMPTY | type |
  791. (mode & SMARTFS_DIRENT_MODE));
  792. #endif
  793. #endif /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */
  794. if (sectorno == 0xFFFF)
  795. {
  796. /* Allocate a new sector for the file / dir */
  797. ret = FS_IOCTL(fs, BIOC_ALLOCSECT, 0xFFFF);
  798. if (ret < 0)
  799. {
  800. goto errout;
  801. }
  802. nextsector = (uint16_t) ret;
  803. /* Set the newly allocated sector's type (file or dir) */
  804. #ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
  805. if (sf)
  806. {
  807. /* Using sector buffer and we have an open file context. Just update
  808. * the sector buffer in the open file context.
  809. */
  810. memset(sf->buffer, CONFIG_SMARTFS_ERASEDSTATE, fs->fs_llformat.availbytes);
  811. chainheader = (struct smartfs_chain_header_s *) sf->buffer;
  812. chainheader->type = SMARTFS_SECTOR_TYPE_FILE;
  813. sf->bflags = SMARTFS_BFLAG_DIRTY | SMARTFS_BFLAG_NEWALLOC;
  814. }
  815. else
  816. #endif
  817. {
  818. if ((type & SMARTFS_DIRENT_TYPE) == SMARTFS_DIRENT_TYPE_DIR)
  819. {
  820. chainheader->type = SMARTFS_SECTOR_TYPE_DIR;
  821. }
  822. else
  823. {
  824. chainheader->type = SMARTFS_SECTOR_TYPE_FILE;
  825. }
  826. readwrite.count = 1;
  827. readwrite.offset = offsetof(struct smartfs_chain_header_s, type);
  828. readwrite.buffer = (uint8_t *) &chainheader->type;
  829. readwrite.logsector = nextsector;
  830. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  831. if (ret < 0)
  832. {
  833. ferr("ERROR: Error %d setting new sector type for sector %d\n",
  834. ret, nextsector);
  835. goto errout;
  836. }
  837. }
  838. }
  839. else
  840. {
  841. /* Use the provided sector number */
  842. nextsector = sectorno;
  843. }
  844. /* Create the directory entry to be written in the parent's sector */
  845. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  846. smartfs_wrle16(&entry->firstsector, nextsector);
  847. smartfs_wrle16(&entry->utc, time(NULL));
  848. #else
  849. entry->firstsector = nextsector;
  850. entry->utc = time(NULL);
  851. #endif
  852. memset(entry->name, 0, fs->fs_llformat.namesize);
  853. strncpy(entry->name, filename, fs->fs_llformat.namesize);
  854. /* Now write the new entry to the parent directory sector */
  855. readwrite.logsector = psector;
  856. readwrite.offset = offset;
  857. readwrite.count = entrysize;
  858. readwrite.buffer = (uint8_t *) &fs->fs_rwbuffer[offset];
  859. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  860. if (ret < 0)
  861. {
  862. goto errout;
  863. }
  864. /* Now fill in the entry */
  865. direntry->firstsector = nextsector;
  866. direntry->dsector = psector;
  867. direntry->doffset = offset;
  868. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  869. direntry->flags = smartfs_rdle16(&entry->flags);
  870. direntry->utc = smartfs_rdle32(&entry->utc);
  871. #else
  872. direntry->flags = entry->flags;
  873. direntry->utc = entry->utc;
  874. #endif
  875. direntry->datlen = 0;
  876. if (direntry->name == NULL)
  877. {
  878. direntry->name = (FAR char *) kmm_malloc(fs->fs_llformat.namesize+1);
  879. }
  880. memset(direntry->name, 0, fs->fs_llformat.namesize+1);
  881. strncpy(direntry->name, filename, fs->fs_llformat.namesize);
  882. ret = OK;
  883. errout:
  884. return ret;
  885. }
  886. /****************************************************************************
  887. * Name: smartfs_deleteentry
  888. *
  889. * Description: Deletes an entry from the filesystem (file or dir) by
  890. * freeing all the entry's sectors and then marking it inactive
  891. * in it's parent's directory sector. For a directory, it
  892. * does not validate the directory is empty, nor does it do
  893. * a recursive delete.
  894. *
  895. ****************************************************************************/
  896. int smartfs_deleteentry(struct smartfs_mountpt_s *fs,
  897. struct smartfs_entry_s *entry)
  898. {
  899. int ret;
  900. uint16_t nextsector;
  901. uint16_t sector;
  902. uint16_t count;
  903. uint16_t entrysize;
  904. uint16_t offset;
  905. struct smartfs_entry_header_s *direntry;
  906. struct smartfs_chain_header_s *header;
  907. struct smart_read_write_s readwrite;
  908. /* Okay, delete the file. Loop through each sector and release them
  909. *
  910. * TODO: We really should walk the list backward to avoid lost
  911. * sectors in the event we lose power. However this requires
  912. * allocating a buffer to build the sector list since we don't
  913. * store a doubly-linked list of sectors on the device. We
  914. * could test if the sector data buffer is big enough and
  915. * just use that, and only allocate a new buffer if the
  916. * sector buffer isn't big enough. Do do this, however, we
  917. * need to change the code below as it is using the a few
  918. * bytes of the buffer to read in header info.
  919. */
  920. nextsector = entry->firstsector;
  921. header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
  922. readwrite.offset = 0;
  923. readwrite.count = sizeof(struct smartfs_chain_header_s);
  924. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  925. while (nextsector != SMARTFS_ERASEDSTATE_16BIT)
  926. {
  927. /* Read the next sector into our buffer */
  928. sector = nextsector;
  929. readwrite.logsector = sector;
  930. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  931. if (ret < 0)
  932. {
  933. ferr("ERROR: Error reading sector %d\n", nextsector);
  934. break;
  935. }
  936. /* Release this sector */
  937. nextsector = SMARTFS_NEXTSECTOR(header);
  938. ret = FS_IOCTL(fs, BIOC_FREESECT, sector);
  939. }
  940. /* Remove the entry from the directory tree */
  941. readwrite.logsector = entry->dsector;
  942. readwrite.offset = 0;
  943. readwrite.count = fs->fs_llformat.availbytes;
  944. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  945. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  946. if (ret < 0)
  947. {
  948. ferr("ERROR: Error reading directory info at sector %d\n",
  949. entry->dsector);
  950. goto errout;
  951. }
  952. /* Mark this entry as inactive */
  953. direntry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[entry->doffset];
  954. #if CONFIG_SMARTFS_ERASEDSTATE == 0xFF
  955. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  956. smartfs_wrle16(&direntry->flags, smartfs_rdle16(&direntry->flags) & ~SMARTFS_DIRENT_ACTIVE);
  957. #else
  958. direntry->flags &= ~SMARTFS_DIRENT_ACTIVE;
  959. #endif
  960. #else /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */
  961. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  962. smartfs_wrle16(&direntry->flags, smartfs_rdle16(&direntry->flags) | SMARTFS_DIRENT_ACTIVE);
  963. #else
  964. direntry->flags |= SMARTFS_DIRENT_ACTIVE;
  965. #endif
  966. #endif /* CONFIG_SMARTFS_ERASEDSTATE == 0xFF */
  967. /* Write the updated flags back to the sector */
  968. readwrite.offset = entry->doffset;
  969. readwrite.count = sizeof(uint16_t);
  970. readwrite.buffer = (uint8_t *) &direntry->flags;
  971. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  972. if (ret < 0)
  973. {
  974. ferr("ERROR: Error marking entry inactive at sector %d\n",
  975. entry->dsector);
  976. goto errout;
  977. }
  978. /* Test if any entries in this sector are being used */
  979. if ((entry->dsector != fs->fs_rootsector) &&
  980. (entry->dsector != entry->dfirst))
  981. {
  982. /* Scan the sector and count used entries */
  983. count = 0;
  984. offset = sizeof(struct smartfs_chain_header_s);
  985. entrysize = sizeof(struct smartfs_entry_header_s) + fs->fs_llformat.namesize;
  986. while (offset + entrysize < fs->fs_llformat.availbytes)
  987. {
  988. /* Test the next entry */
  989. direntry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  990. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  991. if (((smartfs_rdle16(&direntry->flags) & SMARTFS_DIRENT_EMPTY) !=
  992. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) &&
  993. ((smartfs_rdle16(&direntry->flags) & SMARTFS_DIRENT_ACTIVE) ==
  994. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  995. #else
  996. if (((direntry->flags & SMARTFS_DIRENT_EMPTY) !=
  997. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) &&
  998. ((direntry->flags & SMARTFS_DIRENT_ACTIVE) ==
  999. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  1000. #endif
  1001. {
  1002. /* Count this entry */
  1003. count++;
  1004. }
  1005. /* Advance to next entry */
  1006. offset += entrysize;
  1007. }
  1008. /* Test if the count it zero. If it is, then we will release the sector */
  1009. if (count == 0)
  1010. {
  1011. /* Okay, to release the sector, we must find the sector that we
  1012. * are chained to and remove ourselves from the chain. First
  1013. * save our nextsector value so we can "unchain" ourselves.
  1014. */
  1015. nextsector = SMARTFS_NEXTSECTOR(header);
  1016. /* Now loop through the dir sectors to find ourselves in the chain */
  1017. sector = entry->dfirst;
  1018. readwrite.offset = 0;
  1019. readwrite.count = sizeof(struct smartfs_chain_header_s);
  1020. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  1021. while (sector != SMARTFS_ERASEDSTATE_16BIT)
  1022. {
  1023. /* Read the header for the next sector */
  1024. readwrite.logsector = sector;
  1025. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  1026. if (ret < 0)
  1027. {
  1028. ferr("ERROR: Error reading sector %d\n", nextsector);
  1029. break;
  1030. }
  1031. /* Test if this sector "points" to us */
  1032. if (SMARTFS_NEXTSECTOR(header) == entry->dsector)
  1033. {
  1034. /* We found ourselves in the chain. Update the chain. */
  1035. SMARTFS_NEXTSECTOR(header) = nextsector;
  1036. readwrite.offset = offsetof(struct smartfs_chain_header_s, nextsector);
  1037. readwrite.count = sizeof(uint16_t);
  1038. readwrite.buffer = header->nextsector;
  1039. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  1040. if (ret < 0)
  1041. {
  1042. ferr("ERROR: Error unchaining sector (%d)\n", nextsector);
  1043. goto errout;
  1044. }
  1045. /* Now release our sector */
  1046. ret = FS_IOCTL(fs, BIOC_FREESECT, (unsigned long) entry->dsector);
  1047. if (ret < 0)
  1048. {
  1049. ferr("ERROR: Error freeing sector %d\n", entry->dsector);
  1050. goto errout;
  1051. }
  1052. /* Break out of the loop, we are done! */
  1053. break;
  1054. }
  1055. /* Chain to the next sector */
  1056. sector = SMARTFS_NEXTSECTOR(header);
  1057. }
  1058. }
  1059. }
  1060. ret = OK;
  1061. errout:
  1062. return ret;
  1063. }
  1064. /****************************************************************************
  1065. * Name: smartfs_countdirentries
  1066. *
  1067. * Description: Counts the number of items in the specified directory entry.
  1068. * This routine assumes you have validated the entry you are
  1069. * passing is in fact a directory sector, though it checks
  1070. * just in case you were stupid :-)
  1071. *
  1072. ****************************************************************************/
  1073. int smartfs_countdirentries(struct smartfs_mountpt_s *fs,
  1074. struct smartfs_entry_s *entry)
  1075. {
  1076. int ret;
  1077. uint16_t nextsector;
  1078. uint16_t offset;
  1079. uint16_t entrysize;
  1080. int count;
  1081. struct smartfs_entry_header_s *direntry;
  1082. struct smartfs_chain_header_s *header;
  1083. struct smart_read_write_s readwrite;
  1084. /* Walk through the directory's sectors and count entries */
  1085. count = 0;
  1086. nextsector = entry->firstsector;
  1087. while (nextsector != SMARTFS_ERASEDSTATE_16BIT)
  1088. {
  1089. /* Read the next sector into our buffer */
  1090. readwrite.logsector = nextsector;
  1091. readwrite.offset = 0;
  1092. readwrite.count = fs->fs_llformat.availbytes;
  1093. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  1094. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  1095. if (ret < 0)
  1096. {
  1097. ferr("ERROR: Error reading sector %d\n", nextsector);
  1098. break;
  1099. }
  1100. /* Validate this is a directory type sector */
  1101. header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
  1102. if (header->type != SMARTFS_SECTOR_TYPE_DIR)
  1103. {
  1104. ferr("ERROR: Sector %d is not a DIR sector!\n", nextsector);
  1105. goto errout;
  1106. }
  1107. /* Loop for all entries in this sector and count them */
  1108. offset = sizeof(struct smartfs_chain_header_s);
  1109. entrysize = sizeof(struct smartfs_entry_header_s) + fs->fs_llformat.namesize;
  1110. direntry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  1111. while (offset + entrysize < readwrite.count)
  1112. {
  1113. #ifdef CONFIG_SMARTFS_ALIGNED_ACCESS
  1114. if (((smartfs_rdle16(&direntry->flags) & SMARTFS_DIRENT_EMPTY) !=
  1115. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) &&
  1116. ((smartfs_rdle16(&direntry->flags) & SMARTFS_DIRENT_ACTIVE) ==
  1117. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  1118. #else
  1119. if (((direntry->flags & SMARTFS_DIRENT_EMPTY) !=
  1120. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_EMPTY)) &&
  1121. ((direntry->flags & SMARTFS_DIRENT_ACTIVE) ==
  1122. (SMARTFS_ERASEDSTATE_16BIT & SMARTFS_DIRENT_ACTIVE)))
  1123. #endif
  1124. {
  1125. /* Count this entry */
  1126. count++;
  1127. }
  1128. offset += entrysize;
  1129. direntry = (struct smartfs_entry_header_s *) &fs->fs_rwbuffer[offset];
  1130. }
  1131. /* Get the next sector from the header */
  1132. nextsector = SMARTFS_NEXTSECTOR(header);
  1133. }
  1134. ret = count;
  1135. errout:
  1136. return ret;
  1137. }
  1138. /****************************************************************************
  1139. * Name: smartfs_truncatefile
  1140. *
  1141. * Description: Truncates an existing file on the device so that it occupies
  1142. * zero bytes and can be completely re-written.
  1143. *
  1144. ****************************************************************************/
  1145. int smartfs_truncatefile(struct smartfs_mountpt_s *fs,
  1146. struct smartfs_entry_s *entry, FAR struct smartfs_ofile_s *sf)
  1147. {
  1148. int ret;
  1149. uint16_t nextsector;
  1150. uint16_t sector;
  1151. struct smartfs_chain_header_s *header;
  1152. struct smart_read_write_s readwrite;
  1153. /* Walk through the directory's sectors and count entries */
  1154. nextsector = entry->firstsector;
  1155. header = (struct smartfs_chain_header_s *) fs->fs_rwbuffer;
  1156. while (nextsector != SMARTFS_ERASEDSTATE_16BIT)
  1157. {
  1158. /* Read the next sector's header into our buffer */
  1159. readwrite.logsector = nextsector;
  1160. readwrite.offset = 0;
  1161. readwrite.count = sizeof(struct smartfs_chain_header_s);
  1162. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  1163. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  1164. if (ret < 0)
  1165. {
  1166. ferr("ERROR: Error reading sector %d header\n", nextsector);
  1167. goto errout;
  1168. }
  1169. /* Get the next chained sector */
  1170. sector = SMARTFS_NEXTSECTOR(header);
  1171. /* If this is the 1st sector of the file, then just overwrite
  1172. * the sector data with the erased state value. The underlying
  1173. * SMART block driver will detect this and release the old
  1174. * sector and create a new one with the new (blank) data.
  1175. */
  1176. if (nextsector == entry->firstsector)
  1177. {
  1178. #ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
  1179. /* When we have a sector buffer in use, simply skip the first sector */
  1180. nextsector = sector;
  1181. continue;
  1182. #else
  1183. /* Fill our buffer with erased data */
  1184. memset(fs->fs_rwbuffer, CONFIG_SMARTFS_ERASEDSTATE, fs->fs_llformat.availbytes);
  1185. header->type = SMARTFS_SECTOR_TYPE_FILE;
  1186. /* Now write the new sector data */
  1187. readwrite.count = fs->fs_llformat.availbytes;
  1188. ret = FS_IOCTL(fs, BIOC_WRITESECT, (unsigned long) &readwrite);
  1189. if (ret < 0)
  1190. {
  1191. ferr("ERROR: Error blanking 1st sector (%d) of file\n", nextsector);
  1192. goto errout;
  1193. }
  1194. /* Set the entry's data length to zero ... we just truncated */
  1195. entry->datlen = 0;
  1196. #endif /* CONFIG_SMARTFS_USE_SECTOR_BUFFER */
  1197. }
  1198. else
  1199. {
  1200. /* Not the 1st sector -- release it */
  1201. ret = FS_IOCTL(fs, BIOC_FREESECT, (unsigned long) nextsector);
  1202. if (ret < 0)
  1203. {
  1204. ferr("ERROR: Error freeing sector %d\n", nextsector);
  1205. goto errout;
  1206. }
  1207. }
  1208. /* Now move on to the next sector */
  1209. nextsector = sector;
  1210. }
  1211. /* Now deal with the first sector in the event we are using a sector buffer
  1212. * like we would be if CRC is enabled.
  1213. */
  1214. #ifdef CONFIG_SMARTFS_USE_SECTOR_BUFFER
  1215. if (sf)
  1216. {
  1217. /* Using sector buffer and we have an open file context. Just update
  1218. * the sector buffer in the open file context.
  1219. */
  1220. readwrite.logsector = entry->firstsector;
  1221. readwrite.offset = 0;
  1222. readwrite.count = sizeof(struct smartfs_chain_header_s);
  1223. readwrite.buffer = (uint8_t *) fs->fs_rwbuffer;
  1224. ret = FS_IOCTL(fs, BIOC_READSECT, (unsigned long) &readwrite);
  1225. memset(sf->buffer, CONFIG_SMARTFS_ERASEDSTATE, fs->fs_llformat.availbytes);
  1226. header = (struct smartfs_chain_header_s *) sf->buffer;
  1227. header->type = SMARTFS_SECTOR_TYPE_FILE;
  1228. sf->bflags = SMARTFS_BFLAG_DIRTY;
  1229. entry->datlen = 0;
  1230. }
  1231. #endif
  1232. ret = OK;
  1233. errout:
  1234. return ret;
  1235. }
  1236. /****************************************************************************
  1237. * Name: smartfs_get_first_mount
  1238. *
  1239. * Description: Returns a pointer to the first mounted smartfs volume.
  1240. *
  1241. ****************************************************************************/
  1242. #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_FS_PROCFS_EXCLUDE_SMARTFS)
  1243. FAR struct smartfs_mountpt_s *smartfs_get_first_mount(void)
  1244. {
  1245. return g_mounthead;
  1246. }
  1247. #endif