+/*
+ * If the file at @path has Linux-style extended attributes, read them into
+ * memory and add them to @inode as a tagged item.
+ */
+static noinline_for_stack int
+scan_linux_xattrs(const char *path, struct wim_inode *inode)
+{
+ char _names[256];
+ char *names = _names;
+ ssize_t names_size = ARRAY_LEN(_names);
+ int ret = 0;
+
+retry:
+ /* Gather the names of the xattrs of the file at @path */
+ names_size = llistxattr(path, names, names_size);
+ if (names_size == 0) /* No xattrs? */
+ goto out;
+ if (names_size < 0) {
+ /* xattrs unsupported or disabled? */
+ if (errno == ENOTSUP || errno == ENOSYS)
+ goto out;
+ if (errno == ERANGE) {
+ /*
+ * Not enough space in @names. Ask for how much space
+ * we need, then try again.
+ */
+ names_size = llistxattr(path, NULL, 0);
+ if (names_size == 0)
+ goto out;
+ if (names_size > 0) {
+ if (names != _names)
+ FREE(names);
+ names = MALLOC(names_size);
+ if (!names) {
+ ret = WIMLIB_ERR_NOMEM;
+ goto out;
+ }
+ goto retry;
+ }
+ }
+ /* Some other error occurred. */
+ ERROR_WITH_ERRNO("\"%s\": unable to list extended attributes",
+ path);
+ ret = WIMLIB_ERR_STAT;
+ goto out;
+ }
+
+ /*
+ * We have a nonempty list of xattr names. Gather the xattr values and
+ * add them as a tagged item.
+ */
+ ret = create_xattr_item(path, inode, names, names_size);
+out:
+ if (names != _names)
+ FREE(names);
+ return ret;
+}
+#endif /* HAVE_XATTR_SUPPORT */
+
+static int
+unix_scan_regular_file(const char *path, u64 blocks, u64 size,
+ struct wim_inode *inode,
+ struct list_head *unhashed_blobs)
+{
+ struct blob_descriptor *blob = NULL;
+ struct wim_inode_stream *strm;
+
+ /*
+ * Set FILE_ATTRIBUTE_SPARSE_FILE if the file uses less disk space than
+ * expected given its size.
+ */
+ if (blocks < DIV_ROUND_UP(size, 512))
+ inode->i_attributes = FILE_ATTRIBUTE_SPARSE_FILE;
+ else
+ inode->i_attributes = FILE_ATTRIBUTE_NORMAL;
+
+ if (size) {
+ blob = new_blob_descriptor();
+ if (unlikely(!blob))
+ goto err_nomem;
+ blob->file_on_disk = STRDUP(path);
+ if (unlikely(!blob->file_on_disk))
+ goto err_nomem;
+ blob->blob_location = BLOB_IN_FILE_ON_DISK;
+ blob->size = size;
+ blob->file_inode = inode;