CX · Reference guideftp
PlaygroundDownloadsAboutv0.18.0-pre.1

ftp

FTP and FTPS (RFC 959, explicit AUTH TLS and implicit TLS, both channels protected) over cx-platform/net, and the seven-verb file surface of file_surface.md instantiated over it: list, stat, get, put, rename, delete, mkdir under a bound root no path and no link escapes, resumable transfers over REST, size, time and stall bounds. Every decision is a pure def — the reply reader, the data-endpoint check that refuses the FTP bounce, the TLS posture check, the resolution, the classification of reply codes onto the contract's nine classes, the resume plan — and the nine verbs charge the net capability for both connections.

ftp:resolve

[$ftp:resolve] ($root::string $path::string) -> string — Resolve a path lexically beneath the bound root; a path that resolves outside it raises CXER6805.

      [?lib 'cx-platform/ftp']
[$ftp:resolve '/srv/drop' '/etc/shadow']
    
      cx-err:CXER6805
    

ftp:read-reply

[$ftp:read-reply] ($text::string) -> element — Read one RFC 959 reply, single-line or multiline, as [reply code= text=] with one [line] per line; a reply whose closing line never arrives raises CXER6804.

ftp:check-data-endpoint

[$ftp:check-data-endpoint] ($peer::string $reply) -> element — The endpoint a data connection may be dialed at: the control connection's peer and only the port from a 227 or 229 reply; a 227 naming another host is the FTP bounce and raises CXER6802.

ftp:check-tls

[$ftp:check-tls] ($posture $observed) -> bool — True when the observed control and data channels are both TLS under a declared tls=:explicit or tls=:implicit posture; a refused AUTH TLS or a cleartext data channel raises CXER6801.

ftp:classify

[$ftp:classify] ($reply) -> any — Map an FTP reply code, read with the verb it answered, onto the file surface's nine error classes; a completion answers [classified state=:complete], an unclassified code is :protocol and not retryable.

ftp:plan-transfer

[$ftp:plan-transfer] ($request $partial) -> element — The resume plan — offset, remaining, address, TYPE I and the REST/RETR or REST/STOR pair — or CXER6816 for a partial that does not agree with the source or a peer that refuses REST.

ftp:resolve-pair

[$ftp:resolve-pair] ($root::string $from::string $to::string) -> element — Resolve BOTH of rename's paths beneath the bound root as [pair from= to=]; either one escaping raises CXER6805 — RNFR and RNTO are two commands and both are confined.

ftp:check-name

[$ftp:check-name] ($name::string) -> string — A name is one path segment: a separator, CR, LF or NUL raises CXER6807 where it enters — on FTP's line-oriented control channel a CR is a second command.

ftp:check-binding

[$ftp:check-binding] ($b) -> element — Judge a binding: a credential value raises CXER6310, active mode without a declared mode=:active raises CXER6818, a missing or loosened TLS posture raises CXER6801; a missing root, host, scheme or basic credential handle is reported as [findings].

ftp:check-bounds

[$ftp:check-bounds] ($b $obs $now) -> bool — True when an observation is inside the bounds, every bound inclusive: entries over max-entries raise CXER6813, octets over max-bytes CXER6814, a duration or a stall past the floor CXER6815; $now is an argument.

ftp:bind-bounds

[$ftp:bind-bounds] ($ceiling $bounds) -> element — The effective bounds, each the lower of the ceiling and the deployment's; a deployment raising a bound is refused CXER6813 at binding time.

ftp:read-listing

[$ftp:read-listing] ($root::string $format $text::string $path::string) -> element — Read MLSD (:mlsd) or LIST (:list) output as the file surface's [listing] of [entry] elements, complete or a refusal; a LIST shape this module does not recognize raises CXER6819 and is never half-read.

ftp:read-entry

[$ftp:read-entry] ($root::string $path::string $text::string) -> element — Read MLST's fact line as the [entry] for one path — what the entry is and never what it points at, a link's target checked against the root.

ftp:open

[$ftp:open] ($binding $opts::map) -> element — Open an FTPS session: dial under net, TLS from the first octet or AUTH TLS, then USER/PASS, PBSZ 0, PROT P and TYPE I, both channels held to the declared posture; idempotent per binding.

ftp:close

[$ftp:close] ($session) -> null — QUIT and close the control connection; idempotent.

ftp:list

[$ftp:list] ($session $path::string $opts::map) -> element — List one directory beneath the root over a data connection dialed only at the control peer — MLSD where the peer offers RFC 3659, LIST otherwise — bounded by entries and octets.

ftp:stat

[$ftp:stat] ($session $path::string $opts::map) -> element — MLST one path beneath the root and answer its [entry]; a peer without RFC 3659 is refused CXER6804 rather than guessed at.

ftp:get

[$ftp:get] ($session $path::string $opts::map) -> element — Transfer a file from the peer in TYPE I, resumably over REST from the partial the caller holds; the octets ride as the [transfer]'s [data], and a cut transfer is CXER6800 carrying the partial it resumes from.

ftp:put

[$ftp:put] ($session $path::string $source $opts::map) -> element — Transfer octets to the peer with STOR, resumably with REST and never APPE; an existing path is :exists before a byte is sent — put never overwrites implicitly.

ftp:rename

[$ftp:rename] ($session $from::string $to::string $opts::map) -> element — RNFR then RNTO with both paths resolved beneath the root; never over an existing target.

ftp:delete

[$ftp:delete] ($session $path::string $opts::map) -> element — Delete one file (DELE) or one empty directory (RMD), the kind MLST established; never recursive, and an absent path is :not-found.

ftp:mkdir

[$ftp:mkdir] ($session $path::string $opts::map) -> element — Make one directory (MKD), one segment; there is no implicit parent tree.

ftp:test-server

[$ftp:test-server] ($spec) -> element — Boot the in-process FTPS test server on 127.0.0.1 over an in-memory tree the spec seeds, with the TLS identity and the adversarial postures it declares.

ftp:test-server-stop

[$ftp:test-server-stop] ($server) -> null — Stop an in-process test server.

ftp:test-server-file

[$ftp:test-server-file] ($server $path::string) -> any — The octets the in-process test server holds at a path, or null.