mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
fix(run): keep the permission bits of extracted artifact files
Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
2 files changed
+29
-2
No files matched your search
@@ -259,7 +259,8 @@ func extractZip(ctx context.Context, body io.Reader, dir string, clobber, skipEx
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// extractFile writes one archive entry to path with the permissions the umask allows.
|
// extractFile writes one archive entry to path with its permission bits, such as an executable's,
|
||||||
|
// as far as the umask allows; special bits such as setuid are dropped.
|
||||||
func extractFile(entry *zip.File, path string, clobber, skipExisting bool) error {
|
func extractFile(entry *zip.File, path string, clobber, skipExisting bool) error {
|
||||||
if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
|
if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -268,7 +269,7 @@ func extractFile(entry *zip.File, path string, clobber, skipExisting bool) error
|
|||||||
if clobber {
|
if clobber {
|
||||||
flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
|
flags = os.O_WRONLY | os.O_CREATE | os.O_TRUNC
|
||||||
}
|
}
|
||||||
file, err := os.OpenFile(path, flags, 0o666)
|
file, err := os.OpenFile(path, flags, cmp.Or(entry.Mode().Perm(), 0o666))
|
||||||
if errors.Is(err, os.ErrExist) && skipExisting {
|
if errors.Is(err, os.ErrExist) && skipExisting {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gitea.dev/tea/internal/clierr"
|
"gitea.dev/tea/internal/clierr"
|
||||||
@@ -127,6 +128,31 @@ func TestRunDownloadExtractsArtifactsByName(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtractZipKeepsPermissionBits(t *testing.T) {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
t.Skip("Windows has no permission bits")
|
||||||
|
}
|
||||||
|
var archive bytes.Buffer
|
||||||
|
writer := zip.NewWriter(&archive)
|
||||||
|
for name, mode := range map[string]os.FileMode{"bin/tool": 0o755, "setuid": 0o755 | os.ModeSetuid, "data": 0o644} {
|
||||||
|
header := &zip.FileHeader{Name: name}
|
||||||
|
header.SetMode(mode)
|
||||||
|
file, err := writer.CreateHeader(header)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = file.Write([]byte(name))
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
require.NoError(t, writer.Close())
|
||||||
|
dir := t.TempDir()
|
||||||
|
require.NoError(t, extractZip(context.Background(), &archive, dir, false, false))
|
||||||
|
for name, executable := range map[string]bool{"bin/tool": true, "setuid": true, "data": false} {
|
||||||
|
info, err := os.Stat(filepath.Join(dir, name))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, executable, info.Mode().Perm()&0o100 != 0, name)
|
||||||
|
require.Zero(t, info.Mode()&os.ModeSetuid, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// filepathReplace puts dir in place of {dir} in text.
|
// filepathReplace puts dir in place of {dir} in text.
|
||||||
func filepathReplace(text, dir string) string {
|
func filepathReplace(text, dir string) string {
|
||||||
return string(bytes.ReplaceAll([]byte(text), []byte("{dir}"), []byte(dir)))
|
return string(bytes.ReplaceAll([]byte(text), []byte("{dir}"), []byte(dir)))
|
||||||
|
|||||||
Reference in new issue
Block a user