aboutsummaryrefslogtreecommitdiff
path: root/session.go
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-10-21 19:52:17 +0700
committerShulhan <ms@kilabit.info>2023-10-21 19:59:10 +0700
commitf1cdc424327be91cfdbeb35449275cd8582bba8d (patch)
tree5d350edefd9a17400179252a1018be7004988fe7 /session.go
parent143e4c8c6825884ae864563b93689200a55c2d49 (diff)
downloadawwan-f1cdc424327be91cfdbeb35449275cd8582bba8d.tar.xz
all: implement remote "#get!" and "#put!" with owner and mode
When script with magic command "#get!" or "#put!" executed using "play" command, one can changes the owner and/or permission mode by setting the user/group and permission bits after the magic command, for example, #get!user:group+0600 src dst Will changes the owner of dst in local into "user:group" with permission "0600", while #put!user:group+0600 src dst Will changes the owner of dst in remote into "user:group" with permission "0600".
Diffstat (limited to 'session.go')
-rw-r--r--session.go78
1 files changed, 72 insertions, 6 deletions
diff --git a/session.go b/session.go
index bab3607..90c951d 100644
--- a/session.go
+++ b/session.go
@@ -306,18 +306,37 @@ func (ses *Session) SudoCopy(req *Request, stmt *Statement) (err error) {
// SudoGet copy file from remote that can be accessed by root on remote, to
// local.
-func (ses *Session) SudoGet(stmt *Statement) (err error) {
- var logp = `SudoGet`
+// If the owner and mode is set, it will also changes using sudo.
+func (ses *Session) SudoGet(req *Request, stmt *Statement) (err error) {
+ var (
+ logp = `SudoGet`
+ src = stmt.args[0]
+ dst = stmt.args[1]
+ )
- err = ses.sshc.sudoGet(stmt.args[0], stmt.args[1])
+ err = ses.sshc.sudoGet(src, dst)
if err != nil {
return fmt.Errorf("%s: %w", logp, err)
}
+
+ if stmt.mode != 0 {
+ err = ses.localSudoChmod(req, dst, stmt.mode)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
+ }
+ if len(stmt.owner) != 0 {
+ err = ses.localSudoChown(req, dst, stmt.owner)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
+ }
+
return nil
}
// SudoPut copy file from local to remote using sudo.
-func (ses *Session) SudoPut(stmt *Statement) (err error) {
+func (ses *Session) SudoPut(req *Request, stmt *Statement) (err error) {
var (
logp = `SudoPut`
src = stmt.args[0]
@@ -342,6 +361,19 @@ func (ses *Session) SudoPut(stmt *Statement) (err error) {
return fmt.Errorf("%s: %w", logp, err)
}
+ if stmt.mode != 0 {
+ err = ses.sshc.sudoChmod(dst, stmt.mode)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
+ }
+ if len(stmt.owner) != 0 {
+ err = ses.sshc.sudoChown(dst, stmt.owner)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, logp, err)
+ }
+ }
+
return nil
}
@@ -475,9 +507,9 @@ func (ses *Session) executeScriptOnRemote(req *Request, pos linePosition) (err e
case statementKindPut:
err = ses.Put(stmt)
case statementKindSudoGet:
- err = ses.SudoGet(stmt)
+ err = ses.SudoGet(req, stmt)
case statementKindSudoPut:
- err = ses.SudoPut(stmt)
+ err = ses.SudoPut(req, stmt)
}
if err != nil {
fmt.Fprintf(req.stderr, "!!! %s\n", err)
@@ -705,6 +737,40 @@ func (ses *Session) loadRawEnv(content []byte) (err error) {
return nil
}
+// localSudoChmod change the file permission in local environment using
+// sudo.
+func (ses *Session) localSudoChmod(req *Request, file string, mode fs.FileMode) (err error) {
+ var (
+ fsmode = strconv.FormatUint(uint64(mode), 8)
+ sudoChmod = &Statement{
+ kind: statementKindDefault,
+ cmd: `sudo`,
+ args: []string{`chmod`, fsmode, file},
+ raw: []byte(fmt.Sprintf(`sudo chmod %o %q`, mode, file)),
+ }
+ )
+ err = ExecLocal(req, sudoChmod)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, sudoChmod.raw, err)
+ }
+ return nil
+}
+
+// localSudoChown change the file owner in local environment using sudo.
+func (ses *Session) localSudoChown(req *Request, file, owner string) (err error) {
+ var sudoChown = &Statement{
+ kind: statementKindDefault,
+ cmd: `sudo`,
+ args: []string{`chown`, owner, file},
+ raw: []byte(fmt.Sprintf(`sudo chown %s %q`, owner, file)),
+ }
+ err = ExecLocal(req, sudoChown)
+ if err != nil {
+ return fmt.Errorf(`%s: %w`, sudoChown.raw, err)
+ }
+ return nil
+}
+
// render apply the session and environment variables into input stream `in`
// and return the result.
// It will return an error if the input cannot be parsed or one variable