forked from HowardHinnant/date
Allow the option to not use the std::system api and make the default NOT use it for all platforms.
This commit is contained in:
129
tz.cpp
129
tz.cpp
@@ -107,6 +107,14 @@
|
|||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <wordexp.h>
|
# include <wordexp.h>
|
||||||
|
# if !USE_SHELL_API
|
||||||
|
# include <sys/stat.h>
|
||||||
|
# include <sys/fcntl.h>
|
||||||
|
# include <dirent.h>
|
||||||
|
# include <cstring>
|
||||||
|
# include <sys/wait.h>
|
||||||
|
# include <sys/types.h>
|
||||||
|
# endif //!USE_SHELL_API
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
|
|
||||||
#if HAS_REMOTE_API
|
#if HAS_REMOTE_API
|
||||||
@@ -2168,7 +2176,7 @@ remote_download(const std::string& version)
|
|||||||
// using _mkdir and CreateProcess etc.
|
// using _mkdir and CreateProcess etc.
|
||||||
// But use the current means now as matches Unix implementations and while
|
// But use the current means now as matches Unix implementations and while
|
||||||
// in proof of concept / testing phase.
|
// in proof of concept / testing phase.
|
||||||
|
// TODO! Use <filesystem> eventually.
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
remove_folder_and_subfolders(const std::string& folder)
|
remove_folder_and_subfolders(const std::string& folder)
|
||||||
@@ -2182,7 +2190,7 @@ remove_folder_and_subfolders(const std::string& folder)
|
|||||||
return std::system(cmd.c_str()) == EXIT_SUCCESS;
|
return std::system(cmd.c_str()) == EXIT_SUCCESS;
|
||||||
# else // !USE_SHELL_API
|
# else // !USE_SHELL_API
|
||||||
// Create a buffer containing the path to delete. It must be terminated
|
// Create a buffer containing the path to delete. It must be terminated
|
||||||
// by two nulls. Who designs these API's...
|
// by two nuls. Who designs these API's...
|
||||||
std::vector<char> from;
|
std::vector<char> from;
|
||||||
from.assign(folder.begin(), folder.end());
|
from.assign(folder.begin(), folder.end());
|
||||||
from.push_back('\0');
|
from.push_back('\0');
|
||||||
@@ -2197,7 +2205,54 @@ remove_folder_and_subfolders(const std::string& folder)
|
|||||||
return false;
|
return false;
|
||||||
# endif // !USE_SHELL_API
|
# endif // !USE_SHELL_API
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
|
# if USE_SHELL_API
|
||||||
return std::system(("rm -R " + folder).c_str()) == EXIT_SUCCESS;
|
return std::system(("rm -R " + folder).c_str()) == EXIT_SUCCESS;
|
||||||
|
# else // !USE_SHELL_API
|
||||||
|
struct dir_deleter {
|
||||||
|
dir_deleter() {}
|
||||||
|
void operator()(DIR* d) const
|
||||||
|
{
|
||||||
|
if (d != nullptr)
|
||||||
|
{
|
||||||
|
int result = closedir(d);
|
||||||
|
assert(result == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
using closedir_ptr = std::unique_ptr<DIR, dir_deleter>;
|
||||||
|
|
||||||
|
std::string filename;
|
||||||
|
struct stat statbuf;
|
||||||
|
size_t folder_len = folder.length();
|
||||||
|
struct dirent* p = nullptr;
|
||||||
|
|
||||||
|
closedir_ptr d(opendir(folder.c_str()));
|
||||||
|
bool r = d.get() != nullptr;
|
||||||
|
while (r && (p=readdir(d.get())) != nullptr)
|
||||||
|
{
|
||||||
|
if (strcmp(p->d_name, ".") == 0 || strcmp(p->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// + 2 for path delimiter and nul terminator.
|
||||||
|
size_t buf_len = folder_len + strlen(p->d_name) + 2;
|
||||||
|
filename.resize(buf_len);
|
||||||
|
size_t path_len = static_cast<size_t>(
|
||||||
|
snprintf(&filename[0], buf_len, "%s/%s", folder.c_str(), p->d_name));
|
||||||
|
assert(path_len == buf_len - 1);
|
||||||
|
filename.resize(path_len);
|
||||||
|
|
||||||
|
if (stat(filename.c_str(), &statbuf) == 0)
|
||||||
|
r = S_ISDIR(statbuf.st_mode)
|
||||||
|
? remove_folder_and_subfolders(filename)
|
||||||
|
: unlink(filename.c_str()) == 0;
|
||||||
|
}
|
||||||
|
d.reset();
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
r = rmdir(folder.c_str()) == 0;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
# endif // !USE_SHELL_API
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2216,7 +2271,11 @@ make_directory(const std::string& folder)
|
|||||||
return _mkdir(folder.c_str()) == 0;
|
return _mkdir(folder.c_str()) == 0;
|
||||||
# endif // !USE_SHELL_API
|
# endif // !USE_SHELL_API
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
|
# if USE_SHELL_API
|
||||||
return std::system(("mkdir " + folder).c_str()) == EXIT_SUCCESS;
|
return std::system(("mkdir " + folder).c_str()) == EXIT_SUCCESS;
|
||||||
|
# else // !USE_SHELL_API
|
||||||
|
return mkdir(folder.c_str(), 0777) == 0;
|
||||||
|
# endif // !USE_SHELL_API
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2234,7 +2293,11 @@ delete_file(const std::string& file)
|
|||||||
return _unlink(file.c_str()) == 0;
|
return _unlink(file.c_str()) == 0;
|
||||||
# endif // !USE_SHELL_API
|
# endif // !USE_SHELL_API
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
|
# if USE_SHELL_API
|
||||||
return std::system(("rm " + file).c_str()) == EXIT_SUCCESS;
|
return std::system(("rm " + file).c_str()) == EXIT_SUCCESS;
|
||||||
|
# else // !USE_SHELL_API
|
||||||
|
return unlink(file.c_str()) == 0;
|
||||||
|
# endif // !USE_SHELL_API
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2278,6 +2341,7 @@ get_unzip_program()
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !USE_SHELL_API
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
run_program(const std::string& command)
|
run_program(const std::string& command)
|
||||||
@@ -2305,6 +2369,7 @@ run_program(const std::string& command)
|
|||||||
}
|
}
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
#endif // !USE_SHELL_API
|
||||||
|
|
||||||
static
|
static
|
||||||
std::string
|
std::string
|
||||||
@@ -2326,7 +2391,7 @@ extract_gz_file(const std::string& version, const std::string& gz_file,
|
|||||||
auto unzip_prog = get_unzip_program();
|
auto unzip_prog = get_unzip_program();
|
||||||
bool unzip_result = false;
|
bool unzip_result = false;
|
||||||
// Use the unzip program to extract the tar file from the archive.
|
// Use the unzip program to extract the tar file from the archive.
|
||||||
|
|
||||||
// Aim to create a string like:
|
// Aim to create a string like:
|
||||||
// "C:\Program Files\7-Zip\7z.exe" x "C:\Users\SomeUser\Downloads\tzdata2016d.tar.gz"
|
// "C:\Program Files\7-Zip\7z.exe" x "C:\Users\SomeUser\Downloads\tzdata2016d.tar.gz"
|
||||||
// -o"C:\Users\SomeUser\Downloads\tzdata"
|
// -o"C:\Users\SomeUser\Downloads\tzdata"
|
||||||
@@ -2381,11 +2446,67 @@ extract_gz_file(const std::string& version, const std::string& gz_file,
|
|||||||
|
|
||||||
#else // !_WIN32
|
#else // !_WIN32
|
||||||
|
|
||||||
|
#if !USE_SHELL_API
|
||||||
|
static
|
||||||
|
int
|
||||||
|
run_program(const char* prog, const char*const args[])
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) // Child failed to start.
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (pid != 0)
|
||||||
|
{
|
||||||
|
// We are in the parent. Child started. Wait for it.
|
||||||
|
pid_t ret;
|
||||||
|
int status;
|
||||||
|
while ((ret = waitpid(pid, &status, 0)) == -1)
|
||||||
|
{
|
||||||
|
if (errno != EINTR)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ret != -1)
|
||||||
|
{
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
printf("Child issues!\n");
|
||||||
|
|
||||||
|
return EXIT_FAILURE; // Not sure what status of child is.
|
||||||
|
}
|
||||||
|
else // We are in the child process. Start the program the parent wants to run.
|
||||||
|
{
|
||||||
|
|
||||||
|
if (execv(prog, const_cast<char**>(args)) == -1) // Does not return.
|
||||||
|
{
|
||||||
|
perror("unreachable 0\n");
|
||||||
|
_Exit(127);
|
||||||
|
}
|
||||||
|
printf("unreachable 2\n");
|
||||||
|
}
|
||||||
|
printf("unreachable 2\n");
|
||||||
|
// Unreachable.
|
||||||
|
assert(false);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
#endif // !USE_SHELL_API
|
||||||
|
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
extract_gz_file(const std::string&, const std::string& gz_file, const std::string&)
|
extract_gz_file(const std::string&, const std::string& gz_file, const std::string&)
|
||||||
{
|
{
|
||||||
if (std::system(("tar -xzf " + gz_file + " -C " + install).c_str()) == EXIT_SUCCESS)
|
#if USE_SHELL_API
|
||||||
|
bool unzipped = std::system(("tar -xzf " + gz_file + " -C " + install).c_str()) == EXIT_SUCCESS;
|
||||||
|
#else // !USE_SHELL_API
|
||||||
|
const char prog[] = {"/usr/bin/tar"};
|
||||||
|
const char*const args[] =
|
||||||
|
{
|
||||||
|
prog, "-xzf", gz_file.c_str(), "-C", install.c_str(), nullptr
|
||||||
|
};
|
||||||
|
bool unzipped = (run_program(prog, args) == EXIT_SUCCESS);
|
||||||
|
#endif // !USE_SHELL_API
|
||||||
|
if (unzipped)
|
||||||
{
|
{
|
||||||
delete_file(gz_file);
|
delete_file(gz_file);
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user