# `Opsmaru.Incus.SFTP`
[🔗](https://github.com/upmaru/opsmaru-incus/blob/v0.1.0/lib/opsmaru/incus/sftp.ex#L1)

SFTP v3 client over the native Incus raw upgrade, matching the pinned `pkg/sftp`
v1.13.10 client returned by `GetInstanceFileSFTP` and
`GetStoragePoolVolumeFileSFTP`. No SSH or host files.

A session is shared: any process may call it, and requests are pipelined with
distinct ids whose replies are matched by id, as goroutines share a Go
`*sftp.Client`. It closes on `close/1`, peer EOF, its stream lifetime, or when
the process that opened it exits. In-flight requests are bounded by the
connection's queue limit.

Path and metadata calls send the pinned packets, including the compound steps
of `remove/2`, `mkdir_all/2`, `remove_all/2`, `glob/2` and `walk/3`. Paths are
sent as given; only packet and connection bounds apply. A compound call stops at
the first error that is not a native status, so it never sends more mutations
after a possibly accepted one.

Native status errors are `:sftp_status` with the code, message and language,
plus `response.class` (`:eof`, `:not_exist`, `:permission` or `nil`) as Go
normalizes them, and `response.op`/`response.path` where Go returns an
`os.PathError`. A request whose local deadline passes fails alone: a possibly
sent mutation is `:uncertain` and never replayed, and its late reply is
discarded. Malformed, oversized or unmatched frames end the session and fail
every pending request, mutations as `:uncertain`. Closing a session releases
its channel without deleting backend files or canceling Incus.

`open/2`, `create/2` and `open_file/3` return an `Opsmaru.Incus.SFTP.File`
bound to this session, which keeps its native handle and position.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `chmod`

Go `Chmod`: permission and special bits (Go `FileMode` flags are honored).

# `chown`

Go `Chown`: integer ids wrap to uint32 as natively.

# `chtimes`

Go `Chtimes`: Unix seconds or `DateTime`s, sent as native uint32 seconds.

# `close`

# `create`

Go `Create`: opens `path` read/write, creating or truncating it.

# `extensions`

# `getwd`

Go `Getwd`: `real_path(session, ".")`.

# `glob`

Go `Glob`: the paths matching a shell pattern. As natively, a pattern without
metacharacters that does not exist and unreadable directories yield no matches.

# `has_extension`

Go `HasExtension`: `{:ok, data}` when the server announced the extension.

# `instance`

# `join`

Go `path.Join`, as `sftp.Join`.

# `link`

Go `Link`: a hard link `new` to `old` (`hardlink@openssh.com`).

# `lstat`

Go `Lstat`: attributes of `path` itself, without following a symlink.

# `match`

Go `path.Match`, as `sftp.Match`.

# `mkdir`

Go `Mkdir`.

# `mkdir_all`

Go `MkdirAll`: creates `path` and any missing parents.

# `open`

Go `Open`: opens `path` for reading.

# `open_file`

Go `OpenFile`: opens `path` with `:read_only`, `:write_only`, `:read_write`,
`:append`, `:create`, `:truncate` and `:exclusive`, mapped as Go's `toPflags`
maps the `os` flags. No access flag means read-only, and conflicting access
flags send neither read nor write, as natively.

# `posix_rename`

Go `PosixRename` (`posix-rename@openssh.com`).

# `read_dir`

Go `ReadDir`: the entries of a directory in server order, without `.` and `..`.

# `read_link`

Go `ReadLink`: the target of a symbolic link.

# `real_path`

Go `RealPath`: the server's canonical absolute path.

# `remove`

Go `Remove`: removes a file, else a directory. When both fail with different
native errors, the pinned client stats `path` to choose which to return.

# `remove_all`

Go `RemoveAll`: removes `path` and everything it contains.

# `remove_directory`

Go `RemoveDirectory`: removes an empty directory.

# `rename`

Go `Rename`.

# `set_extended_data`

Go `SetExtendedData`: `{type, data}` pairs.

# `split`

Go `path.Split`, as `sftp.Split`.

# `stat`

Go `Stat`: attributes of the file `path` names, following symlinks.

# `stat_vfs`

Go `StatVFS` (`statvfs@openssh.com`).

# `symlink`

Go `Symlink`: a symbolic link `new` pointing at `old`.

# `truncate`

Go `Truncate`: the size wraps to uint64 as natively.

# `volume`

# `walk`

Go `Walk` (kr/fs `Walker`): a lazy stream of `{path, {:ok, stat} | {:error, error}}`
in the pinned order. `skip: fun(path, stat)` returning true skips a directory's
contents, like `SkipDir`. A directory that cannot be read is yielded again with
its error.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
