mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 07:31:57 +00:00
Merge pull request #52198 from azat/qemu-compressor
Fix self extracting binaries under qemu linux-user (qemu-$ARCH-static)
This commit is contained in:
commit
d816d8b92f
@ -362,11 +362,12 @@ int decompressFiles(int input_fd, char * path, char * name, bool & have_compress
|
||||
|
||||
#else
|
||||
|
||||
int read_exe_path(char *exe, size_t/* buf_sz*/)
|
||||
int read_exe_path(char *exe, size_t buf_sz)
|
||||
{
|
||||
if (realpath("/proc/self/exe", exe) == nullptr)
|
||||
return 1;
|
||||
return 0;
|
||||
ssize_t n = readlink("/proc/self/exe", exe, buf_sz - 1);
|
||||
if (n > 0)
|
||||
exe[n] = '\0';
|
||||
return n > 0 && n < static_cast<ssize_t>(buf_sz);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -430,58 +431,55 @@ int main(int/* argc*/, char* argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lock = -1;
|
||||
/// Protection from double decompression
|
||||
#if !defined(OS_DARWIN) && !defined(OS_FREEBSD)
|
||||
/// get inode of this executable
|
||||
uint64_t inode = getInode(self);
|
||||
/// In some cases /proc/self/maps may not contain the inode for the
|
||||
/// /proc/self/exe, one of such examples are using qemu-*-static, in this
|
||||
/// case maps will be proxied through the qemu, and it will remove
|
||||
/// information about itself from it.
|
||||
if (inode != 0)
|
||||
if (inode == 0)
|
||||
{
|
||||
std::stringstream lock_path; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
||||
lock_path << "/tmp/" << name << ".decompression." << inode << ".lock";
|
||||
lock = open(lock_path.str().c_str(), O_CREAT | O_RDWR, 0666);
|
||||
if (lock < 0)
|
||||
std::cerr << "Unable to obtain inode for exe '" << self << "'." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::stringstream lock_path; // STYLE_CHECK_ALLOW_STD_STRING_STREAM
|
||||
lock_path << "/tmp/" << name << ".decompression." << inode << ".lock";
|
||||
int lock = open(lock_path.str().c_str(), O_CREAT | O_RDWR, 0666);
|
||||
if (lock < 0)
|
||||
{
|
||||
perror("lock open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// lock file should be closed on exec call
|
||||
fcntl(lock, F_SETFD, FD_CLOEXEC);
|
||||
|
||||
if (lockf(lock, F_LOCK, 0))
|
||||
{
|
||||
perror("lockf");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// inconsistency in WSL1 Ubuntu - inode reported in /proc/self/maps is a 64bit to
|
||||
/// 32bit conversion of input_info.st_ino
|
||||
if (input_info.st_ino & 0xFFFFFFFF00000000 && !(inode & 0xFFFFFFFF00000000))
|
||||
input_info.st_ino &= 0x00000000FFFFFFFF;
|
||||
|
||||
/// if decompression was performed by another process since this copy was started
|
||||
/// then file referred by path "self" is already pointing to different inode
|
||||
if (input_info.st_ino != inode)
|
||||
{
|
||||
struct stat lock_info;
|
||||
if (0 != fstat(lock, &lock_info))
|
||||
{
|
||||
perror("lock open");
|
||||
perror("fstat lock");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// lock file should be closed on exec call
|
||||
fcntl(lock, F_SETFD, FD_CLOEXEC);
|
||||
/// size 1 of lock file indicates that another decompressor has found active executable
|
||||
if (lock_info.st_size == 1)
|
||||
execv(self, argv);
|
||||
|
||||
if (lockf(lock, F_LOCK, 0))
|
||||
{
|
||||
perror("lockf");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// inconsistency in WSL1 Ubuntu - inode reported in /proc/self/maps is a 64bit to
|
||||
/// 32bit conversion of input_info.st_ino
|
||||
if (input_info.st_ino & 0xFFFFFFFF00000000 && !(inode & 0xFFFFFFFF00000000))
|
||||
input_info.st_ino &= 0x00000000FFFFFFFF;
|
||||
|
||||
/// if decompression was performed by another process since this copy was started
|
||||
/// then file referred by path "self" is already pointing to different inode
|
||||
if (input_info.st_ino != inode)
|
||||
{
|
||||
struct stat lock_info;
|
||||
if (0 != fstat(lock, &lock_info))
|
||||
{
|
||||
perror("fstat lock");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// size 1 of lock file indicates that another decompressor has found active executable
|
||||
if (lock_info.st_size == 1)
|
||||
execv(self, argv);
|
||||
|
||||
printf("No target executable - decompression only was performed.\n");
|
||||
return 0;
|
||||
}
|
||||
printf("No target executable - decompression only was performed.\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -549,19 +547,21 @@ int main(int/* argc*/, char* argv[])
|
||||
|
||||
if (has_exec)
|
||||
{
|
||||
#if !defined(OS_DARWIN) && !defined(OS_FREEBSD)
|
||||
/// write one byte to the lock in case other copies of compressed are running to indicate that
|
||||
/// execution should be performed
|
||||
if (lock >= 0)
|
||||
write(lock, "1", 1);
|
||||
write(lock, "1", 1);
|
||||
#endif
|
||||
execv(self, argv);
|
||||
|
||||
/// This part of code will be reached only if error happened
|
||||
perror("execv");
|
||||
return 1;
|
||||
}
|
||||
#if !defined(OS_DARWIN) && !defined(OS_FREEBSD)
|
||||
/// since inodes can be reused - it's a precaution if lock file already exists and have size of 1
|
||||
if (lock >= 0)
|
||||
ftruncate(lock, 0);
|
||||
ftruncate(lock, 0);
|
||||
#endif
|
||||
|
||||
printf("No target executable - decompression only was performed.\n");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user