dfs_file.c 61 KB

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