diff --git a/utils/self-extracting-executable/decompressor.cpp b/utils/self-extracting-executable/decompressor.cpp index 9bdc95d8bcf..c0c97b1d711 100644 --- a/utils/self-extracting-executable/decompressor.cpp +++ b/utils/self-extracting-executable/decompressor.cpp @@ -21,11 +21,16 @@ #endif #if defined OS_DARWIN +# include # include // define 64 bit macros # define le64toh(x) OSSwapLittleToHostInt64(x) #endif +#if defined(OS_FREEBSD) +# include +#endif + #include "types.h" /// decompress part @@ -82,7 +87,7 @@ int decompress(char * input, char * output, off_t start, off_t end, size_t max_n pid = fork(); if (-1 == pid) { - perror(nullptr); + perror("fork"); /// If fork failed just decompress data in main process. if (0 != doDecompress(input, output, in_pointer, out_pointer, size, decompressed_size, dctx)) { @@ -170,7 +175,7 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress struct stat info_in; if (0 != fstat(input_fd, &info_in)) { - perror(nullptr); + perror("fstat"); return 1; } @@ -178,7 +183,7 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress char * input = static_cast(mmap(nullptr, info_in.st_size, PROT_READ, MAP_PRIVATE, input_fd, 0)); if (input == MAP_FAILED) { - perror(nullptr); + perror("mmap"); return 1; } @@ -202,9 +207,9 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress struct statfs fs_info; if (0 != fstatfs(input_fd, &fs_info)) { - perror(nullptr); + perror("fstatfs"); if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); return 1; } if (fs_info.f_blocks * info_in.st_blksize < decompressed_full_size) @@ -241,7 +246,7 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress int fd = mkstemp(file_name); if (fd == -1) { - perror(nullptr); + perror("mkstemp"); return 1; } close(fd); @@ -254,18 +259,18 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress if (output_fd == -1) { - perror(nullptr); + perror("open"); if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); return 1; } /// Prepare output file if (0 != ftruncate(output_fd, le64toh(file_info.uncompressed_size))) { - perror(nullptr); + perror("ftruncate"); if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); return 1; } @@ -278,9 +283,9 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress ); if (output == MAP_FAILED) { - perror(nullptr); + perror("mmap"); if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); return 1; } @@ -288,29 +293,70 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress if (0 != decompress(input, output, le64toh(file_info.start), le64toh(file_info.end))) { if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); if (0 != munmap(output, le64toh(file_info.uncompressed_size))) - perror(nullptr); + perror("munmap"); return 1; } if (0 != fsync(output_fd)) - perror(nullptr); + perror("fsync"); if (0 != close(output_fd)) - perror(nullptr); + perror("close"); } if (0 != munmap(input, info_in.st_size)) - perror(nullptr); + perror("munmap"); return 0; } +#if defined(OS_DARWIN) + + int read_exe_path(char *exe, size_t buf_sz) + { + uint32_t size = buf_sz; + char apple[size]; + if (_NSGetExecutablePath(apple, &size) != 0) + return 1; + if (realpath(apple, exe) == nullptr) + return 1; + return 0; + } + +#elif defined(OS_FREEBSD) + + int read_exe_path(char *exe, size_t buf_sz) + { + int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t length = buf_sz; + int error = sysctl(name, 4, exe, &length, nullptr, 0); + if (error < 0 || length <= 1) + return 1; + return 0; + } + +#else + + int read_exe_path(char *exe, size_t/* buf_sz*/) + { + if (realpath("/proc/self/exe", exe) == nullptr) + return 1; + return 0; + } + +#endif int main(int/* argc*/, char* argv[]) { - char file_path[strlen(argv[0]) + 1]; - memset(file_path, 0, sizeof(file_path)); - strcpy(file_path, argv[0]); + char self[4096] = {0}; + if (read_exe_path(self, 4096) == -1) + { + perror("read_exe_path"); + return 1; + } + + char file_path[strlen(self) + 1]; + strcpy(file_path, self); char * path = nullptr; char * name = strrchr(file_path, '/'); @@ -323,10 +369,10 @@ int main(int/* argc*/, char* argv[]) else name = file_path; - int input_fd = open(argv[0], O_RDONLY); + int input_fd = open(self, O_RDONLY); if (input_fd == -1) { - perror(nullptr); + perror("open"); return 1; } @@ -339,16 +385,16 @@ int main(int/* argc*/, char* argv[]) { printf("Error happened during decompression.\n"); if (0 != close(input_fd)) - perror(nullptr); + perror("close"); return 1; } if (0 != close(input_fd)) - perror(nullptr); + perror("close"); - if (unlink(argv[0])) + if (unlink(self)) { - perror(nullptr); + perror("unlink"); return 1; } @@ -357,34 +403,34 @@ int main(int/* argc*/, char* argv[]) else { const char * const decompressed_name_fmt = "%s.decompressed.%s"; - int decompressed_name_len = snprintf(nullptr, 0, decompressed_name_fmt, argv[0], decompressed_suffix); + int decompressed_name_len = snprintf(nullptr, 0, decompressed_name_fmt, self, decompressed_suffix); char decompressed_name[decompressed_name_len + 1]; - (void)snprintf(decompressed_name, decompressed_name_len + 1, decompressed_name_fmt, argv[0], decompressed_suffix); + (void)snprintf(decompressed_name, decompressed_name_len + 1, decompressed_name_fmt, self, decompressed_suffix); std::error_code ec; - std::filesystem::copy_file(static_cast(decompressed_name), argv[0], ec); + std::filesystem::copy_file(static_cast(decompressed_name), static_cast(self), ec); if (ec) { std::cerr << ec.message() << std::endl; return 1; } - if (chmod(argv[0], decompressed_umask)) + if (chmod(self, decompressed_umask)) { - perror(nullptr); + perror("chmod"); return 1; } if (unlink(decompressed_name)) { - perror(nullptr); + perror("unlink"); return 1; } - execv(argv[0], argv); + execv(self, argv); /// This part of code will be reached only if error happened - perror(nullptr); + perror("execv"); return 1; } }