Skip to content

Commit

Permalink
Fix tar extraction issue where parent directories don't exist.
Browse files Browse the repository at this point in the history
Extracting LCOW layers to vhd fails when a file shows up in the
tar list before the parent directory of that file shows up. This change fixes that by
always creating any non existing parent directories and then updating their permissions
later when actual directory entry shows up.

Signed-off-by: Amit Barve <[email protected]>
  • Loading branch information
ambarve committed Mar 16, 2021
1 parent 5d9980c commit bdddc24
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
39 changes: 39 additions & 0 deletions ext4/internal/compactext4/compact.go
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,45 @@ func (w *Writer) lookup(name string, mustExist bool) (*inode, *inode, string, er
return dir, child, childname, nil
}

// CreateWithParents adds a file to the file system creating the parent directories in the path if
// they don't exist (like `mkdir -p`). These non existing parent directories are created
// with the same permissions as that of it's parent directory. It is expected that the a
// call to make these parent directories will be made at a later point with the correct
// permissions, at that time the permissions of these directories will be updated.
func (w *Writer) CreateWithParents(name string, f *File) error {
// go through the directories in the path one by one and create the
// parent directories if they don't exist.
cleanname := path.Clean("/" + name)[1:]
parentDirs, _ := path.Split(cleanname)
currentPath := ""
root := w.root()
dirname := ""
for parentDirs != "" {
dirname, parentDirs = splitFirst(parentDirs)
currentPath += "/" + dirname
if _, ok := root.Children[dirname]; !ok {
f := &File{
Mode: root.Mode,
Atime: time.Now(),
Mtime: time.Now(),
Ctime: time.Now(),
Crtime: time.Now(),
Size: 0,
Uid: root.Uid,
Gid: root.Gid,
Devmajor: root.Devmajor,
Devminor: root.Devminor,
Xattrs: make(map[string][]byte),
}
if err := w.Create(currentPath, f); err != nil {
return fmt.Errorf("failed while creating parent directories: %w", err)
}
}
root = root.Children[dirname]
}
return w.Create(name, f)
}

// Create adds a file to the file system.
func (w *Writer) Create(name string, f *File) error {
if err := w.finishInode(); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion ext4/tar2ext4/tar2ext4.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func Convert(r io.Reader, w io.ReadWriteSeeker, options ...Option) error {
}
f.Mode &= ^compactext4.TypeMask
f.Mode |= typ
err = fs.Create(hdr.Name, f)
err = fs.CreateWithParents(hdr.Name, f)
if err != nil {
return err
}
Expand Down

0 comments on commit bdddc24

Please sign in to comment.