Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The symbolic links are not preserved when unpacking a zip (other formats not tested) #21

Closed
Skywalker13 opened this issue Jan 31, 2017 · 4 comments

Comments

@Skywalker13
Copy link

See subject

@oaleynik
Copy link

oaleynik commented May 25, 2017

Same here. @Skywalker13 did you find solution for this?

@Skywalker13
Copy link
Author

Skywalker13 commented May 25, 2017

Yes but I use archive/zip instead:

package main

import (
	"archive/zip"
	"io"
	"os"
	"path/filepath"
)

// Unzip a file to a destination and preserve the symlinks
// Based on http://stackoverflow.com/a/24792688/842097 with symlink additions
func unzip(src, dest string) error {
	r, err := zip.OpenReader(src)
	if err != nil {
		return err
	}
	defer func() {
		if err := r.Close(); err != nil {
			panic(err)
		}
	}()

	os.MkdirAll(dest, 0755)

	// Closure to address file descriptors issue with all the deferred .Close() methods
	extractAndWriteFile := func(f *zip.File) error {
		rc, err := f.Open()
		if err != nil {
			return err
		}
		defer func() {
			if err := rc.Close(); err != nil {
				panic(err)
			}
		}()

		path := filepath.Join(dest, f.Name)

		if f.FileInfo().IsDir() {
			os.MkdirAll(path, f.Mode())
		} else if f.FileInfo().Mode()&os.ModeSymlink != 0 {
			buffer := make([]byte, f.FileInfo().Size())
			size, err := rc.Read(buffer)
			if err != nil {
				return err
			}

			target := string(buffer[:size])

			err = os.Symlink(target, path)
			if err != nil {
				return err
			}
		} else {
			os.MkdirAll(filepath.Dir(path), f.Mode())
			f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
			if err != nil {
				return err
			}
			defer func() {
				if err = f.Close(); err != nil {
					panic(err)
				}
			}()

			_, err = io.Copy(f, rc)
			if err != nil {
				return err
			}
		}
		return nil
	}

	for _, f := range r.File {
		err := extractAndWriteFile(f)
		if err != nil {
			return err
		}
	}

	return nil
}

@mholt
Copy link
Owner

mholt commented May 25, 2017

Hmmm, want to make a pull request? :D

@oaleynik
Copy link

@Skywalker13 really appreciate actual example - saves me a lot of time! If you will have an hour of free time or so, as @mholt said - PR would be awesome! Thanks again!

oaleynik added a commit to oaleynik/nwjs-autoupdater that referenced this issue Jun 14, 2017
mholt/archiver package can't currently handle symbolic links

This adds custom zip extraction based on
mholt/archiver#21 (comment)

Closes #8
oaleynik added a commit to oaleynik/nwjs-autoupdater that referenced this issue Jun 14, 2017
mholt/archiver package can't currently handle symbolic links

This adds custom zip extraction based on
mholt/archiver#21 (comment)

Closes #8
peterpostmann added a commit to peterpostmann/archiver that referenced this issue Mar 7, 2018
peterpostmann added a commit to peterpostmann/archiver that referenced this issue Mar 7, 2018
peterpostmann added a commit to peterpostmann/archiver that referenced this issue Mar 7, 2018
@mholt mholt mentioned this issue Nov 9, 2018
@mholt mholt closed this as completed in #92 Dec 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants