fat_write.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * fat_write.c
  4. *
  5. * R/W (V)FAT 12/16/32 filesystem implementation by Donggeun Kim
  6. */
  7. #include <common.h>
  8. #include <command.h>
  9. #include <config.h>
  10. #include <fat.h>
  11. #include <log.h>
  12. #include <malloc.h>
  13. #include <asm/byteorder.h>
  14. #include <part.h>
  15. #include <asm/cache.h>
  16. #include <linux/ctype.h>
  17. #include <div64.h>
  18. #include <linux/math64.h>
  19. #include "fat.c"
  20. static void uppercase(char *str, int len)
  21. {
  22. int i;
  23. for (i = 0; i < len; i++) {
  24. *str = toupper(*str);
  25. str++;
  26. }
  27. }
  28. static int total_sector;
  29. static int disk_write(__u32 block, __u32 nr_blocks, void *buf)
  30. {
  31. ulong ret;
  32. if (!cur_dev)
  33. return -1;
  34. if (cur_part_info.start + block + nr_blocks >
  35. cur_part_info.start + total_sector) {
  36. printf("error: overflow occurs\n");
  37. return -1;
  38. }
  39. ret = blk_dwrite(cur_dev, cur_part_info.start + block, nr_blocks, buf);
  40. if (nr_blocks && ret == 0)
  41. return -1;
  42. return ret;
  43. }
  44. /*
  45. * Set short name in directory entry
  46. */
  47. static void set_name(dir_entry *dirent, const char *filename)
  48. {
  49. char s_name[VFAT_MAXLEN_BYTES];
  50. char *period;
  51. int period_location, len, i, ext_num;
  52. if (filename == NULL)
  53. return;
  54. len = strlen(filename);
  55. if (len == 0)
  56. return;
  57. strcpy(s_name, filename);
  58. uppercase(s_name, len);
  59. period = strchr(s_name, '.');
  60. if (period == NULL) {
  61. period_location = len;
  62. ext_num = 0;
  63. } else {
  64. period_location = period - s_name;
  65. ext_num = len - period_location - 1;
  66. }
  67. /* Pad spaces when the length of file name is shorter than eight */
  68. if (period_location < 8) {
  69. memcpy(dirent->name, s_name, period_location);
  70. for (i = period_location; i < 8; i++)
  71. dirent->name[i] = ' ';
  72. } else if (period_location == 8) {
  73. memcpy(dirent->name, s_name, period_location);
  74. } else {
  75. memcpy(dirent->name, s_name, 6);
  76. dirent->name[6] = '~';
  77. dirent->name[7] = '1';
  78. }
  79. if (ext_num < 3) {
  80. memcpy(dirent->ext, s_name + period_location + 1, ext_num);
  81. for (i = ext_num; i < 3; i++)
  82. dirent->ext[i] = ' ';
  83. } else
  84. memcpy(dirent->ext, s_name + period_location + 1, 3);
  85. debug("name : %s\n", dirent->name);
  86. debug("ext : %s\n", dirent->ext);
  87. }
  88. /*
  89. * Write fat buffer into block device
  90. */
  91. static int flush_dirty_fat_buffer(fsdata *mydata)
  92. {
  93. int getsize = FATBUFBLOCKS;
  94. __u32 fatlength = mydata->fatlength;
  95. __u8 *bufptr = mydata->fatbuf;
  96. __u32 startblock = mydata->fatbufnum * FATBUFBLOCKS;
  97. debug("debug: evicting %d, dirty: %d\n", mydata->fatbufnum,
  98. (int)mydata->fat_dirty);
  99. if ((!mydata->fat_dirty) || (mydata->fatbufnum == -1))
  100. return 0;
  101. /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
  102. if (startblock + getsize > fatlength)
  103. getsize = fatlength - startblock;
  104. startblock += mydata->fat_sect;
  105. /* Write FAT buf */
  106. if (disk_write(startblock, getsize, bufptr) < 0) {
  107. debug("error: writing FAT blocks\n");
  108. return -1;
  109. }
  110. if (mydata->fats == 2) {
  111. /* Update corresponding second FAT blocks */
  112. startblock += mydata->fatlength;
  113. if (disk_write(startblock, getsize, bufptr) < 0) {
  114. debug("error: writing second FAT blocks\n");
  115. return -1;
  116. }
  117. }
  118. mydata->fat_dirty = 0;
  119. return 0;
  120. }
  121. /*
  122. * Set the file name information from 'name' into 'slotptr',
  123. */
  124. static int str2slot(dir_slot *slotptr, const char *name, int *idx)
  125. {
  126. int j, end_idx = 0;
  127. for (j = 0; j <= 8; j += 2) {
  128. if (name[*idx] == 0x00) {
  129. slotptr->name0_4[j] = 0;
  130. slotptr->name0_4[j + 1] = 0;
  131. end_idx++;
  132. goto name0_4;
  133. }
  134. slotptr->name0_4[j] = name[*idx];
  135. (*idx)++;
  136. end_idx++;
  137. }
  138. for (j = 0; j <= 10; j += 2) {
  139. if (name[*idx] == 0x00) {
  140. slotptr->name5_10[j] = 0;
  141. slotptr->name5_10[j + 1] = 0;
  142. end_idx++;
  143. goto name5_10;
  144. }
  145. slotptr->name5_10[j] = name[*idx];
  146. (*idx)++;
  147. end_idx++;
  148. }
  149. for (j = 0; j <= 2; j += 2) {
  150. if (name[*idx] == 0x00) {
  151. slotptr->name11_12[j] = 0;
  152. slotptr->name11_12[j + 1] = 0;
  153. end_idx++;
  154. goto name11_12;
  155. }
  156. slotptr->name11_12[j] = name[*idx];
  157. (*idx)++;
  158. end_idx++;
  159. }
  160. if (name[*idx] == 0x00)
  161. return 1;
  162. return 0;
  163. /* Not used characters are filled with 0xff 0xff */
  164. name0_4:
  165. for (; end_idx < 5; end_idx++) {
  166. slotptr->name0_4[end_idx * 2] = 0xff;
  167. slotptr->name0_4[end_idx * 2 + 1] = 0xff;
  168. }
  169. end_idx = 5;
  170. name5_10:
  171. end_idx -= 5;
  172. for (; end_idx < 6; end_idx++) {
  173. slotptr->name5_10[end_idx * 2] = 0xff;
  174. slotptr->name5_10[end_idx * 2 + 1] = 0xff;
  175. }
  176. end_idx = 11;
  177. name11_12:
  178. end_idx -= 11;
  179. for (; end_idx < 2; end_idx++) {
  180. slotptr->name11_12[end_idx * 2] = 0xff;
  181. slotptr->name11_12[end_idx * 2 + 1] = 0xff;
  182. }
  183. return 1;
  184. }
  185. static int new_dir_table(fat_itr *itr);
  186. static int flush_dir(fat_itr *itr);
  187. /*
  188. * Fill dir_slot entries with appropriate name, id, and attr
  189. * 'itr' will point to a next entry
  190. */
  191. static int
  192. fill_dir_slot(fat_itr *itr, const char *l_name)
  193. {
  194. __u8 temp_dir_slot_buffer[MAX_LFN_SLOT * sizeof(dir_slot)];
  195. dir_slot *slotptr = (dir_slot *)temp_dir_slot_buffer;
  196. __u8 counter = 0, checksum;
  197. int idx = 0, ret;
  198. /* Get short file name checksum value */
  199. checksum = mkcksum(itr->dent->name, itr->dent->ext);
  200. do {
  201. memset(slotptr, 0x00, sizeof(dir_slot));
  202. ret = str2slot(slotptr, l_name, &idx);
  203. slotptr->id = ++counter;
  204. slotptr->attr = ATTR_VFAT;
  205. slotptr->alias_checksum = checksum;
  206. slotptr++;
  207. } while (ret == 0);
  208. slotptr--;
  209. slotptr->id |= LAST_LONG_ENTRY_MASK;
  210. while (counter >= 1) {
  211. memcpy(itr->dent, slotptr, sizeof(dir_slot));
  212. slotptr--;
  213. counter--;
  214. if (itr->remaining == 0)
  215. flush_dir(itr);
  216. /* allocate a cluster for more entries */
  217. if (!fat_itr_next(itr))
  218. if (!itr->dent &&
  219. (!itr->is_root || itr->fsdata->fatsize == 32) &&
  220. new_dir_table(itr))
  221. return -1;
  222. }
  223. return 0;
  224. }
  225. /*
  226. * Set the entry at index 'entry' in a FAT (12/16/32) table.
  227. */
  228. static int set_fatent_value(fsdata *mydata, __u32 entry, __u32 entry_value)
  229. {
  230. __u32 bufnum, offset, off16;
  231. __u16 val1, val2;
  232. switch (mydata->fatsize) {
  233. case 32:
  234. bufnum = entry / FAT32BUFSIZE;
  235. offset = entry - bufnum * FAT32BUFSIZE;
  236. break;
  237. case 16:
  238. bufnum = entry / FAT16BUFSIZE;
  239. offset = entry - bufnum * FAT16BUFSIZE;
  240. break;
  241. case 12:
  242. bufnum = entry / FAT12BUFSIZE;
  243. offset = entry - bufnum * FAT12BUFSIZE;
  244. break;
  245. default:
  246. /* Unsupported FAT size */
  247. return -1;
  248. }
  249. /* Read a new block of FAT entries into the cache. */
  250. if (bufnum != mydata->fatbufnum) {
  251. int getsize = FATBUFBLOCKS;
  252. __u8 *bufptr = mydata->fatbuf;
  253. __u32 fatlength = mydata->fatlength;
  254. __u32 startblock = bufnum * FATBUFBLOCKS;
  255. /* Cap length if fatlength is not a multiple of FATBUFBLOCKS */
  256. if (startblock + getsize > fatlength)
  257. getsize = fatlength - startblock;
  258. if (flush_dirty_fat_buffer(mydata) < 0)
  259. return -1;
  260. startblock += mydata->fat_sect;
  261. if (disk_read(startblock, getsize, bufptr) < 0) {
  262. debug("Error reading FAT blocks\n");
  263. return -1;
  264. }
  265. mydata->fatbufnum = bufnum;
  266. }
  267. /* Mark as dirty */
  268. mydata->fat_dirty = 1;
  269. /* Set the actual entry */
  270. switch (mydata->fatsize) {
  271. case 32:
  272. ((__u32 *) mydata->fatbuf)[offset] = cpu_to_le32(entry_value);
  273. break;
  274. case 16:
  275. ((__u16 *) mydata->fatbuf)[offset] = cpu_to_le16(entry_value);
  276. break;
  277. case 12:
  278. off16 = (offset * 3) / 4;
  279. switch (offset & 0x3) {
  280. case 0:
  281. val1 = cpu_to_le16(entry_value) & 0xfff;
  282. ((__u16 *)mydata->fatbuf)[off16] &= ~0xfff;
  283. ((__u16 *)mydata->fatbuf)[off16] |= val1;
  284. break;
  285. case 1:
  286. val1 = cpu_to_le16(entry_value) & 0xf;
  287. val2 = (cpu_to_le16(entry_value) >> 4) & 0xff;
  288. ((__u16 *)mydata->fatbuf)[off16] &= ~0xf000;
  289. ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 12);
  290. ((__u16 *)mydata->fatbuf)[off16 + 1] &= ~0xff;
  291. ((__u16 *)mydata->fatbuf)[off16 + 1] |= val2;
  292. break;
  293. case 2:
  294. val1 = cpu_to_le16(entry_value) & 0xff;
  295. val2 = (cpu_to_le16(entry_value) >> 8) & 0xf;
  296. ((__u16 *)mydata->fatbuf)[off16] &= ~0xff00;
  297. ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 8);
  298. ((__u16 *)mydata->fatbuf)[off16 + 1] &= ~0xf;
  299. ((__u16 *)mydata->fatbuf)[off16 + 1] |= val2;
  300. break;
  301. case 3:
  302. val1 = cpu_to_le16(entry_value) & 0xfff;
  303. ((__u16 *)mydata->fatbuf)[off16] &= ~0xfff0;
  304. ((__u16 *)mydata->fatbuf)[off16] |= (val1 << 4);
  305. break;
  306. default:
  307. break;
  308. }
  309. break;
  310. default:
  311. return -1;
  312. }
  313. return 0;
  314. }
  315. /*
  316. * Determine the next free cluster after 'entry' in a FAT (12/16/32) table
  317. * and link it to 'entry'. EOC marker is not set on returned entry.
  318. */
  319. static __u32 determine_fatent(fsdata *mydata, __u32 entry)
  320. {
  321. __u32 next_fat, next_entry = entry + 1;
  322. while (1) {
  323. next_fat = get_fatent(mydata, next_entry);
  324. if (next_fat == 0) {
  325. /* found free entry, link to entry */
  326. set_fatent_value(mydata, entry, next_entry);
  327. break;
  328. }
  329. next_entry++;
  330. }
  331. debug("FAT%d: entry: %08x, entry_value: %04x\n",
  332. mydata->fatsize, entry, next_entry);
  333. return next_entry;
  334. }
  335. /**
  336. * set_sectors() - write data to sectors
  337. *
  338. * Write 'size' bytes from 'buffer' into the specified sector.
  339. *
  340. * @mydata: data to be written
  341. * @startsect: sector to be written to
  342. * @buffer: data to be written
  343. * @size: bytes to be written (but not more than the size of a cluster)
  344. * Return: 0 on success, -1 otherwise
  345. */
  346. static int
  347. set_sectors(fsdata *mydata, u32 startsect, u8 *buffer, u32 size)
  348. {
  349. u32 nsects = 0;
  350. int ret;
  351. debug("startsect: %d\n", startsect);
  352. if ((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1)) {
  353. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  354. debug("FAT: Misaligned buffer address (%p)\n", buffer);
  355. while (size >= mydata->sect_size) {
  356. memcpy(tmpbuf, buffer, mydata->sect_size);
  357. ret = disk_write(startsect++, 1, tmpbuf);
  358. if (ret != 1) {
  359. debug("Error writing data (got %d)\n", ret);
  360. return -1;
  361. }
  362. buffer += mydata->sect_size;
  363. size -= mydata->sect_size;
  364. }
  365. } else if (size >= mydata->sect_size) {
  366. nsects = size / mydata->sect_size;
  367. ret = disk_write(startsect, nsects, buffer);
  368. if (ret != nsects) {
  369. debug("Error writing data (got %d)\n", ret);
  370. return -1;
  371. }
  372. startsect += nsects;
  373. buffer += nsects * mydata->sect_size;
  374. size -= nsects * mydata->sect_size;
  375. }
  376. if (size) {
  377. ALLOC_CACHE_ALIGN_BUFFER(__u8, tmpbuf, mydata->sect_size);
  378. /* Do not leak content of stack */
  379. memset(tmpbuf, 0, mydata->sect_size);
  380. memcpy(tmpbuf, buffer, size);
  381. ret = disk_write(startsect, 1, tmpbuf);
  382. if (ret != 1) {
  383. debug("Error writing data (got %d)\n", ret);
  384. return -1;
  385. }
  386. }
  387. return 0;
  388. }
  389. /**
  390. * set_cluster() - write data to cluster
  391. *
  392. * Write 'size' bytes from 'buffer' into the specified cluster.
  393. *
  394. * @mydata: data to be written
  395. * @clustnum: cluster to be written to
  396. * @buffer: data to be written
  397. * @size: bytes to be written (but not more than the size of a cluster)
  398. * Return: 0 on success, -1 otherwise
  399. */
  400. static int
  401. set_cluster(fsdata *mydata, u32 clustnum, u8 *buffer, u32 size)
  402. {
  403. return set_sectors(mydata, clust_to_sect(mydata, clustnum),
  404. buffer, size);
  405. }
  406. static int
  407. flush_dir(fat_itr *itr)
  408. {
  409. fsdata *mydata = itr->fsdata;
  410. u32 startsect, sect_offset, nsects;
  411. if (!itr->is_root || mydata->fatsize == 32)
  412. return set_cluster(mydata, itr->clust, itr->block,
  413. mydata->clust_size * mydata->sect_size);
  414. sect_offset = itr->clust * mydata->clust_size;
  415. startsect = mydata->rootdir_sect + sect_offset;
  416. /* do not write past the end of rootdir */
  417. nsects = min_t(u32, mydata->clust_size,
  418. mydata->rootdir_size - sect_offset);
  419. return set_sectors(mydata, startsect, itr->block,
  420. nsects * mydata->sect_size);
  421. }
  422. static __u8 tmpbuf_cluster[MAX_CLUSTSIZE] __aligned(ARCH_DMA_MINALIGN);
  423. /*
  424. * Read and modify data on existing and consecutive cluster blocks
  425. */
  426. static int
  427. get_set_cluster(fsdata *mydata, __u32 clustnum, loff_t pos, __u8 *buffer,
  428. loff_t size, loff_t *gotsize)
  429. {
  430. unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
  431. __u32 startsect;
  432. loff_t wsize;
  433. int clustcount, i, ret;
  434. *gotsize = 0;
  435. if (!size)
  436. return 0;
  437. assert(pos < bytesperclust);
  438. startsect = clust_to_sect(mydata, clustnum);
  439. debug("clustnum: %d, startsect: %d, pos: %lld\n",
  440. clustnum, startsect, pos);
  441. /* partial write at beginning */
  442. if (pos) {
  443. wsize = min(bytesperclust - pos, size);
  444. ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
  445. if (ret != mydata->clust_size) {
  446. debug("Error reading data (got %d)\n", ret);
  447. return -1;
  448. }
  449. memcpy(tmpbuf_cluster + pos, buffer, wsize);
  450. ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
  451. if (ret != mydata->clust_size) {
  452. debug("Error writing data (got %d)\n", ret);
  453. return -1;
  454. }
  455. size -= wsize;
  456. buffer += wsize;
  457. *gotsize += wsize;
  458. startsect += mydata->clust_size;
  459. if (!size)
  460. return 0;
  461. }
  462. /* full-cluster write */
  463. if (size >= bytesperclust) {
  464. clustcount = lldiv(size, bytesperclust);
  465. if (!((unsigned long)buffer & (ARCH_DMA_MINALIGN - 1))) {
  466. wsize = clustcount * bytesperclust;
  467. ret = disk_write(startsect,
  468. clustcount * mydata->clust_size,
  469. buffer);
  470. if (ret != clustcount * mydata->clust_size) {
  471. debug("Error writing data (got %d)\n", ret);
  472. return -1;
  473. }
  474. size -= wsize;
  475. buffer += wsize;
  476. *gotsize += wsize;
  477. startsect += clustcount * mydata->clust_size;
  478. } else {
  479. for (i = 0; i < clustcount; i++) {
  480. memcpy(tmpbuf_cluster, buffer, bytesperclust);
  481. ret = disk_write(startsect,
  482. mydata->clust_size,
  483. tmpbuf_cluster);
  484. if (ret != mydata->clust_size) {
  485. debug("Error writing data (got %d)\n",
  486. ret);
  487. return -1;
  488. }
  489. size -= bytesperclust;
  490. buffer += bytesperclust;
  491. *gotsize += bytesperclust;
  492. startsect += mydata->clust_size;
  493. }
  494. }
  495. }
  496. /* partial write at end */
  497. if (size) {
  498. wsize = size;
  499. ret = disk_read(startsect, mydata->clust_size, tmpbuf_cluster);
  500. if (ret != mydata->clust_size) {
  501. debug("Error reading data (got %d)\n", ret);
  502. return -1;
  503. }
  504. memcpy(tmpbuf_cluster, buffer, wsize);
  505. ret = disk_write(startsect, mydata->clust_size, tmpbuf_cluster);
  506. if (ret != mydata->clust_size) {
  507. debug("Error writing data (got %d)\n", ret);
  508. return -1;
  509. }
  510. size -= wsize;
  511. buffer += wsize;
  512. *gotsize += wsize;
  513. }
  514. assert(!size);
  515. return 0;
  516. }
  517. /*
  518. * Find the first empty cluster
  519. */
  520. static int find_empty_cluster(fsdata *mydata)
  521. {
  522. __u32 fat_val, entry = 3;
  523. while (1) {
  524. fat_val = get_fatent(mydata, entry);
  525. if (fat_val == 0)
  526. break;
  527. entry++;
  528. }
  529. return entry;
  530. }
  531. /*
  532. * Allocate a cluster for additional directory entries
  533. */
  534. static int new_dir_table(fat_itr *itr)
  535. {
  536. fsdata *mydata = itr->fsdata;
  537. int dir_newclust = 0;
  538. unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
  539. dir_newclust = find_empty_cluster(mydata);
  540. set_fatent_value(mydata, itr->clust, dir_newclust);
  541. if (mydata->fatsize == 32)
  542. set_fatent_value(mydata, dir_newclust, 0xffffff8);
  543. else if (mydata->fatsize == 16)
  544. set_fatent_value(mydata, dir_newclust, 0xfff8);
  545. else if (mydata->fatsize == 12)
  546. set_fatent_value(mydata, dir_newclust, 0xff8);
  547. itr->clust = dir_newclust;
  548. itr->next_clust = dir_newclust;
  549. if (flush_dirty_fat_buffer(mydata) < 0)
  550. return -1;
  551. memset(itr->block, 0x00, bytesperclust);
  552. itr->dent = (dir_entry *)itr->block;
  553. itr->last_cluster = 1;
  554. itr->remaining = bytesperclust / sizeof(dir_entry) - 1;
  555. return 0;
  556. }
  557. /*
  558. * Set empty cluster from 'entry' to the end of a file
  559. */
  560. static int clear_fatent(fsdata *mydata, __u32 entry)
  561. {
  562. __u32 fat_val;
  563. while (!CHECK_CLUST(entry, mydata->fatsize)) {
  564. fat_val = get_fatent(mydata, entry);
  565. if (fat_val != 0)
  566. set_fatent_value(mydata, entry, 0);
  567. else
  568. break;
  569. entry = fat_val;
  570. }
  571. /* Flush fat buffer */
  572. if (flush_dirty_fat_buffer(mydata) < 0)
  573. return -1;
  574. return 0;
  575. }
  576. /*
  577. * Set start cluster in directory entry
  578. */
  579. static void set_start_cluster(const fsdata *mydata, dir_entry *dentptr,
  580. __u32 start_cluster)
  581. {
  582. if (mydata->fatsize == 32)
  583. dentptr->starthi =
  584. cpu_to_le16((start_cluster & 0xffff0000) >> 16);
  585. dentptr->start = cpu_to_le16(start_cluster & 0xffff);
  586. }
  587. /*
  588. * Check whether adding a file makes the file system to
  589. * exceed the size of the block device
  590. * Return -1 when overflow occurs, otherwise return 0
  591. */
  592. static int check_overflow(fsdata *mydata, __u32 clustnum, loff_t size)
  593. {
  594. __u32 startsect, sect_num, offset;
  595. if (clustnum > 0)
  596. startsect = clust_to_sect(mydata, clustnum);
  597. else
  598. startsect = mydata->rootdir_sect;
  599. sect_num = div_u64_rem(size, mydata->sect_size, &offset);
  600. if (offset != 0)
  601. sect_num++;
  602. if (startsect + sect_num > total_sector)
  603. return -1;
  604. return 0;
  605. }
  606. /*
  607. * Write at most 'maxsize' bytes from 'buffer' into
  608. * the file associated with 'dentptr'
  609. * Update the number of bytes written in *gotsize and return 0
  610. * or return -1 on fatal errors.
  611. */
  612. static int
  613. set_contents(fsdata *mydata, dir_entry *dentptr, loff_t pos, __u8 *buffer,
  614. loff_t maxsize, loff_t *gotsize)
  615. {
  616. unsigned int bytesperclust = mydata->clust_size * mydata->sect_size;
  617. __u32 curclust = START(dentptr);
  618. __u32 endclust = 0, newclust = 0;
  619. u64 cur_pos, filesize;
  620. loff_t offset, actsize, wsize;
  621. *gotsize = 0;
  622. filesize = pos + maxsize;
  623. debug("%llu bytes\n", filesize);
  624. if (!filesize) {
  625. if (!curclust)
  626. return 0;
  627. if (!CHECK_CLUST(curclust, mydata->fatsize) ||
  628. IS_LAST_CLUST(curclust, mydata->fatsize)) {
  629. clear_fatent(mydata, curclust);
  630. set_start_cluster(mydata, dentptr, 0);
  631. return 0;
  632. }
  633. debug("curclust: 0x%x\n", curclust);
  634. debug("Invalid FAT entry\n");
  635. return -1;
  636. }
  637. if (!curclust) {
  638. assert(pos == 0);
  639. goto set_clusters;
  640. }
  641. /* go to cluster at pos */
  642. cur_pos = bytesperclust;
  643. while (1) {
  644. if (pos <= cur_pos)
  645. break;
  646. if (IS_LAST_CLUST(curclust, mydata->fatsize))
  647. break;
  648. newclust = get_fatent(mydata, curclust);
  649. if (!IS_LAST_CLUST(newclust, mydata->fatsize) &&
  650. CHECK_CLUST(newclust, mydata->fatsize)) {
  651. debug("curclust: 0x%x\n", curclust);
  652. debug("Invalid FAT entry\n");
  653. return -1;
  654. }
  655. cur_pos += bytesperclust;
  656. curclust = newclust;
  657. }
  658. if (IS_LAST_CLUST(curclust, mydata->fatsize)) {
  659. assert(pos == cur_pos);
  660. goto set_clusters;
  661. }
  662. assert(pos < cur_pos);
  663. cur_pos -= bytesperclust;
  664. /* overwrite */
  665. assert(IS_LAST_CLUST(curclust, mydata->fatsize) ||
  666. !CHECK_CLUST(curclust, mydata->fatsize));
  667. while (1) {
  668. /* search for allocated consecutive clusters */
  669. actsize = bytesperclust;
  670. endclust = curclust;
  671. while (1) {
  672. if (filesize <= (cur_pos + actsize))
  673. break;
  674. newclust = get_fatent(mydata, endclust);
  675. if (newclust != endclust + 1)
  676. break;
  677. if (IS_LAST_CLUST(newclust, mydata->fatsize))
  678. break;
  679. if (CHECK_CLUST(newclust, mydata->fatsize)) {
  680. debug("curclust: 0x%x\n", curclust);
  681. debug("Invalid FAT entry\n");
  682. return -1;
  683. }
  684. actsize += bytesperclust;
  685. endclust = newclust;
  686. }
  687. /* overwrite to <curclust..endclust> */
  688. if (pos < cur_pos)
  689. offset = 0;
  690. else
  691. offset = pos - cur_pos;
  692. wsize = min_t(unsigned long long, actsize, filesize - cur_pos);
  693. wsize -= offset;
  694. if (get_set_cluster(mydata, curclust, offset,
  695. buffer, wsize, &actsize)) {
  696. printf("Error get-and-setting cluster\n");
  697. return -1;
  698. }
  699. buffer += wsize;
  700. *gotsize += wsize;
  701. cur_pos += offset + wsize;
  702. if (filesize <= cur_pos)
  703. break;
  704. if (IS_LAST_CLUST(newclust, mydata->fatsize))
  705. /* no more clusters */
  706. break;
  707. curclust = newclust;
  708. }
  709. if (filesize <= cur_pos) {
  710. /* no more write */
  711. newclust = get_fatent(mydata, endclust);
  712. if (!IS_LAST_CLUST(newclust, mydata->fatsize)) {
  713. /* truncate the rest */
  714. clear_fatent(mydata, newclust);
  715. /* Mark end of file in FAT */
  716. if (mydata->fatsize == 12)
  717. newclust = 0xfff;
  718. else if (mydata->fatsize == 16)
  719. newclust = 0xffff;
  720. else if (mydata->fatsize == 32)
  721. newclust = 0xfffffff;
  722. set_fatent_value(mydata, endclust, newclust);
  723. }
  724. return 0;
  725. }
  726. curclust = endclust;
  727. filesize -= cur_pos;
  728. assert(!do_div(cur_pos, bytesperclust));
  729. set_clusters:
  730. /* allocate and write */
  731. assert(!pos);
  732. /* Assure that curclust is valid */
  733. if (!curclust) {
  734. curclust = find_empty_cluster(mydata);
  735. set_start_cluster(mydata, dentptr, curclust);
  736. } else {
  737. newclust = get_fatent(mydata, curclust);
  738. if (IS_LAST_CLUST(newclust, mydata->fatsize)) {
  739. newclust = determine_fatent(mydata, curclust);
  740. set_fatent_value(mydata, curclust, newclust);
  741. curclust = newclust;
  742. } else {
  743. debug("error: something wrong\n");
  744. return -1;
  745. }
  746. }
  747. /* TODO: already partially written */
  748. if (check_overflow(mydata, curclust, filesize)) {
  749. printf("Error: no space left: %llu\n", filesize);
  750. return -1;
  751. }
  752. actsize = bytesperclust;
  753. endclust = curclust;
  754. do {
  755. /* search for consecutive clusters */
  756. while (actsize < filesize) {
  757. newclust = determine_fatent(mydata, endclust);
  758. if ((newclust - 1) != endclust)
  759. /* write to <curclust..endclust> */
  760. goto getit;
  761. if (CHECK_CLUST(newclust, mydata->fatsize)) {
  762. debug("newclust: 0x%x\n", newclust);
  763. debug("Invalid FAT entry\n");
  764. return 0;
  765. }
  766. endclust = newclust;
  767. actsize += bytesperclust;
  768. }
  769. /* set remaining bytes */
  770. actsize = filesize;
  771. if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
  772. debug("error: writing cluster\n");
  773. return -1;
  774. }
  775. *gotsize += actsize;
  776. /* Mark end of file in FAT */
  777. if (mydata->fatsize == 12)
  778. newclust = 0xfff;
  779. else if (mydata->fatsize == 16)
  780. newclust = 0xffff;
  781. else if (mydata->fatsize == 32)
  782. newclust = 0xfffffff;
  783. set_fatent_value(mydata, endclust, newclust);
  784. return 0;
  785. getit:
  786. if (set_cluster(mydata, curclust, buffer, (u32)actsize) != 0) {
  787. debug("error: writing cluster\n");
  788. return -1;
  789. }
  790. *gotsize += actsize;
  791. filesize -= actsize;
  792. buffer += actsize;
  793. if (CHECK_CLUST(newclust, mydata->fatsize)) {
  794. debug("newclust: 0x%x\n", newclust);
  795. debug("Invalid FAT entry\n");
  796. return 0;
  797. }
  798. actsize = bytesperclust;
  799. curclust = endclust = newclust;
  800. } while (1);
  801. return 0;
  802. }
  803. /*
  804. * Fill dir_entry
  805. */
  806. static void fill_dentry(fsdata *mydata, dir_entry *dentptr,
  807. const char *filename, __u32 start_cluster, __u32 size, __u8 attr)
  808. {
  809. set_start_cluster(mydata, dentptr, start_cluster);
  810. dentptr->size = cpu_to_le32(size);
  811. dentptr->attr = attr;
  812. set_name(dentptr, filename);
  813. }
  814. /*
  815. * Find a directory entry based on filename or start cluster number
  816. * If the directory entry is not found,
  817. * the new position for writing a directory entry will be returned
  818. */
  819. static dir_entry *find_directory_entry(fat_itr *itr, char *filename)
  820. {
  821. int match = 0;
  822. while (fat_itr_next(itr)) {
  823. /* check both long and short name: */
  824. if (!strcasecmp(filename, itr->name))
  825. match = 1;
  826. else if (itr->name != itr->s_name &&
  827. !strcasecmp(filename, itr->s_name))
  828. match = 1;
  829. if (!match)
  830. continue;
  831. if (itr->dent->name[0] == '\0')
  832. return NULL;
  833. else
  834. return itr->dent;
  835. }
  836. /* allocate a cluster for more entries */
  837. if (!itr->dent &&
  838. (!itr->is_root || itr->fsdata->fatsize == 32) &&
  839. new_dir_table(itr))
  840. /* indicate that allocating dent failed */
  841. itr->dent = NULL;
  842. return NULL;
  843. }
  844. static int split_filename(char *filename, char **dirname, char **basename)
  845. {
  846. char *p, *last_slash, *last_slash_cont;
  847. again:
  848. p = filename;
  849. last_slash = NULL;
  850. last_slash_cont = NULL;
  851. while (*p) {
  852. if (ISDIRDELIM(*p)) {
  853. last_slash = p;
  854. last_slash_cont = p;
  855. /* continuous slashes */
  856. while (ISDIRDELIM(*p))
  857. last_slash_cont = p++;
  858. if (!*p)
  859. break;
  860. }
  861. p++;
  862. }
  863. if (last_slash) {
  864. if (last_slash_cont == (filename + strlen(filename) - 1)) {
  865. /* remove trailing slashes */
  866. *last_slash = '\0';
  867. goto again;
  868. }
  869. if (last_slash == filename) {
  870. /* avoid ""(null) directory */
  871. *dirname = "/";
  872. } else {
  873. *last_slash = '\0';
  874. *dirname = filename;
  875. }
  876. *last_slash_cont = '\0';
  877. *basename = last_slash_cont + 1;
  878. } else {
  879. *dirname = "/"; /* root by default */
  880. *basename = filename;
  881. }
  882. return 0;
  883. }
  884. /**
  885. * normalize_longname() - check long file name and convert to lower case
  886. *
  887. * We assume here that the FAT file system is using an 8bit code page.
  888. * Linux typically uses CP437, EDK2 assumes CP1250.
  889. *
  890. * @l_filename: preallocated buffer receiving the normalized name
  891. * @filename: filename to normalize
  892. * Return: 0 on success, -1 on failure
  893. */
  894. static int normalize_longname(char *l_filename, const char *filename)
  895. {
  896. const char *p, illegal[] = "<>:\"/\\|?*";
  897. if (strlen(filename) >= VFAT_MAXLEN_BYTES)
  898. return -1;
  899. for (p = filename; *p; ++p) {
  900. if ((unsigned char)*p < 0x20)
  901. return -1;
  902. if (strchr(illegal, *p))
  903. return -1;
  904. }
  905. strcpy(l_filename, filename);
  906. downcase(l_filename, VFAT_MAXLEN_BYTES);
  907. return 0;
  908. }
  909. int file_fat_write_at(const char *filename, loff_t pos, void *buffer,
  910. loff_t size, loff_t *actwrite)
  911. {
  912. dir_entry *retdent;
  913. fsdata datablock = { .fatbuf = NULL, };
  914. fsdata *mydata = &datablock;
  915. fat_itr *itr = NULL;
  916. int ret = -1;
  917. char *filename_copy, *parent, *basename;
  918. char l_filename[VFAT_MAXLEN_BYTES];
  919. debug("writing %s\n", filename);
  920. filename_copy = strdup(filename);
  921. if (!filename_copy)
  922. return -ENOMEM;
  923. split_filename(filename_copy, &parent, &basename);
  924. if (!strlen(basename)) {
  925. ret = -EINVAL;
  926. goto exit;
  927. }
  928. filename = basename;
  929. if (normalize_longname(l_filename, filename)) {
  930. printf("FAT: illegal filename (%s)\n", filename);
  931. ret = -EINVAL;
  932. goto exit;
  933. }
  934. itr = malloc_cache_aligned(sizeof(fat_itr));
  935. if (!itr) {
  936. ret = -ENOMEM;
  937. goto exit;
  938. }
  939. ret = fat_itr_root(itr, &datablock);
  940. if (ret)
  941. goto exit;
  942. total_sector = datablock.total_sect;
  943. ret = fat_itr_resolve(itr, parent, TYPE_DIR);
  944. if (ret) {
  945. printf("%s: doesn't exist (%d)\n", parent, ret);
  946. goto exit;
  947. }
  948. retdent = find_directory_entry(itr, l_filename);
  949. if (retdent) {
  950. if (fat_itr_isdir(itr)) {
  951. ret = -EISDIR;
  952. goto exit;
  953. }
  954. /* A file exists */
  955. if (pos == -1)
  956. /* Append to the end */
  957. pos = FAT2CPU32(retdent->size);
  958. if (pos > retdent->size) {
  959. /* No hole allowed */
  960. ret = -EINVAL;
  961. goto exit;
  962. }
  963. /* Update file size in a directory entry */
  964. retdent->size = cpu_to_le32(pos + size);
  965. } else {
  966. /* Create a new file */
  967. if (itr->is_root) {
  968. /* root dir cannot have "." or ".." */
  969. if (!strcmp(l_filename, ".") ||
  970. !strcmp(l_filename, "..")) {
  971. ret = -EINVAL;
  972. goto exit;
  973. }
  974. }
  975. if (!itr->dent) {
  976. printf("Error: allocating new dir entry\n");
  977. ret = -EIO;
  978. goto exit;
  979. }
  980. if (pos) {
  981. /* No hole allowed */
  982. ret = -EINVAL;
  983. goto exit;
  984. }
  985. memset(itr->dent, 0, sizeof(*itr->dent));
  986. /* Calculate checksum for short name */
  987. set_name(itr->dent, filename);
  988. /* Set long name entries */
  989. if (fill_dir_slot(itr, filename)) {
  990. ret = -EIO;
  991. goto exit;
  992. }
  993. /* Set short name entry */
  994. fill_dentry(itr->fsdata, itr->dent, filename, 0, size, 0x20);
  995. retdent = itr->dent;
  996. }
  997. ret = set_contents(mydata, retdent, pos, buffer, size, actwrite);
  998. if (ret < 0) {
  999. printf("Error: writing contents\n");
  1000. ret = -EIO;
  1001. goto exit;
  1002. }
  1003. debug("attempt to write 0x%llx bytes\n", *actwrite);
  1004. /* Flush fat buffer */
  1005. ret = flush_dirty_fat_buffer(mydata);
  1006. if (ret) {
  1007. printf("Error: flush fat buffer\n");
  1008. ret = -EIO;
  1009. goto exit;
  1010. }
  1011. /* Write directory table to device */
  1012. ret = flush_dir(itr);
  1013. if (ret) {
  1014. printf("Error: writing directory entry\n");
  1015. ret = -EIO;
  1016. }
  1017. exit:
  1018. free(filename_copy);
  1019. free(mydata->fatbuf);
  1020. free(itr);
  1021. return ret;
  1022. }
  1023. int file_fat_write(const char *filename, void *buffer, loff_t offset,
  1024. loff_t maxsize, loff_t *actwrite)
  1025. {
  1026. return file_fat_write_at(filename, offset, buffer, maxsize, actwrite);
  1027. }
  1028. static int fat_dir_entries(fat_itr *itr)
  1029. {
  1030. fat_itr *dirs;
  1031. fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata;
  1032. /* for FATBUFSIZE */
  1033. int count;
  1034. dirs = malloc_cache_aligned(sizeof(fat_itr));
  1035. if (!dirs) {
  1036. debug("Error: allocating memory\n");
  1037. count = -ENOMEM;
  1038. goto exit;
  1039. }
  1040. /* duplicate fsdata */
  1041. fat_itr_child(dirs, itr);
  1042. fsdata = *dirs->fsdata;
  1043. /* allocate local fat buffer */
  1044. fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE);
  1045. if (!fsdata.fatbuf) {
  1046. debug("Error: allocating memory\n");
  1047. count = -ENOMEM;
  1048. goto exit;
  1049. }
  1050. fsdata.fatbufnum = -1;
  1051. dirs->fsdata = &fsdata;
  1052. for (count = 0; fat_itr_next(dirs); count++)
  1053. ;
  1054. exit:
  1055. free(fsdata.fatbuf);
  1056. free(dirs);
  1057. return count;
  1058. }
  1059. static int delete_dentry(fat_itr *itr)
  1060. {
  1061. fsdata *mydata = itr->fsdata;
  1062. dir_entry *dentptr = itr->dent;
  1063. /* free cluster blocks */
  1064. clear_fatent(mydata, START(dentptr));
  1065. if (flush_dirty_fat_buffer(mydata) < 0) {
  1066. printf("Error: flush fat buffer\n");
  1067. return -EIO;
  1068. }
  1069. /*
  1070. * update a directory entry
  1071. * TODO:
  1072. * - long file name support
  1073. * - find and mark the "new" first invalid entry as name[0]=0x00
  1074. */
  1075. memset(dentptr, 0, sizeof(*dentptr));
  1076. dentptr->name[0] = 0xe5;
  1077. if (flush_dir(itr)) {
  1078. printf("error: writing directory entry\n");
  1079. return -EIO;
  1080. }
  1081. return 0;
  1082. }
  1083. int fat_unlink(const char *filename)
  1084. {
  1085. fsdata fsdata = { .fatbuf = NULL, };
  1086. fat_itr *itr = NULL;
  1087. int n_entries, ret;
  1088. char *filename_copy, *dirname, *basename;
  1089. filename_copy = strdup(filename);
  1090. if (!filename_copy) {
  1091. printf("Error: allocating memory\n");
  1092. ret = -ENOMEM;
  1093. goto exit;
  1094. }
  1095. split_filename(filename_copy, &dirname, &basename);
  1096. if (!strcmp(dirname, "/") && !strcmp(basename, "")) {
  1097. printf("Error: cannot remove root\n");
  1098. ret = -EINVAL;
  1099. goto exit;
  1100. }
  1101. itr = malloc_cache_aligned(sizeof(fat_itr));
  1102. if (!itr) {
  1103. printf("Error: allocating memory\n");
  1104. ret = -ENOMEM;
  1105. goto exit;
  1106. }
  1107. ret = fat_itr_root(itr, &fsdata);
  1108. if (ret)
  1109. goto exit;
  1110. total_sector = fsdata.total_sect;
  1111. ret = fat_itr_resolve(itr, dirname, TYPE_DIR);
  1112. if (ret) {
  1113. printf("%s: doesn't exist (%d)\n", dirname, ret);
  1114. ret = -ENOENT;
  1115. goto exit;
  1116. }
  1117. if (!find_directory_entry(itr, basename)) {
  1118. printf("%s: doesn't exist\n", basename);
  1119. ret = -ENOENT;
  1120. goto exit;
  1121. }
  1122. if (fat_itr_isdir(itr)) {
  1123. n_entries = fat_dir_entries(itr);
  1124. if (n_entries < 0) {
  1125. ret = n_entries;
  1126. goto exit;
  1127. }
  1128. if (n_entries > 2) {
  1129. printf("Error: directory is not empty: %d\n",
  1130. n_entries);
  1131. ret = -EINVAL;
  1132. goto exit;
  1133. }
  1134. }
  1135. ret = delete_dentry(itr);
  1136. exit:
  1137. free(fsdata.fatbuf);
  1138. free(itr);
  1139. free(filename_copy);
  1140. return ret;
  1141. }
  1142. int fat_mkdir(const char *new_dirname)
  1143. {
  1144. dir_entry *retdent;
  1145. fsdata datablock = { .fatbuf = NULL, };
  1146. fsdata *mydata = &datablock;
  1147. fat_itr *itr = NULL;
  1148. char *dirname_copy, *parent, *dirname;
  1149. char l_dirname[VFAT_MAXLEN_BYTES];
  1150. int ret = -1;
  1151. loff_t actwrite;
  1152. unsigned int bytesperclust;
  1153. dir_entry *dotdent = NULL;
  1154. dirname_copy = strdup(new_dirname);
  1155. if (!dirname_copy)
  1156. goto exit;
  1157. split_filename(dirname_copy, &parent, &dirname);
  1158. if (!strlen(dirname)) {
  1159. ret = -EINVAL;
  1160. goto exit;
  1161. }
  1162. if (normalize_longname(l_dirname, dirname)) {
  1163. printf("FAT: illegal filename (%s)\n", dirname);
  1164. ret = -EINVAL;
  1165. goto exit;
  1166. }
  1167. itr = malloc_cache_aligned(sizeof(fat_itr));
  1168. if (!itr) {
  1169. ret = -ENOMEM;
  1170. goto exit;
  1171. }
  1172. ret = fat_itr_root(itr, &datablock);
  1173. if (ret)
  1174. goto exit;
  1175. total_sector = datablock.total_sect;
  1176. ret = fat_itr_resolve(itr, parent, TYPE_DIR);
  1177. if (ret) {
  1178. printf("%s: doesn't exist (%d)\n", parent, ret);
  1179. goto exit;
  1180. }
  1181. retdent = find_directory_entry(itr, l_dirname);
  1182. if (retdent) {
  1183. printf("%s: already exists\n", l_dirname);
  1184. ret = -EEXIST;
  1185. goto exit;
  1186. } else {
  1187. if (itr->is_root) {
  1188. /* root dir cannot have "." or ".." */
  1189. if (!strcmp(l_dirname, ".") ||
  1190. !strcmp(l_dirname, "..")) {
  1191. ret = -EINVAL;
  1192. goto exit;
  1193. }
  1194. }
  1195. if (!itr->dent) {
  1196. printf("Error: allocating new dir entry\n");
  1197. ret = -EIO;
  1198. goto exit;
  1199. }
  1200. memset(itr->dent, 0, sizeof(*itr->dent));
  1201. /* Set short name to set alias checksum field in dir_slot */
  1202. set_name(itr->dent, dirname);
  1203. fill_dir_slot(itr, dirname);
  1204. /* Set attribute as archive for regular file */
  1205. fill_dentry(itr->fsdata, itr->dent, dirname, 0, 0,
  1206. ATTR_DIR | ATTR_ARCH);
  1207. retdent = itr->dent;
  1208. }
  1209. /* Default entries */
  1210. bytesperclust = mydata->clust_size * mydata->sect_size;
  1211. dotdent = malloc_cache_aligned(bytesperclust);
  1212. if (!dotdent) {
  1213. ret = -ENOMEM;
  1214. goto exit;
  1215. }
  1216. memset(dotdent, 0, bytesperclust);
  1217. memcpy(dotdent[0].name, ". ", 8);
  1218. memcpy(dotdent[0].ext, " ", 3);
  1219. dotdent[0].attr = ATTR_DIR | ATTR_ARCH;
  1220. memcpy(dotdent[1].name, ".. ", 8);
  1221. memcpy(dotdent[1].ext, " ", 3);
  1222. dotdent[1].attr = ATTR_DIR | ATTR_ARCH;
  1223. set_start_cluster(mydata, &dotdent[1], itr->start_clust);
  1224. ret = set_contents(mydata, retdent, 0, (__u8 *)dotdent,
  1225. bytesperclust, &actwrite);
  1226. if (ret < 0) {
  1227. printf("Error: writing contents\n");
  1228. goto exit;
  1229. }
  1230. /* Write twice for "." */
  1231. set_start_cluster(mydata, &dotdent[0], START(retdent));
  1232. ret = set_contents(mydata, retdent, 0, (__u8 *)dotdent,
  1233. bytesperclust, &actwrite);
  1234. if (ret < 0) {
  1235. printf("Error: writing contents\n");
  1236. goto exit;
  1237. }
  1238. /* Flush fat buffer */
  1239. ret = flush_dirty_fat_buffer(mydata);
  1240. if (ret) {
  1241. printf("Error: flush fat buffer\n");
  1242. goto exit;
  1243. }
  1244. /* Write directory table to device */
  1245. ret = flush_dir(itr);
  1246. if (ret)
  1247. printf("Error: writing directory entry\n");
  1248. exit:
  1249. free(dirname_copy);
  1250. free(mydata->fatbuf);
  1251. free(itr);
  1252. free(dotdent);
  1253. return ret;
  1254. }