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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil {
|
||||
return err
|
||||
@@ -268,7 +269,7 @@ func extractFile(entry *zip.File, path string, clobber, skipExisting bool) error
|
||||
if clobber {
|
||||
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 {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"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.
|
||||
func filepathReplace(text, dir string) string {
|
||||
return string(bytes.ReplaceAll([]byte(text), []byte("{dir}"), []byte(dir)))
|
||||
|
||||
Reference in new issue
Block a user