dfs_file.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-05-05 Bernard Implement file APIs in dfs v2.0
  9. */
  10. #include "errno.h"
  11. #include "fcntl.h"
  12. #include <dfs.h>
  13. #include "dfs_file.h"
  14. #include "dfs_dentry.h"
  15. #include "dfs_fs.h"
  16. #include "dfs_mnt.h"
  17. #include "dfs_private.h"
  18. #define DBG_TAG "DFS.file"
  19. #define DBG_LVL DBG_WARNING
  20. #include <rtdbg.h>
  21. #define MAX_RW_COUNT 0xfffc0000
  22. /*
  23. * rw_verify_area doesn't like huge counts. We limit
  24. * them to something that fits in "int" so that others
  25. * won't have to do range checks all the time.
  26. */
  27. ssize_t rw_verify_area(struct dfs_file *file, off_t *ppos, size_t count)
  28. {
  29. off_t pos;
  30. ssize_t retval = -EINVAL;
  31. if ((size_t)count < 0)
  32. return retval;
  33. pos = *ppos;
  34. if (pos < 0)
  35. {
  36. if (count >= -pos) /* both values are in 0..LLONG_MAX */
  37. return -EOVERFLOW;
  38. }
  39. return count > MAX_RW_COUNT ? MAX_RW_COUNT : count;
  40. }
  41. void dfs_file_set_fpos(struct dfs_file *file, off_t fpos)
  42. {
  43. if (file)
  44. {
  45. rt_mutex_take(&file->pos_lock, RT_WAITING_FOREVER);
  46. file->fpos = fpos;
  47. rt_mutex_release(&file->pos_lock);
  48. }
  49. }
  50. void dfs_file_init(struct dfs_file *file)
  51. {
  52. if (file)
  53. {
  54. rt_memset(file, 0x00, sizeof(struct dfs_file));
  55. file->magic = DFS_FD_MAGIC;
  56. rt_mutex_init(&file->pos_lock, "fpos", RT_IPC_FLAG_PRIO);
  57. rt_atomic_store(&(file->ref_count), 1);
  58. }
  59. }
  60. void dfs_file_deinit(struct dfs_file *file)
  61. {
  62. if (file)
  63. {
  64. rt_mutex_detach(&file->pos_lock);
  65. }
  66. }
  67. static void dfs_file_unref(struct dfs_file *file)
  68. {
  69. rt_err_t ret = RT_EOK;
  70. ret = dfs_file_lock();
  71. if (ret == RT_EOK)
  72. {
  73. if (rt_atomic_load(&(file->ref_count)) == 1)
  74. {
  75. /* should release this file */
  76. if (file->dentry)
  77. {
  78. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry(%s))", file->dentry->pathname);
  79. dfs_dentry_unref(file->dentry);
  80. file->dentry = RT_NULL;
  81. }
  82. else if (file->vnode)
  83. {
  84. if (file->vnode->ref_count > 1)
  85. {
  86. file->vnode->ref_count--;
  87. }
  88. else if (file->vnode->ref_count == 1)
  89. {
  90. rt_free(file->vnode);
  91. file->vnode = RT_NULL;
  92. }
  93. }
  94. LOG_I("release a file: %p", file);
  95. }
  96. dfs_file_unlock();
  97. }
  98. }
  99. struct dfs_dentry* dfs_file_follow_link(struct dfs_dentry *dentry)
  100. {
  101. int ret = 0;
  102. if (dentry && dentry->vnode && dentry->vnode->type == FT_SYMLINK)
  103. {
  104. char *buf = NULL;
  105. buf = (char *) rt_malloc (DFS_PATH_MAX);
  106. if (buf)
  107. {
  108. do
  109. {
  110. ret = dentry->mnt->fs_ops->readlink(dentry, buf, DFS_PATH_MAX);
  111. if (ret > 0)
  112. {
  113. struct dfs_mnt *mnt = NULL;
  114. if (buf[0] != '/')
  115. {
  116. char *dir = dfs_dentry_pathname(dentry);
  117. /* is the relative directory */
  118. if (dir)
  119. {
  120. char *fullpath = dfs_normalize_path(dir, buf);
  121. if (fullpath)
  122. {
  123. strncpy(buf, fullpath, DFS_PATH_MAX);
  124. rt_free(fullpath);
  125. }
  126. rt_free(dir);
  127. }
  128. }
  129. mnt = dfs_mnt_lookup(buf);
  130. if (mnt)
  131. {
  132. struct dfs_dentry *de = dfs_dentry_lookup(mnt, buf, 0);
  133. /* release the old dentry */
  134. dfs_dentry_unref(dentry);
  135. dentry = de;
  136. }
  137. }
  138. else
  139. {
  140. break;
  141. }
  142. } while (dentry && dentry->vnode->type == FT_SYMLINK);
  143. }
  144. rt_free(buf);
  145. }
  146. return dentry;
  147. }
  148. /*
  149. * this function is creat a nolink path.
  150. *
  151. * @param mnt
  152. * @param fullpath
  153. * @param mode 0 middle path nolink; 1 all path nolink.
  154. *
  155. * @return new path.
  156. */
  157. static char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode)
  158. {
  159. int index = 0;
  160. char *path = RT_NULL;
  161. char link_fn[DFS_PATH_MAX] = {0};
  162. struct dfs_dentry *dentry = RT_NULL;
  163. path = (char *)rt_malloc(DFS_PATH_MAX);
  164. if (!path)
  165. {
  166. return path;
  167. }
  168. if (*mnt && fullpath)
  169. {
  170. int i = 0;
  171. char *fp = fullpath;
  172. while (*fp != '\0')
  173. {
  174. fp++;
  175. i++;
  176. if (*fp == '/')
  177. {
  178. rt_memcpy(path + index, fp - i, i);
  179. path[index + i] = '\0';
  180. dentry = dfs_dentry_lookup(*mnt, path, 0);
  181. if (dentry && dentry->vnode->type == FT_SYMLINK)
  182. {
  183. int ret = -1;
  184. if ((*mnt)->fs_ops->readlink)
  185. {
  186. ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
  187. }
  188. if (ret > 0)
  189. {
  190. int len = rt_strlen(link_fn);
  191. if (link_fn[0] == '/')
  192. {
  193. rt_memcpy(path, link_fn, len);
  194. index = len;
  195. }
  196. else
  197. {
  198. path[index] = '/';
  199. index++;
  200. rt_memcpy(path + index, link_fn, len);
  201. index += len;
  202. }
  203. path[index] = '\0';
  204. *mnt = dfs_mnt_lookup(path);
  205. }
  206. else
  207. {
  208. rt_kprintf("link error: %s\n", path);
  209. }
  210. }
  211. else
  212. {
  213. index += i;
  214. }
  215. dfs_dentry_unref(dentry);
  216. i = 0;
  217. }
  218. }
  219. if (i)
  220. {
  221. rt_memcpy(path + index, fp - i, i);
  222. path[index + i] = '\0';
  223. if (mode)
  224. {
  225. dentry = dfs_dentry_lookup(*mnt, path, 0);
  226. if (dentry && dentry->vnode->type == FT_SYMLINK)
  227. {
  228. int ret = -1;
  229. if ((*mnt)->fs_ops->readlink)
  230. {
  231. ret = (*mnt)->fs_ops->readlink(dentry, link_fn, DFS_PATH_MAX);
  232. }
  233. if (ret > 0)
  234. {
  235. int len = rt_strlen(link_fn);
  236. if (link_fn[0] == '/')
  237. {
  238. rt_memcpy(path, link_fn, len);
  239. index = len;
  240. }
  241. else
  242. {
  243. path[index] = '/';
  244. index++;
  245. rt_memcpy(path + index, link_fn, len);
  246. index += len;
  247. }
  248. path[index] = '\0';
  249. *mnt = dfs_mnt_lookup(path);
  250. }
  251. else
  252. {
  253. rt_kprintf("link error: %s\n", path);
  254. }
  255. }
  256. dfs_dentry_unref(dentry);
  257. }
  258. }
  259. }
  260. else
  261. {
  262. rt_free(path);
  263. path = RT_NULL;
  264. }
  265. //rt_kprintf("%s: %s => %s\n", __FUNCTION__, fullpath, path);
  266. return path;
  267. }
  268. /**
  269. * this function will open a file which specified by path with specified oflags.
  270. *
  271. * @param fd the file descriptor pointer to return the corresponding result.
  272. * @param path the specified file path.
  273. * @param oflags the oflags for open operator.
  274. *
  275. * @return 0 on successful, -1 on failed.
  276. */
  277. int dfs_file_open(struct dfs_file *file, const char *path, int oflags, mode_t mode)
  278. {
  279. int ret = -RT_ERROR;;
  280. char *fullpath = RT_NULL;
  281. struct dfs_dentry *dentry = RT_NULL;
  282. int fflags = dfs_fflags(oflags);
  283. if (mode == 0)
  284. {
  285. mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); /* 0666 */
  286. }
  287. if (file && path)
  288. {
  289. fullpath = dfs_normalize_path(NULL, path);
  290. if (fullpath)
  291. {
  292. struct dfs_mnt *mnt = RT_NULL;
  293. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  294. mnt = dfs_mnt_lookup(fullpath);
  295. if (mnt)
  296. {
  297. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  298. if (tmp)
  299. {
  300. rt_free(fullpath);
  301. fullpath = tmp;
  302. }
  303. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
  304. dentry = dfs_dentry_lookup(mnt, fullpath, oflags);
  305. if (dentry && dentry->vnode->type == FT_SYMLINK)
  306. {
  307. /* it's a symbol link but not follow */
  308. if (oflags & O_NOFOLLOW)
  309. {
  310. /* no follow symbol link */
  311. dfs_dentry_unref(dentry);
  312. dentry = RT_NULL;
  313. }
  314. else
  315. {
  316. struct dfs_dentry *target_dentry = RT_NULL;
  317. /* follow symbol link */
  318. target_dentry = dfs_file_follow_link(dentry);
  319. if (target_dentry)
  320. {
  321. dentry = target_dentry;
  322. }
  323. }
  324. }
  325. if (dentry)
  326. {
  327. if (oflags & O_DIRECTORY)
  328. {
  329. if (dentry->vnode->type != FT_DIRECTORY)
  330. {
  331. dfs_dentry_unref(dentry);
  332. dentry = RT_NULL;
  333. }
  334. }
  335. else if (dentry->vnode->type == FT_DIRECTORY)
  336. {
  337. if (fflags & (DFS_F_FWRITE))
  338. {
  339. dfs_dentry_unref(dentry);
  340. dentry = RT_NULL;
  341. }
  342. else
  343. {
  344. oflags |= O_DIRECTORY;
  345. }
  346. }
  347. }
  348. if (oflags & O_CREAT)
  349. {
  350. if (dentry)
  351. {
  352. oflags &= ~O_CREAT;
  353. if (oflags & O_EXCL)
  354. {
  355. oflags &= ~O_EXCL;
  356. /* the dentry already exists */
  357. dfs_dentry_unref(dentry);
  358. dentry = RT_NULL;
  359. }
  360. }
  361. else
  362. {
  363. /* create file/directory */
  364. if (mnt->fs_ops->create_vnode)
  365. {
  366. struct dfs_vnode *vnode = RT_NULL;
  367. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", fullpath);
  368. dentry = dfs_dentry_create(mnt, fullpath);
  369. if (dentry)
  370. {
  371. mode &= ~S_IFMT;
  372. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->create_vnode");
  373. vnode = mnt->fs_ops->create_vnode(dentry, oflags & O_DIRECTORY ? FT_DIRECTORY:FT_REGULAR, mode);
  374. if (vnode)
  375. {
  376. /* set vnode */
  377. dentry->vnode = vnode; /* the refcount of created vnode is 1. no need to reference */
  378. dfs_dentry_insert(dentry);
  379. }
  380. else
  381. {
  382. DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "create failed.");
  383. dfs_dentry_unref(dentry);
  384. dentry = RT_NULL;
  385. }
  386. }
  387. }
  388. }
  389. }
  390. if (dentry)
  391. {
  392. rt_bool_t permission = RT_TRUE;
  393. file->dentry = dentry;
  394. file->vnode = dentry->vnode;
  395. file->fops = dentry->mnt->fs_ops->default_fops;
  396. file->flags = oflags;
  397. /* check permission */
  398. if (!(oflags & O_CREAT))
  399. {
  400. if (fflags & DFS_F_FWRITE)
  401. {
  402. if (!(file->vnode->mode & S_IWUSR))
  403. {
  404. permission = RT_FALSE;
  405. }
  406. }
  407. if (fflags & DFS_F_FREAD)
  408. {
  409. if (!(file->vnode->mode & S_IRUSR))
  410. {
  411. permission = RT_FALSE;
  412. }
  413. }
  414. if (oflags & O_EXEC)
  415. {
  416. if (!(file->vnode->mode & S_IXUSR))
  417. {
  418. permission = RT_FALSE;
  419. }
  420. }
  421. }
  422. if (permission && file->fops->open)
  423. {
  424. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fops->open(file)");
  425. ret = file->fops->open(file);
  426. if (ret < 0)
  427. {
  428. LOG_E("open %s failed in file system: %s", path, dentry->mnt->fs_ops->name);
  429. DLOG(msg, mnt->fs_ops->name, "dfs_file", DLOG_MSG_RET, "open failed.");
  430. dfs_file_unref(file);
  431. }
  432. else
  433. {
  434. /* for char/block device */
  435. if ((S_ISCHR(file->vnode->mode)) || (S_ISBLK(file->vnode->mode)))
  436. {
  437. file->fops = file->vnode->fops;
  438. }
  439. }
  440. }
  441. else
  442. {
  443. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "no permission or fops->open");
  444. dfs_file_unref(file);
  445. }
  446. }
  447. else
  448. {
  449. LOG_I("lookup file:%s failed in file system", path);
  450. }
  451. }
  452. rt_free(fullpath);
  453. }
  454. if (ret >= 0 && (oflags & O_TRUNC))
  455. {
  456. /* trunc file */
  457. if (!(fflags & DFS_F_FWRITE) || file->vnode->type == FT_DIRECTORY)
  458. {
  459. /* truncate on read a only file or a directory */
  460. DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file), trunc on RDOnly or directory");
  461. ret = -RT_ERROR;
  462. }
  463. else
  464. {
  465. if (file->fops->truncate)
  466. {
  467. DLOG(msg, "dfs_file", dentry->mnt->fs_ops->name, DLOG_MSG, "fops->truncate(file, 0)");
  468. ret = file->fops->truncate(file, 0);
  469. }
  470. }
  471. if (ret < 0)
  472. {
  473. dfs_file_unref(file);
  474. }
  475. file->flags &= ~O_TRUNC;
  476. }
  477. }
  478. return ret;
  479. }
  480. int dfs_file_close(struct dfs_file *file)
  481. {
  482. int ret = -RT_ERROR;
  483. if (file)
  484. {
  485. if (dfs_file_lock() == RT_EOK)
  486. {
  487. rt_atomic_t ref_count = rt_atomic_load(&(file->ref_count));
  488. if (ref_count == 1 && file->fops && file->fops->close)
  489. {
  490. DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->close(file)");
  491. ret = file->fops->close(file);
  492. if (ret == 0) /* close file sucessfully */
  493. {
  494. DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file)");
  495. dfs_file_unref(file);
  496. }
  497. else
  498. {
  499. LOG_W("close file:%s failed on low level file system", file->dentry->pathname);
  500. }
  501. }
  502. else
  503. {
  504. DLOG(msg, "dfs_file", "dfs_file", DLOG_MSG, "dfs_file_unref(file)");
  505. dfs_file_unref(file);
  506. ret = 0;
  507. }
  508. dfs_file_unlock();
  509. }
  510. }
  511. return ret;
  512. }
  513. ssize_t dfs_file_read(struct dfs_file *file, void *buf, size_t len)
  514. {
  515. ssize_t ret = -EBADF;
  516. if (file)
  517. {
  518. /* check whether read */
  519. if (!(dfs_fflags(file->flags) & DFS_F_FREAD))
  520. {
  521. ret = -EPERM;
  522. }
  523. else if (!file->fops || !file->fops->read)
  524. {
  525. ret = -ENOSYS;
  526. }
  527. else if (file->vnode && file->vnode->type != FT_DIRECTORY)
  528. {
  529. off_t pos;
  530. pos = file->fpos;
  531. ret = rw_verify_area(file, &pos, len);
  532. if (ret > 0)
  533. {
  534. len = ret;
  535. ret = file->fops->read(file, buf, len, &pos);
  536. if (ret > 0)
  537. {
  538. dfs_file_set_fpos(file, pos);
  539. }
  540. }
  541. }
  542. }
  543. return ret;
  544. }
  545. ssize_t dfs_file_write(struct dfs_file *file, const void *buf, size_t len)
  546. {
  547. size_t ret = -EBADF;
  548. if (file)
  549. {
  550. if (!(dfs_fflags(file->flags) & DFS_F_FWRITE))
  551. {
  552. LOG_W("bad write flags.");
  553. ret = -EBADF;
  554. }
  555. else if (!file->fops || !file->fops->write)
  556. {
  557. LOG_W("no fops write.");
  558. ret = -ENOSYS;
  559. }
  560. else if (file->vnode && file->vnode->type != FT_DIRECTORY)
  561. {
  562. off_t pos;
  563. pos = file->fpos;
  564. ret = rw_verify_area(file, &pos, len);
  565. if (ret > 0)
  566. {
  567. len = ret;
  568. DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG,
  569. "dfs_file_write(fd, buf, %d)", len);
  570. ret = file->fops->write(file, buf, len, &pos);
  571. if (ret > 0)
  572. {
  573. dfs_file_set_fpos(file, pos);
  574. }
  575. }
  576. }
  577. }
  578. return ret;
  579. }
  580. int generic_dfs_lseek(struct dfs_file *file, off_t offset, int whence)
  581. {
  582. off_t foffset;
  583. if (whence == SEEK_SET)
  584. foffset = offset;
  585. else if (whence == SEEK_CUR)
  586. foffset = file->fpos + offset;
  587. else if (whence == SEEK_END)
  588. foffset = file->vnode->size + offset;
  589. else
  590. return -EINVAL;
  591. dfs_file_set_fpos(file, foffset);
  592. return foffset;
  593. }
  594. off_t dfs_file_lseek(struct dfs_file *file, off_t offset, int wherece)
  595. {
  596. off_t retval;
  597. if (!file)
  598. return -EBADF;
  599. retval = -EINVAL;
  600. if (file->fops->lseek)
  601. {
  602. retval = file->fops->lseek(file, offset, wherece);
  603. if (retval >= 0)
  604. {
  605. dfs_file_set_fpos(file, retval);
  606. }
  607. }
  608. return retval;
  609. }
  610. int dfs_file_stat(const char *path, struct stat *buf)
  611. {
  612. int ret = -ENOENT;
  613. char *fullpath = RT_NULL;
  614. struct dfs_mnt *mnt = RT_NULL;
  615. struct dfs_dentry *dentry = RT_NULL;
  616. fullpath = dfs_normalize_path(NULL, path);
  617. if (fullpath)
  618. {
  619. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  620. mnt = dfs_mnt_lookup(fullpath);
  621. if (mnt)
  622. {
  623. char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
  624. if (tmp)
  625. {
  626. rt_free(fullpath);
  627. fullpath = tmp;
  628. }
  629. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
  630. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  631. if (dentry)
  632. {
  633. DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
  634. if (mnt->fs_ops->stat)
  635. {
  636. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
  637. ret = mnt->fs_ops->stat(dentry, buf);
  638. }
  639. /* unref dentry */
  640. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
  641. dfs_dentry_unref(dentry);
  642. dentry = RT_NULL;
  643. }
  644. }
  645. rt_free(fullpath);
  646. fullpath = RT_NULL;
  647. }
  648. else
  649. {
  650. ret = -ENOMEM;
  651. }
  652. return ret;
  653. }
  654. int dfs_file_lstat(const char *path, struct stat *buf)
  655. {
  656. int ret = -ENOENT;
  657. char *fullpath = RT_NULL;
  658. struct dfs_mnt *mnt = RT_NULL;
  659. struct dfs_dentry *dentry = RT_NULL;
  660. fullpath = dfs_normalize_path(NULL, path);
  661. if (fullpath)
  662. {
  663. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  664. mnt = dfs_mnt_lookup(fullpath);
  665. if (mnt)
  666. {
  667. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  668. if (tmp)
  669. {
  670. rt_free(fullpath);
  671. fullpath = tmp;
  672. }
  673. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
  674. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  675. if (dentry)
  676. {
  677. DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
  678. if (mnt->fs_ops->stat)
  679. {
  680. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
  681. ret = mnt->fs_ops->stat(dentry, buf);
  682. }
  683. /* unref dentry */
  684. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
  685. dfs_dentry_unref(dentry);
  686. dentry = RT_NULL;
  687. }
  688. }
  689. rt_free(fullpath);
  690. fullpath = RT_NULL;
  691. }
  692. else
  693. {
  694. ret = -ENOMEM;
  695. }
  696. rt_set_errno(-ret);
  697. return ret;
  698. }
  699. int dfs_file_fstat(struct dfs_file *file, struct stat *buf)
  700. {
  701. size_t ret = -EBADF;
  702. if (file)
  703. {
  704. if (file->fops && file->fops->ioctl)
  705. {
  706. // ret = file->fops->fstat(file, buf);
  707. }
  708. else
  709. {
  710. ret = -ENOSYS;
  711. }
  712. }
  713. else
  714. {
  715. ret = -EBADF;
  716. }
  717. return ret;
  718. }
  719. int dfs_file_setattr(const char *path, struct dfs_attr *attr)
  720. {
  721. int ret = -RT_ERROR;
  722. char *fullpath = RT_NULL;
  723. struct dfs_mnt *mnt = RT_NULL;
  724. struct dfs_dentry *dentry = RT_NULL;
  725. fullpath = dfs_normalize_path(NULL, path);
  726. if (fullpath)
  727. {
  728. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  729. mnt = dfs_mnt_lookup(fullpath);
  730. if (mnt)
  731. {
  732. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  733. if (tmp)
  734. {
  735. rt_free(fullpath);
  736. fullpath = tmp;
  737. }
  738. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
  739. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  740. if (dentry)
  741. {
  742. DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
  743. if (mnt->fs_ops->setattr)
  744. {
  745. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->setattr(dentry, attr)");
  746. ret = mnt->fs_ops->setattr(dentry, attr);
  747. }
  748. /* unref dentry */
  749. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
  750. dfs_dentry_unref(dentry);
  751. dentry = RT_NULL;
  752. }
  753. }
  754. rt_free(fullpath);
  755. fullpath = RT_NULL;
  756. }
  757. return ret;
  758. }
  759. int dfs_file_ioctl(struct dfs_file *file, int cmd, void *args)
  760. {
  761. size_t ret = 0;
  762. if (file)
  763. {
  764. if (file->fops && file->fops->ioctl)
  765. {
  766. ret = file->fops->ioctl(file, cmd, args);
  767. }
  768. else
  769. {
  770. ret = -ENOSYS;
  771. }
  772. }
  773. else
  774. {
  775. ret = -EBADF;
  776. }
  777. return ret;
  778. }
  779. int dfs_file_fcntl(int fd, int cmd, unsigned long arg)
  780. {
  781. int ret = 0;
  782. struct dfs_file *file;
  783. file = fd_get(fd);
  784. if (file)
  785. {
  786. switch (cmd)
  787. {
  788. case F_DUPFD:
  789. ret = dfs_dup(fd, arg);
  790. break;
  791. case F_GETFD:
  792. ret = file->mode;
  793. break;
  794. case F_SETFD:
  795. file->mode = arg;
  796. break;
  797. case F_GETFL:
  798. ret = file->flags;
  799. break;
  800. case F_SETFL:
  801. file->flags = arg;
  802. break;
  803. case F_GETLK:
  804. break;
  805. case F_SETLK:
  806. case F_SETLKW:
  807. break;
  808. default:
  809. ret = -EPERM;
  810. break;
  811. }
  812. }
  813. else
  814. {
  815. ret = -EBADF;
  816. }
  817. return ret;
  818. }
  819. int dfs_file_fsync(struct dfs_file *file)
  820. {
  821. int ret = -EBADF;
  822. if (file)
  823. {
  824. if (file->fops->flush)
  825. {
  826. ret = file->fops->flush(file);
  827. }
  828. }
  829. return ret;
  830. }
  831. int dfs_file_unlink(const char *path)
  832. {
  833. int ret = -RT_ERROR;
  834. char *fullpath = RT_NULL;
  835. struct dfs_mnt *mnt = RT_NULL;
  836. struct dfs_dentry *dentry = RT_NULL;
  837. fullpath = dfs_normalize_path(NULL, path);
  838. if (fullpath)
  839. {
  840. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  841. mnt = dfs_mnt_lookup(fullpath);
  842. if (mnt)
  843. {
  844. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  845. if (tmp)
  846. {
  847. rt_free(fullpath);
  848. fullpath = tmp;
  849. }
  850. if (strcmp(mnt->fullpath, fullpath) != 0)
  851. {
  852. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
  853. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  854. if (dentry)
  855. {
  856. rt_bool_t has_child = RT_FALSE;
  857. has_child = dfs_mnt_has_child_mnt(mnt, fullpath);
  858. if (has_child == RT_FALSE && rt_atomic_load(&(dentry->ref_count)) == 1)
  859. {
  860. /* no child mnt point, unlink it */
  861. ret = -RT_ERROR;
  862. if (mnt->fs_ops->unlink)
  863. {
  864. ret = mnt->fs_ops->unlink(dentry);
  865. }
  866. }
  867. else
  868. {
  869. ret = -EBUSY;
  870. }
  871. /* release this dentry */
  872. dfs_dentry_unref(dentry);
  873. }
  874. else
  875. {
  876. /* no this entry */
  877. ret = -ENOENT;
  878. }
  879. }
  880. else
  881. {
  882. /* it's a mount point, failed for busy */
  883. ret = -EBUSY;
  884. }
  885. }
  886. else
  887. {
  888. ret = -ENOENT;
  889. }
  890. /* release fullpath */
  891. rt_free(fullpath);
  892. }
  893. else
  894. {
  895. ret = -ENOMEM;
  896. }
  897. return ret;
  898. }
  899. int dfs_file_link(const char *oldname, const char *newname)
  900. {
  901. int ret = -1;
  902. struct stat stat;
  903. struct dfs_mnt *mnt = RT_NULL;
  904. char *old_fullpath, *new_fullpath;
  905. if (dfs_file_isdir(oldname) == 0)
  906. {
  907. return ret;
  908. }
  909. if (dfs_file_lstat(newname, &stat) >= 0)
  910. {
  911. return ret;
  912. }
  913. old_fullpath = dfs_normalize_path(NULL, oldname);
  914. if (old_fullpath)
  915. {
  916. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", old_fullpath);
  917. mnt = dfs_mnt_lookup(old_fullpath);
  918. if (mnt == RT_NULL)
  919. {
  920. rt_free(old_fullpath);
  921. return -1;
  922. }
  923. char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
  924. if (tmp)
  925. {
  926. rt_free(old_fullpath);
  927. old_fullpath = tmp;
  928. }
  929. }
  930. new_fullpath = dfs_normalize_path(NULL, newname);
  931. if (new_fullpath)
  932. {
  933. char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
  934. if (tmp)
  935. {
  936. rt_free(new_fullpath);
  937. new_fullpath = tmp;
  938. }
  939. }
  940. if (old_fullpath && new_fullpath)
  941. {
  942. struct dfs_dentry *old_dentry, *new_dentry;
  943. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", old_fullpath);
  944. old_dentry = dfs_dentry_lookup(mnt, old_fullpath, 0);
  945. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", new_fullpath);
  946. new_dentry = dfs_dentry_create(mnt, new_fullpath);
  947. if (old_dentry && new_dentry)
  948. {
  949. if (mnt->fs_ops->link)
  950. {
  951. ret = mnt->fs_ops->link(old_dentry, new_dentry);
  952. }
  953. }
  954. dfs_dentry_unref(old_dentry);
  955. dfs_dentry_unref(new_dentry);
  956. }
  957. if (old_fullpath)
  958. {
  959. rt_free(old_fullpath);
  960. }
  961. if (new_fullpath)
  962. {
  963. rt_free(new_fullpath);
  964. }
  965. return ret;
  966. }
  967. /* symlink creates a symbolic link named `linkpath` which contains the string `target`. */
  968. int dfs_file_symlink(const char *target, const char *linkpath)
  969. {
  970. int ret = -RT_ERROR;
  971. char *fullpath = RT_NULL, *parent = RT_NULL;
  972. struct dfs_mnt *mnt = RT_NULL;
  973. struct dfs_dentry *dentry = RT_NULL;
  974. if (target && linkpath)
  975. {
  976. if (linkpath[0] != '/')
  977. {
  978. fullpath = dfs_normalize_path(NULL, linkpath);
  979. }
  980. else
  981. {
  982. fullpath = (char*)linkpath;
  983. }
  984. /* linkpath should be not exist */
  985. if (dfs_file_access(fullpath, O_RDONLY) != 0)
  986. {
  987. char *index;
  988. /* get parent path */
  989. index = strrchr(fullpath, '/');
  990. if (index)
  991. {
  992. int length = index - fullpath;
  993. if (length > 0)
  994. {
  995. parent = (char*) rt_malloc (length + 1);
  996. if (parent)
  997. {
  998. memcpy(parent, fullpath, length);
  999. parent[length] = '\0';
  1000. }
  1001. }
  1002. else
  1003. {
  1004. parent = (char*) rt_malloc (1 + 1);
  1005. if (parent)
  1006. {
  1007. parent[0] = '/';
  1008. parent[1] = '\0';
  1009. }
  1010. }
  1011. }
  1012. if (parent)
  1013. {
  1014. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  1015. mnt = dfs_mnt_lookup(parent);
  1016. if (mnt)
  1017. {
  1018. char *tmp = dfs_nolink_path(&mnt, parent, 0);
  1019. if (tmp)
  1020. {
  1021. rt_free(parent);
  1022. parent = tmp;
  1023. }
  1024. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
  1025. dentry = dfs_dentry_lookup(mnt, parent, 0);
  1026. if (dentry)
  1027. {
  1028. if (dentry->mnt->fs_ops->symlink)
  1029. {
  1030. char *path = dfs_normalize_path(NULL, target);
  1031. if (path)
  1032. {
  1033. char *tmp = dfs_nolink_path(&mnt, path, 0);
  1034. if (tmp)
  1035. {
  1036. rt_free(path);
  1037. path = tmp;
  1038. }
  1039. else
  1040. {
  1041. tmp = path;
  1042. }
  1043. if (dfs_file_access(path, O_RDONLY) == 0)
  1044. {
  1045. ret = rt_strncmp(parent, path, strlen(parent));
  1046. if (ret == 0)
  1047. {
  1048. tmp = path + strlen(parent);
  1049. if (*tmp == '/')
  1050. {
  1051. tmp ++;
  1052. }
  1053. }
  1054. ret = mnt->fs_ops->symlink(dentry, tmp, index + 1);
  1055. }
  1056. else
  1057. {
  1058. ret = -ENOENT;
  1059. }
  1060. rt_free(path);
  1061. }
  1062. }
  1063. else
  1064. {
  1065. ret = -ENOSYS;
  1066. }
  1067. dfs_dentry_unref(dentry);
  1068. }
  1069. else
  1070. {
  1071. ret = -ENOENT;
  1072. }
  1073. }
  1074. else
  1075. {
  1076. ret = -ENOENT;
  1077. }
  1078. rt_free(parent);
  1079. }
  1080. }
  1081. if (fullpath != linkpath)
  1082. rt_free(fullpath);
  1083. }
  1084. else
  1085. {
  1086. ret = -EINVAL;
  1087. }
  1088. return ret;
  1089. }
  1090. int dfs_file_readlink(const char *path, char *buf, int bufsize)
  1091. {
  1092. int ret = -RT_ERROR;
  1093. char *fullpath = RT_NULL;
  1094. struct dfs_mnt *mnt = RT_NULL;
  1095. struct dfs_dentry *dentry = RT_NULL;
  1096. fullpath = dfs_normalize_path(NULL, path);
  1097. if (fullpath)
  1098. {
  1099. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  1100. mnt = dfs_mnt_lookup(fullpath);
  1101. if (mnt)
  1102. {
  1103. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  1104. if (tmp)
  1105. {
  1106. rt_free(fullpath);
  1107. fullpath = tmp;
  1108. }
  1109. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", fullpath);
  1110. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  1111. if (dentry)
  1112. {
  1113. if (mnt->fs_ops->readlink)
  1114. {
  1115. ret = mnt->fs_ops->readlink(dentry, buf, bufsize);
  1116. }
  1117. else
  1118. {
  1119. ret = -ENOSYS;
  1120. }
  1121. /* release this dentry */
  1122. dfs_dentry_unref(dentry);
  1123. }
  1124. else
  1125. {
  1126. /* no this entry */
  1127. ret = -ENOENT;
  1128. }
  1129. }
  1130. else
  1131. {
  1132. ret = -ENOENT;
  1133. }
  1134. /* release fullpath */
  1135. rt_free(fullpath);
  1136. }
  1137. else
  1138. {
  1139. ret = -ENOMEM;
  1140. }
  1141. return ret;
  1142. }
  1143. int dfs_file_rename(const char *old_file, const char *new_file)
  1144. {
  1145. int ret = -1;
  1146. struct dfs_mnt *mnt = RT_NULL;
  1147. char *old_fullpath, *new_fullpath;
  1148. old_fullpath = dfs_normalize_path(NULL, old_file);
  1149. if (old_fullpath)
  1150. {
  1151. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", old_fullpath);
  1152. mnt = dfs_mnt_lookup(old_fullpath);
  1153. if (mnt == RT_NULL)
  1154. {
  1155. rt_free(old_fullpath);
  1156. return -1;
  1157. }
  1158. char *tmp = dfs_nolink_path(&mnt, old_fullpath, 0);
  1159. if (tmp)
  1160. {
  1161. rt_free(old_fullpath);
  1162. old_fullpath = tmp;
  1163. }
  1164. }
  1165. new_fullpath = dfs_normalize_path(NULL, new_file);
  1166. if (new_fullpath)
  1167. {
  1168. char *tmp = dfs_nolink_path(&mnt, new_fullpath, 0);
  1169. if (tmp)
  1170. {
  1171. rt_free(new_fullpath);
  1172. new_fullpath = tmp;
  1173. }
  1174. }
  1175. if (old_fullpath && new_fullpath)
  1176. {
  1177. struct dfs_dentry *old_dentry, *new_dentry;
  1178. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_lookup(mnt, %s)", old_fullpath);
  1179. old_dentry = dfs_dentry_lookup(mnt, old_fullpath, 0);
  1180. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_create(%s)", new_fullpath);
  1181. new_dentry = dfs_dentry_create(mnt, new_fullpath);
  1182. if (old_dentry && new_dentry)
  1183. {
  1184. if (mnt->fs_ops->rename)
  1185. {
  1186. ret = mnt->fs_ops->rename(old_dentry, new_dentry);
  1187. }
  1188. }
  1189. dfs_dentry_unref(old_dentry);
  1190. dfs_dentry_unref(new_dentry);
  1191. }
  1192. if (old_fullpath)
  1193. {
  1194. rt_free(old_fullpath);
  1195. }
  1196. if (new_fullpath)
  1197. {
  1198. rt_free(new_fullpath);
  1199. }
  1200. return ret;
  1201. }
  1202. int dfs_file_ftruncate(struct dfs_file *file, off_t length)
  1203. {
  1204. int ret = 0;
  1205. if (file)
  1206. {
  1207. if (file->fops->truncate)
  1208. {
  1209. ret = file->fops->truncate(file, length);
  1210. }
  1211. else
  1212. {
  1213. ret = -ENOSYS;
  1214. }
  1215. }
  1216. else
  1217. {
  1218. ret = -EBADF;
  1219. }
  1220. return ret;
  1221. }
  1222. int dfs_file_flush(struct dfs_file *file)
  1223. {
  1224. int ret = 0;
  1225. if (file)
  1226. {
  1227. if (file->fops->flush)
  1228. {
  1229. ret = file->fops->flush(file);
  1230. }
  1231. else
  1232. {
  1233. ret = -ENOSYS;
  1234. }
  1235. }
  1236. else
  1237. {
  1238. ret = -EBADF;
  1239. }
  1240. return ret;
  1241. }
  1242. int dfs_file_getdents(struct dfs_file *file, struct dirent *dirp, size_t nbytes)
  1243. {
  1244. int ret = -RT_ERROR;
  1245. if (file)
  1246. {
  1247. if (file->vnode && S_ISDIR(file->vnode->mode))
  1248. {
  1249. if (file->fops && file->fops->getdents)
  1250. {
  1251. DLOG(msg, "dfs_file", file->dentry->mnt->fs_ops->name, DLOG_MSG, "fops->getdents()");
  1252. ret = file->fops->getdents(file, dirp, nbytes);
  1253. }
  1254. }
  1255. }
  1256. else
  1257. {
  1258. ret = -EBADF;
  1259. }
  1260. return ret;
  1261. }
  1262. /**
  1263. * this function will check the path is it a directory.
  1264. *
  1265. * @param path the file path.
  1266. *
  1267. * @return 0 on is dir, -1 on not dir.
  1268. */
  1269. int dfs_file_isdir(const char *path)
  1270. {
  1271. int ret = -RT_ERROR;
  1272. char *fullpath = RT_NULL;
  1273. struct dfs_mnt *mnt = RT_NULL;
  1274. struct dfs_dentry *dentry = RT_NULL;
  1275. fullpath = dfs_normalize_path(NULL, path);
  1276. if (fullpath)
  1277. {
  1278. DLOG(msg, "dfs_file", "mnt", DLOG_MSG, "dfs_mnt_lookup(%s)", fullpath);
  1279. mnt = dfs_mnt_lookup(fullpath);
  1280. if (mnt)
  1281. {
  1282. char *tmp = dfs_nolink_path(&mnt, fullpath, 1);
  1283. if (tmp)
  1284. {
  1285. rt_free(fullpath);
  1286. fullpath = tmp;
  1287. }
  1288. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dentry = dfs_dentry_lookup(mnt, %s)", fullpath);
  1289. dentry = dfs_dentry_lookup(mnt, fullpath, 0);
  1290. if (dentry)
  1291. {
  1292. DLOG(msg, "dentry", "dfs_file", DLOG_MSG_RET, "return dentry");
  1293. if (mnt->fs_ops->stat)
  1294. {
  1295. struct stat stat = {0};
  1296. DLOG(msg, "dfs_file", mnt->fs_ops->name, DLOG_MSG, "fs_ops->stat(dentry, buf)");
  1297. ret = mnt->fs_ops->stat(dentry, &stat);
  1298. if (ret == RT_EOK && S_ISDIR(stat.st_mode))
  1299. {
  1300. ret = RT_EOK;
  1301. }
  1302. else
  1303. {
  1304. ret = -RT_ERROR;
  1305. }
  1306. }
  1307. /* unref dentry */
  1308. DLOG(msg, "dfs_file", "dentry", DLOG_MSG, "dfs_dentry_unref(dentry)");
  1309. dfs_dentry_unref(dentry);
  1310. dentry = RT_NULL;
  1311. }
  1312. }
  1313. rt_free(fullpath);
  1314. fullpath = RT_NULL;
  1315. }
  1316. return ret;
  1317. }
  1318. int dfs_file_access(const char *path, mode_t mode)
  1319. {
  1320. int ret;
  1321. struct dfs_file file;
  1322. dfs_file_init(&file);
  1323. if (dfs_file_open(&file, path, O_RDONLY, mode) >= 0)
  1324. {
  1325. ret = 0;
  1326. dfs_file_close(&file);
  1327. }
  1328. else
  1329. {
  1330. ret = -1;
  1331. }
  1332. dfs_file_deinit(&file);
  1333. return ret;
  1334. }
  1335. int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2)
  1336. {
  1337. int ret = 0;
  1338. if (file && mmap2)
  1339. {
  1340. if (file->vnode->type != FT_DEVICE || !file->vnode->fops->ioctl)
  1341. {
  1342. rt_set_errno(EINVAL);
  1343. }
  1344. else if (file->vnode->type == FT_DEVICE && file->vnode->fops->ioctl)
  1345. {
  1346. ret = file->vnode->fops->ioctl(file, RT_FIOMMAP2, mmap2);
  1347. if (ret != 0)
  1348. {
  1349. ret = ret > 0 ? ret : -ret;
  1350. rt_set_errno(ret);
  1351. }
  1352. }
  1353. }
  1354. return ret;
  1355. }
  1356. #ifdef RT_USING_FINSH
  1357. #define _COLOR_RED "\033[31m"
  1358. #define _COLOR_GREEN "\033[32m"
  1359. #define _COLOR_BLUE "\033[34m"
  1360. #define _COLOR_CYAN "\033[36m"
  1361. #define _COLOR_WHITE "\033[37m"
  1362. #define _COLOR_NORMAL "\033[0m"
  1363. void ls(const char *pathname)
  1364. {
  1365. struct dirent dirent;
  1366. struct stat stat;
  1367. int length;
  1368. char *fullpath, *path;
  1369. struct dfs_file file;
  1370. if (pathname == NULL)
  1371. {
  1372. #ifdef DFS_USING_WORKDIR
  1373. /* open current working directory */
  1374. path = rt_strdup(working_directory);
  1375. #else
  1376. path = rt_strdup("/");
  1377. #endif
  1378. if (path == NULL)
  1379. {
  1380. return; /* out of memory */
  1381. }
  1382. }
  1383. else
  1384. {
  1385. path = dfs_normalize_path(NULL, (char *)pathname);
  1386. if (path == NULL)
  1387. {
  1388. return; /* out of memory */
  1389. }
  1390. }
  1391. dfs_file_init(&file);
  1392. /* list directory */
  1393. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_DIRECTORY, 0)", path);
  1394. if (dfs_file_open(&file, path, O_DIRECTORY, 0) >= 0)
  1395. {
  1396. char *link_fn = (char *) rt_malloc (DFS_PATH_MAX);
  1397. if (link_fn)
  1398. {
  1399. rt_kprintf("Directory %s:\n", path);
  1400. do
  1401. {
  1402. memset(&dirent, 0, sizeof(struct dirent));
  1403. DLOG(group, "foreach_item");
  1404. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_getdents(&dirent)");
  1405. length = dfs_file_getdents(&file, &dirent, sizeof(struct dirent));
  1406. if (length > 0)
  1407. {
  1408. DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "dirent.d_name=%s", dirent.d_name);
  1409. memset(&stat, 0, sizeof(struct stat));
  1410. /* build full path for each file */
  1411. fullpath = dfs_normalize_path(path, dirent.d_name);
  1412. if (fullpath == NULL)
  1413. break;
  1414. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_lstat(%s, &stat)", fullpath);
  1415. if (dfs_file_lstat(fullpath, &stat) == 0)
  1416. {
  1417. if (S_ISDIR(stat.st_mode))
  1418. {
  1419. rt_kprintf(_COLOR_BLUE "%-20s" _COLOR_NORMAL, dirent.d_name);
  1420. rt_kprintf("%-25s\n", "<DIR>");
  1421. }
  1422. else if (S_ISLNK(stat.st_mode))
  1423. {
  1424. int ret = 0;
  1425. rt_kprintf(_COLOR_CYAN "%-20s" _COLOR_NORMAL, dirent.d_name);
  1426. ret = dfs_file_readlink(fullpath, link_fn, DFS_PATH_MAX);
  1427. if (ret > 0)
  1428. {
  1429. char *link_path = link_fn;
  1430. struct dfs_mnt *mnt = RT_NULL;
  1431. mnt = dfs_mnt_lookup(fullpath);
  1432. if (mnt)
  1433. {
  1434. char *tmp = dfs_nolink_path(&mnt, fullpath, 0);
  1435. if (tmp)
  1436. {
  1437. char *index;
  1438. index = strrchr(fullpath, '/');
  1439. if (index)
  1440. {
  1441. int length = index - fullpath;
  1442. char *parent = (char*) rt_malloc (length + 1);
  1443. if (parent)
  1444. {
  1445. rt_memcpy(parent, fullpath, length);
  1446. parent[length] = '\0';
  1447. ret = rt_strncmp(parent, link_fn, length);
  1448. if (ret == 0)
  1449. {
  1450. link_path = link_fn + length;
  1451. if (*link_path == '/')
  1452. {
  1453. link_path ++;
  1454. }
  1455. }
  1456. rt_free(parent);
  1457. }
  1458. }
  1459. rt_free(tmp);
  1460. }
  1461. }
  1462. rt_kprintf("-> %s\n", link_path);
  1463. }
  1464. else
  1465. {
  1466. rt_kprintf(_COLOR_RED "-> link_error\n" _COLOR_NORMAL);
  1467. }
  1468. }
  1469. else if (stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
  1470. {
  1471. rt_kprintf(_COLOR_GREEN "%-20s" _COLOR_NORMAL, dirent.d_name);
  1472. rt_kprintf("%-25lu\n", (unsigned long)stat.st_size);
  1473. }
  1474. else
  1475. {
  1476. rt_kprintf("%-20s", dirent.d_name);
  1477. rt_kprintf("%-25lu\n", (unsigned long)stat.st_size);
  1478. }
  1479. }
  1480. else
  1481. {
  1482. rt_kprintf(_COLOR_RED "%-20s" _COLOR_NORMAL, dirent.d_name);
  1483. }
  1484. rt_free(fullpath);
  1485. }
  1486. else
  1487. {
  1488. DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "return NULL");
  1489. }
  1490. DLOG(group_end);
  1491. } while (length > 0);
  1492. rt_free(link_fn);
  1493. }
  1494. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_close()");
  1495. dfs_file_close(&file);
  1496. }
  1497. else
  1498. {
  1499. rt_kprintf("No such directory\n");
  1500. }
  1501. dfs_file_deinit(&file);
  1502. DLOG(msg, "dfs_file", "dfs", DLOG_MSG_RET, "return");
  1503. rt_free(path);
  1504. }
  1505. void cat(const char *filename)
  1506. {
  1507. int length = 0;
  1508. char buffer[81];
  1509. struct dfs_file file;
  1510. if (filename && dfs_file_isdir(filename) == 0)
  1511. {
  1512. rt_kprintf("cat: %s Is a directory\n", filename);
  1513. return;
  1514. }
  1515. dfs_file_init(&file);
  1516. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_open(%s, O_RDONLY, 0)", filename);
  1517. if (dfs_file_open(&file, filename, O_RDONLY, 0) < 0)
  1518. {
  1519. rt_kprintf("Open %s failed\n", filename);
  1520. dfs_file_deinit(&file);
  1521. return;
  1522. }
  1523. do
  1524. {
  1525. rt_memset(buffer, 0x0, sizeof(buffer));
  1526. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_read(fd, buffer, %d)", sizeof(buffer) - 1);
  1527. length = dfs_file_read(&file, (void *)buffer, sizeof(buffer) - 1);
  1528. if (length > 0)
  1529. {
  1530. buffer[length] = '\0';
  1531. rt_kprintf("%s", buffer);
  1532. }
  1533. } while (length > 0);
  1534. rt_kprintf("\n");
  1535. DLOG(msg, "dfs", "dfs_file", DLOG_MSG, "dfs_file_close()");
  1536. dfs_file_close(&file);
  1537. dfs_file_deinit(&file);
  1538. }
  1539. #define BUF_SZ 4096
  1540. static void copyfile(const char *src, const char *dst)
  1541. {
  1542. int ret;
  1543. struct dfs_file src_file, dst_file;
  1544. rt_uint8_t *block_ptr;
  1545. rt_int32_t read_bytes;
  1546. block_ptr = (rt_uint8_t *)rt_malloc(BUF_SZ);
  1547. if (block_ptr == NULL)
  1548. {
  1549. rt_kprintf("out of memory\n");
  1550. return;
  1551. }
  1552. dfs_file_init(&src_file);
  1553. ret = dfs_file_open(&src_file, src, O_RDONLY, 0);
  1554. if (ret < 0)
  1555. {
  1556. dfs_file_deinit(&src_file);
  1557. rt_free(block_ptr);
  1558. rt_kprintf("Read %s failed\n", src);
  1559. return;
  1560. }
  1561. dfs_file_init(&dst_file);
  1562. ret = dfs_file_open(&dst_file, dst, O_WRONLY | O_CREAT, 0);
  1563. if (ret < 0)
  1564. {
  1565. dfs_file_deinit(&dst_file);
  1566. dfs_file_close(&src_file);
  1567. dfs_file_deinit(&src_file);
  1568. rt_free(block_ptr);
  1569. rt_kprintf("Write %s failed\n", dst);
  1570. return;
  1571. }
  1572. do
  1573. {
  1574. read_bytes = dfs_file_read(&src_file, block_ptr, BUF_SZ);
  1575. if (read_bytes > 0)
  1576. {
  1577. int length;
  1578. length = dfs_file_write(&dst_file, block_ptr, read_bytes);
  1579. if (length != read_bytes)
  1580. {
  1581. /* write failed. */
  1582. rt_kprintf("Write file data failed, errno=%d\n", length);
  1583. break;
  1584. }
  1585. }
  1586. } while (read_bytes > 0);
  1587. dfs_file_close(&dst_file);
  1588. dfs_file_deinit(&dst_file);
  1589. dfs_file_close(&src_file);
  1590. dfs_file_deinit(&src_file);
  1591. rt_free(block_ptr);
  1592. }
  1593. extern int mkdir(const char *path, mode_t mode);
  1594. static void copydir(const char *src, const char *dst)
  1595. {
  1596. struct dirent dirent;
  1597. struct stat stat;
  1598. int length;
  1599. struct dfs_file file;
  1600. dfs_file_init(&file);
  1601. if (dfs_file_open(&file, src, O_DIRECTORY, 0) < 0)
  1602. {
  1603. rt_kprintf("open %s failed\n", src);
  1604. dfs_file_deinit(&file);
  1605. return ;
  1606. }
  1607. do
  1608. {
  1609. rt_memset(&dirent, 0, sizeof(struct dirent));
  1610. length = dfs_file_getdents(&file, &dirent, sizeof(struct dirent));
  1611. if (length > 0)
  1612. {
  1613. char *src_entry_full = NULL;
  1614. char *dst_entry_full = NULL;
  1615. if (strcmp(dirent.d_name, "..") == 0 || strcmp(dirent.d_name, ".") == 0)
  1616. continue;
  1617. /* build full path for each file */
  1618. if ((src_entry_full = dfs_normalize_path(src, dirent.d_name)) == NULL)
  1619. {
  1620. rt_kprintf("out of memory!\n");
  1621. break;
  1622. }
  1623. if ((dst_entry_full = dfs_normalize_path(dst, dirent.d_name)) == NULL)
  1624. {
  1625. rt_kprintf("out of memory!\n");
  1626. rt_free(src_entry_full);
  1627. break;
  1628. }
  1629. rt_memset(&stat, 0, sizeof(struct stat));
  1630. if (dfs_file_lstat(src_entry_full, &stat) != 0)
  1631. {
  1632. rt_kprintf("open file: %s failed\n", dirent.d_name);
  1633. continue;
  1634. }
  1635. if (S_ISDIR(stat.st_mode))
  1636. {
  1637. mkdir(dst_entry_full, 0);
  1638. copydir(src_entry_full, dst_entry_full);
  1639. }
  1640. else
  1641. {
  1642. copyfile(src_entry_full, dst_entry_full);
  1643. }
  1644. rt_free(src_entry_full);
  1645. rt_free(dst_entry_full);
  1646. }
  1647. }
  1648. while (length > 0);
  1649. dfs_file_close(&file);
  1650. dfs_file_deinit(&file);
  1651. }
  1652. static const char *_get_path_lastname(const char *path)
  1653. {
  1654. char *ptr;
  1655. if ((ptr = (char *)strrchr(path, '/')) == NULL)
  1656. return path;
  1657. /* skip the '/' then return */
  1658. return ++ptr;
  1659. }
  1660. void copy(const char *src, const char *dst)
  1661. {
  1662. #define FLAG_SRC_TYPE 0x03
  1663. #define FLAG_SRC_IS_DIR 0x01
  1664. #define FLAG_SRC_IS_FILE 0x02
  1665. #define FLAG_SRC_NON_EXSIT 0x00
  1666. #define FLAG_DST_TYPE 0x0C
  1667. #define FLAG_DST_IS_DIR 0x04
  1668. #define FLAG_DST_IS_FILE 0x08
  1669. #define FLAG_DST_NON_EXSIT 0x00
  1670. struct stat stat;
  1671. uint32_t flag = 0;
  1672. /* check the staus of src and dst */
  1673. if (dfs_file_lstat(src, &stat) < 0)
  1674. {
  1675. rt_kprintf("copy failed, bad %s\n", src);
  1676. return;
  1677. }
  1678. if (S_ISDIR(stat.st_mode))
  1679. flag |= FLAG_SRC_IS_DIR;
  1680. else
  1681. flag |= FLAG_SRC_IS_FILE;
  1682. if (dfs_file_stat(dst, &stat) < 0)
  1683. {
  1684. flag |= FLAG_DST_NON_EXSIT;
  1685. }
  1686. else
  1687. {
  1688. if (S_ISDIR(stat.st_mode))
  1689. flag |= FLAG_DST_IS_DIR;
  1690. else
  1691. flag |= FLAG_DST_IS_FILE;
  1692. }
  1693. //2. check status
  1694. if ((flag & FLAG_SRC_IS_DIR) && (flag & FLAG_DST_IS_FILE))
  1695. {
  1696. rt_kprintf("cp faild, cp dir to file is not permitted!\n");
  1697. return ;
  1698. }
  1699. //3. do copy
  1700. if (flag & FLAG_SRC_IS_FILE)
  1701. {
  1702. if (flag & FLAG_DST_IS_DIR)
  1703. {
  1704. char *fdst;
  1705. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  1706. if (fdst == NULL)
  1707. {
  1708. rt_kprintf("out of memory\n");
  1709. return;
  1710. }
  1711. copyfile(src, fdst);
  1712. rt_free(fdst);
  1713. }
  1714. else
  1715. {
  1716. copyfile(src, dst);
  1717. }
  1718. }
  1719. else //flag & FLAG_SRC_IS_DIR
  1720. {
  1721. if (flag & FLAG_DST_IS_DIR)
  1722. {
  1723. char *fdst;
  1724. fdst = dfs_normalize_path(dst, _get_path_lastname(src));
  1725. if (fdst == NULL)
  1726. {
  1727. rt_kprintf("out of memory\n");
  1728. return;
  1729. }
  1730. mkdir(fdst, 0);
  1731. copydir(src, fdst);
  1732. rt_free(fdst);
  1733. }
  1734. else if ((flag & FLAG_DST_TYPE) == FLAG_DST_NON_EXSIT)
  1735. {
  1736. mkdir(dst, 0);
  1737. copydir(src, dst);
  1738. }
  1739. else
  1740. {
  1741. copydir(src, dst);
  1742. }
  1743. }
  1744. }
  1745. FINSH_FUNCTION_EXPORT(copy, copy file or dir)
  1746. #endif