class.lisp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. (in-package :hurd-tree-translator)
  2. ;;
  3. ;; This file contains a special kind of translator:
  4. ;; the tree-translator
  5. ;; It implements without much hassle the directory callbacks
  6. ;; and maintains a structured directory hierarchy.
  7. ;;
  8. (defclass tree-translator (translator)
  9. ((name :initform "tree-translator"
  10. :documentation "Translator name"))
  11. (:documentation "The tree-translator."))
  12. (defmethod propagate-read-to-execute ((stat stat))
  13. "Enables the execute permission bit if the read bit is on."
  14. (if (has-perms-p stat :read :owner)
  15. (set-perms stat :exec :owner))
  16. (if (has-perms-p stat :read :group)
  17. (set-perms stat :exec :group))
  18. (if (has-perms-p stat :read :others)
  19. (set-perms stat :exec :others))
  20. t)
  21. ;; It ensures the root node is a directory
  22. ;; and calls the function fill-root-node to fill the directory
  23. ;; structure.
  24. (define-callback make-root-node tree-translator
  25. (underlying-node underlying-stat)
  26. (declare (ignore underlying-node))
  27. (when (not (is-dir-p underlying-stat))
  28. (propagate-read-to-execute underlying-stat))
  29. (set-trans underlying-stat nil)
  30. (let ((obj (make-instance 'dir-entry
  31. :stat underlying-stat)))
  32. (setf (stat-get (stat obj) 'st-nlink) 2)
  33. (fill-root-node translator obj)
  34. obj))
  35. (define-callback fill-root-node tree-translator
  36. ((root dir-entry))
  37. "This should be used to construct the directory structure. 'root' is the newly created
  38. root node."
  39. nil)
  40. (define-callback directory-lookup tree-translator
  41. (node user filename)
  42. (unless (has-access-p node user :read)
  43. (return-from directory-lookup nil))
  44. (let ((found (cond
  45. ((string= filename ".") node)
  46. ((string= filename "..") (parent node))
  47. (t (get-entry node filename)))))
  48. (when (and found
  49. (has-access-p found user :read))
  50. found)))
  51. (define-callback number-of-entries tree-translator
  52. (node user)
  53. (cond
  54. ((has-access-p node user :read)
  55. (dir-size node))
  56. (t 0)))
  57. (defun not-permitted-entries-p (name)
  58. (or (string= name ".")
  59. (string= name "..")))
  60. (define-callback get-entries tree-translator
  61. (node user start end)
  62. (unless (has-access-p node user :read)
  63. (return-from get-entries nil))
  64. (let* (return-list
  65. (real-start (max 0 (- start 2))))
  66. (when (and (<= start 1) (>= end 1))
  67. (push (make-dirent ".." 1 :dir) return-list))
  68. (when (= start 0)
  69. (push (make-node-dirent "." node) return-list))
  70. (append return-list
  71. (mapcar (lambda (inner-entry)
  72. (make-node-dirent (name inner-entry) (node inner-entry)))
  73. (get-dir-entries node
  74. real-start
  75. (- (1- end) real-start))))))
  76. (define-callback create-directory tree-translator
  77. (node user name mode)
  78. (when (not-permitted-entries-p name)
  79. (return-from create-directory nil))
  80. (unless (is-owner-p node user)
  81. (return-from create-directory nil))
  82. (let ((old (get-entry node name)))
  83. (cond
  84. (old nil)
  85. (t
  86. (add-entry node (make-instance
  87. 'dir-entry
  88. :stat (make-stat (stat node) :mode mode)
  89. :parent node)
  90. name)))))
  91. (define-callback remove-directory-entry tree-translator
  92. (node user name)
  93. (when (not-permitted-entries-p name)
  94. (return-from remove-directory-entry nil))
  95. (let ((found (get-entry node name)))
  96. (when found
  97. (when (is-owner-p found user)
  98. (cond
  99. ((and (is-dir-p (stat found))
  100. (plusp (- (dir-size found) 2)))
  101. :directory-not-empty)
  102. (t
  103. (remove-dir-entry node name)))))))
  104. (define-callback create-hard-link tree-translator
  105. (dir user file name)
  106. (when (not-permitted-entries-p name)
  107. (return-from create-hard-link nil))
  108. (when (is-owner-p dir user)
  109. (add-entry dir file name)
  110. t))
  111. (define-callback file-rename tree-translator
  112. (user old-dir old-name new-dir new-name)
  113. (when (not-permitted-entries-p new-name)
  114. (return-from file-rename nil))
  115. (let ((old-entry (get-entry old-dir old-name)))
  116. (when (and (is-owner-p old-entry user)
  117. (is-owner-p new-dir user)
  118. (has-access-p new-dir user :write))
  119. (rename-dir-entry old-dir old-name new-dir new-name t)
  120. t)))