dir-lookup.lisp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. (in-package :hurd-translator)
  2. ;; Functions used to verify circular links.
  3. (defun %has-node-p (table node)
  4. (multiple-value-bind (foo found-p)
  5. (gethash node table)
  6. (declare (ignore foo))
  7. found-p))
  8. (defun %put-node (table node)
  9. (setf (gethash node table) nil)
  10. table)
  11. (defun %create-new-protid (open-node user node flags newnode-p)
  12. (let* ((new-flags (disable-flags flags +open-create-flags+))
  13. (allow-ret (allow-open-p *translator* node user new-flags newnode-p)))
  14. (cond
  15. ((eq t allow-ret)
  16. (when (flag-is-p flags :trunc)
  17. (unless (file-change-size *translator* node user 0)
  18. (return-from %create-new-protid :not-permitted)))
  19. (let* ((new-user (make-iouser :old user))
  20. (new-open-node (make-open-node
  21. node
  22. new-flags
  23. :copy open-node))
  24. (new-protid
  25. (new-protid *translator*
  26. new-user
  27. new-open-node)))
  28. (values :retry-normal
  29. ""
  30. (get-right new-protid)
  31. :make-send)))
  32. ((eq nil allow-ret) :not-permitted)
  33. (t allow-ret))))
  34. (defun %must-handle-shadow-roots (open-node node this-path)
  35. (and (or (eq (root *translator*) node)
  36. (eq (shadow-root open-node) node))
  37. (string= this-path "..")
  38. (or (eq node (shadow-root open-node))
  39. (port-valid-p (root-parent open-node)))))
  40. (defun %handle-shadow-roots (open-node node rest-path)
  41. (cond
  42. ((eq node (shadow-root open-node))
  43. (values :retry-reauth
  44. (if (null rest-path)
  45. ""
  46. (join-path rest-path))
  47. (shadow-root-parent open-node)
  48. :copy-send))
  49. ((port-valid-p (root-parent open-node))
  50. (values :retry-reauth
  51. (if (null rest-path)
  52. ""
  53. (join-path rest-path))
  54. (root-parent open-node)
  55. :copy-send))))
  56. (defun %handle-symlinks (open-node user dir node rest-path flags mode table)
  57. (let ((target (link node)))
  58. (cond
  59. ((eq (char target 0) #\/) ; Points to root /!
  60. (values :retry-magical
  61. (concatenate-string target
  62. "/"
  63. (join-path rest-path))
  64. nil
  65. :make-send))
  66. (t
  67. ; Lookup new path based on the symlink target.
  68. (%dir-lookup open-node
  69. user
  70. dir
  71. (if (null rest-path)
  72. (split-path target)
  73. (append (remove "" (split-path target) :test #'string=)
  74. rest-path))
  75. (disable-flags flags :creat)
  76. mode
  77. (%put-node table node))))))
  78. (defun %must-handle-symlink (node user flags rest-path)
  79. (and node
  80. (is-lnk-p (stat node))
  81. (link node)
  82. (allow-link-p *translator* node user)
  83. (or rest-path
  84. (and (not (flag-is-p flags :nolink))
  85. (not (flag-is-p flags :notrans))))))
  86. (defun %must-handle-translator (node flags rest-path)
  87. (and (or (not (flag-is-p flags :notrans))
  88. rest-path) ; This is not the path end, so we must continue
  89. (box-translated-p (box node))))
  90. (defun %dir-lookup (open-node user node path-ls flags mode table)
  91. (let ((this-path (first path-ls))
  92. (rest-path (rest path-ls)))
  93. (when (string= this-path "") ; this is last path
  94. (return-from %dir-lookup
  95. (%create-new-protid open-node user node flags nil)))
  96. (when (%must-handle-shadow-roots open-node node this-path)
  97. (return-from %dir-lookup
  98. (%handle-shadow-roots open-node node rest-path)))
  99. (let ((found-node (directory-lookup *translator* node user this-path)))
  100. (cond
  101. (found-node ; File exists.
  102. (when (%must-handle-translator found-node flags rest-path)
  103. (let* ((empty-user (make-empty-iouser))
  104. (new-open-node (make-open-node node
  105. nil
  106. :copy open-node))
  107. (protid (new-protid *translator* empty-user new-open-node))
  108. (*current-dotdot* (get-send-right protid))
  109. (*current-node* found-node))
  110. (multiple-value-bind (retry retry-name port)
  111. (fetch-root (box found-node)
  112. *current-dotdot*
  113. (if rest-path flags nil)
  114. user
  115. #'get-translator-callback
  116. (callback fetch-root-callback))
  117. (unless (or (eq retry :no-such-file)
  118. (null retry))
  119. (return-from %dir-lookup
  120. (values retry
  121. (concatenate-string retry-name
  122. "/"
  123. (join-path rest-path))
  124. port
  125. :move-send))))))
  126. (cond
  127. ((and (flag-is-p flags :creat)
  128. (flag-is-p flags :excl))
  129. :file-exists)
  130. ((%must-handle-symlink found-node user flags rest-path)
  131. (if (%has-node-p table found-node)
  132. :too-many-links
  133. (%handle-symlinks open-node user node found-node rest-path flags mode table)))
  134. ((null rest-path)
  135. (%create-new-protid open-node user found-node flags nil))
  136. ((and rest-path
  137. (not (is-dir-p (stat found-node))))
  138. :not-directory)
  139. (t
  140. (%dir-lookup open-node user found-node rest-path flags mode table))))
  141. ; File does not exist.
  142. (t
  143. (cond
  144. ((and (flag-is-p flags :creat)
  145. (null rest-path))
  146. (set-vtx mode nil)
  147. (set-spare mode nil)
  148. (set-type mode :reg)
  149. (let ((new-node (create-file *translator*
  150. node
  151. user
  152. this-path
  153. mode)))
  154. (unless new-node
  155. (return-from %dir-lookup :not-permitted))
  156. (%create-new-protid open-node user new-node flags t)))
  157. (t
  158. :no-such-file)))))))
  159. (%add-callback do-dir-lookup (filename protid flags mode)
  160. "Lookup filename in protid with 'flags' and creation 'mode'.
  161. Must return four things:
  162. Type of retry.
  163. Filename to retry.
  164. Retry port.
  165. Retry port type.
  166. "
  167. (cond
  168. ((and (not (string= "" filename))
  169. (eq (char filename 0) #\/))
  170. (values :retry-magical
  171. filename
  172. nil
  173. :make-send))
  174. (t
  175. (%dir-lookup (open-node protid)
  176. (get-user protid)
  177. (get-node protid)
  178. (split-path filename)
  179. flags
  180. mode
  181. (make-hash-table)))))
  182. (def-fs-interface :dir-lookup ((dir-port port)
  183. (filename :string)
  184. (flags open-flags)
  185. (mode mode-t)
  186. (do-retry :pointer)
  187. (retry-name :pointer)
  188. (retry-port port-pointer)
  189. (retry-port-type :pointer))
  190. (with-lookup dir-protid dir-port
  191. (multiple-value-bind (ret-do-retry
  192. ret-retry-name
  193. ret-retry-port
  194. ret-retry-port-type)
  195. (do-dir-lookup *translator*
  196. filename
  197. dir-protid
  198. flags
  199. mode)
  200. (cond
  201. ((null ret-retry-name) ret-do-retry) ;; Some error ocurred
  202. (t
  203. (setf (mem-ref do-retry 'retry-type) ret-do-retry)
  204. (lisp-string-to-foreign ret-retry-name
  205. retry-name
  206. (1+ (length ret-retry-name)))
  207. (setf (mem-ref retry-port 'port) ret-retry-port)
  208. (setf (mem-ref retry-port-type 'msg-type-name) ret-retry-port-type)
  209. t)))))