/fs/vfs.c

https://gitlab.com/adam.lukaitis/osdev · C · 249 lines · 199 code · 14 blank · 36 comment · 47 complexity · 226cbd55f6b4a3af50edf67ee88b4c8e MD5 · raw file

  1. /** @author Levente Kurusa <levex@linux.com> **/
  2. #include <stdint.h>
  3. #include "../include/display.h"
  4. #include "../include/hal.h"
  5. #include "../include/mutex.h"
  6. #include "../include/tasking.h"
  7. #include "../include/device.h"
  8. #include "../include/vfs.h"
  9. #include "../include/proc.h"
  10. #include "../include/memory.h"
  11. #include "../include/string.h"
  12. #include "../include/ext2.h"
  13. #include "../include/devfs.h"
  14. MODULE("VFS");
  15. #define MAX_MOUNTS 16
  16. uint8_t __init_vfs = 0;
  17. mount_info_t **mount_points = 0;
  18. int last_mount_id = 0;
  19. device_t *check_mount(char *loc)
  20. {
  21. for(int i = 0; i < last_mount_id; i++)
  22. {
  23. if(strcmp(loc, mount_points[i]->loc) == 0)
  24. {
  25. return mount_points[i]->dev;
  26. }
  27. }
  28. return 0;
  29. }
  30. uint8_t list_mount()
  31. {
  32. for(int i = 0;i < MAX_MOUNTS;i ++)
  33. {
  34. if(!mount_points[i])break;
  35. kprintf("%s on %s type: %s\n", mount_points[i]->dev->name,
  36. mount_points[i]->loc, mount_points[i]->dev->fs->name);
  37. }
  38. return 1;
  39. }
  40. uint8_t device_try_to_mount(device_t *dev, char *loc)
  41. {
  42. if(!dev || !(dev->unique_id)) return 0;
  43. if(check_mount(loc)) return 0;
  44. if(ext2_probe(dev)) {
  45. if(ext2_mount(dev, dev->fs->priv_data))
  46. {
  47. mount_info_t *m = (mount_info_t *)malloc(sizeof(mount_info_t));
  48. m->loc = loc;
  49. m->dev = dev;
  50. last_mount_id++;
  51. mount_points[last_mount_id - 1] = m;
  52. return 1;
  53. }
  54. return 0;
  55. }
  56. if(procfs_probe(dev))
  57. {
  58. if(procfs_mount(dev, dev->fs->priv_data))
  59. {
  60. mount_info_t *m = (mount_info_t *)malloc(sizeof(mount_info_t));
  61. m->loc = loc;
  62. m->dev = dev;
  63. last_mount_id++;
  64. mount_points[last_mount_id - 1] = m;
  65. return 1;
  66. }
  67. return 0;
  68. }
  69. if(devfs_probe(dev))
  70. {
  71. if(devfs_mount(dev, dev->fs->priv_data))
  72. {
  73. mount_info_t *m = (mount_info_t *)malloc(sizeof(mount_info_t));
  74. m->loc = loc;
  75. m->dev = dev;
  76. last_mount_id++;
  77. mount_points[last_mount_id - 1] = m;
  78. return 1;
  79. }
  80. return 0;
  81. }
  82. return 0;
  83. }
  84. inline uint8_t __find_mount(char *filename, int *adjust)
  85. {
  86. char *orig = (char *)malloc(strlen(filename) + 1);
  87. memset(orig, 0, strlen(filename) + 1);
  88. memcpy(orig, filename, strlen(filename) + 1);
  89. if(orig[strlen(orig)] == '/') str_backspace(orig, '/');
  90. while(1)
  91. {
  92. for(int i = 0;i<MAX_MOUNTS; i++)
  93. {
  94. if(!mount_points[i]) break;
  95. if(strcmp(mount_points[i]->loc, orig) == 0)
  96. {
  97. /* Adjust the orig to make it relative to fs/dev */
  98. *adjust = (strlen(orig) - 1);
  99. /*kprintf("returning %s (%d) i=%d orig=%s adjust=%d\n", mount_points[i]->dev->name,
  100. mount_points[i]->dev->unique_id, i, orig, *adjust);*/
  101. free(orig);
  102. return i;
  103. }
  104. }
  105. if(strcmp(orig, "/") == 0)
  106. break;
  107. str_backspace(orig, '/');
  108. }
  109. return 0;
  110. }
  111. uint8_t vfs_read(char *filename, char *buffer)
  112. {
  113. /* Correct algorithm to resolve mounts:
  114. * In a loop remove until '/' and then look for match
  115. * if no match, continue until last '/' and then we know
  116. * it is on the root_device
  117. */
  118. int adjust = 0;
  119. int i = __find_mount(filename, &adjust);
  120. filename += adjust;
  121. //kprintf("Passing with adjust %d: %s\n", adjust, filename);
  122. int rc = mount_points[i]->dev->fs->read(filename, buffer,
  123. mount_points[i]->dev, mount_points[i]->dev->fs->priv_data);
  124. return rc;
  125. }
  126. uint32_t vfs_ls(char *dir, char* buffer)
  127. {
  128. /* Algorithm:
  129. * For each mount, backspace one, compare with 'dir'
  130. * if yes, print out its dir name!
  131. */
  132. char *orig = (char *)malloc(strlen(dir) + 1);
  133. memset(orig, 0, strlen(dir) + 1);
  134. memcpy(orig, dir, strlen(dir) + 1);
  135. while(1)
  136. {
  137. for(int i = 0; i < MAX_MOUNTS; i++)
  138. {
  139. if(!mount_points[i]) break;
  140. /* Backspace one, check if it equals dir, if so print DIR name */
  141. /* If the mount's location equals the backspaced location...*/
  142. if(strcmp(mount_points[i]->loc, orig) == 0)
  143. {
  144. /* Then adjust and send. */
  145. mount_points[i]->dev->fs->read_dir(dir + strlen(mount_points[i]->loc) - 1,
  146. buffer, mount_points[i]->dev, mount_points[i]->dev->fs->priv_data);
  147. /* Now, we have found who hosts this directory, look
  148. * for those that are mounted to this directory's host.
  149. */
  150. for(int k = 0; k < MAX_MOUNTS; k++)
  151. {
  152. if(!mount_points[k]) break;
  153. char *mount = (char *)malloc(strlen(mount_points[k]->loc) + 1);
  154. memcpy(mount, mount_points[k]->loc, strlen(mount_points[k]->loc) + 1);
  155. str_backspace(mount, '/');
  156. if(strcmp(mount, dir) == 0)
  157. {
  158. char *p = mount_points[k]->loc + strlen(dir);
  159. if(strlen(p) == 0 || strlen(p) == 1) continue;
  160. kprintf("%s\n", p);
  161. }
  162. free(mount);
  163. }
  164. break;
  165. }
  166. }
  167. if(strcmp(orig, "/") == 0) break;
  168. str_backspace(orig, '/');
  169. }
  170. free(orig);
  171. return 1;
  172. }
  173. uint8_t vfs_exist_in_dir(char *wd, char *fn)
  174. {
  175. char *filename = (char *)malloc(strlen(wd) + 2 + strlen(fn));
  176. memset(filename, 0, strlen(wd) + 2 + strlen(fn));
  177. memcpy(filename, wd, strlen(wd));
  178. memcpy(filename+strlen(wd), fn, strlen(fn));
  179. memset(filename+strlen(wd)+strlen(fn) + 1, '\0', 1);
  180. /* Algorithm:
  181. * For each mount, check if it is mounted to wd
  182. * If it is, return 1
  183. */
  184. /* @TODO: fix */
  185. if(filename[strlen(filename)] != '/')
  186. {
  187. uint32_t index = strlen(filename);
  188. filename[index] = '/';
  189. filename[index+1] = 0;
  190. }
  191. int rc = 0;
  192. char *o = (char *)malloc(strlen(filename) + 2);
  193. memset(o, 0, strlen(filename) + 2);
  194. memcpy(o, filename, strlen(filename) + 1);
  195. /*if(o[strlen(o)] != '/')
  196. {
  197. uint32_t index = strlen(o);
  198. o[index] = '/';
  199. o[index+1] = 0;
  200. }*/
  201. while(1)
  202. {
  203. for(int i = 0;i < MAX_MOUNTS; i++)
  204. {
  205. if(!mount_points[i]) break;
  206. //kprintf("Checking %s with %s\n", o, mount_points[i]->loc);
  207. if(strcmp(o, mount_points[i]->loc) == 0)
  208. {
  209. //kprintf("filename:%s\n", filename);
  210. //kprintf("strlen: %d str:%s\n",strlen(mount_points[i]->loc), mount_points[i]->loc );
  211. filename += strlen(mount_points[i]->loc) - 1;
  212. /*kprintf("Passing: %s fn:%s, wd:%s to %s (%d)\n", filename, fn, wd,
  213. mount_points[i]->dev->name, mount_points[i]->dev->unique_id);*/
  214. rc = mount_points[i]->dev->fs->exist(filename,
  215. mount_points[i]->dev, mount_points[i]->dev->fs->priv_data);
  216. free(o);
  217. free(filename);
  218. return rc;
  219. }
  220. }
  221. if(strcmp(o, "/") == 0)
  222. break;
  223. str_backspace(o, '/');
  224. }
  225. free(o);
  226. free(filename);
  227. return rc;
  228. }
  229. void vfs_init()
  230. {
  231. mprint("Loading VFS\n");
  232. mount_points = (mount_info_t **)malloc(sizeof(uint32_t) * MAX_MOUNTS);
  233. __init_vfs = 1;
  234. _kill();
  235. }