1
0

vfs.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /* Copyright (C) 2013 by John Cronin <jncronin@tysos.org>
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. * The above copyright notice and this permission notice shall be included in
  10. * all copies or substantial portions of the Software.
  11. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. * THE SOFTWARE.
  18. */
  19. #include "vfs.h"
  20. #include "errno.h"
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include "output.h"
  25. static struct vfs_entry *first = (void*)0;
  26. static struct vfs_entry *def = (void*)0;
  27. #define MAX_DEV_NAMES 256
  28. static char *device_names[MAX_DEV_NAMES] = { 0 };
  29. static int next_dev_name = 0;
  30. static void vfs_add(struct vfs_entry *ve)
  31. {
  32. ve->next = first;
  33. first = ve;
  34. if(next_dev_name < (MAX_DEV_NAMES - 1))
  35. {
  36. device_names[next_dev_name] = ve->device_name;
  37. device_names[next_dev_name + 1] = 0;
  38. next_dev_name++;
  39. }
  40. }
  41. char **vfs_get_device_list()
  42. {
  43. return device_names;
  44. }
  45. static struct vfs_entry *find_ve(const char *path)
  46. {
  47. struct vfs_entry *cur = first;
  48. while(cur)
  49. {
  50. if(!strcmp(cur->device_name, path))
  51. return cur;
  52. cur = cur->next;
  53. }
  54. return (void *)0;
  55. }
  56. int vfs_set_default(char *dev_name)
  57. {
  58. struct vfs_entry *dev = find_ve(dev_name);
  59. if(dev)
  60. {
  61. def = dev;
  62. return 0;
  63. }
  64. return -1;
  65. }
  66. static void free_split_dir(char **sp)
  67. {
  68. char **s = sp;
  69. while(*s)
  70. {
  71. free(*s);
  72. s++;
  73. }
  74. free(sp);
  75. }
  76. static void free_dirent_list(struct dirent *d)
  77. {
  78. while(d)
  79. {
  80. struct dirent *tmp = d;
  81. d = d->next;
  82. free(tmp);
  83. }
  84. }
  85. static char **split_dir(const char *path, struct vfs_entry **ve)
  86. {
  87. int dir_start = 0;
  88. int dir_count = 0;
  89. // First iterate through counting the number of directories
  90. int slen = strlen(path);
  91. int reading_dev = 0;
  92. *ve = def;
  93. for(int i = 0; i < slen; i++)
  94. {
  95. if(path[i] == '(')
  96. {
  97. if(i == 0)
  98. reading_dev = 1;
  99. else
  100. {
  101. printf("VFS: dir parse error, invalid '(' in %s position %i\n",
  102. path, i);
  103. return (void*)0;
  104. }
  105. }
  106. else if(path[i] == ')')
  107. {
  108. if(!reading_dev)
  109. {
  110. printf("VFS: dir parse error, invalid ')' in %s position %i\n",
  111. path, i);
  112. return (void*)0;
  113. }
  114. // The device name runs from position 1 to 'i'
  115. char *dev_name = (char *)malloc(i);
  116. strncpy(dev_name, &path[1], i - 1);
  117. dev_name[i - 1] = 0;
  118. *ve = find_ve(dev_name);
  119. reading_dev = 0;
  120. dir_start = i + 1;
  121. }
  122. else if(path[i] == '/')
  123. {
  124. if(reading_dev)
  125. {
  126. printf("VFS: dir parse error, invalid '/' in device name in %s "
  127. "at position %i\n", path, i);
  128. return (void*)0;
  129. }
  130. if(i != (dir_start))
  131. dir_count++;
  132. else
  133. dir_start++;
  134. }
  135. else if(i == (slen - 1))
  136. dir_count++;
  137. }
  138. if(*ve == (void*)0)
  139. {
  140. printf("VFS: unable to determine device name when parsing %s\n", path);
  141. return (void*)0;
  142. }
  143. // Now iterate through again assigning to the path array
  144. int cur_dir = 0;
  145. char **ret = (char **)malloc((dir_count + 1) * sizeof(char *));
  146. ret[dir_count] = 0; // null terminate
  147. int cur_idx = dir_start;
  148. int cur_dir_start = dir_start;
  149. while(cur_dir < dir_count)
  150. {
  151. while((path[cur_idx] != '/') && (path[cur_idx] != 0))
  152. cur_idx++;
  153. // Found a '/'
  154. int path_bit_length = cur_idx - cur_dir_start;
  155. char *pb = (char *)malloc((path_bit_length + 1) * sizeof(char));
  156. for(int i = 0; i < path_bit_length; i++)
  157. pb[i] = path[cur_dir_start + i];
  158. pb[path_bit_length] = 0;
  159. cur_idx++;
  160. cur_dir_start = cur_idx;
  161. ret[cur_dir++] = pb;
  162. }
  163. return ret;
  164. }
  165. int vfs_register(struct fs *fs)
  166. {
  167. if(fs == (void *)0)
  168. return -1;
  169. if(fs->parent == (void *)0)
  170. return -1;
  171. struct vfs_entry *ve = (struct vfs_entry *)malloc(sizeof(struct vfs_entry));
  172. memset(ve, 0, sizeof(struct vfs_entry));
  173. ve->device_name = fs->parent->device_name;
  174. ve->fs = fs;
  175. vfs_add(ve);
  176. if(def == (void*)0)
  177. def = ve;
  178. return 0;
  179. }
  180. void vfs_list_devices()
  181. {
  182. struct vfs_entry *cur = first;
  183. while(cur)
  184. {
  185. printf("%s(%s) ", cur->device_name, cur->fs->fs_name);
  186. cur = cur->next;
  187. }
  188. }
  189. static struct dirent *read_directory(const char *path)
  190. {
  191. char **p;
  192. struct vfs_entry *ve;
  193. p = split_dir(path, &ve);
  194. if(p == (void *)0)
  195. return (void *)0;
  196. struct dirent *ret = ve->fs->read_directory(ve->fs, p);
  197. free_split_dir(p);
  198. return ret;
  199. }
  200. /*
  201. DIR *opendir(const char *name)
  202. {
  203. struct dirent *ret = read_directory(name);
  204. if(ret == (void*)0)
  205. return (void*)0;
  206. struct dir_info *di = (struct dir_info *)malloc(sizeof(struct dir_info));
  207. di->first = ret;
  208. di->next = ret;
  209. return di;
  210. }
  211. struct dirent *readdir(DIR *dirp)
  212. {
  213. if(dirp == (void*)0)
  214. return (void*)0;
  215. struct dirent *ret = dirp->next;
  216. if(dirp->next)
  217. dirp->next = dirp->next->next;
  218. return ret;
  219. }
  220. int closedir(DIR *dirp)
  221. {
  222. if(dirp)
  223. {
  224. if(dirp->first)
  225. free_dirent_list(dirp->first);
  226. free(dirp);
  227. return 0;
  228. }
  229. else
  230. return -1;
  231. }
  232. size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
  233. {
  234. if(stream == (void *)0)
  235. return 0;
  236. size_t bytes_to_read = size * nmemb;
  237. if(bytes_to_read > (size_t)(stream->len - stream->pos))
  238. bytes_to_read = (size_t)(stream->len - stream->pos);
  239. size_t nmemb_to_read = bytes_to_read / size;
  240. bytes_to_read = nmemb_to_read * size;
  241. bytes_to_read = stream->fs->fread(stream->fs, ptr, bytes_to_read, stream);
  242. return bytes_to_read / size;
  243. }
  244. size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream)
  245. {
  246. if(stream == NULL)
  247. {
  248. errno = EINVAL;
  249. return 0;
  250. }
  251. size_t bytes_to_write = size * nmemb;
  252. if((stream == stdout) || (stream == stderr))
  253. {
  254. uint8_t *c_buf = (uint8_t *)ptr;
  255. for(size_t i = 0; i < bytes_to_write; i++)
  256. split_putc((char)c_buf[i]);
  257. }
  258. else
  259. {
  260. size_t nmemb_to_write = bytes_to_write / size;
  261. bytes_to_write = nmemb_to_write * size;
  262. if(stream->fs->fwrite == NULL)
  263. {
  264. errno = EROFS;
  265. return 0;
  266. }
  267. bytes_to_write = stream->fs->fwrite(stream->fs, ptr, bytes_to_write, stream);
  268. }
  269. return bytes_to_write / size;
  270. }
  271. int fflush(FILE *fp)
  272. {
  273. if(fp == NULL)
  274. {
  275. errno = EINVAL;
  276. return -1;
  277. }
  278. if(fp->fflush_cb)
  279. fp->fflush_cb(fp);
  280. if(fp->fs->fflush)
  281. fp->fs->fflush(fp);
  282. return 0;
  283. }
  284. int fclose(FILE *fp)
  285. {
  286. if(fp == NULL)
  287. {
  288. errno = EINVAL;
  289. return -1;
  290. }
  291. fflush(fp);
  292. if(fp->fs->fclose)
  293. fp->fs->fclose(fp->fs, fp);
  294. free(fp);
  295. return 0;
  296. }
  297. int feof(FILE *stream)
  298. {
  299. if(!stream)
  300. {
  301. errno = EINVAL;
  302. return -1;
  303. }
  304. if(stream->flags & VFS_FLAGS_EOF)
  305. return 1;
  306. else
  307. return 0;
  308. }
  309. int ferror(FILE *stream)
  310. {
  311. if(!stream)
  312. {
  313. errno = EINVAL;
  314. return -1;
  315. }
  316. if(stream->flags & VFS_FLAGS_ERROR)
  317. return 1;
  318. else
  319. return 0;
  320. }
  321. long fsize(FILE *stream)
  322. {
  323. if(!stream)
  324. {
  325. errno = EINVAL;
  326. return -1;
  327. }
  328. if(stream->fs->fsize)
  329. return stream->fs->fsize(stream);
  330. else
  331. return stream->len;
  332. }
  333. long ftell(FILE *stream)
  334. {
  335. if(!stream)
  336. {
  337. errno = EINVAL;
  338. return -1;
  339. }
  340. if(stream->fs->ftell)
  341. return stream->fs->ftell(stream);
  342. else
  343. return stream->pos;
  344. }
  345. int fseek(FILE *stream, long offset, int whence)
  346. {
  347. if(!stream)
  348. {
  349. errno = EINVAL;
  350. return -1;
  351. }
  352. if(stream->fs->fseek)
  353. return stream->fs->fseek(stream, offset, whence);
  354. switch(whence)
  355. {
  356. case SEEK_SET:
  357. stream->pos = offset;
  358. break;
  359. case SEEK_END:
  360. stream->pos = stream->len - offset;
  361. break;
  362. case SEEK_CUR:
  363. stream->pos += offset;
  364. break;
  365. default:
  366. return -1;
  367. }
  368. if(stream->pos < 0)
  369. stream->pos = 0;
  370. if(stream->pos > stream->len)
  371. stream->pos = stream->len;
  372. return 0;
  373. }
  374. FILE *fopen(const char *path, const char *mode)
  375. {
  376. char **p;
  377. struct vfs_entry *ve;
  378. if(path == (void *)0)
  379. {
  380. errno = EFAULT;
  381. return (void*)0;
  382. }
  383. p = split_dir(path, &ve);
  384. if(p == (void *)0)
  385. {
  386. errno = EFAULT;
  387. return (void *)0;
  388. }
  389. if((NULL == p[0]) || (!strcmp(p[0], ":")))
  390. {
  391. free_split_dir(p);
  392. // These represent attempts to open the whole device as a single file
  393. // We can only do this if the filesystem allows it
  394. if(ve->fs->flags & FS_FLAG_SUPPORTS_EMPTY_FNAME)
  395. return ve->fs->fopen(ve->fs, NULL, mode);
  396. else
  397. {
  398. errno = EFAULT;
  399. return NULL;
  400. }
  401. }
  402. // Trim off the last entry
  403. char **p_iter = p;
  404. while(*p_iter)
  405. p_iter++;
  406. char *fname = p[(p_iter - p) - 1];
  407. p[(p_iter - p) - 1] = 0;
  408. // Read the containing directory
  409. struct dirent *dir = ve->fs->read_directory(ve->fs, p);
  410. struct dirent *dir_start = dir;
  411. if(dir == (void*)0)
  412. {
  413. free_split_dir(p);
  414. free(fname);
  415. return (void*)0;
  416. }
  417. struct dirent *file = (void *)0;
  418. while(dir)
  419. {
  420. if(!strcmp(dir->name, fname))
  421. {
  422. file = dir;
  423. break;
  424. }
  425. dir = dir->next;
  426. }
  427. free_split_dir(p);
  428. free(fname);
  429. if(!file)
  430. {
  431. free_dirent_list(dir_start);
  432. return (void*)0;
  433. }
  434. // Read the file
  435. FILE *ret = ve->fs->fopen(ve->fs, file, mode);
  436. free_dirent_list(dir_start);
  437. return ret;
  438. }
  439. */