fat_write.c 33 KB

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