lifeng 9453c52364 iSulad: update Mulan v1 to Mulan v2
Signed-off-by: lifeng <lifeng68@huawei.com>
2020-04-27 09:43:55 +08:00

304 lines
6.2 KiB
C

/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: leizhongkai
* Create: 2020-1-21
* Description: common functions of isulad-shim
******************************************************************************/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <linux/limits.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <stdarg.h>
#include "common.h"
extern int g_log_fd;
int set_fd_no_inherited(int fd)
{
int ret = SHIM_ERR;
int flag = -1;
flag = fcntl(fd, F_GETFD, 0);
if (flag < 0) {
return SHIM_ERR;
}
ret = fcntl(fd, F_SETFD, flag | FD_CLOEXEC);
if (ret != 0) {
return SHIM_ERR;
}
return SHIM_OK;
}
ssize_t read_nointr(int fd, void *buf, size_t count)
{
ssize_t nret;
if (buf == NULL) {
return -1;
}
for (;;) {
nret = read(fd, buf, count);
if (nret < 0 && (errno == EINTR || errno == EAGAIN)) {
continue;
} else {
break;
}
}
return nret;
}
ssize_t write_nointr(int fd, const void *buf, size_t count)
{
ssize_t nret;
if (buf == NULL) {
return -1;
}
for (;;) {
nret = write(fd, buf, count);
if (nret < 0 && (errno == EINTR || errno == EAGAIN)) {
continue;
} else {
break;
}
}
return nret;
}
bool file_exists(const char *f)
{
struct stat buf;
int nret;
if (f == NULL) {
return false;
}
nret = stat(f, &buf);
if (nret < 0) {
return false;
}
return true;
}
int cmd_combined_output(const char *binary, const char *params[], void *output, int *output_len)
{
int ret = SHIM_ERR;
int status = 0;
int exec_fd[2] = { -1, -1 };
int stdio[2] = { -1, -1 };
pid_t pid = 0;
char exec_buff[BUFSIZ] = { 0 };
ssize_t nread;
if (pipe2(exec_fd, O_CLOEXEC) != 0) {
return SHIM_ERR;
}
if (pipe2(stdio, O_CLOEXEC) != 0) {
return SHIM_ERR;
}
pid = fork();
if (pid == (pid_t) - 1) {
return SHIM_ERR;
}
// child
if (pid == (pid_t)0) {
close(exec_fd[0]);
close(stdio[0]);
dup2(stdio[1], 1);
dup2(stdio[1], 2);
execvp(binary, (char * const *)params);
(void)dprintf(exec_fd[1], "fork/exec error: %s", strerror(errno));
_exit(EXIT_FAILURE);
}
// parent
close(exec_fd[1]);
close(stdio[1]);
nread = read_nointr(exec_fd[0], exec_buff, BUFSIZ - 1);
if (nread > 0) {
ret = SHIM_ERR;
goto out;
}
*output_len = read_nointr(stdio[0], output, BUFSIZ - 1);
close(stdio[0]);
close(exec_fd[0]);
wait(&status);
ret = SHIM_OK;
out:
if (ret != SHIM_OK && pid != 0) {
kill(pid, 9);
}
return ret;
}
int generate_random_str(char *id, size_t len)
{
int fd = -1;
int num = 0;
size_t i;
const int m = 256;
len = len / 2;
fd = open("/dev/urandom", O_RDONLY);
if (fd == -1) {
return SHIM_ERR;
}
for (i = 0; i < len; i++) {
int nret;
if (read(fd, &num, sizeof(int)) < 0) {
close(fd);
return SHIM_ERR;
}
unsigned char rs = (unsigned char)(num % m);
nret = snprintf((id + i * 2), ((len - i) * 2 + 1), "%02x", (unsigned int)rs);
if (nret < 0) {
close(fd);
return SHIM_ERR;
}
}
close(fd);
id[i * 2] = '\0';
return SHIM_OK;
}
void write_message(int fd, const char *level, const char *fmt, ...)
{
#define MAX_MSG_JSON_TEMPLATE 32
#define MAX_MESSAGE_CONTENT_LEN 128
#define MAX_MESSAGE_LEN (MAX_MSG_JSON_TEMPLATE + MAX_MESSAGE_CONTENT_LEN)
if (fd < 0) {
return;
}
char buf[MAX_MESSAGE_CONTENT_LEN] = { 0 };
char msg[MAX_MESSAGE_LEN] = { 0 };
int nwrite = -1;
va_list arg_list;
va_start(arg_list, fmt);
vsnprintf(buf, MAX_MESSAGE_CONTENT_LEN, fmt, arg_list);
va_end(arg_list);
snprintf(msg, MAX_MESSAGE_LEN - 1, "{\"level\": \"%s\", \"msg\": \"%s\"}\n", level, buf);
nwrite = write(fd, msg, strlen(msg));
if (nwrite != strlen(msg)) {
return;
}
return;
}
/* note: This function can only read small text file. */
char *read_text_file(const char *path)
{
char *buf = NULL;
long len = 0;
size_t readlen = 0;
FILE *filp = NULL;
const long max_size = 10 * 1024 * 1024; /* 10M */
if (path == NULL) {
return NULL;
}
filp = fopen(path, "r");
if (filp == NULL) {
goto err_out;
}
if (fseek(filp, 0, SEEK_END)) {
goto err_out;
}
len = ftell(filp);
if (len > max_size) {
goto err_out;
}
if (fseek(filp, 0, SEEK_SET)) {
goto err_out;
}
buf = (char *)calloc(1, (size_t)(len + 1));
if (buf == NULL) {
goto err_out;
}
readlen = fread(buf, 1, (size_t)len, filp);
if (((readlen < (size_t)len) && (!feof(filp))) || (readlen > (size_t)len)) {
if (buf != NULL) {
free(buf);
buf = NULL;
}
goto err_out;
}
buf[(size_t)len] = 0;
err_out:
if (filp != NULL) {
fclose(filp);
}
return buf;
}
void close_fd(int *pfd)
{
if (pfd != NULL && *pfd != -1) {
close(*pfd);
*pfd = -1;
}
}
int open_no_inherit(const char *path, int flag, mode_t mode)
{
int fd = -1;
int ret = SHIM_ERR;
fd = open(path, flag, mode);
if (fd < 0) {
return -1;
}
ret = set_fd_no_inherited(fd);
if (ret != SHIM_OK) {
close(fd);
return -1;
}
return fd;
}