diff options
| author | Shulhan <ms@kilabit.info> | 2023-10-21 19:52:17 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-10-21 19:59:10 +0700 |
| commit | f1cdc424327be91cfdbeb35449275cd8582bba8d (patch) | |
| tree | 5d350edefd9a17400179252a1018be7004988fe7 /session.go | |
| parent | 143e4c8c6825884ae864563b93689200a55c2d49 (diff) | |
| download | awwan-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.go | 78 |
1 files changed, 72 insertions, 6 deletions
@@ -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 |
