From 2132fbb68a89498ecc7590b8e1fb3a19932e40c5 Mon Sep 17 00:00:00 2001 From: Diptanu Choudhury Date: Tue, 8 Nov 2016 10:57:29 -0800 Subject: [PATCH] Fixed permission issues on client --- client/allocdir/alloc_dir.go | 66 +++++++++++++++++++++++++++---- client/allocdir/alloc_dir_test.go | 65 ++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 7 deletions(-) diff --git a/client/allocdir/alloc_dir.go b/client/allocdir/alloc_dir.go index c230169bf..3acc174e6 100644 --- a/client/allocdir/alloc_dir.go +++ b/client/allocdir/alloc_dir.go @@ -313,13 +313,12 @@ func (d *AllocDir) Embed(task string, entries map[string]string) error { // Embedding a single file if !s.IsDir() { - destDir := filepath.Join(taskdir, filepath.Dir(dest)) - if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil { - return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err) + if err := d.createDir(taskdir, filepath.Dir(dest)); err != nil { + return fmt.Errorf("Couldn't create destination directory 11 %v: %v", dest, err) } // Copy the file. - taskEntry := filepath.Join(destDir, filepath.Base(dest)) + taskEntry := filepath.Join(taskdir, dest) if err := d.linkOrCopy(source, taskEntry, s.Mode().Perm()); err != nil { return err } @@ -327,10 +326,10 @@ func (d *AllocDir) Embed(task string, entries map[string]string) error { continue } - // Create destination directory. destDir := filepath.Join(taskdir, dest) - if err := os.MkdirAll(destDir, s.Mode().Perm()); err != nil { - return fmt.Errorf("Couldn't create destination directory %v: %v", destDir, err) + // Create destination directory. + if err := d.createDir(taskdir, dest); err != nil { + return fmt.Errorf("Couldn't create destination directory 22 %v: %v", destDir, err) } // Enumerate the files in source. @@ -565,3 +564,56 @@ func (d *AllocDir) GetSecretDir(task string) (string, error) { return filepath.Join(t, TaskSecrets), nil } } + +// createDir creates a directory structure inside the basepath. This functions +// preserves the permissions of each of the subdirectories in the relative path +// by looking up the permissions in the host. +func (d *AllocDir) createDir(basePath, relPath string) error { + filePerms, err := d.splitPath(relPath) + if err != nil { + return err + } + for i := len(filePerms) - 1; i >= 0; i-- { + fi := filePerms[i] + destDir := filepath.Join(basePath, fi.Name) + if err := os.MkdirAll(destDir, fi.Perm); err != nil { + return err + } + } + return nil +} + +// fileInfo holds the path and the permissions of a file +type fileInfo struct { + Name string + Perm os.FileMode +} + +// splitPath stats each subdirectory of a path +func (d *AllocDir) splitPath(path string) ([]fileInfo, error) { + var mode os.FileMode + i, err := os.Stat(path) + if err != nil { + mode = os.ModePerm + } else { + mode = i.Mode() + } + var dirs []fileInfo + dirs = append(dirs, fileInfo{Name: path, Perm: mode}) + currentDir := path + for { + dir := filepath.Dir(filepath.Clean(currentDir)) + if dir == currentDir { + break + } + i, err = os.Stat(dir) + if err != nil { + mode = os.ModePerm + } else { + mode = i.Mode() + } + dirs = append(dirs, fileInfo{Name: dir, Perm: mode}) + currentDir = dir + } + return dirs, nil +} diff --git a/client/allocdir/alloc_dir_test.go b/client/allocdir/alloc_dir_test.go index 948253865..daf38832e 100644 --- a/client/allocdir/alloc_dir_test.go +++ b/client/allocdir/alloc_dir_test.go @@ -5,6 +5,7 @@ import ( "bytes" "io" "io/ioutil" + "log" "os" "path/filepath" "reflect" @@ -417,3 +418,67 @@ func TestAllocDir_ReadAt_SecretDir(t *testing.T) { t.Fatalf("ReadAt of secret file didn't error: %v", err) } } + +func TestAllocDir_SplitPath(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "tmpdirtest") + if err != nil { + log.Fatal(err) + } + defer os.RemoveAll(dir) + + dest := filepath.Join(dir, "/foo/bar/baz") + if err := os.MkdirAll(dest, os.ModePerm); err != nil { + t.Fatalf("err: %v", err) + } + + d := NewAllocDir(dir) + defer d.Destroy() + + info, err := d.splitPath(dest) + if err != nil { + t.Fatalf("err: %v", err) + } + if len(info) != 6 { + t.Fatalf("expected: %v, actual: %v", 6, len(info)) + } +} + +func TestAllocDir_CreateDir(t *testing.T) { + dir, err := ioutil.TempDir("/tmp", "tmpdirtest") + if err != nil { + t.Fatalf("err: %v", err) + } + defer os.RemoveAll(dir) + + // create a subdir and a file + subdir := filepath.Join(dir, "subdir") + if err := os.MkdirAll(subdir, 0760); err != nil { + t.Fatalf("err: %v", err) + } + subdirMode, err := os.Stat(subdir) + if err != nil { + t.Fatalf("err: %v", err) + } + + // Create the above hierarchy under another destination + dir1, err := ioutil.TempDir("/tmp", "tempdirdest") + if err != nil { + t.Fatalf("err: %v", err) + } + + d := NewAllocDir(dir) + defer d.Destroy() + + if err := d.createDir(dir1, subdir); err != nil { + t.Fatalf("err: %v", err) + } + + // Ensure that the subdir had the right perm + fi, err := os.Stat(filepath.Join(dir1, dir, "subdir")) + if err != nil { + t.Fatalf("err: %v", err) + } + if fi.Mode() != subdirMode.Mode() { + t.Fatalf("wrong file mode: %v, expected: %v", fi.Mode(), subdirMode.Mode()) + } +}