Skip to content

Commit a5aafed

Browse files
Added python3 fallback code when ftp command is not available
1 parent bcb210e commit a5aafed

1 file changed

Lines changed: 58 additions & 24 deletions

File tree

tests/fineftp_test/src/stou_helper.h

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -98,34 +98,68 @@ void uploadWithStou(const std::string& filePath,
9898
+ scriptPath + "\"";
9999

100100
#else
101-
// ----- Linux / macOS: use the standard ftp client -----
102-
// The `sunique` command tells the ftp client to use STOU instead of
103-
// STOR when executing `put`, so the server picks a unique filename.
104-
// We write the commands to a temp script file and pipe it via `-n`
105-
// (no auto-login) to avoid interactive prompts.
101+
// ----- Linux / macOS -----
102+
// macOS removed the built-in `ftp` client, so we check at runtime:
103+
// 1. `ftp` — available on most Linux distros; uses `sunique` + `put`
104+
// 2. `python3` — fallback using ftplib.storbinary('STOU ...'), works everywhere
106105
std::string portStr = std::to_string(port);
107-
108-
std::string ftpScript;
109-
ftpScript += "open " + host + " " + portStr + "\n";
110-
ftpScript += "user anonymous anonymous@\n";
111-
ftpScript += "binary\n";
112-
ftpScript += "sunique\n";
113-
ftpScript += "put " + filePath + "\n";
114-
ftpScript += "bye\n";
115-
116-
// Write script to a temp file
117-
std::string scriptPath = "/tmp/ftp_stou_upload.ftp";
118-
{
119-
std::ofstream scriptFile(scriptPath);
120-
if (!scriptFile.is_open()) {
121-
std::cerr << "Failed to create temp script: " << scriptPath << "\n";
122-
return;
106+
std::string scriptPath = "/tmp/ftp_stou_upload_script";
107+
std::string cmd;
108+
109+
// Check if the `ftp` command exists
110+
if (system("command -v ftp > /dev/null 2>&1") == 0) {
111+
// --- Use the standard ftp client with sunique ---
112+
std::string ftpScript;
113+
ftpScript += "open " + host + " " + portStr + "\n";
114+
ftpScript += "user anonymous anonymous@\n";
115+
ftpScript += "binary\n";
116+
ftpScript += "sunique\n";
117+
ftpScript += "put " + filePath + "\n";
118+
ftpScript += "bye\n";
119+
120+
scriptPath += ".ftp";
121+
{
122+
std::ofstream f(scriptPath);
123+
if (!f.is_open()) {
124+
std::cerr << "Failed to create temp script: " << scriptPath << "\n";
125+
return;
126+
}
127+
f << ftpScript;
123128
}
124-
scriptFile << ftpScript;
129+
// -n = no auto-login (we login manually via the "user" command)
130+
cmd = "ftp -n < \"" + scriptPath + "\"";
131+
125132
}
133+
else if (system("command -v python3 > /dev/null 2>&1") == 0) {
134+
// --- Fallback: Python 3 ftplib (available on macOS) ---
135+
std::string pyScript;
136+
pyScript += "import sys\n";
137+
pyScript += "from ftplib import FTP\n";
138+
pyScript += "ftp = FTP()\n";
139+
pyScript += "ftp.connect('" + host + "', " + portStr + ")\n";
140+
pyScript += "ftp.login('anonymous', 'anonymous@')\n";
141+
pyScript += "ftp.set_pasv(True)\n";
142+
pyScript += "with open('" + filePath + "', 'rb') as f:\n";
143+
pyScript += " result = ftp.storbinary('STOU " + filePath + "', f)\n";
144+
pyScript += "print(result)\n";
145+
pyScript += "ftp.quit()\n";
146+
147+
scriptPath += ".py";
148+
{
149+
std::ofstream f(scriptPath);
150+
if (!f.is_open()) {
151+
std::cerr << "Failed to create temp script: " << scriptPath << "\n";
152+
return;
153+
}
154+
f << pyScript;
155+
}
156+
cmd = "python3 \"" + scriptPath + "\"";
126157

127-
// -n = no auto-login (we login manually via the "user" command)
128-
std::string cmd = "ftp -n < \"" + scriptPath + "\"";
158+
}
159+
else {
160+
std::cerr << "Error: neither 'ftp' nor 'python3' found on this system.\n";
161+
return;
162+
}
129163
#endif
130164

131165
std::cout << "Running command:\n" << cmd << "\n\n";

0 commit comments

Comments
 (0)