fs_userfs.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989
  1. /****************************************************************************
  2. * fs/userfs/fs_userfs.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <sys/types.h>
  25. #include <sys/statfs.h>
  26. #include <sys/stat.h>
  27. #include <sys/socket.h>
  28. #include <stdint.h>
  29. #include <stdbool.h>
  30. #include <string.h>
  31. #include <fcntl.h>
  32. #include <assert.h>
  33. #include <errno.h>
  34. #include <debug.h>
  35. #include <arpa/inet.h>
  36. #include <netinet/in.h>
  37. #include <nuttx/kmalloc.h>
  38. #include <nuttx/fs/fs.h>
  39. #include <nuttx/fs/userfs.h>
  40. #include <nuttx/fs/dirent.h>
  41. #include <nuttx/fs/ioctl.h>
  42. #include <nuttx/net/net.h>
  43. #include <nuttx/semaphore.h>
  44. /****************************************************************************
  45. * Pre-processor Definitions
  46. ****************************************************************************/
  47. #define IOBUFFER_SIZE(p) (USERFS_REQ_MAXSIZE + (p)->mxwrite)
  48. /****************************************************************************
  49. * Private Types
  50. ****************************************************************************/
  51. /* This structure holds the internal state of the UserFS proxy */
  52. struct userfs_state_s
  53. {
  54. /* Fields copied from struct userfs_config_s */
  55. size_t mxwrite; /* The max size of a write data */
  56. /* Internal state */
  57. struct socket psock; /* Client socket instance */
  58. struct sockaddr_in server; /* Server address */
  59. sem_t exclsem; /* Exclusive access for request-response sequence */
  60. /* I/O Buffer (actual size depends on USERFS_REQ_MAXSIZE and the configured
  61. * mxwrite).
  62. */
  63. uint8_t iobuffer[1];
  64. };
  65. #define SIZEOF_USERFS_STATE_S(n) (sizeof(struct userfs_state_s) + (n) - 1)
  66. /****************************************************************************
  67. * Private Function Prototypes
  68. ****************************************************************************/
  69. static int userfs_open(FAR struct file *filep, const char *relpath,
  70. int oflags, mode_t mode);
  71. static int userfs_close(FAR struct file *filep);
  72. static ssize_t userfs_read(FAR struct file *filep, char *buffer,
  73. size_t buflen);
  74. static ssize_t userfs_read(FAR struct file *filep, FAR char *buffer,
  75. size_t buflen);
  76. static ssize_t userfs_write(FAR struct file *filep, FAR const char *buffer,
  77. size_t buflen);
  78. static off_t userfs_seek(FAR struct file *filep, off_t offset, int whence);
  79. static int userfs_ioctl(FAR struct file *filep, int cmd,
  80. unsigned long arg);
  81. static int userfs_sync(FAR struct file *filep);
  82. static int userfs_dup(FAR const struct file *oldp,
  83. FAR struct file *newp);
  84. static int userfs_fstat(FAR const struct file *filep,
  85. FAR struct stat *buf);
  86. static int userfs_truncate(FAR struct file *filep, off_t length);
  87. static int userfs_opendir(FAR struct inode *mountpt,
  88. FAR const char *relpath, FAR struct fs_dirent_s *dir);
  89. static int userfs_closedir(FAR struct inode *mountpt,
  90. FAR struct fs_dirent_s *dir);
  91. static int userfs_readdir(FAR struct inode *mountpt,
  92. FAR struct fs_dirent_s *dir);
  93. static int userfs_rewinddir(FAR struct inode *mountpt,
  94. FAR struct fs_dirent_s *dir);
  95. static int userfs_bind(FAR struct inode *blkdriver, FAR const void *data,
  96. FAR void **handle);
  97. static int userfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
  98. unsigned int flags);
  99. static int userfs_statfs(FAR struct inode *mountpt,
  100. FAR struct statfs *buf);
  101. static int userfs_unlink(FAR struct inode *mountpt,
  102. FAR const char *relpath);
  103. static int userfs_mkdir(FAR struct inode *mountpt,
  104. FAR const char *relpath, mode_t mode);
  105. static int userfs_rmdir(FAR struct inode *mountpt,
  106. FAR const char *relpath);
  107. static int userfs_rename(FAR struct inode *mountpt,
  108. FAR const char *oldrelpath, FAR const char *newrelpath);
  109. static int userfs_stat(FAR struct inode *mountpt,
  110. FAR const char *relpath, FAR struct stat *buf);
  111. /****************************************************************************
  112. * Public Data
  113. ****************************************************************************/
  114. /* See fs_mount.c -- this structure is explicitly extern'ed there.
  115. * We use the old-fashioned kind of initializers so that this will compile
  116. * with any compiler.
  117. */
  118. const struct mountpt_operations userfs_operations =
  119. {
  120. userfs_open, /* open */
  121. userfs_close, /* close */
  122. userfs_read, /* read */
  123. userfs_write, /* write */
  124. userfs_seek, /* seek */
  125. userfs_ioctl, /* ioctl */
  126. userfs_sync, /* sync */
  127. userfs_dup, /* dup */
  128. userfs_fstat, /* fstat */
  129. userfs_truncate, /* truncate */
  130. userfs_opendir, /* opendir */
  131. userfs_closedir, /* closedir */
  132. userfs_readdir, /* readdir */
  133. userfs_rewinddir, /* rewinddir */
  134. userfs_bind, /* bind */
  135. userfs_unbind, /* unbind */
  136. userfs_statfs, /* statfs */
  137. userfs_unlink, /* unlink */
  138. userfs_mkdir, /* mkdir */
  139. userfs_rmdir, /* rmdir */
  140. userfs_rename, /* rename */
  141. userfs_stat /* stat */
  142. };
  143. /****************************************************************************
  144. * Private Functions
  145. ****************************************************************************/
  146. /****************************************************************************
  147. * Name: userfs_open
  148. ****************************************************************************/
  149. static int userfs_open(FAR struct file *filep, FAR const char *relpath,
  150. int oflags, mode_t mode)
  151. {
  152. FAR struct userfs_state_s *priv;
  153. FAR struct userfs_open_request_s *req;
  154. FAR struct userfs_open_response_s *resp;
  155. ssize_t nsent;
  156. ssize_t nrecvd;
  157. int pathlen;
  158. int ret;
  159. finfo("Open '%s'\n", relpath);
  160. DEBUGASSERT(filep != NULL &&
  161. filep->f_inode != NULL &&
  162. filep->f_inode->i_private != NULL);
  163. priv = filep->f_inode->i_private;
  164. /* Check the path length */
  165. DEBUGASSERT(relpath != NULL);
  166. pathlen = strlen(relpath);
  167. if (pathlen > priv->mxwrite)
  168. {
  169. return -E2BIG;
  170. }
  171. /* Get exclusive access */
  172. ret = nxsem_wait(&priv->exclsem);
  173. if (ret < 0)
  174. {
  175. return ret;
  176. }
  177. /* Construct and send the request to the server */
  178. req = (FAR struct userfs_open_request_s *)priv->iobuffer;
  179. req->req = USERFS_REQ_OPEN;
  180. req->oflags = oflags;
  181. req->mode = mode;
  182. strncpy(req->relpath, relpath, priv->mxwrite);
  183. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  184. SIZEOF_USERFS_OPEN_REQUEST_S(pathlen + 1), 0,
  185. (FAR struct sockaddr *)&priv->server,
  186. sizeof(struct sockaddr_in));
  187. if (nsent < 0)
  188. {
  189. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  190. nxsem_post(&priv->exclsem);
  191. return (int)nsent;
  192. }
  193. /* Then get the response from the server */
  194. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  195. 0, NULL, NULL);
  196. nxsem_post(&priv->exclsem);
  197. if (nrecvd < 0)
  198. {
  199. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  200. return (int)nrecvd;
  201. }
  202. if (nrecvd != sizeof(struct userfs_open_response_s))
  203. {
  204. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  205. return -EIO;
  206. }
  207. /* Save the returned openinfo as the filep private data. */
  208. resp = (FAR struct userfs_open_response_s *)priv->iobuffer;
  209. if (resp->resp != USERFS_RESP_OPEN)
  210. {
  211. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  212. return -EIO;
  213. }
  214. filep->f_priv = resp->openinfo;
  215. return resp->ret;
  216. }
  217. /****************************************************************************
  218. * Name: userfs_close
  219. ****************************************************************************/
  220. static int userfs_close(FAR struct file *filep)
  221. {
  222. FAR struct userfs_state_s *priv;
  223. FAR struct userfs_close_request_s *req;
  224. FAR struct userfs_close_response_s *resp;
  225. ssize_t nsent;
  226. ssize_t nrecvd;
  227. int ret;
  228. DEBUGASSERT(filep != NULL &&
  229. filep->f_inode != NULL &&
  230. filep->f_inode->i_private != NULL);
  231. priv = filep->f_inode->i_private;
  232. /* Get exclusive access */
  233. ret = nxsem_wait(&priv->exclsem);
  234. if (ret < 0)
  235. {
  236. return ret;
  237. }
  238. /* Construct and send the request to the server */
  239. req = (FAR struct userfs_close_request_s *)priv->iobuffer;
  240. req->req = USERFS_REQ_CLOSE;
  241. req->openinfo = filep->f_priv;
  242. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  243. sizeof(struct userfs_close_request_s), 0,
  244. (FAR struct sockaddr *)&priv->server,
  245. sizeof(struct sockaddr_in));
  246. if (nsent < 0)
  247. {
  248. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  249. nxsem_post(&priv->exclsem);
  250. return (int)nsent;
  251. }
  252. /* Then get the response from the server */
  253. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  254. 0, NULL, NULL);
  255. nxsem_post(&priv->exclsem);
  256. if (nrecvd < 0)
  257. {
  258. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  259. return (int)nrecvd;
  260. }
  261. if (nrecvd != sizeof(struct userfs_close_response_s))
  262. {
  263. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  264. return -EIO;
  265. }
  266. resp = (FAR struct userfs_close_response_s *)priv->iobuffer;
  267. if (resp->resp != USERFS_RESP_CLOSE)
  268. {
  269. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  270. return -EIO;
  271. }
  272. if (resp->ret >= 0)
  273. {
  274. filep->f_priv = NULL;
  275. }
  276. return resp->ret;
  277. }
  278. /****************************************************************************
  279. * Name: userfs_read
  280. ****************************************************************************/
  281. static ssize_t userfs_read(FAR struct file *filep, char *buffer,
  282. size_t buflen)
  283. {
  284. FAR struct userfs_state_s *priv;
  285. FAR struct userfs_read_request_s *req;
  286. FAR struct userfs_read_response_s *resp;
  287. ssize_t nsent;
  288. ssize_t nrecvd;
  289. int respsize;
  290. int ret;
  291. finfo("Read %zu bytes from offset %jd\n", buflen, (intmax_t)filep->f_pos);
  292. DEBUGASSERT(filep != NULL &&
  293. filep->f_inode != NULL &&
  294. filep->f_inode->i_private != NULL);
  295. priv = filep->f_inode->i_private;
  296. /* Get exclusive access */
  297. ret = nxsem_wait(&priv->exclsem);
  298. if (ret < 0)
  299. {
  300. return ret;
  301. }
  302. /* Construct and send the request to the server */
  303. req = (FAR struct userfs_read_request_s *)priv->iobuffer;
  304. req->req = USERFS_REQ_READ;
  305. req->openinfo = filep->f_priv;
  306. req->readlen = buflen;
  307. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  308. sizeof(struct userfs_read_request_s), 0,
  309. (FAR struct sockaddr *)&priv->server,
  310. sizeof(struct sockaddr_in));
  311. if (nsent < 0)
  312. {
  313. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  314. nxsem_post(&priv->exclsem);
  315. return (int)nsent;
  316. }
  317. /* Then get the response from the server */
  318. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  319. 0, NULL, NULL);
  320. nxsem_post(&priv->exclsem);
  321. if (nrecvd < 0)
  322. {
  323. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  324. return (int)nrecvd;
  325. }
  326. if (nrecvd < SIZEOF_USERFS_READ_RESPONSE_S(0))
  327. {
  328. ferr("ERROR: Response too small: %u\n", (unsigned int)nrecvd);
  329. return -EIO;
  330. }
  331. resp = (FAR struct userfs_read_response_s *)priv->iobuffer;
  332. if (resp->resp != USERFS_RESP_READ)
  333. {
  334. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  335. return -EIO;
  336. }
  337. if (resp->nread > buflen)
  338. {
  339. ferr("ERROR: Response size too large: %u\n", (unsigned int)nrecvd);
  340. return -EIO;
  341. }
  342. respsize = SIZEOF_USERFS_READ_RESPONSE_S(resp->nread);
  343. if (respsize != nrecvd)
  344. {
  345. ferr("ERROR: Incorrect response size: %u\n", (unsigned int)nrecvd);
  346. return -EIO;
  347. }
  348. /* Copy the received data to the user buffer */
  349. memcpy(buffer, resp->rddata, resp->nread);
  350. return resp->nread;
  351. }
  352. /****************************************************************************
  353. * Name: userfs_write
  354. ****************************************************************************/
  355. static ssize_t userfs_write(FAR struct file *filep, FAR const char *buffer,
  356. size_t buflen)
  357. {
  358. FAR struct userfs_state_s *priv;
  359. FAR struct userfs_write_request_s *req;
  360. FAR struct userfs_write_response_s *resp;
  361. ssize_t nsent;
  362. ssize_t nrecvd;
  363. int ret;
  364. finfo("Write %zu bytes to offset %jd\n", buflen, (intmax_t)filep->f_pos);
  365. DEBUGASSERT(filep != NULL &&
  366. filep->f_inode != NULL &&
  367. filep->f_inode->i_private != NULL);
  368. priv = filep->f_inode->i_private;
  369. /* Perform multiple writes if the write length exceeds the configured
  370. * maximum (mxwrite).
  371. */
  372. if (buflen > priv->mxwrite)
  373. {
  374. return -E2BIG; /* No implemented yet */
  375. }
  376. /* Get exclusive access */
  377. ret = nxsem_wait(&priv->exclsem);
  378. if (ret < 0)
  379. {
  380. return ret;
  381. }
  382. /* Construct and send the request to the server */
  383. req = (FAR struct userfs_write_request_s *)priv->iobuffer;
  384. req->req = USERFS_REQ_WRITE;
  385. req->openinfo = filep->f_priv;
  386. req->writelen = buflen;
  387. memcpy(req->wrdata, buffer, buflen);
  388. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  389. SIZEOF_USERFS_WRITE_REQUEST_S(buflen), 0,
  390. (FAR struct sockaddr *)&priv->server,
  391. sizeof(struct sockaddr_in));
  392. if (nsent < 0)
  393. {
  394. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  395. nxsem_post(&priv->exclsem);
  396. return (int)nsent;
  397. }
  398. /* Then get the response from the server */
  399. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  400. 0, NULL, NULL);
  401. nxsem_post(&priv->exclsem);
  402. if (nrecvd < 0)
  403. {
  404. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  405. return (int)nrecvd;
  406. }
  407. if (nrecvd != sizeof(struct userfs_write_response_s))
  408. {
  409. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  410. return -EIO;
  411. }
  412. resp = (FAR struct userfs_write_response_s *)priv->iobuffer;
  413. if (resp->resp != USERFS_RESP_WRITE)
  414. {
  415. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  416. return -EIO;
  417. }
  418. return resp->nwritten;
  419. }
  420. /****************************************************************************
  421. * Name: userfs_seek
  422. ****************************************************************************/
  423. static off_t userfs_seek(FAR struct file *filep, off_t offset, int whence)
  424. {
  425. FAR struct userfs_state_s *priv;
  426. FAR struct userfs_seek_request_s *req;
  427. FAR struct userfs_seek_response_s *resp;
  428. ssize_t nsent;
  429. ssize_t nrecvd;
  430. int ret;
  431. finfo("Offset %lu bytes to whence=%d\n", (unsigned long)offset, whence);
  432. DEBUGASSERT(filep != NULL &&
  433. filep->f_inode != NULL &&
  434. filep->f_inode->i_private != NULL);
  435. priv = filep->f_inode->i_private;
  436. /* Get exclusive access */
  437. ret = nxsem_wait(&priv->exclsem);
  438. if (ret < 0)
  439. {
  440. return ret;
  441. }
  442. /* Construct and send the request to the server */
  443. req = (FAR struct userfs_seek_request_s *)priv->iobuffer;
  444. req->req = USERFS_REQ_SEEK;
  445. req->openinfo = filep->f_priv;
  446. req->offset = offset;
  447. req->whence = whence;
  448. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  449. sizeof(struct userfs_seek_request_s), 0,
  450. (FAR struct sockaddr *)&priv->server,
  451. sizeof(struct sockaddr_in));
  452. if (nsent < 0)
  453. {
  454. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  455. nxsem_post(&priv->exclsem);
  456. return (int)nsent;
  457. }
  458. /* Then get the response from the server */
  459. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  460. 0, NULL, NULL);
  461. nxsem_post(&priv->exclsem);
  462. if (nrecvd < 0)
  463. {
  464. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  465. return (int)nrecvd;
  466. }
  467. if (nrecvd != sizeof(struct userfs_seek_response_s))
  468. {
  469. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  470. return -EIO;
  471. }
  472. resp = (FAR struct userfs_seek_response_s *)priv->iobuffer;
  473. if (resp->resp != USERFS_RESP_SEEK)
  474. {
  475. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  476. return -EIO;
  477. }
  478. return resp->ret;
  479. }
  480. /****************************************************************************
  481. * Name: userfs_ioctl
  482. ****************************************************************************/
  483. static int userfs_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
  484. {
  485. FAR struct userfs_state_s *priv;
  486. FAR struct userfs_ioctl_request_s *req;
  487. FAR struct userfs_ioctl_response_s *resp;
  488. ssize_t nsent;
  489. ssize_t nrecvd;
  490. int ret;
  491. finfo("cmd: %d arg: %08lx\n", cmd, arg);
  492. DEBUGASSERT(filep != NULL &&
  493. filep->f_inode != NULL &&
  494. filep->f_inode->i_private != NULL);
  495. priv = filep->f_inode->i_private;
  496. /* Get exclusive access */
  497. ret = nxsem_wait(&priv->exclsem);
  498. if (ret < 0)
  499. {
  500. return ret;
  501. }
  502. /* Construct and send the request to the server */
  503. req = (FAR struct userfs_ioctl_request_s *)priv->iobuffer;
  504. req->req = USERFS_REQ_IOCTL;
  505. req->openinfo = filep->f_priv;
  506. req->cmd = cmd;
  507. req->arg = arg;
  508. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  509. sizeof(struct userfs_ioctl_request_s), 0,
  510. (FAR struct sockaddr *)&priv->server,
  511. sizeof(struct sockaddr_in));
  512. if (nsent < 0)
  513. {
  514. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  515. nxsem_post(&priv->exclsem);
  516. return (int)nsent;
  517. }
  518. /* Then get the response from the server */
  519. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  520. 0, NULL, NULL);
  521. nxsem_post(&priv->exclsem);
  522. if (nrecvd < 0)
  523. {
  524. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  525. return (int)nrecvd;
  526. }
  527. if (nrecvd != sizeof(struct userfs_ioctl_response_s))
  528. {
  529. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  530. return -EIO;
  531. }
  532. resp = (FAR struct userfs_ioctl_response_s *)priv->iobuffer;
  533. if (resp->resp != USERFS_RESP_IOCTL)
  534. {
  535. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  536. return -EIO;
  537. }
  538. return resp->ret;
  539. }
  540. /****************************************************************************
  541. * Name: userfs_sync
  542. ****************************************************************************/
  543. static int userfs_sync(FAR struct file *filep)
  544. {
  545. FAR struct userfs_state_s *priv;
  546. FAR struct userfs_sync_request_s *req;
  547. FAR struct userfs_sync_response_s *resp;
  548. ssize_t nsent;
  549. ssize_t nrecvd;
  550. int ret;
  551. DEBUGASSERT(filep != NULL &&
  552. filep->f_inode != NULL &&
  553. filep->f_inode->i_private != NULL);
  554. priv = filep->f_inode->i_private;
  555. /* Get exclusive access */
  556. ret = nxsem_wait(&priv->exclsem);
  557. if (ret < 0)
  558. {
  559. return ret;
  560. }
  561. /* Construct and send the request to the server */
  562. req = (FAR struct userfs_sync_request_s *)priv->iobuffer;
  563. req->req = USERFS_REQ_SYNC;
  564. req->openinfo = filep->f_priv;
  565. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  566. sizeof(struct userfs_sync_request_s), 0,
  567. (FAR struct sockaddr *)&priv->server,
  568. sizeof(struct sockaddr_in));
  569. if (nsent < 0)
  570. {
  571. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  572. nxsem_post(&priv->exclsem);
  573. return (int)nsent;
  574. }
  575. /* Then get the response from the server */
  576. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  577. 0, NULL, NULL);
  578. nxsem_post(&priv->exclsem);
  579. if (nrecvd < 0)
  580. {
  581. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  582. return (int)nrecvd;
  583. }
  584. if (nrecvd != sizeof(struct userfs_sync_response_s))
  585. {
  586. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  587. return -EIO;
  588. }
  589. resp = (FAR struct userfs_sync_response_s *)priv->iobuffer;
  590. if (resp->resp != USERFS_RESP_SYNC)
  591. {
  592. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  593. return -EIO;
  594. }
  595. return resp->ret;
  596. }
  597. /****************************************************************************
  598. * Name: userfs_dup
  599. *
  600. * Description:
  601. * Duplicate open file data in the new file structure.
  602. *
  603. ****************************************************************************/
  604. static int userfs_dup(FAR const struct file *oldp, FAR struct file *newp)
  605. {
  606. FAR struct userfs_state_s *priv;
  607. FAR struct userfs_dup_request_s *req;
  608. FAR struct userfs_dup_response_s *resp;
  609. ssize_t nsent;
  610. ssize_t nrecvd;
  611. int ret;
  612. finfo("Dup %p->%p\n", oldp, newp);
  613. DEBUGASSERT(oldp != NULL &&
  614. oldp->f_inode != NULL &&
  615. oldp->f_inode->i_private != NULL);
  616. priv = oldp->f_inode->i_private;
  617. /* Get exclusive access */
  618. ret = nxsem_wait(&priv->exclsem);
  619. if (ret < 0)
  620. {
  621. return ret;
  622. }
  623. /* Construct and send the request to the server */
  624. req = (FAR struct userfs_dup_request_s *)priv->iobuffer;
  625. req->req = USERFS_REQ_DUP;
  626. req->openinfo = oldp->f_priv;
  627. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  628. sizeof(struct userfs_dup_request_s), 0,
  629. (FAR struct sockaddr *)&priv->server,
  630. sizeof(struct sockaddr_in));
  631. if (nsent < 0)
  632. {
  633. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  634. nxsem_post(&priv->exclsem);
  635. return (int)nsent;
  636. }
  637. /* Then get the response from the server */
  638. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  639. 0, NULL, NULL);
  640. nxsem_post(&priv->exclsem);
  641. if (nrecvd < 0)
  642. {
  643. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  644. return (int)nrecvd;
  645. }
  646. if (nrecvd != sizeof(struct userfs_dup_response_s))
  647. {
  648. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  649. return -EIO;
  650. }
  651. resp = (FAR struct userfs_dup_response_s *)priv->iobuffer;
  652. if (resp->resp != USERFS_RESP_DUP)
  653. {
  654. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  655. return -EIO;
  656. }
  657. newp->f_priv = resp->openinfo;
  658. return resp->ret;
  659. }
  660. /****************************************************************************
  661. * Name: userfs_fstat
  662. *
  663. * Description:
  664. * Obtain information about an open file associated with the file
  665. * descriptor 'fd', and will write it to the area pointed to by 'buf'.
  666. *
  667. ****************************************************************************/
  668. static int userfs_fstat(FAR const struct file *filep, FAR struct stat *buf)
  669. {
  670. FAR struct userfs_state_s *priv;
  671. FAR struct userfs_fstat_request_s *req;
  672. FAR struct userfs_fstat_response_s *resp;
  673. ssize_t nsent;
  674. ssize_t nrecvd;
  675. int ret;
  676. DEBUGASSERT(filep != NULL &&
  677. filep->f_inode != NULL &&
  678. filep->f_inode->i_private != NULL);
  679. priv = filep->f_inode->i_private;
  680. /* Get exclusive access */
  681. ret = nxsem_wait(&priv->exclsem);
  682. if (ret < 0)
  683. {
  684. return ret;
  685. }
  686. /* Construct and send the request to the server */
  687. req = (FAR struct userfs_fstat_request_s *)priv->iobuffer;
  688. req->req = USERFS_REQ_FSTAT;
  689. req->openinfo = filep->f_priv;
  690. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  691. sizeof(struct userfs_fstat_request_s), 0,
  692. (FAR struct sockaddr *)&priv->server,
  693. sizeof(struct sockaddr_in));
  694. if (nsent < 0)
  695. {
  696. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  697. nxsem_post(&priv->exclsem);
  698. return (int)nsent;
  699. }
  700. /* Then get the response from the server */
  701. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  702. 0, NULL, NULL);
  703. nxsem_post(&priv->exclsem);
  704. if (nrecvd < 0)
  705. {
  706. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  707. return (int)nrecvd;
  708. }
  709. if (nrecvd != sizeof(struct userfs_fstat_response_s))
  710. {
  711. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  712. return -EIO;
  713. }
  714. resp = (FAR struct userfs_fstat_response_s *)priv->iobuffer;
  715. if (resp->resp != USERFS_RESP_FSTAT)
  716. {
  717. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  718. return -EIO;
  719. }
  720. /* Return the status of the directory entry */
  721. DEBUGASSERT(buf != NULL);
  722. memcpy(buf, &resp->buf, sizeof(struct stat));
  723. return resp->ret;
  724. }
  725. /****************************************************************************
  726. * Name: userfs_truncate
  727. *
  728. * Description:
  729. * Set the size of the regular file referred to by 'filep' to 'length'
  730. *
  731. ****************************************************************************/
  732. static int userfs_truncate(FAR struct file *filep, off_t length)
  733. {
  734. FAR struct userfs_state_s *priv;
  735. FAR struct userfs_truncate_request_s *req;
  736. FAR struct userfs_truncate_response_s *resp;
  737. ssize_t nsent;
  738. ssize_t nrecvd;
  739. int ret;
  740. DEBUGASSERT(filep != NULL &&
  741. filep->f_inode != NULL &&
  742. filep->f_inode->i_private != NULL);
  743. priv = filep->f_inode->i_private;
  744. /* Get exclusive access */
  745. ret = nxsem_wait(&priv->exclsem);
  746. if (ret < 0)
  747. {
  748. return ret;
  749. }
  750. /* Construct and send the request to the server */
  751. req = (FAR struct userfs_truncate_request_s *)priv->iobuffer;
  752. req->req = USERFS_REQ_TRUNCATE;
  753. req->openinfo = filep->f_priv;
  754. req->length = length;
  755. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  756. sizeof(struct userfs_truncate_request_s), 0,
  757. (FAR struct sockaddr *)&priv->server,
  758. sizeof(struct sockaddr_in));
  759. if (nsent < 0)
  760. {
  761. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  762. nxsem_post(&priv->exclsem);
  763. return (int)nsent;
  764. }
  765. /* Then get the response from the server */
  766. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  767. 0, NULL, NULL);
  768. nxsem_post(&priv->exclsem);
  769. if (nrecvd < 0)
  770. {
  771. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  772. return (int)nrecvd;
  773. }
  774. if (nrecvd != sizeof(struct userfs_truncate_response_s))
  775. {
  776. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  777. return -EIO;
  778. }
  779. resp = (FAR struct userfs_truncate_response_s *)priv->iobuffer;
  780. if (resp->resp != USERFS_RESP_FSTAT)
  781. {
  782. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  783. return -EIO;
  784. }
  785. /* Return the result of truncate operation */
  786. return resp->ret;
  787. }
  788. /****************************************************************************
  789. * Name: userfs_opendir
  790. *
  791. * Description:
  792. * Open a directory
  793. *
  794. ****************************************************************************/
  795. static int userfs_opendir(FAR struct inode *mountpt, FAR const char *relpath,
  796. FAR struct fs_dirent_s *dir)
  797. {
  798. FAR struct userfs_state_s *priv;
  799. FAR struct userfs_opendir_request_s *req;
  800. FAR struct userfs_opendir_response_s *resp;
  801. ssize_t nsent;
  802. ssize_t nrecvd;
  803. int pathlen;
  804. int ret;
  805. finfo("relpath: \"%s\"\n", relpath ? relpath : "NULL");
  806. DEBUGASSERT(mountpt != NULL &&
  807. mountpt->i_private != NULL);
  808. priv = mountpt->i_private;
  809. /* Check the path length */
  810. DEBUGASSERT(relpath != NULL);
  811. pathlen = strlen(relpath);
  812. if (pathlen > priv->mxwrite)
  813. {
  814. return -E2BIG;
  815. }
  816. /* Get exclusive access */
  817. ret = nxsem_wait(&priv->exclsem);
  818. if (ret < 0)
  819. {
  820. return ret;
  821. }
  822. /* Construct and send the request to the server */
  823. req = (FAR struct userfs_opendir_request_s *)priv->iobuffer;
  824. req->req = USERFS_REQ_OPENDIR;
  825. strncpy(req->relpath, relpath, priv->mxwrite);
  826. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  827. SIZEOF_USERFS_OPENDIR_REQUEST_S(pathlen + 1), 0,
  828. (FAR struct sockaddr *)&priv->server,
  829. sizeof(struct sockaddr_in));
  830. if (nsent < 0)
  831. {
  832. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  833. nxsem_post(&priv->exclsem);
  834. return (int)nsent;
  835. }
  836. /* Then get the response from the server */
  837. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  838. 0, NULL, NULL);
  839. nxsem_post(&priv->exclsem);
  840. if (nrecvd < 0)
  841. {
  842. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  843. return (int)nrecvd;
  844. }
  845. if (nrecvd != sizeof(struct userfs_opendir_response_s))
  846. {
  847. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  848. return -EIO;
  849. }
  850. resp = (FAR struct userfs_opendir_response_s *)priv->iobuffer;
  851. if (resp->resp != USERFS_RESP_OPENDIR)
  852. {
  853. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  854. return -EIO;
  855. }
  856. /* Save the opaque dir reference in struct fs_dirent_s */
  857. DEBUGASSERT(dir != NULL);
  858. dir->u.userfs.fs_dir = resp->dir;
  859. return resp->ret;
  860. }
  861. /****************************************************************************
  862. * Name: userfs_closedir
  863. *
  864. * Description:
  865. * Close a directory
  866. *
  867. ****************************************************************************/
  868. static int userfs_closedir(FAR struct inode *mountpt,
  869. FAR struct fs_dirent_s *dir)
  870. {
  871. FAR struct userfs_state_s *priv;
  872. FAR struct userfs_closedir_request_s *req;
  873. FAR struct userfs_closedir_response_s *resp;
  874. ssize_t nsent;
  875. ssize_t nrecvd;
  876. int ret;
  877. DEBUGASSERT(mountpt != NULL &&
  878. mountpt->i_private != NULL);
  879. priv = mountpt->i_private;
  880. /* Get exclusive access */
  881. ret = nxsem_wait(&priv->exclsem);
  882. if (ret < 0)
  883. {
  884. return ret;
  885. }
  886. /* Construct and send the request to the server */
  887. req = (FAR struct userfs_closedir_request_s *)priv->iobuffer;
  888. req->req = USERFS_REQ_CLOSEDIR;
  889. req->dir = dir->u.userfs.fs_dir;
  890. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  891. sizeof(struct userfs_closedir_request_s), 0,
  892. (FAR struct sockaddr *)&priv->server,
  893. sizeof(struct sockaddr_in));
  894. if (nsent < 0)
  895. {
  896. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  897. nxsem_post(&priv->exclsem);
  898. return (int)nsent;
  899. }
  900. /* Then get the response from the server */
  901. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  902. 0, NULL, NULL);
  903. nxsem_post(&priv->exclsem);
  904. if (nrecvd < 0)
  905. {
  906. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  907. return (int)nrecvd;
  908. }
  909. if (nrecvd != sizeof(struct userfs_closedir_response_s))
  910. {
  911. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  912. return -EIO;
  913. }
  914. resp = (FAR struct userfs_closedir_response_s *)priv->iobuffer;
  915. if (resp->resp != USERFS_RESP_CLOSEDIR)
  916. {
  917. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  918. return -EIO;
  919. }
  920. return resp->ret;
  921. }
  922. /****************************************************************************
  923. * Name: userfs_readdir
  924. *
  925. * Description: Read the next directory entry
  926. *
  927. ****************************************************************************/
  928. static int userfs_readdir(FAR struct inode *mountpt,
  929. FAR struct fs_dirent_s *dir)
  930. {
  931. FAR struct userfs_state_s *priv;
  932. FAR struct userfs_readdir_request_s *req;
  933. FAR struct userfs_readdir_response_s *resp;
  934. ssize_t nsent;
  935. ssize_t nrecvd;
  936. int ret;
  937. DEBUGASSERT(mountpt != NULL &&
  938. mountpt->i_private != NULL);
  939. priv = mountpt->i_private;
  940. /* Get exclusive access */
  941. ret = nxsem_wait(&priv->exclsem);
  942. if (ret < 0)
  943. {
  944. return ret;
  945. }
  946. /* Construct and send the request to the server */
  947. req = (FAR struct userfs_readdir_request_s *)priv->iobuffer;
  948. req->req = USERFS_REQ_READDIR;
  949. req->dir = dir->u.userfs.fs_dir;
  950. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  951. sizeof(struct userfs_readdir_request_s), 0,
  952. (FAR struct sockaddr *)&priv->server,
  953. sizeof(struct sockaddr_in));
  954. if (nsent < 0)
  955. {
  956. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  957. nxsem_post(&priv->exclsem);
  958. return (int)nsent;
  959. }
  960. /* Then get the response from the server */
  961. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  962. 0, NULL, NULL);
  963. nxsem_post(&priv->exclsem);
  964. if (nrecvd < 0)
  965. {
  966. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  967. return (int)nrecvd;
  968. }
  969. if (nrecvd != sizeof(struct userfs_readdir_response_s))
  970. {
  971. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  972. return -EIO;
  973. }
  974. resp = (FAR struct userfs_readdir_response_s *)priv->iobuffer;
  975. if (resp->resp != USERFS_RESP_READDIR)
  976. {
  977. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  978. return -EIO;
  979. }
  980. /* Return the dirent */
  981. DEBUGASSERT(dir != NULL);
  982. memcpy(&dir->fd_dir, &resp->entry, sizeof(struct dirent));
  983. return resp->ret;
  984. }
  985. /****************************************************************************
  986. * Name: userfs_rewindir
  987. *
  988. * Description: Reset directory read to the first entry
  989. *
  990. ****************************************************************************/
  991. static int userfs_rewinddir(FAR struct inode *mountpt,
  992. FAR struct fs_dirent_s *dir)
  993. {
  994. FAR struct userfs_state_s *priv;
  995. FAR struct userfs_rewinddir_request_s *req;
  996. FAR struct userfs_rewinddir_response_s *resp;
  997. ssize_t nsent;
  998. ssize_t nrecvd;
  999. int ret;
  1000. DEBUGASSERT(mountpt != NULL &&
  1001. mountpt->i_private != NULL);
  1002. priv = mountpt->i_private;
  1003. /* Get exclusive access */
  1004. ret = nxsem_wait(&priv->exclsem);
  1005. if (ret < 0)
  1006. {
  1007. return ret;
  1008. }
  1009. /* Construct and send the request to the server */
  1010. req = (FAR struct userfs_rewinddir_request_s *)priv->iobuffer;
  1011. req->req = USERFS_REQ_REWINDDIR;
  1012. req->dir = dir->u.userfs.fs_dir;
  1013. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1014. sizeof(struct userfs_rewinddir_request_s), 0,
  1015. (FAR struct sockaddr *)&priv->server,
  1016. sizeof(struct sockaddr_in));
  1017. if (nsent < 0)
  1018. {
  1019. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1020. nxsem_post(&priv->exclsem);
  1021. return (int)nsent;
  1022. }
  1023. /* Then get the response from the server */
  1024. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1025. 0, NULL, NULL);
  1026. nxsem_post(&priv->exclsem);
  1027. if (nrecvd < 0)
  1028. {
  1029. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1030. return (int)nrecvd;
  1031. }
  1032. if (nrecvd != sizeof(struct userfs_rewinddir_response_s))
  1033. {
  1034. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1035. return -EIO;
  1036. }
  1037. resp = (FAR struct userfs_rewinddir_response_s *)priv->iobuffer;
  1038. if (resp->resp != USERFS_RESP_REWINDDIR)
  1039. {
  1040. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1041. return -EIO;
  1042. }
  1043. return resp->ret;
  1044. }
  1045. /****************************************************************************
  1046. * Name: userfs_bind
  1047. *
  1048. * Description: This implements a portion of the mount operation. This
  1049. * function allocates and initializes the mountpoint private data and
  1050. * binds the blockdriver inode to the filesystem private data. The final
  1051. * binding of the private data (containing the blockdriver) to the
  1052. * mountpoint is performed by mount().
  1053. *
  1054. ****************************************************************************/
  1055. static int userfs_bind(FAR struct inode *blkdriver, FAR const void *data,
  1056. FAR void **handle)
  1057. {
  1058. FAR struct userfs_state_s *priv;
  1059. FAR const struct userfs_config_s *config;
  1060. struct sockaddr_in client;
  1061. unsigned int iolen;
  1062. int ret;
  1063. DEBUGASSERT(data != NULL && handle != NULL);
  1064. config = (FAR const struct userfs_config_s *)data;
  1065. /* Allocate an instance of the UserFS state structure */
  1066. iolen = USERFS_REQ_MAXSIZE + config->mxwrite;
  1067. priv = kmm_malloc(SIZEOF_USERFS_STATE_S(iolen));
  1068. if (priv == NULL)
  1069. {
  1070. ferr("ERROR: Failed to allocate state structure\n");
  1071. return -ENOMEM;
  1072. }
  1073. /* Initialize the semaphore that assures mutually exclusive access through
  1074. * the entire request-response sequence.
  1075. */
  1076. nxsem_init(&priv->exclsem, 0, 1);
  1077. /* Copy the configuration data into the allocated structure. Why? First
  1078. * we can't be certain of the life time of the memory underlying the config
  1079. * reference. Also, in the KERNEL build, the config data will like in
  1080. * process-specific memory and cannot be shared across processes.
  1081. */
  1082. priv->mxwrite = config->mxwrite;
  1083. /* Preset the server address */
  1084. priv->server.sin_family = AF_INET;
  1085. priv->server.sin_port = htons(config->portno);
  1086. priv->server.sin_addr.s_addr = HTONL(INADDR_LOOPBACK);
  1087. /* Create a LocalHost UDP client socket */
  1088. ret = psock_socket(PF_INET, SOCK_DGRAM, 0, &priv->psock);
  1089. if (ret < 0)
  1090. {
  1091. ferr("ERROR: socket() failed: %d\n", ret);
  1092. goto errout_with_alloc;
  1093. }
  1094. /* Bind the socket to the client address */
  1095. client.sin_family = AF_INET;
  1096. client.sin_port = 0;
  1097. client.sin_addr.s_addr = HTONL(INADDR_LOOPBACK);
  1098. ret = psock_bind(&priv->psock, (FAR struct sockaddr *)&client,
  1099. sizeof(struct sockaddr_in));
  1100. if (ret < 0)
  1101. {
  1102. ferr("ERROR: bind() failed: %d\n", ret);
  1103. goto errout_with_psock;
  1104. }
  1105. /* Mounted! */
  1106. *handle = (FAR void *)priv;
  1107. return OK;
  1108. errout_with_psock:
  1109. psock_close(&priv->psock);
  1110. errout_with_alloc:
  1111. kmm_free(priv);
  1112. return ret;
  1113. }
  1114. /****************************************************************************
  1115. * Name: userfs_unbind
  1116. *
  1117. * Description: This implements the filesystem portion of the umount
  1118. * operation.
  1119. *
  1120. ****************************************************************************/
  1121. static int userfs_unbind(FAR void *handle, FAR struct inode **blkdriver,
  1122. unsigned int flags)
  1123. {
  1124. FAR struct userfs_state_s *priv = (FAR struct userfs_state_s *)handle;
  1125. FAR struct userfs_destroy_request_s *req;
  1126. FAR struct userfs_destroy_response_s *resp;
  1127. ssize_t nsent;
  1128. ssize_t nrecvd;
  1129. int ret;
  1130. DEBUGASSERT(priv != NULL);
  1131. /* Get exclusive access */
  1132. ret = nxsem_wait(&priv->exclsem);
  1133. if (ret < 0)
  1134. {
  1135. return ret;
  1136. }
  1137. /* Construct and send the request to the server */
  1138. req = (FAR struct userfs_destroy_request_s *)priv->iobuffer;
  1139. req->req = USERFS_REQ_DESTROY;
  1140. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1141. sizeof(struct userfs_destroy_request_s), 0,
  1142. (FAR struct sockaddr *)&priv->server,
  1143. sizeof(struct sockaddr_in));
  1144. if (nsent < 0)
  1145. {
  1146. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1147. nxsem_post(&priv->exclsem);
  1148. return (int)nsent;
  1149. }
  1150. /* Then get the response from the server */
  1151. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1152. 0, NULL, NULL);
  1153. nxsem_post(&priv->exclsem);
  1154. if (nrecvd < 0)
  1155. {
  1156. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1157. return (int)nrecvd;
  1158. }
  1159. if (nrecvd != sizeof(struct userfs_destroy_response_s))
  1160. {
  1161. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1162. return -EIO;
  1163. }
  1164. resp = (FAR struct userfs_destroy_response_s *)priv->iobuffer;
  1165. if (resp->resp != USERFS_RESP_DESTROY)
  1166. {
  1167. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1168. return -EIO;
  1169. }
  1170. /* If the destruction failed, then refuse to unmount at this time */
  1171. if (resp->ret < 0)
  1172. {
  1173. return resp->ret;
  1174. }
  1175. /* Free resources and return success */
  1176. psock_close(&priv->psock);
  1177. kmm_free(priv);
  1178. return OK;
  1179. }
  1180. /****************************************************************************
  1181. * Name: userfs_statfs
  1182. *
  1183. * Description:
  1184. * Return filesystem statistics
  1185. *
  1186. ****************************************************************************/
  1187. static int userfs_statfs(FAR struct inode *mountpt, FAR struct statfs *buf)
  1188. {
  1189. FAR struct userfs_state_s *priv;
  1190. FAR struct userfs_statfs_request_s *req;
  1191. FAR struct userfs_statfs_response_s *resp;
  1192. ssize_t nsent;
  1193. ssize_t nrecvd;
  1194. int ret;
  1195. DEBUGASSERT(mountpt != NULL &&
  1196. mountpt->i_private != NULL);
  1197. priv = mountpt->i_private;
  1198. /* Get exclusive access */
  1199. ret = nxsem_wait(&priv->exclsem);
  1200. if (ret < 0)
  1201. {
  1202. return ret;
  1203. }
  1204. /* Construct and send the request to the server */
  1205. req = (FAR struct userfs_statfs_request_s *)priv->iobuffer;
  1206. req->req = USERFS_REQ_STATFS;
  1207. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1208. sizeof(struct userfs_statfs_request_s), 0,
  1209. (FAR struct sockaddr *)&priv->server,
  1210. sizeof(struct sockaddr_in));
  1211. if (nsent < 0)
  1212. {
  1213. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1214. nxsem_post(&priv->exclsem);
  1215. return (int)nsent;
  1216. }
  1217. /* Then get the response from the server */
  1218. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1219. 0, NULL, NULL);
  1220. nxsem_post(&priv->exclsem);
  1221. if (nrecvd < 0)
  1222. {
  1223. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1224. return (int)nrecvd;
  1225. }
  1226. if (nrecvd != sizeof(struct userfs_statfs_response_s))
  1227. {
  1228. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1229. return -EIO;
  1230. }
  1231. resp = (FAR struct userfs_statfs_response_s *)priv->iobuffer;
  1232. if (resp->resp != USERFS_RESP_STATFS)
  1233. {
  1234. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1235. return -EIO;
  1236. }
  1237. /* Return the status of the file system */
  1238. DEBUGASSERT(buf != NULL);
  1239. memcpy(buf, &resp->buf, sizeof(struct statfs));
  1240. return resp->ret;
  1241. }
  1242. /****************************************************************************
  1243. * Name: userfs_unlink
  1244. *
  1245. * Description:
  1246. * Remove a directory entry
  1247. *
  1248. ****************************************************************************/
  1249. static int userfs_unlink(FAR struct inode *mountpt,
  1250. FAR const char *relpath)
  1251. {
  1252. FAR struct userfs_state_s *priv;
  1253. FAR struct userfs_unlink_request_s *req;
  1254. FAR struct userfs_unlink_response_s *resp;
  1255. ssize_t nsent;
  1256. ssize_t nrecvd;
  1257. int pathlen;
  1258. int ret;
  1259. DEBUGASSERT(mountpt != NULL &&
  1260. mountpt->i_private != NULL);
  1261. priv = mountpt->i_private;
  1262. /* Check the path length */
  1263. DEBUGASSERT(relpath != NULL);
  1264. pathlen = strlen(relpath);
  1265. if (pathlen > priv->mxwrite)
  1266. {
  1267. return -E2BIG;
  1268. }
  1269. /* Get exclusive access */
  1270. ret = nxsem_wait(&priv->exclsem);
  1271. if (ret < 0)
  1272. {
  1273. return ret;
  1274. }
  1275. /* Construct and send the request to the server */
  1276. req = (FAR struct userfs_unlink_request_s *)priv->iobuffer;
  1277. req->req = USERFS_REQ_UNLINK;
  1278. strncpy(req->relpath, relpath, priv->mxwrite);
  1279. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1280. SIZEOF_USERFS_UNLINK_REQUEST_S(pathlen + 1), 0,
  1281. (FAR struct sockaddr *)&priv->server,
  1282. sizeof(struct sockaddr_in));
  1283. if (nsent < 0)
  1284. {
  1285. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1286. nxsem_post(&priv->exclsem);
  1287. return (int)nsent;
  1288. }
  1289. /* Then get the response from the server */
  1290. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1291. 0, NULL, NULL);
  1292. nxsem_post(&priv->exclsem);
  1293. if (nrecvd < 0)
  1294. {
  1295. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1296. return (int)nrecvd;
  1297. }
  1298. if (nrecvd != sizeof(struct userfs_unlink_response_s))
  1299. {
  1300. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1301. return -EIO;
  1302. }
  1303. resp = (FAR struct userfs_unlink_response_s *)priv->iobuffer;
  1304. if (resp->resp != USERFS_RESP_UNLINK)
  1305. {
  1306. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1307. return -EIO;
  1308. }
  1309. return resp->ret;
  1310. }
  1311. /****************************************************************************
  1312. * Name: userfs_mkdir
  1313. *
  1314. * Description:
  1315. * Create a new directory
  1316. *
  1317. ****************************************************************************/
  1318. static int userfs_mkdir(FAR struct inode *mountpt,
  1319. FAR const char *relpath, mode_t mode)
  1320. {
  1321. FAR struct userfs_state_s *priv;
  1322. FAR struct userfs_mkdir_request_s *req;
  1323. FAR struct userfs_mkdir_response_s *resp;
  1324. ssize_t nsent;
  1325. ssize_t nrecvd;
  1326. int pathlen;
  1327. int ret;
  1328. DEBUGASSERT(mountpt != NULL &&
  1329. mountpt->i_private != NULL);
  1330. priv = mountpt->i_private;
  1331. /* Check the path length */
  1332. DEBUGASSERT(relpath != NULL);
  1333. pathlen = strlen(relpath);
  1334. if (pathlen > priv->mxwrite)
  1335. {
  1336. return -E2BIG;
  1337. }
  1338. /* Get exclusive access */
  1339. ret = nxsem_wait(&priv->exclsem);
  1340. if (ret < 0)
  1341. {
  1342. return ret;
  1343. }
  1344. /* Construct and send the request to the server */
  1345. req = (FAR struct userfs_mkdir_request_s *)priv->iobuffer;
  1346. req->req = USERFS_REQ_MKDIR;
  1347. req->mode = mode;
  1348. strncpy(req->relpath, relpath, priv->mxwrite);
  1349. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1350. SIZEOF_USERFS_MKDIR_REQUEST_S(pathlen + 1), 0,
  1351. (FAR struct sockaddr *)&priv->server,
  1352. sizeof(struct sockaddr_in));
  1353. if (nsent < 0)
  1354. {
  1355. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1356. nxsem_post(&priv->exclsem);
  1357. return (int)nsent;
  1358. }
  1359. /* Then get the response from the server */
  1360. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1361. 0, NULL, NULL);
  1362. nxsem_post(&priv->exclsem);
  1363. if (nrecvd < 0)
  1364. {
  1365. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1366. return (int)nrecvd;
  1367. }
  1368. if (nrecvd != sizeof(struct userfs_mkdir_response_s))
  1369. {
  1370. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1371. return -EIO;
  1372. }
  1373. resp = (FAR struct userfs_mkdir_response_s *)priv->iobuffer;
  1374. if (resp->resp != USERFS_RESP_MKDIR)
  1375. {
  1376. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1377. return -EIO;
  1378. }
  1379. return resp->ret;
  1380. }
  1381. /****************************************************************************
  1382. * Name: userfs_rmdir
  1383. *
  1384. * Description:
  1385. * Remove a directory
  1386. *
  1387. ****************************************************************************/
  1388. static int userfs_rmdir(FAR struct inode *mountpt,
  1389. FAR const char *relpath)
  1390. {
  1391. FAR struct userfs_state_s *priv;
  1392. FAR struct userfs_rmdir_request_s *req;
  1393. FAR struct userfs_rmdir_response_s *resp;
  1394. ssize_t nsent;
  1395. ssize_t nrecvd;
  1396. int pathlen;
  1397. int ret;
  1398. DEBUGASSERT(mountpt != NULL &&
  1399. mountpt->i_private != NULL);
  1400. priv = mountpt->i_private;
  1401. /* Check the path length */
  1402. DEBUGASSERT(relpath != NULL);
  1403. pathlen = strlen(relpath);
  1404. if (pathlen > priv->mxwrite)
  1405. {
  1406. return -E2BIG;
  1407. }
  1408. /* Get exclusive access */
  1409. ret = nxsem_wait(&priv->exclsem);
  1410. if (ret < 0)
  1411. {
  1412. return ret;
  1413. }
  1414. /* Construct and send the request to the server */
  1415. req = (FAR struct userfs_rmdir_request_s *)priv->iobuffer;
  1416. req->req = USERFS_REQ_RMDIR;
  1417. strncpy(req->relpath, relpath, priv->mxwrite);
  1418. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1419. SIZEOF_USERFS_RMDIR_REQUEST_S(pathlen + 1), 0,
  1420. (FAR struct sockaddr *)&priv->server,
  1421. sizeof(struct sockaddr_in));
  1422. if (nsent < 0)
  1423. {
  1424. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1425. nxsem_post(&priv->exclsem);
  1426. return (int)nsent;
  1427. }
  1428. /* Then get the response from the server */
  1429. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1430. 0, NULL, NULL);
  1431. nxsem_post(&priv->exclsem);
  1432. if (nrecvd < 0)
  1433. {
  1434. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1435. return (int)nrecvd;
  1436. }
  1437. if (nrecvd != sizeof(struct userfs_rmdir_response_s))
  1438. {
  1439. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1440. return -EIO;
  1441. }
  1442. resp = (FAR struct userfs_rmdir_response_s *)priv->iobuffer;
  1443. if (resp->resp != USERFS_RESP_RMDIR)
  1444. {
  1445. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1446. return -EIO;
  1447. }
  1448. return resp->ret;
  1449. }
  1450. /****************************************************************************
  1451. * Name: userfs_rename
  1452. *
  1453. * Description:
  1454. * Rename a directory entry
  1455. *
  1456. ****************************************************************************/
  1457. static int userfs_rename(FAR struct inode *mountpt,
  1458. FAR const char *oldrelpath,
  1459. FAR const char *newrelpath)
  1460. {
  1461. FAR struct userfs_state_s *priv;
  1462. FAR struct userfs_rename_request_s *req;
  1463. FAR struct userfs_rename_response_s *resp;
  1464. int oldpathlen;
  1465. int newpathlen;
  1466. ssize_t nsent;
  1467. ssize_t nrecvd;
  1468. int ret;
  1469. DEBUGASSERT(mountpt != NULL &&
  1470. mountpt->i_private != NULL);
  1471. priv = mountpt->i_private;
  1472. /* Check the path lengths */
  1473. DEBUGASSERT(oldrelpath != NULL && newrelpath != NULL);
  1474. oldpathlen = strlen(oldrelpath) + 1;
  1475. newpathlen = strlen(newrelpath) + 1;
  1476. if ((oldpathlen + newpathlen) > priv->mxwrite)
  1477. {
  1478. return -E2BIG;
  1479. }
  1480. /* Get exclusive access */
  1481. ret = nxsem_wait(&priv->exclsem);
  1482. if (ret < 0)
  1483. {
  1484. return ret;
  1485. }
  1486. /* Construct and send the request to the server */
  1487. req = (FAR struct userfs_rename_request_s *)priv->iobuffer;
  1488. req->req = USERFS_REQ_RENAME;
  1489. req->newoffset = oldpathlen;
  1490. strncpy(req->oldrelpath, oldrelpath, oldpathlen);
  1491. strncpy(&req->oldrelpath[oldpathlen], newrelpath, newpathlen);
  1492. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1493. SIZEOF_USERFS_RENAME_REQUEST_S(oldpathlen, newpathlen),
  1494. 0, (FAR struct sockaddr *)&priv->server,
  1495. sizeof(struct sockaddr_in));
  1496. if (nsent < 0)
  1497. {
  1498. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1499. nxsem_post(&priv->exclsem);
  1500. return (int)nsent;
  1501. }
  1502. /* Then get the response from the server */
  1503. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1504. 0, NULL, NULL);
  1505. nxsem_post(&priv->exclsem);
  1506. if (nrecvd < 0)
  1507. {
  1508. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1509. return (int)nrecvd;
  1510. }
  1511. if (nrecvd != sizeof(struct userfs_rename_response_s))
  1512. {
  1513. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1514. return -EIO;
  1515. }
  1516. resp = (FAR struct userfs_rename_response_s *)priv->iobuffer;
  1517. if (resp->resp != USERFS_RESP_RENAME)
  1518. {
  1519. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1520. return -EIO;
  1521. }
  1522. return resp->ret;
  1523. }
  1524. /****************************************************************************
  1525. * Name: userfs_stat
  1526. *
  1527. * Description:
  1528. * Return information about a file or directory
  1529. *
  1530. ****************************************************************************/
  1531. static int userfs_stat(FAR struct inode *mountpt, FAR const char *relpath,
  1532. FAR struct stat *buf)
  1533. {
  1534. FAR struct userfs_state_s *priv;
  1535. FAR struct userfs_stat_request_s *req;
  1536. FAR struct userfs_stat_response_s *resp;
  1537. ssize_t nsent;
  1538. ssize_t nrecvd;
  1539. int pathlen;
  1540. int ret;
  1541. DEBUGASSERT(mountpt != NULL &&
  1542. mountpt->i_private != NULL);
  1543. priv = mountpt->i_private;
  1544. /* Check the path length */
  1545. DEBUGASSERT(relpath != NULL);
  1546. pathlen = strlen(relpath);
  1547. if (pathlen > priv->mxwrite)
  1548. {
  1549. return -E2BIG;
  1550. }
  1551. /* Get exclusive access */
  1552. ret = nxsem_wait(&priv->exclsem);
  1553. if (ret < 0)
  1554. {
  1555. return ret;
  1556. }
  1557. /* Construct and send the request to the server */
  1558. req = (FAR struct userfs_stat_request_s *)priv->iobuffer;
  1559. req->req = USERFS_REQ_STAT;
  1560. strncpy(req->relpath, relpath, priv->mxwrite);
  1561. nsent = psock_sendto(&priv->psock, priv->iobuffer,
  1562. SIZEOF_USERFS_STAT_REQUEST_S(pathlen + 1), 0,
  1563. (FAR struct sockaddr *)&priv->server,
  1564. sizeof(struct sockaddr_in));
  1565. if (nsent < 0)
  1566. {
  1567. ferr("ERROR: psock_sendto failed: %d\n", (int)nsent);
  1568. nxsem_post(&priv->exclsem);
  1569. return (int)nsent;
  1570. }
  1571. /* Then get the response from the server */
  1572. nrecvd = psock_recvfrom(&priv->psock, priv->iobuffer, IOBUFFER_SIZE(priv),
  1573. 0, NULL, NULL);
  1574. nxsem_post(&priv->exclsem);
  1575. if (nrecvd < 0)
  1576. {
  1577. ferr("ERROR: psock_recvfrom failed: %d\n", (int)nrecvd);
  1578. return (int)nrecvd;
  1579. }
  1580. if (nrecvd != sizeof(struct userfs_stat_response_s))
  1581. {
  1582. ferr("ERROR: Response size incorrect: %u\n", (unsigned int)nrecvd);
  1583. return -EIO;
  1584. }
  1585. resp = (FAR struct userfs_stat_response_s *)priv->iobuffer;
  1586. if (resp->resp != USERFS_RESP_STAT)
  1587. {
  1588. ferr("ERROR: Incorrect response: %u\n", resp->resp);
  1589. return -EIO;
  1590. }
  1591. /* Return the directory entry status */
  1592. DEBUGASSERT(buf != NULL);
  1593. memcpy(buf, &resp->buf, sizeof(struct stat));
  1594. return resp->ret;
  1595. }
  1596. /****************************************************************************
  1597. * Public Functions
  1598. ****************************************************************************/