soong_jar: Implement symlinks, fix directories
Ensure that we only create one directory entry, not one with a / at the
end and another without. Clean incoming paths to prevent other similar
duplicates.
When adding directories specified directly as inputs, use the relative
path just like files, not the full path.
Instead of traversing symlinks, addg them to the zip file directly.
Present an error instead of crashing when an input does not exist.
Change-Id: Id6d6561fe12c28398f6096bf9bcae602bb7aa491
diff --git a/cmd/soong_jar/soong_jar.go b/cmd/soong_jar/soong_jar.go
index 4a4a3ab..6461f8c 100644
--- a/cmd/soong_jar/soong_jar.go
+++ b/cmd/soong_jar/soong_jar.go
@@ -41,7 +41,7 @@
return fmt.Errorf("must pass -C before -f")
}
- *l = append(*l, fileArg{*relativeRoot, s})
+ *l = append(*l, fileArg{filepath.Clean(*relativeRoot), s})
return nil
}
@@ -162,6 +162,8 @@
}
func (z *zipWriter) writeRelFile(root, file string) error {
+ file = filepath.Clean(file)
+
rel, err := filepath.Rel(root, file)
if err != nil {
return err
@@ -176,11 +178,17 @@
}
func (z *zipWriter) writeFile(rel, file string) error {
- if s, _ := os.Stat(file); s.IsDir() {
+ if s, err := os.Lstat(file); err != nil {
+ return err
+ } else if s.IsDir() {
if z.directories {
- return z.writeDirectory(file)
+ return z.writeDirectory(rel)
}
return nil
+ } else if s.Mode()&os.ModeSymlink != 0 {
+ return z.writeSymlink(rel, file)
+ } else if !s.Mode().IsRegular() {
+ return fmt.Errorf("%s is not a file, directory, or symlink", file)
}
if z.directories {
@@ -217,13 +225,17 @@
}
func (z *zipWriter) writeDirectory(dir string) error {
- for dir != "" && !z.createdDirs[dir] {
+ if dir != "" && !strings.HasSuffix(dir, "/") {
+ dir = dir + "/"
+ }
+
+ for dir != "" && dir != "./" && !z.createdDirs[dir] {
z.createdDirs[dir] = true
dirHeader := &zip.FileHeader{
Name: dir,
}
- dirHeader.SetMode(os.ModeDir)
+ dirHeader.SetMode(0700 | os.ModeDir)
dirHeader.SetModTime(z.time)
_, err := z.w.CreateHeader(dirHeader)
@@ -236,3 +248,31 @@
return nil
}
+
+func (z *zipWriter) writeSymlink(rel, file string) error {
+ if z.directories {
+ dir, _ := filepath.Split(rel)
+ if err := z.writeDirectory(dir); err != nil {
+ return err
+ }
+ }
+
+ fileHeader := &zip.FileHeader{
+ Name: rel,
+ }
+ fileHeader.SetModTime(z.time)
+ fileHeader.SetMode(0700 | os.ModeSymlink)
+
+ out, err := z.w.CreateHeader(fileHeader)
+ if err != nil {
+ return err
+ }
+
+ dest, err := os.Readlink(file)
+ if err != nil {
+ return err
+ }
+
+ _, err = io.WriteString(out, dest)
+ return err
+}