diff --git a/HISTORY b/HISTORY index e4e837c..340331d 100644 --- a/HISTORY +++ b/HISTORY @@ -1,4 +1,9 @@ +Version 1.59 2022-07-21 + * open file with flag O_CLOEXEC + * add global var g_set_cloexec and macro FC_SET_CLOEXEC + * add function fc_get_first_lines + Version 1.58 2022-06-04 * add function conn_pool_connect_server_ex1 to support service name * add function conn_pool_get_connection_ex to support service name diff --git a/INSTALL b/INSTALL index eae6fbd..0a74471 100644 --- a/INSTALL +++ b/INSTALL @@ -12,6 +12,5 @@ Chinese language: http://www.fastken.com/ # the command lines as: git clone https://github.com/happyfish100/libfastcommon.git - cd libfastcommon; git checkout V1.0.57 + cd libfastcommon; git checkout V1.0.59 ./make.sh clean && ./make.sh && ./make.sh install - diff --git a/libfastcommon.spec b/libfastcommon.spec index 4c42478..b8302a3 100644 --- a/libfastcommon.spec +++ b/libfastcommon.spec @@ -3,7 +3,7 @@ %define CommitVersion %(echo $COMMIT_VERSION) Name: libfastcommon -Version: 1.0.58 +Version: 1.0.59 Release: 1%{?dist} Summary: c common functions library extracted from my open source projects FastDFS License: LGPL diff --git a/php-fastcommon/fastcommon.c b/php-fastcommon/fastcommon.c index 0f36b3a..21d14a9 100644 --- a/php-fastcommon/fastcommon.c +++ b/php-fastcommon/fastcommon.c @@ -1237,8 +1237,8 @@ static PHPFileContext *fetch_file_context(const char *filename) static int fc_open_file(PHPFileContext *ctx) { - if ((ctx->fd = open(ctx->filename, O_WRONLY | - O_CREAT | O_APPEND, 0644)) < 0) + if ((ctx->fd = open(ctx->filename, O_WRONLY | O_CREAT | + O_APPEND | O_CLOEXEC, 0644)) < 0) { logError("file: "__FILE__", line: %d, " "open file \"%s\" to write fail, " diff --git a/src/buffered_file_writer.c b/src/buffered_file_writer.c index 00b0ab6..307041f 100644 --- a/src/buffered_file_writer.c +++ b/src/buffered_file_writer.c @@ -49,7 +49,8 @@ int buffered_file_writer_open_ex(BufferedFileWriter *writer, } snprintf(writer->filename, sizeof(writer->filename), "%s", filename); - writer->fd = open(writer->filename, O_WRONLY | O_CREAT | O_TRUNC, mode); + writer->fd = open(writer->filename, O_WRONLY | + O_CREAT | O_TRUNC | O_CLOEXEC, mode); if (writer->fd < 0) { result = errno != 0 ? errno : EIO; diff --git a/src/connection_pool.c b/src/connection_pool.c index ff8fa3c..6d05941 100644 --- a/src/connection_pool.c +++ b/src/connection_pool.c @@ -181,7 +181,8 @@ int conn_pool_async_connect_server_ex(ConnectionInfo *conn, return result; } -static inline void conn_pool_get_key(const ConnectionInfo *conn, char *key, int *key_len) +static inline void conn_pool_get_key(const ConnectionInfo *conn, + char *key, int *key_len) { *key_len = sprintf(key, "%s_%u", conn->ip_addr, conn->port); } diff --git a/src/id_generator.c b/src/id_generator.c index bf0b5ef..b666af8 100644 --- a/src/id_generator.c +++ b/src/id_generator.c @@ -123,13 +123,14 @@ int id_generator_init_extra_ex(struct idg_context *context, const char *filename mid = ntohl(ip_addr.s_addr) & ((1 << mid_bits) - 1); } - if ((context->fd = open(filename, O_RDWR)) < 0) + if ((context->fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) { if (errno == ENOENT) { mode_t old_mode; old_mode = umask(0); - if ((context->fd=open(filename, O_RDWR | O_CREAT, mode)) < 0) + if ((context->fd=open(filename, O_RDWR | O_CREAT | + O_CLOEXEC, mode)) < 0) { result = errno != 0 ? errno : EACCES; } diff --git a/src/logger.c b/src/logger.c index 2a8f600..4541c61 100644 --- a/src/logger.c +++ b/src/logger.c @@ -158,8 +158,8 @@ static int log_print_header(LogContext *pContext) static int log_open(LogContext *pContext) { int result; - if ((pContext->log_fd = open(pContext->log_filename, O_WRONLY | \ - O_CREAT | O_APPEND | pContext->fd_flags, 0644)) < 0) + if ((pContext->log_fd = open(pContext->log_filename, O_WRONLY | O_CREAT | + O_APPEND | O_CLOEXEC | pContext->fd_flags, 0644)) < 0) { fprintf(stderr, "open log file \"%s\" to write fail, " \ "errno: %d, error info: %s\n", \ diff --git a/src/pthread_func.h b/src/pthread_func.h index 8f5c0a3..e27b5b4 100644 --- a/src/pthread_func.h +++ b/src/pthread_func.h @@ -114,9 +114,9 @@ static inline void fc_timedwait_sec(pthread_mutex_t *lock, { struct timespec ts; - PTHREAD_MUTEX_LOCK(lock); ts.tv_sec = get_current_time() + timeout; ts.tv_nsec = 0; + PTHREAD_MUTEX_LOCK(lock); pthread_cond_timedwait(cond, lock, &ts); PTHREAD_MUTEX_UNLOCK(lock); } @@ -128,9 +128,9 @@ static inline void fc_timedwait_ms(pthread_mutex_t *lock, struct timespec ts; expires_ms = get_current_time_ms() + timeout_ms; - PTHREAD_MUTEX_LOCK(lock); ts.tv_sec = expires_ms / 1000; ts.tv_nsec = (expires_ms % 1000) * (1000 * 1000); + PTHREAD_MUTEX_LOCK(lock); pthread_cond_timedwait(cond, lock, &ts); PTHREAD_MUTEX_UNLOCK(lock); } diff --git a/src/sched_thread.c b/src/sched_thread.c index e140433..4628436 100644 --- a/src/sched_thread.c +++ b/src/sched_thread.c @@ -127,9 +127,9 @@ static int sched_init_entries(ScheduleEntry *entries, const int count) if (pEntry->interval <= 0) { - logError("file: "__FILE__", line: %d, " \ - "shedule interval %d <= 0", \ - __LINE__, pEntry->interval); + logError("file: "__FILE__", line: %d, " + "shedule id: %d, interval %d <= 0", + __LINE__, pEntry->id, pEntry->interval); return EINVAL; } diff --git a/src/shared_func.c b/src/shared_func.c index c1fa180..85ab39b 100644 --- a/src/shared_func.c +++ b/src/shared_func.c @@ -45,6 +45,8 @@ #endif #endif +bool g_set_cloexec = false; + char *formatDatetime(const time_t nTime, \ const char *szDateFormat, \ char *buff, const int buff_size) @@ -335,7 +337,7 @@ int getUserProcIds(const char *progName, const bool bAllOwners, \ if ((bAllOwners || (statbuf.st_uid == myuid)) && S_ISDIR(statbuf.st_mode)) { sprintf(filepath, "%s/cmdline", fullpath); - if ((fd = open(filepath, O_RDONLY))<0) + if ((fd=open(filepath, O_RDONLY | O_CLOEXEC))<0) { continue; } @@ -734,7 +736,7 @@ int fc_get_file_line_count_ex(const char *filename, return ENOMEM; } - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { result = errno != 0 ? errno : EACCES; logError("file: "__FILE__", line: %d, " @@ -1314,7 +1316,7 @@ int getFileContent(const char *filename, char **buff, int64_t *file_size) } } - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { *buff = NULL; @@ -1368,7 +1370,7 @@ int getFileContentEx(const char *filename, char *buff, return EINVAL; } - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { *size = 0; @@ -1406,7 +1408,7 @@ int writeToFile(const char *filename, const char *buff, const int file_size) int fd; int result; - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); if (fd < 0) { result = errno != 0 ? errno : EIO; @@ -1480,7 +1482,7 @@ int fc_copy_file(const char *src_filename, const char *dest_filename) int bytes; char buff[16 * 1024]; - src_fd = open(src_filename, O_RDONLY); + src_fd = open(src_filename, O_RDONLY | O_CLOEXEC); if (src_fd < 0) { result = errno != 0 ? errno : ENOENT; @@ -1490,7 +1492,8 @@ int fc_copy_file(const char *src_filename, const char *dest_filename) return result; } - dest_fd = open(dest_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + dest_fd = open(dest_filename, O_WRONLY | O_CREAT | + O_TRUNC | O_CLOEXEC, 0644); if (dest_fd < 0) { result = errno != 0 ? errno : EIO; @@ -3709,9 +3712,11 @@ int fc_get_first_line(const char *filename, char *buff, read_bytes = buff_size - 1; if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) { + line->len = 0; return result; } if (read_bytes == 0) { + line->len = 0; return ENOENT; } @@ -3721,6 +3726,7 @@ int fc_get_first_line(const char *filename, char *buff, "file: %s, line no: 1, " "expect new line char \"\\n\"", __LINE__, filename); + line->len = 0; return EINVAL; } line->str = buff; @@ -3728,6 +3734,54 @@ int fc_get_first_line(const char *filename, char *buff, return 0; } +int fc_get_first_lines(const char *filename, char *buff, + const int buff_size, string_t *lines, int *count) +{ + int result; + int target_count; + int64_t read_bytes; + char *p; + char *end; + char *line_end; + + if (*count <= 0) { + lines->len = 0; + return EINVAL; + } + + read_bytes = buff_size - 1; + if ((result=getFileContentEx(filename, buff, 0, &read_bytes)) != 0) { + *count = 0; + lines->len = 0; + return result; + } + if (read_bytes == 0) { + *count = 0; + lines->len = 0; + return ENOENT; + } + + target_count = *count; + *count = 0; + p = buff; + end = buff + read_bytes; + while (p < end) { + line_end = (char *)memchr(p, '\n', end - p); + if (line_end == NULL) { + break; + } + + p = line_end + 1; + if (++(*count) == target_count) { + break; + } + } + + lines->str = buff; + lines->len = p - buff; + return (*count > 0 ? 0 : ENOENT); +} + int fc_get_last_line(const char *filename, char *buff, const int buff_size, int64_t *file_size, string_t *line) { @@ -3736,10 +3790,12 @@ int fc_get_last_line(const char *filename, char *buff, int result; if ((result=getFileSize(filename, file_size)) != 0) { + line->len = 0; return result; } if (*file_size == 0) { + line->len = 0; return ENOENT; } @@ -3752,9 +3808,11 @@ int fc_get_last_line(const char *filename, char *buff, if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) { + line->len = 0; return result; } if (read_bytes == 0) { + line->len = 0; return ENOENT; } @@ -3779,16 +3837,19 @@ int fc_get_last_lines(const char *filename, char *buff, int result; if (*count <= 0) { + lines->len = 0; return EINVAL; } if ((result=getFileSize(filename, &file_size)) != 0) { *count = 0; + lines->len = 0; return result; } if (file_size == 0) { *count = 0; + lines->len = 0; return ENOENT; } @@ -3801,10 +3862,13 @@ int fc_get_last_lines(const char *filename, char *buff, if ((result=getFileContentEx(filename, buff, offset, &read_bytes)) != 0) { + *count = 0; + lines->len = 0; return result; } if (read_bytes == 0) { *count = 0; + lines->len = 0; return ENOENT; } diff --git a/src/shared_func.h b/src/shared_func.h index eff3f92..bdf42ff 100644 --- a/src/shared_func.h +++ b/src/shared_func.h @@ -41,10 +41,20 @@ normalize_path_ex(from, filename, full_filename, size, \ NORMALIZE_FLAGS_URL_ENABLED_AND_APPEND_PARAMS) +#define FC_SET_CLOEXEC(fd) \ + if (g_set_cloexec) fd_set_cloexec(fd) + #ifdef __cplusplus extern "C" { #endif + extern bool g_set_cloexec; + +static inline void fc_enable_fd_cloexec(const bool cloexec) +{ + g_set_cloexec = cloexec; +} + /** lowercase the string * parameters: * src: input string, will be changed @@ -1146,6 +1156,9 @@ int fc_copy_to_path(const char *src_filename, const char *dest_path); int fc_get_first_line(const char *filename, char *buff, const int buff_size, string_t *line); +int fc_get_first_lines(const char *filename, char *buff, + const int buff_size, string_t *lines, int *count); + int fc_get_last_line(const char *filename, char *buff, const int buff_size, int64_t *file_size, string_t *line); @@ -1198,7 +1211,7 @@ int fc_safe_write_file_init(SafeWriteFileInfo *fi, static inline int fc_safe_write_file_open(SafeWriteFileInfo *fi) { - const int flags = O_WRONLY | O_CREAT | O_TRUNC; + const int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC; int result; if ((fi->fd=open(fi->tmp_filename, flags, 0644)) < 0) { diff --git a/src/sockopt.c b/src/sockopt.c index 127c407..b45b364 100644 --- a/src/sockopt.c +++ b/src/sockopt.c @@ -1012,6 +1012,7 @@ int socketCreateEx2(int af, const char *server_ip, return -1; } + FC_SET_CLOEXEC(sock); SET_SOCKOPT_NOSIGPIPE(sock); if (flags != 0) { @@ -1402,6 +1403,7 @@ int socketServer2(int af, const char *bind_ipaddr, const int port, int *err_no) return -1; } + FC_SET_CLOEXEC(sock); SET_SOCKOPT_NOSIGPIPE(sock); result = 1; @@ -1476,7 +1478,8 @@ int tcprecvfile(int sock, const char *filename, const int64_t file_bytes, \ recv_func = tcprecvdata_ex; } - write_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + write_fd = open(filename, O_WRONLY | O_CREAT | + O_TRUNC | O_CLOEXEC, 0644); if (write_fd < 0) { return errno != 0 ? errno : EACCES; @@ -1544,7 +1547,7 @@ int tcprecvfile(int sock, const char *filename, const int64_t file_bytes, \ break; } - read_fd = open(filename, O_RDONLY); + read_fd = open(filename, O_RDONLY | O_CLOEXEC); if (read_fd < 0) { return errno != 0 ? errno : EACCES; @@ -1627,7 +1630,8 @@ int tcprecvfile_ex(int sock, const char *filename, const int64_t file_bytes, \ recv_func = tcprecvdata_ex; } - fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); + fd = open(filename, O_WRONLY | O_CREAT | + O_TRUNC | O_CLOEXEC, 0644); if (fd < 0) { return errno != 0 ? errno : EACCES; @@ -1761,7 +1765,7 @@ int tcpsendfile_ex(int sock, const char *filename, const int64_t file_offset, \ int64_t remain_bytes; #endif - fd = open(filename, O_RDONLY); + fd = open(filename, O_RDONLY | O_CLOEXEC); if (fd < 0) { *total_send_bytes = 0; @@ -1779,7 +1783,7 @@ int tcpsendfile_ex(int sock, const char *filename, const int64_t file_offset, \ if (flags & O_NONBLOCK) { - if (fcntl(sock, F_SETFL, flags & ~O_NONBLOCK) == -1) + if (fcntl(sock, F_SETFL, flags & ~O_NONBLOCK) < 0) { *total_send_bytes = 0; return errno != 0 ? errno : EACCES; @@ -1873,7 +1877,7 @@ int tcpsendfile_ex(int sock, const char *filename, const int64_t file_offset, \ if (flags & O_NONBLOCK) //restore { - if (fcntl(sock, F_SETFL, flags) == -1) + if (fcntl(sock, F_SETFL, flags) < 0) { result = errno != 0 ? errno : EACCES; } @@ -2124,7 +2128,7 @@ int tcpsetnonblockopt(int fd) return errno != 0 ? errno : EACCES; } - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) + if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { logError("file: "__FILE__", line: %d, " \ "fcntl failed, errno: %d, error info: %s.", \ diff --git a/src/system_info.c b/src/system_info.c index faf7b5c..f6cb3d4 100644 --- a/src/system_info.c +++ b/src/system_info.c @@ -843,7 +843,7 @@ int get_device_block_size(const char *device, int *block_size) int fd; size_t bs; - if ((fd=open(device, O_RDONLY)) < 0) { + if ((fd=open(device, O_RDONLY | O_CLOEXEC)) < 0) { result = errno != 0 ? errno : ENOENT; logError("file: "__FILE__", line: %d, " "open device %s fail, errno: %d, error info: %s", @@ -885,7 +885,9 @@ static int get_block_size_by_write(const char *path, int *block_size) snprintf(tmp_filename, sizeof(tmp_filename), "%s/.blksize-test.tmp", path); - if ((fd=open(tmp_filename, O_WRONLY | O_CREAT | O_DIRECT, 0755)) < 0) { + if ((fd=open(tmp_filename, O_WRONLY | O_CREAT | + O_DIRECT | O_CLOEXEC, 0755)) < 0) + { result = errno != 0 ? errno : ENOENT; logError("file: "__FILE__", line: %d, " "open file %s fail, errno: %d, error info: %s",