write tool fixes
This commit is contained in:
+2
-2
@@ -197,8 +197,8 @@ int rune_width(int cp);
|
|||||||
|
|
||||||
void mkdir_p(std::string_view dir);
|
void mkdir_p(std::string_view dir);
|
||||||
std::string project_id();
|
std::string project_id();
|
||||||
std::string bantam_tmp_dir();
|
std::string bantam_tmp_dir(std::string_view sess_id = "");
|
||||||
std::string tool_res_dir();
|
std::string tool_res_dir(std::string_view sess_id = "");
|
||||||
std::string md5_hex(std::string_view data);
|
std::string md5_hex(std::string_view data);
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
|
|||||||
@@ -229,6 +229,8 @@ static int AL(Cfg &cfg, Messages &msgs, Usage &out, volatile int *interrupted, s
|
|||||||
else if (!has_line && !has_byte && !has_del_lines && !has_del_bytes) {
|
else if (!has_line && !has_byte && !has_del_lines && !has_del_bytes) {
|
||||||
/* No offset/deletion parameters: overwrite the whole file. */
|
/* No offset/deletion parameters: overwrite the whole file. */
|
||||||
std::string c = filter_text(cv);
|
std::string c = filter_text(cv);
|
||||||
|
/* Ensure the written file ends with a single trailing newline. */
|
||||||
|
if (!c.empty() && c.back() != '\n') c.push_back('\n');
|
||||||
auto sl = fp.find_last_of('/');
|
auto sl = fp.find_last_of('/');
|
||||||
if (sl != std::string::npos) mkdir_p(std::string_view(fp).substr(0, sl));
|
if (sl != std::string::npos) mkdir_p(std::string_view(fp).substr(0, sl));
|
||||||
else mkdir_p(".");
|
else mkdir_p(".");
|
||||||
@@ -236,6 +238,10 @@ static int AL(Cfg &cfg, Messages &msgs, Usage &out, volatile int *interrupted, s
|
|||||||
else { res = sfmt("Successfully wrote %zu bytes to %s", c.size(), fp.c_str()); }
|
else { res = sfmt("Successfully wrote %zu bytes to %s", c.size(), fp.c_str()); }
|
||||||
} else {
|
} else {
|
||||||
int werr = 0; std::string c = filter_text(cv);
|
int werr = 0; std::string c = filter_text(cv);
|
||||||
|
/* Line-based edits keep the text-file trailing-newline convention;
|
||||||
|
* byte-based edits are exact byte operations and must not have a
|
||||||
|
* newline injected. */
|
||||||
|
if (!(has_byte || has_del_bytes) && !c.empty() && c.back() != '\n') c.push_back('\n');
|
||||||
res = write_file(fp, line_off, byte_off, del_lines, del_bytes, c, &werr);
|
res = write_file(fp, line_off, byte_off, del_lines, del_bytes, c, &werr);
|
||||||
if (werr) sty = 31;
|
if (werr) sty = 31;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -291,6 +291,13 @@ std::string write_file(std::string_view path, long line_offset, long byte_offset
|
|||||||
nd.append(data, 0, prefix_len);
|
nd.append(data, 0, prefix_len);
|
||||||
nd.append(content);
|
nd.append(content);
|
||||||
if (suffix_len) nd.append(data, end_del, suffix_len);
|
if (suffix_len) nd.append(data, end_del, suffix_len);
|
||||||
|
/* Keep a single trailing newline for line-based / whole-file text writes.
|
||||||
|
* Byte-based edits are exact byte operations and must not be mutated with an
|
||||||
|
* injected newline, so the guard is skipped whenever a byte offset or byte
|
||||||
|
* deletion is actually in effect. */
|
||||||
|
bool byte_based = (line_offset < 0 && byte_offset >= 0) ||
|
||||||
|
(del_lines < 0 && del_bytes >= 0);
|
||||||
|
if (!byte_based && !nd.empty() && nd.back() != '\n') nd.push_back('\n');
|
||||||
if (!write_file_str(p, nd)) {
|
if (!write_file_str(p, nd)) {
|
||||||
*err = 1;
|
*err = 1;
|
||||||
return sfmt("[tool error: write %s: %s]", p.c_str(), strerror(errno));
|
return sfmt("[tool error: write %s: %s]", p.c_str(), strerror(errno));
|
||||||
|
|||||||
@@ -192,15 +192,27 @@ void mkdir_p(std::string_view dir) {
|
|||||||
}
|
}
|
||||||
mkdir(path.c_str(), 0755);
|
mkdir(path.c_str(), 0755);
|
||||||
}
|
}
|
||||||
std::string bantam_tmp_dir() {
|
std::string bantam_tmp_dir(std::string_view sess_id) {
|
||||||
const char *tmp = std::getenv("TMPDIR");
|
const char *tmp = std::getenv("TMPDIR");
|
||||||
if (!tmp || !*tmp) tmp = "/tmp";
|
if (!tmp || !*tmp) tmp = "/tmp";
|
||||||
std::string p = std::string(tmp) + "/bantam";
|
std::string base(tmp);
|
||||||
|
/* Drop a single trailing slash so we never build a "//bantam" path (which
|
||||||
|
* some platforms treat as a special "super-root"); keep "/" itself intact. */
|
||||||
|
if (base.size() > 1 && base.back() == '/') base.pop_back();
|
||||||
|
std::string p = base;
|
||||||
|
if (p != "/") p += "/";
|
||||||
|
p += "bantam";
|
||||||
|
/* Segregate temporary artifacts per session so different projects/sessions
|
||||||
|
* never share or collide on scratch files. */
|
||||||
|
std::string sid(sess_id);
|
||||||
|
if (sid.empty()) sid = project_id();
|
||||||
|
if (!sid.empty()) { p += "/"; p += sid; }
|
||||||
mkdir_p(p);
|
mkdir_p(p);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
std::string tool_res_dir() {
|
|
||||||
std::string base = bantam_tmp_dir();
|
std::string tool_res_dir(std::string_view sess_id) {
|
||||||
|
std::string base = bantam_tmp_dir(sess_id);
|
||||||
std::string p = base + "/toolres";
|
std::string p = base + "/toolres";
|
||||||
mkdir_p(p);
|
mkdir_p(p);
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
Reference in New Issue
Block a user