Skip to content

ltfs_ordered_copy: preserve directory attributes (#392) - #658

Open
MitchelTighe wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
MitchelTighe:fix/ordered-copy-folder-attrs-392
Open

MitchelTighe wants to merge 2 commits into
LinearTapeFileSystem:mainfrom
MitchelTighe:fix/ordered-copy-folder-attrs-392

Conversation

@MitchelTighe

@MitchelTighe MitchelTighe commented Oct 15, 2026 •

Copy link
Copy Markdown

Fixes #392

ltfs_ordered_copy creates destination directories with os.mkdir() only, so even with -p or -a every copied directory gets the current time and the umask default mode, and its extended attributes are dropped.

Change

  • While walking the source tree, remember each source/destination directory pair.
  • After all files have been copied, apply the attributes with shutil.copystat(), plus the xattrs when -a is given.
    • This has to happen after the copy, because writing a file updates the mtime of the directory that contains it.
    • It runs deepest first, because updating a child directory updates its parent.
  • Without -p/-a the behaviour is unchanged. A failure to copy one directory's attributes is logged as a warning and doesn't abort the copy.

Testing
I ran the tool against a small local harness, an on-disk source tree plus an xattr shim standing in for an LTFS volume, so no real tape was involved. These cases were checked:

  • -r -p on nested directories with distinct modes and mtimes: before the patch they got umask/now; after it they match the source.
  • An empty directory keeps its attributes.
  • Without -p, directories keep the default mode, as before.

Written with help from an AI assistant (Claude).

Update (second commit): after a closer review, three things were tightened:

  • A source given as dir/ or . copies its contents into DEST. In that case DEST's own attributes are now left alone; the first version overwrote them with the source directory's.
  • Directories are now processed deepest-destination-first, so a parent made read-only can't block its children when there are several sources.
  • Extended attributes are copied before copystat(), and an error from xattr.list() is logged as a warning instead of aborting the run.

Out of scope: intermediate directories created by --keep-tree (via os.makedirs()) still get default attributes. That's the same as current main, and it would be better handled separately.

…m#392)

Directories were created with os.mkdir() and nothing else, so even with
-p or -a every copied directory got the current time and the umask
default mode, and its extended attributes were dropped.

Remember each source/destination directory pair while walking the tree,
and once all files have been copied apply the attributes with
shutil.copystat() (plus the xattrs when -a is given).  This has to happen
after the copy, because writing a file updates the mtime of the directory
that contains it, and deepest first, because updating a child directory
updates its parent.

Without -p/-a the behaviour is unchanged.

Fixes LinearTapeFileSystem#392
@MitchelTighe
MitchelTighe marked this pull request as draft October 16, 2026 00:37
- Do not touch the attributes of DEST itself when the source is given as
  "dir/" or ".", which copy the contents of the directory into DEST.
- Order the directories by destination depth, not by source path length:
  with several sources the two can disagree, and a parent made read-only
  first blocks the update of its children.
- Copy extended attributes before copystat() makes a read-only directory
  read-only, and treat a failing xattr.list() as a warning like the other
  attribute failures instead of aborting the copy.
@MitchelTighe
MitchelTighe marked this pull request as ready for review October 16, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ltfs_ordered_copy not honoring folder attr

1 participant