Skip to content

Instantly share code, notes, and snippets.

@danielcompton danielcompton/ext.clj
Last active Mar 12, 2018

What would you like to do?
Extended attributes in Clojure
(defn supports-extended-attributes?
"Not all filesystems suport Java's UserDefinedFileAttributes (a.k.a. extended attributes),
notably HFS+ and APFS on macOS.
Waiting for to add macOS support."
[^Path path]
(Files/getFileStore path)
^Class UserDefinedFileAttributeView))
(defn ^UserDefinedFileAttributeView get-user-defined-attribute-view [path]
(into-array LinkOption [])))
(def checksum-attribute-name "user.checksum")
(defn get-attribute [path attribute]
(let [view (get-user-defined-attribute-view path)
name attribute
size (.size view name)
attr-buf (ByteBuffer/allocate size)]
(.read view name attr-buf)
(.flip attr-buf)
(str (.decode (Charset/defaultCharset) attr-buf)))
(catch FileSystemException e
(defn set-attribute [path attribute ^String value]
(let [view (get-user-defined-attribute-view path)]
(.write view attribute (.encode (Charset/defaultCharset) value))))
(defn add-file-etag
"Adds an etag for a Ring response which contains a File as the body.
If extended-attributes? is true, then the File is checked for a checksum
and if it doesn't exist then it is added to the file as an extended attribute."
[response extended-attributes?]
(let [file (:body response)]
(if (instance? File file)
(let [path (.toPath file)]
(if extended-attributes?
(if-let [checksum (get-attribute path checksum-attribute-name)]
(response/header response "ETag" checksum)
(let [checksum (checksum-file file)]
(set-attribute path checksum-attribute-name (str checksum))
(response/header response "ETag" checksum)))
(response/header response "ETag" (checksum-file file))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.