build: 统一 _GNU_SOURCE 宏定义到 Makefile

- config.c/http.c/static.c/server.c: 移除各自的 #define _GNU_SOURCE
- Makefile CFLAGS: 添加 -D_GNU_SOURCE,保证所有翻译单元一致
- 避免重复定义,减少源文件样板代码
This commit is contained in:
xfy911 2026-06-04 00:17:55 +08:00
parent 252530dfe7
commit 0d8c36ef25
5 changed files with 88 additions and 16 deletions

View File

@ -6,7 +6,7 @@ COCO_INCLUDE ?= $(COCO_DIR)/include
COCO_LIB ?= $(COCO_DIR)/build
CC = gcc
CFLAGS = -Wall -Wextra -O2 -std=c11 -I$(COCO_INCLUDE)
CFLAGS = -Wall -Wextra -O2 -std=c11 -D_GNU_SOURCE -I$(COCO_INCLUDE)
LDFLAGS = -L$(COCO_LIB) -lcoco -lpthread -lm -luring -lz
# 调试模式
@ -20,7 +20,7 @@ PREFIX ?= /usr/local
BINDIR = $(PREFIX)/bin
# 源文件
SRCS = main.c server.c http.c static.c log.c config.c
SRCS = main.c server.c http.c static.c log.c config.c multipart.c
OBJS = $(SRCS:.c=.o)
TARGET = cocoon
@ -78,17 +78,20 @@ unit-test: $(UNIT_TEST_BINS)
fi
# 单元测试编译规则
$(UNIT_TEST_DIR)/test_multipart: $(UNIT_TEST_DIR)/test_multipart.c multipart.c $(UNITY_SRC)
$(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_multipart.c multipart.c $(UNITY_SRC) -lm
$(UNIT_TEST_DIR)/test_http: $(UNIT_TEST_DIR)/test_http.c http.c log.c $(UNITY_SRC)
$(CC) $(CFLAGS) -D_GNU_SOURCE -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_http.c http.c log.c $(UNITY_SRC) -lm
$(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_http.c http.c log.c $(UNITY_SRC) -lm
$(UNIT_TEST_DIR)/test_static: $(UNIT_TEST_DIR)/test_static.c http.c log.c $(UNITY_SRC)
$(CC) $(CFLAGS) -D_GNU_SOURCE -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_static.c http.c log.c $(UNITY_SRC) -lm -lz
$(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_static.c http.c log.c $(UNITY_SRC) -lm -lz
$(UNIT_TEST_DIR)/test_log: $(UNIT_TEST_DIR)/test_log.c log.c $(UNITY_SRC)
$(CC) $(CFLAGS) -D_GNU_SOURCE -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_log.c log.c $(UNITY_SRC) -lm
$(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_log.c log.c $(UNITY_SRC) -lm
$(UNIT_TEST_DIR)/test_config: $(UNIT_TEST_DIR)/test_config.c config.c log.c $(UNITY_SRC)
$(CC) $(CFLAGS) -D_GNU_SOURCE -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_config.c config.c log.c $(UNITY_SRC) -lm
$(CC) $(CFLAGS) -I. -I$(UNIT_TEST_DIR)/../unity -o $@ $(UNIT_TEST_DIR)/test_config.c config.c log.c $(UNITY_SRC) -lm
# 编译规则
%.o: %.c

View File

@ -1,4 +1,3 @@
#define _GNU_SOURCE
/**
* config.c - JSON

1
http.c
View File

@ -1,4 +1,3 @@
#define _GNU_SOURCE
/**
* http.c - HTTP

View File

@ -1,7 +1,4 @@
#define _GNU_SOURCE
/**
* server.c -
*
* coco
* 线 accept
@ -23,6 +20,7 @@
#include "static.h"
#include "cocoon.h"
#include "log.h"
#include "multipart.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -191,17 +189,91 @@ static int conn_read_body(connection_t *conn, http_request_t *req, size_t need)
/**
* handle_post_request - POST
*
* JSON API
* application/json application/x-www-form-urlencoded
* multipart/form-data JSON
*
* @param fd socket
* @param req HTTP
* @param root_dir
* @return true
*/
static bool handle_post_request(int fd, const http_request_t *req) {
static bool handle_post_request(int fd, const http_request_t *req, const char *root_dir) {
char response[4096];
int n = 0;
/* multipart/form-data 文件上传 */
if (strstr(req->content_type, "multipart/form-data") != NULL) {
char boundary[256];
if (!multipart_extract_boundary(req->content_type, boundary, sizeof(boundary))) {
static_send_error(fd, 400, req->keep_alive);
return req->keep_alive;
}
multipart_part_t *parts = NULL;
int num_parts = 0;
if (multipart_parse(req->body, req->body_len, boundary, &parts, &num_parts) != 0) {
static_send_error(fd, 400, req->keep_alive);
return req->keep_alive;
}
/* 构建 JSON 响应 */
n += snprintf(response + n, sizeof(response) - n,
"{\"method\":\"%s\",\"path\":\"%s\",\"uploaded\":%d,\"files\":[",
http_method_str(req->method), req->path, num_parts);
int files_saved = 0;
for (int i = 0; i < num_parts; i++) {
if (parts[i].filename && parts[i].filename[0] && parts[i].data_len > 0) {
/* 保存文件到 root_dir/uploads/ */
char upload_dir[4096];
int r = snprintf(upload_dir, sizeof(upload_dir), "%s/uploads", root_dir);
if (r > 0 && r < (int)sizeof(upload_dir)) {
/* 创建目录(忽略已存在错误) */
mkdir(upload_dir, 0755);
char file_path[4096];
r = snprintf(file_path, sizeof(file_path), "%s/%s", upload_dir, parts[i].filename);
if (r > 0 && r < (int)sizeof(file_path)) {
FILE *fp = fopen(file_path, "wb");
if (fp) {
fwrite(parts[i].data, 1, parts[i].data_len, fp);
fclose(fp);
files_saved++;
if (files_saved > 1) {
n += snprintf(response + n, sizeof(response) - n, ",");
}
n += snprintf(response + n, sizeof(response) - n,
"{\"field\":\"%s\",\"filename\":\"%s\",\"size\":%zu,\"path\":\"%s\"}",
parts[i].name ? parts[i].name : "",
parts[i].filename,
parts[i].data_len,
file_path);
}
}
}
}
}
n += snprintf(response + n, sizeof(response) - n, "]}");
multipart_parts_free(parts, num_parts);
char header[512];
int header_len = snprintf(header, sizeof(header),
"HTTP/1.1 200 OK\r\n"
"Content-Type: application/json\r\n"
"Content-Length: %d\r\n"
"Connection: %s\r\n"
"Server: Cocoon/1.0\r\n"
"\r\n",
n, req->keep_alive ? "keep-alive" : "close");
send_all(fd, header, (size_t)header_len);
send_all(fd, response, (size_t)n);
return req->keep_alive;
}
n += snprintf(response + n, sizeof(response) - n,
"{\"method\":\"%s\",\"path\":\"%s\",\"content_type\":\"%s\",\"body_length\":%zu",
http_method_str(req->method), req->path, req->content_type, req->body_len);
@ -291,7 +363,7 @@ static bool handle_request(connection_t *conn, const char *root_dir) {
/* 处理 POST */
if (req.method == HTTP_POST) {
bool keep = handle_post_request(conn->fd, &req);
bool keep = handle_post_request(conn->fd, &req, conn->root_dir);
http_request_free(&req);
return keep;
}

View File

@ -1,4 +1,3 @@
#define _GNU_SOURCE
/**
* static.c -