21void apply_scp_flags(
const char *tok,
size_t tlen, ScpMode *mode)
23 for (
size_t k = 1; k < tlen; k++)
27 *mode = ScpMode::SINK;
29 else if (tok[k] ==
'f')
31 *mode = ScpMode::SOURCE;
37ScpMode pc_scp_parse_cmd(
const char *cmd,
size_t cmd_len,
char *path_out,
size_t path_cap)
39 if (!cmd || !path_out || path_cap == 0)
41 return ScpMode::INVALID;
43 ScpMode mode = ScpMode::INVALID;
44 const char *last_tok =
nullptr;
49 while (i < cmd_len && cmd[i] ==
' ')
58 while (i < cmd_len && cmd[i] !=
' ')
62 size_t tlen = i - start;
63 if (tlen >= 2 && cmd[start] ==
'-')
65 apply_scp_flags(cmd + start, tlen, &mode);
69 last_tok = cmd + start;
77 if (mode == ScpMode::INVALID || !last_tok || last_len == 0 || last_len >= path_cap)
79 return ScpMode::INVALID;
81 memcpy(path_out, last_tok, last_len);
82 path_out[last_len] =
'\0';
86bool pc_scp_parse_cline(
const char *line,
size_t len, uint32_t *mode_out, uint64_t *size_out,
char *name_out,
89 if (!line || len < 1 || line[0] !=
'C')
97 while (i < len && line[i] >=
'0' && line[i] <=
'7')
99 mode = mode * 8 + (uint32_t)(line[i] -
'0');
102 if (i == ms || i >= len || line[i] !=
' ')
110 while (i < len && line[i] >=
'0' && line[i] <=
'9')
112 size = size * 10 + (uint64_t)(line[i] -
'0');
115 if (i == ss || i >= len || line[i] !=
' ')
122 while (i < len && line[i] !=
'\n' && line[i] !=
'\0')
126 size_t nlen = i - ns;
127 if (nlen == 0 || nlen >= name_cap)
131 memcpy(name_out, line + ns, nlen);
132 name_out[nlen] =
'\0';
145size_t pc_scp_build_cline(uint32_t mode, uint64_t size,
const char *name,
char *out,
size_t cap)
147 pc_sb sb_out = {out, cap, 0,
true};
149 pc_sb_uint(&sb_out, (uint64_t)((
unsigned)(mode & 07777)), 8, 4);
151 pc_sb_u64(&sb_out, (uint64_t)((
unsigned long long)size));
160 if (n <= 0 || (
size_t)n >= cap)
SCP (RCP) protocol wire codec - the pure, host-testable half of the SCP-over-SSH server (PC_ENABLE_SS...
Bounded no-heap string builder that fails closed on overflow (one shared copy).
size_t pc_sb_finish(pc_sb *b)
NUL-terminate and return the built length, or 0 if the build overflowed.
void pc_sb_uint(pc_sb *b, uint64_t v, unsigned base, unsigned min_digits)
Append v in base (10 or 16), left-padded with '0' to at least min_digits.
void pc_sb_u64(pc_sb *b, uint64_t v)
Append v as decimal (64-bit).
void pc_sb_put(pc_sb *b, const char *s)
Append NUL-terminated s; leaves the buffer untouched and clears ok if it would not fit.
Bump-append target; ok latches false once an append would overflow cap.