getcwd(char *buf, size_t size)

本文介绍Linux系统中获取当前工作目录的方法,包括getcwd(), get_current_dir_name()和getwd()等函数的使用细节及注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 SYNOPSIS
       #include <unistd.h>

       char *getcwd(char *buf, size_t size);
       char *get_current_dir_name(void);
       char *getwd(char *buf);

DESCRIPTION
       The  getcwd() function copies an absolute pathname of the current work-
       ing directory to the array pointed to by buf, which is of length  size.

       If  the  current  absolute  pathname would require a buffer longer than
       size elements, NULL is returned, and errno is set to ERANGE; an  appli-
       cation  should  check  for  this error, and allocate a larger buffer if
       necessary.

       If buf is NULL, the behaviour of getcwd() is undefined.

       As an extension to the  POSIX.1-2001  standard,  Linux  (libc4,  libc5,
       glibc)  getcwd() allocates the buffer dynamically using malloc() if buf
       is NULL on call.  In this case, the allocated  buffer  has  the  length
       size  unless  size  is zero, when buf is allocated as big as necessary.
       It is possible (and, indeed, advisable) to free() the buffers  if  they
       have been obtained this way.

       get_current_dir_name(),  which  is  only  prototyped  if _GNU_SOURCE is
       defined, will malloc(3) an array big enough to hold the current  direc-
       tory  name.   If  the environment variable PWD is set, and its value is
       correct, then that value will be returned.

       getwd(),   which    is    only    prototyped    if    _BSD_SOURCE    or
       _XOPEN_SOURCE_EXTENDED  is  defined, will not malloc(3) any memory. The
       buf argument should be a pointer to an array at  least  PATH_MAX  bytes
       long.   getwd() does only return the first PATH_MAX bytes of the actual
       pathname.  Note that PATH_MAX need not be a compile-time  constant;  it
       may depend on the filesystem and may even be unlimited. For portability
       and security reasons, use of getwd() is deprecated.

RETURN VALUE
       NULL on failure with errno set accordingly, and  buf  on  success.  The
       contents of the array pointed to by buf is undefined on error.

ERRORS
       EACCES Permission  to  read  or  search a component of the filename was
              denied.

       EFAULT buf points to a bad address.

       EINVAL The size argument is zero and buf is not a null pointer.

       ENOENT The current working directory has been unlinked.

       ERANGE The size argument is less than the length of the working  direc-
       descriptors are available, especially on platforms other than Linux.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <dirent.h> #include <time.h> #include <errno.h> #include <ctype.h> #include <signal.h> #include <arpa/inet.h> #include <sys/wait.h> #define PORT 80 #define MAX_CLIENTS 100 #define BUFFER_SIZE 8192 #define ROOT_DIR “” int debug_mode = 1; // 调试模式开关 pid_t main_pid; // 日志函数 void log_message(const char *type, const char *message, int level) { if (level > 0 && !debug_mode) return; time_t now = time(NULL); char *time_str = ctime(&now); time_str[strlen(time_str) - 1] = '\0'; char log_buffer[1024]; snprintf(log_buffer, sizeof(log_buffer), "[%s] %s: %s", time_str, type, message); printf("%s\n", log_buffer); // 写入日志文件(使用O_APPEND保证多进程写入安全) int log_fd = open("webserver.log", O_WRONLY | O_CREAT | O_APPEND, 0644); if (log_fd >= 0) { dprintf(log_fd, "%s\n", log_buffer); close(log_fd); } } // 获取绝对路径 void get_absolute_path(char *abs_path, const char *rel_path) { char cwd[1024]; if (getcwd(cwd, sizeof(cwd))) { snprintf(abs_path, 1024, “%s/%s/%s”, cwd, ROOT_DIR, rel_path); } else { snprintf(abs_path, 1024, “%s/%s”, ROOT_DIR, rel_path); } } // 路径安全检查和规范化 int normalize_path(char *path) { // 移除多余的斜杠 char *src = path; char *dst = path; while (*src) { if (*src == '/' && *(src + 1) == '/') { src++; continue; } *dst++ = *src++; } *dst = '\0'; // 检查路径遍历攻击 if (strstr(path, "..") != NULL) { return 0; } return 1; } // 获取文件类型 const char *get_content_type(const char *path) { const char *ext = strrchr(path, ‘.’); if (ext) { if (strcmp(ext, “.html”) == 0) return “text/html”; if (strcmp(ext, “.htm”) == 0) return “text/html”; if (strcmp(ext, “.css”) == 0) return “text/css”; if (strcmp(ext, “.js”) == 0) return “application/javascript”; if (strcmp(ext, “.json”) == 0) return “application/json”; if (strcmp(ext, “.jpg”) == 0 || strcmp(ext, “.jpeg”) == 0) return “image/jpeg”; if (strcmp(ext, “.png”) == 0) return “image/png”; if (strcmp(ext, “.gif”) == 0) return “image/gif”; if (strcmp(ext, “.ico”) == 0) return “image/x-icon”; if (strcmp(ext, “.svg”) == 0) return “image/svg+xml”; if (strcmp(ext, “.txt”) == 0) return “text/plain”; if (strcmp(ext, “.pdf”) == 0) return “application/pdf”; } return “application/octet-stream”; } // 发送HTTP响应 void send_response(int client_fd, int status, const char *status_text, const char *content_type, const char *body, size_t body_len) { char header[512]; int header_len = snprintf(header, sizeof(header), “HTTP/1.1 %d %s\r\n” “Content-Type: %s\r\n” “Content-Length: %zu\r\n” “Connection: close\r\n\r\n”, status, status_text, content_type, body_len); write(client_fd, header, header_len); if (body && body_len > 0) { write(client_fd, body, body_len); } } // 发送文件 void send_file(int client_fd, const char *path) { char abs_path[1024]; get_absolute_path(abs_path, path); if (!normalize_path(abs_path)) { const char *forbidden = "403 Forbidden"; send_response(client_fd, 403, "Forbidden", "text/plain", forbidden, strlen(forbidden)); log_message("SECURITY", "Path traversal attempt detected", 0); return; } char debug_msg[1024]; snprintf(debug_msg, sizeof(debug_msg), "Accessing file: %s", abs_path); log_message("DEBUG", debug_msg, 1); FILE *file = fopen(abs_path, "rb"); if (!file) { char error_msg[512]; snprintf(error_msg, sizeof(error_msg), "Failed to open %s: %s", abs_path, strerror(errno)); log_message("ERROR", error_msg, 0); const char *not_found = "404 Not Found"; send_response(client_fd, 404, "Not Found", "text/plain", not_found, strlen(not_found)); return; } fseek(file, 0, SEEK_END); long file_size = ftell(file); fseek(file, 0, SEEK_SET); if (file_size <= 0) { fclose(file); const char *server_error = "500 Internal Server Error (Empty file)"; send_response(client_fd, 500, "Internal Server Error", "text/plain", server_error, strlen(server_error)); log_message("ERROR", "File is empty", 0); return; } char *buffer = malloc(file_size); if (!buffer) { fclose(file); const char *server_error = "500 Internal Server Error"; send_response(client_fd, 500, "Internal Server Error", "text/plain", server_error, strlen(server_error)); log_message("ERROR", "Memory allocation failed", 0); return; } size_t read_size = fread(buffer, 1, file_size, file); fclose(file); if (read_size != (size_t) file_size) { free(buffer); const char *server_error = "500 Internal Server Error"; send_response(client_fd, 500, "Internal Server Error", "text/plain", server_error, strlen(server_error)); log_message("ERROR", "File read error", 0); return; } const char *content_type = get_content_type(path); send_response(client_fd, 200, "OK", content_type, buffer, file_size); free(buffer); } // 处理目录请求 void handle_directory(int client_fd, const char *path) { char index_path[1024]; snprintf(index_path, sizeof(index_path), “%s/Contact.html”, path); struct stat st; if (stat(index_path, &st) == 0 && S_ISREG(st.st_mode)) { send_file(client_fd, index_path); } else { const char *not_found = "404 Directory index not found"; send_response(client_fd, 404, "Not Found", "text/plain", not_found, strlen(not_found)); log_message("ERROR", "Directory index not found", 0); } } // 处理客户端请求(现在在子进程中执行) void handle_client(int client_fd) { char buffer[BUFFER_SIZE]; ssize_t bytes_read = read(client_fd, buffer, sizeof(buffer) - 1); if (bytes_read <= 0) { close(client_fd); return; } buffer[bytes_read] = '\0'; if (debug_mode) { char req_msg[BUFFER_SIZE + 50]; snprintf(req_msg, sizeof(req_msg), "Request:\n%.*s", (int) bytes_read, buffer); log_message("REQUEST", req_msg, 1); } char method[16], path[256], protocol[16]; if (sscanf(buffer, "%15s %255s %15s", method, path, protocol) != 3) { const char *bad_request = "400 Bad Request"; send_response(client_fd, 400, "Bad Request", "text/plain", bad_request, strlen(bad_request)); close(client_fd); return; } // 完全忽略 favicon.ico 请求 if (strcmp(path, "/favicon.ico") == 0) { close(client_fd); return; // 直接返回,不发送任何响应 } // 处理路径 char full_path[1024]; if (strcmp(path, "/") == 0) { // 默认显示 Contact.html strcpy(full_path, "Contact.html"); } else { // 跳过开头的斜杠 strcpy(full_path, path + 1); } // 获取绝对路径用于文件检查 char abs_path[1024]; get_absolute_path(abs_path, full_path); // 调试信息 char debug_msg[1024]; snprintf(debug_msg, sizeof(debug_msg), "Resolved path: %s", abs_path); log_message("DEBUG", debug_msg, 1); // 处理GET请求 if (strcmp(method, "GET") == 0) { struct stat st; if (stat(abs_path, &st) == 0) { if (S_ISDIR(st.st_mode)) { // 如果是目录,尝试查找目录下的 Contact.html handle_directory(client_fd, abs_path); } else { // 发送文件 send_file(client_fd, full_path); } } else { // 文件不存在 char error_msg[256]; snprintf(error_msg, sizeof(error_msg), "File not found: %s", abs_path); log_message("ERROR", error_msg, 0); const char *not_found = "404 Not Found"; send_response(client_fd, 404, "Not Found", "text/plain", not_found, strlen(not_found)); } } // 处理POST请求 else if (strcmp(method, "POST") == 0) { // 查找请求体 char *body = strstr(buffer, "\r\n\r\n"); if (body) { body += 4; // 跳过空行 // 记录POST数据 char log_msg[1024]; snprintf(log_msg, sizeof(log_msg), "POST data: %.*s", (int) (bytes_read - (body - buffer)), body); log_message("INFO", log_msg, 1); // 简单的POST处理示例 const char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 12\r\n" "Connection: close\r\n\r\n" "POST Received"; write(client_fd, response, strlen(response)); } else { const char *bad_request = "400 Bad Request (Missing body)"; send_response(client_fd, 400, "Bad Request", "text/plain", bad_request, strlen(bad_request)); } } // 处理其他HTTP方法 else { const char *not_allowed = "405 Method Not Allowed"; send_response(client_fd, 405, "Method Not Allowed", "text/plain", not_allowed, strlen(not_allowed)); } close(client_fd); } // 僵尸进程回收函数 void reap_zombies(int sig) { while (waitpid(-1, NULL, WNOHANG) > 0); } // 清理函数 void cleanup() { log_message(“INFO”, “Server shutting down”, 0); } void handle_signal(int sig) { if (getpid() != main_pid) { _exit(0); // 子进程直接退出 } else if (sig == SIGINT || sig == SIGTERM) { log_message(“INFO”, “Received termination signal, shutting down”, 0); exit(0); // 主进程正常退出 } } int main() { main_pid = getpid(); // 第一行获取主进程PID // 仅主进程注册清理函数 if (getpid() == main_pid) { atexit(cleanup); } // 设置信号处理 signal(SIGINT, handle_signal); signal(SIGTERM, handle_signal); signal(SIGCHLD, reap_zombies); // 添加子进程回收信号 // 创建套接字 int server_fd; if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 设置套接字选项 int opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) { perror("setsockopt failed"); exit(EXIT_FAILURE); } // 绑定地址 struct sockaddr_in address; address . sin_family = AF_INET; address . sin_addr . s_addr = INADDR_ANY; address . sin_port = htons(PORT); if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } // 监听端口 if (listen(server_fd, MAX_CLIENTS) < 0) { perror("listen failed"); exit(EXIT_FAILURE); } // 检查根目录是否存在 char root_path[1024]; get_absolute_path(root_path, ""); struct stat st; if (stat(root_path, &st) != 0 || !S_ISDIR(st.st_mode)) { char error_msg[256]; snprintf(error_msg, sizeof(error_msg), "Root directory '%s' not found or inaccessible", root_path); log_message("FATAL", error_msg, 0); exit(EXIT_FAILURE); } else { char info_msg[256]; snprintf(info_msg, sizeof(info_msg), "Serving files from: %s", root_path); log_message("INFO", info_msg, 0); } log_message("INFO", "Server started successfully (Multi-process)", 0); printf("Multi-process server running on port %d\n", PORT); // 主循环 while (1) { struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &addr_len); if (client_fd < 0) { if (errno == EINTR) continue; // 信号中断处理 perror("accept failed"); continue; } // 记录客户端信息 char client_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &client_addr . sin_addr, client_ip, INET_ADDRSTRLEN); char conn_msg[256]; snprintf(conn_msg, sizeof(conn_msg), "Client connected: %s:%d", client_ip, ntohs(client_addr . sin_port)); log_message("INFO", conn_msg, 1); // 创建子进程处理请求 pid_t pid = fork(); if (pid == 0) { // 子进程 close(server_fd); // 关闭监听套接字 handle_client(client_fd); _exit(EXIT_SUCCESS); // 处理完成后退出 } else if (pid > 0) { // 父进程 close(client_fd); // 关闭父进程中不需要的客户端套接字 } else { perror("fork failed"); close(client_fd); } } close(server_fd); return 0; } #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <sys/epoll.h> #include <fcntl.h> #include <errno.h> #include <sys/stat.h> #include <time.h> #include <arpa/inet.h> #define PORT 80 #define MAX_EVENTS 1024 #define BUFFER_SIZE 8192 #define ROOT_DIR “” int debug_mode = 1; // 连接状态结构体 typedef struct { int fd; char read_buf[BUFFER_SIZE]; size_t read_len; char write_buf[BUFFER_SIZE]; size_t write_len; size_t write_sent; int keep_alive; struct sockaddr_in client_addr; } connection_t; // 日志函数 void log_message(const char *type, const char *message, int level) { if (level > 0 && !debug_mode) return; time_t now = time(NULL); char *time_str = ctime(&now); time_str[strlen(time_str) - 1] = '\0'; char log_buffer[1024]; snprintf(log_buffer, sizeof(log_buffer), "[%s] %s: %s", time_str, type, message); printf("%s\n", log_buffer); // 写入日志文件(使用O_APPEND保证多进程写入安全) int log_fd = open("webserver.log", O_WRONLY | O_CREAT | O_APPEND, 0644); if (log_fd >= 0) { dprintf(log_fd, "%s\n", log_buffer); close(log_fd); } } // 获取绝对路径 void get_absolute_path(char *abs_path, const char *rel_path) { char cwd[1024]; if (getcwd(cwd, sizeof(cwd))) { snprintf(abs_path, 1024, “%s/%s/%s”, cwd, ROOT_DIR, rel_path); } else { snprintf(abs_path, 1024, “%s/%s”, ROOT_DIR, rel_path); } } // 路径安全检查和规范化 int normalize_path(char *path) { // 移除多余的斜杠 char *src = path; char *dst = path; while (*src) { if (*src == '/' && *(src + 1) == '/') { src++; continue; } *dst++ = *src++; } *dst = '\0'; // 检查路径遍历攻击 if (strstr(path, "..") != NULL) { return 0; } return 1; } // 获取文件类型 const char *get_content_type(const char *path) { const char *ext = strrchr(path, ‘.’); if (ext) { if (strcmp(ext, “.html”) == 0) return “text/html”; if (strcmp(ext, “.htm”) == 0) return “text/html”; if (strcmp(ext, “.css”) == 0) return “text/css”; if (strcmp(ext, “.js”) == 0) return “application/javascript”; if (strcmp(ext, “.json”) == 0) return “application/json”; if (strcmp(ext, “.jpg”) == 0 || strcmp(ext, “.jpeg”) == 0) return “image/jpeg”; if (strcmp(ext, “.png”) == 0) return “image/png”; if (strcmp(ext, “.gif”) == 0) return “image/gif”; if (strcmp(ext, “.ico”) == 0) return “image/x-icon”; if (strcmp(ext, “.svg”) == 0) return “image/svg+xml”; if (strcmp(ext, “.txt”) == 0) return “text/plain”; if (strcmp(ext, “.pdf”) == 0) return “application/pdf”; } return “application/octet-stream”; } // 设置非阻塞IO void set_nonblocking(int fd) { int flags = fcntl(fd, F_GETFL, 0); if (flags == -1) { perror(“fcntl F_GETFL”); exit(EXIT_FAILURE); } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) { perror(“fcntl F_SETFL”); exit(EXIT_FAILURE); } } // 创建HTTP响应头 void build_http_header(char *header, int status, const char *status_text, const char *content_type, size_t content_len, int keep_alive) { snprintf(header, BUFFER_SIZE, “HTTP/1.1 %d %s\r\n” “Content-Type: %s\r\n” “Content-Length: %zu\r\n” “Connection: %s\r\n” “Server: epoll-server\r\n\r\n”, status, status_text, content_type, content_len, keep_alive ? “keep-alive” : “close”); } // 发送文件响应 void send_file_response(connection_t *conn, const char *path) { char abs_path[1024]; get_absolute_path(abs_path, path); if (!normalize_path(abs_path)) { const char *forbidden = "403 Forbidden"; build_http_header(conn -> write_buf, 403, "Forbidden", "text/plain", strlen(forbidden), conn -> keep_alive); memcpy(conn -> write_buf + strlen(conn -> write_buf), forbidden, strlen(forbidden)); conn -> write_len = strlen(conn -> write_buf); return; } int fd = open(abs_path, O_RDONLY); if (fd == -1) { const char *not_found = "404 Not Found"; build_http_header(conn -> write_buf, 404, "Not Found", "text/plain", strlen(not_found), conn -> keep_alive); memcpy(conn -> write_buf + strlen(conn -> write_buf), not_found, strlen(not_found)); conn -> write_len = strlen(conn -> write_buf); return; } struct stat st; fstat(fd, &st); off_t file_size = st . st_size; const char *content_type = get_content_type(path); build_http_header(conn -> write_buf, 200, "OK", content_type, file_size, conn -> keep_alive); size_t header_len = strlen(conn -> write_buf); // 使用sendfile零拷贝发送文件 conn -> write_len = header_len; conn -> write_sent = 0; // 如果文件很小,直接读取到内存 if (file_size < BUFFER_SIZE - header_len) { ssize_t n = read(fd, conn -> write_buf + header_len, file_size); if (n > 0) { conn -> write_len += n; } close(fd); } else { // 大文件使用sendfile在发送时处理 close(fd); // 实际发送在事件循环中处理 } } // 处理HTTP请求 void handle_request(connection_t *conn) { // 解析请求行 char method[16], path[256], protocol[16]; if (sscanf(conn -> read_buf, “%15s %255s %15s”, method, path, protocol) != 3) { const char *bad_request = “400 Bad Request”; build_http_header(conn -> write_buf, 400, “Bad Request”, “text/plain”, strlen(bad_request), 0); memcpy(conn -> write_buf + strlen(conn -> write_buf), bad_request, strlen(bad_request)); conn -> write_len = strlen(conn -> write_buf); return; } // 检查Keep-Alive conn -> keep_alive = (strstr(conn -> read_buf, "Connection: keep-alive") != NULL); // 忽略favicon if (strcmp(path, "/favicon.ico") == 0) { conn -> write_len = 0; return; } // 处理路径 char full_path[1024]; if (strcmp(path, "/") == 0) { strcpy(full_path, "Contact.html"); } else { strcpy(full_path, path + 1); } // 处理GET请求 if (strcmp(method, "GET") == 0) { send_file_response(conn, full_path); } // 处理POST请求 else if (strcmp(method, "POST") == 0) { const char *response = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" "Content-Length: 12\r\n" "Connection: close\r\n\r\n" "POST Received"; strncpy(conn -> write_buf, response, strlen(response)); conn -> write_len = strlen(response); conn -> keep_alive = 0; // POST后关闭连接 } // 其他方法 else { const char *not_allowed = "405 Method Not Allowed"; build_http_header(conn -> write_buf, 405, "Method Not Allowed", "text/plain", strlen(not_allowed), 0); memcpy(conn -> write_buf + strlen(conn -> write_buf), not_allowed, strlen(not_allowed)); conn -> write_len = strlen(conn -> write_buf); } } // 初始化服务器套接字 int init_server_socket() { int server_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if (server_fd == -1) { perror(“socket”); exit(EXIT_FAILURE); } int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in address = { .sin_family = AF_INET, .sin_addr.s_addr = INADDR_ANY, .sin_port = htons(PORT) }; if (bind(server_fd, (struct sockaddr *) &address, sizeof(address)) < 0) { perror("bind"); close(server_fd); exit(EXIT_FAILURE); } if (listen(server_fd, SOMAXCONN) < 0) { perror("listen"); close(server_fd); exit(EXIT_FAILURE); } return server_fd; } int main() { int server_fd = init_server_socket(); log_message(“INFO”, “IO Multiplexing server started (epoll)”, 0); // 创建epoll实例 int epoll_fd = epoll_create1(0); if (epoll_fd == -1) { perror("epoll_create1"); close(server_fd); exit(EXIT_FAILURE); } // 添加服务器套接字到epoll struct epoll_event ev; ev . events = EPOLLIN; ev . data . fd = server_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &ev) == -1) { perror("epoll_ctl: server_fd"); close(server_fd); close(epoll_fd); exit(EXIT_FAILURE); } // 事件循环 struct epoll_event events[MAX_EVENTS]; connection_t *connections[MAX_EVENTS] = {0}; while (1) { int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { perror("epoll_wait"); break; } for (int i = 0; i < nfds; i++) { // 新连接 if (events[i] . data . fd == server_fd) { struct sockaddr_in client_addr; socklen_t addr_len = sizeof(client_addr); int client_fd = accept(server_fd, (struct sockaddr *) &client_addr, &addr_len); if (client_fd == -1) { perror("accept"); continue; } set_nonblocking(client_fd); // 创建连接对象 connection_t *conn = malloc(sizeof(connection_t)); if (!conn) { close(client_fd); continue; } *conn = (connection_t){ .fd = client_fd, .read_len = 0, .write_len = 0, .write_sent = 0, .keep_alive = 0, .client_addr = client_addr }; // 添加到epoll监控 ev . events = EPOLLIN | EPOLLET; // 边缘触发模式 ev . data . ptr = conn; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) { perror("epoll_ctl: client_fd"); free(conn); close(client_fd); continue; } connections[client_fd] = conn; char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &client_addr . sin_addr, ip_str, INET_ADDRSTRLEN); char log_msg[128]; snprintf(log_msg, sizeof(log_msg), "Client connected: %s:%d", ip_str, ntohs(client_addr . sin_port)); log_message("INFO", log_msg, 1); } // 客户端事件 else { connection_t *conn = events[i] . data . ptr; // 可读事件 if (events[i] . events & EPOLLIN) { ssize_t count = read(conn -> fd, conn -> read_buf + conn -> read_len, BUFFER_SIZE - conn -> read_len - 1); if (count == -1) { // 错误或EAGAIN if (errno != EAGAIN && errno != EWOULDBLOCK) { goto close_conn; } } else if (count == 0) { // 客户端关闭连接 goto close_conn; } else { conn -> read_len += count; conn -> read_buf[conn -> read_len] = '\0'; // 检查是否收到完整请求 if (strstr(conn -> read_buf, "\r\n\r\n")) { if (debug_mode) { log_message("REQUEST", conn -> read_buf, 1); } handle_request(conn); // 修改为监听写事件 ev . events = EPOLLOUT | EPOLLET; ev . data . ptr = conn; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, conn -> fd, &ev); } } } // 可写事件 if (events[i] . events & EPOLLOUT) { if (conn -> write_len > 0) { ssize_t count = write(conn -> fd, conn -> write_buf + conn -> write_sent, conn -> write_len - conn -> write_sent); if (count == -1) { if (errno != EAGAIN && errno != EWOULDBLOCK) { goto close_conn; } } else { conn -> write_sent += count; // 全部发送完成 if (conn -> write_sent >= conn -> write_len) { if (conn -> keep_alive) { // 保持连接,重置状态 conn -> read_len = 0; conn -> write_len = 0; conn -> write_sent = 0; // 修改为监听读事件 ev . events = EPOLLIN | EPOLLET; ev . data . ptr = conn; epoll_ctl(epoll_fd, EPOLL_CTL_MOD, conn -> fd, &ev); } else { goto close_conn; } } } } } // 错误事件 if (events[i] . events & (EPOLLERR | EPOLLHUP)) { goto close_conn; } continue; close_conn: // 关闭连接并清理 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, conn -> fd, NULL); close(conn -> fd); free(conn); connections[conn -> fd] = NULL; } } } close(server_fd); close(epoll_fd); return 0; } 前一个代码是可正常运行的,后一个不行,请你基于此信息再分析原因
最新发布
08-09
/*---------------------------------------------------------------------------/ / FatFs - FAT file system module include file R0.09 (C)ChaN, 2011 /----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following trems. / / Copyright (C) 2011, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for / personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. / /----------------------------------------------------------------------------*/ #ifndef _FATFS #define _FATFS 6502 /* Revision ID */ #ifdef __cplusplus extern "C" { #endif #include "integer.h" /* Basic integer types */ #include "ffconf.h" /* FatFs configuration options */ #include "HeaderFiles.h" #if _FATFS != _FFCONF #error Wrong configuration file (ffconf.h). #endif /* Definitions of volume management */ #if _MULTI_PARTITION /* Multiple partition configuration */ typedef struct { BYTE pd; /* Physical drive number */ BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ } PARTITION; extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ #define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ #define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ #else /* Single partition configuration */ #define LD2PD(vol) (vol) /* Each logical drive is bound to the same physical drive number */ #define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ #endif /* Type of path name strings on FatFs API */ #if _LFN_UNICODE /* Unicode string */ #if !_USE_LFN #error _LFN_UNICODE must be 0 in non-LFN cfg. #endif #ifndef _INC_TCHAR typedef WCHAR TCHAR; #define _T(x) L ## x #define _TEXT(x) L ## x #endif #else /* ANSI/OEM string */ #ifndef _INC_TCHAR typedef char TCHAR; #define _T(x) x #define _TEXT(x) x #endif #endif /* File system object structure (FATFS) */ typedef struct { BYTE fs_type; /* FAT sub-type (0:Not mounted) */ BYTE drv; /* Physical drive number */ BYTE csize; /* Sectors per cluster (1,2,4...128) */ BYTE n_fats; /* Number of FAT copies (1,2) */ BYTE wflag; /* win[] dirty flag (1:must be written back) */ BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ WORD id; /* File system mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ #endif #if _FS_REENTRANT _SYNC_t sobj; /* Identifier of sync object */ #endif #if !_FS_READONLY DWORD last_clust; /* Last allocated cluster */ DWORD free_clust; /* Number of free clusters */ DWORD fsi_sector; /* fsinfo sector (FAT32) */ #endif #if _FS_RPATH DWORD cdir; /* Current directory start cluster (0:root) */ #endif DWORD n_fatent; /* Number of FAT entries (= number of clusters + 2) */ DWORD fsize; /* Sectors per FAT */ DWORD fatbase; /* FAT start sector */ DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and Data on tiny cfg) */ } FATFS; /* File object structure (FIL) */ typedef struct { FATFS* fs; /* Pointer to the owner file system object */ WORD id; /* Owner file system mount ID */ BYTE flag; /* File status flags */ BYTE pad1; DWORD fptr; /* File read/write pointer (0 on file open) */ DWORD fsize; /* File size */ DWORD sclust; /* File start cluster (0 when fsize==0) */ DWORD clust; /* Current cluster */ DWORD dsect; /* Current data sector */ #if !_FS_READONLY DWORD dir_sect; /* Sector containing the directory entry */ BYTE* dir_ptr; /* Ponter to the directory entry in the window */ #endif #if _USE_FASTSEEK DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif #if _FS_SHARE UINT lockid; /* File lock ID (index of file semaphore table) */ #endif #if !_FS_TINY BYTE buf[_MAX_SS]; /* File data read/write buffer */ #endif } FIL; /* Directory object structure (DIR) */ typedef struct { FATFS* fs; /* Pointer to the owner file system object */ WORD id; /* Owner file system mount ID */ WORD index; /* Current read/write index number */ DWORD sclust; /* Table start cluster (0:Root dir) */ DWORD clust; /* Current cluster */ DWORD sect; /* Current sector */ BYTE* dir; /* Pointer to the current SFN entry in the win[] */ BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ #if _USE_LFN WCHAR* lfn; /* Pointer to the LFN working buffer */ WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ #endif } DIR; /* File status structure (FILINFO) */ typedef struct { DWORD fsize; /* File size */ WORD fdate; /* Last modified date */ WORD ftime; /* Last modified time */ BYTE fattrib; /* Attribute */ TCHAR fname[13]; /* Short file name (8.3 format) */ #if _USE_LFN TCHAR* lfname; /* Pointer to the LFN buffer */ UINT lfsize; /* Size of LFN buffer in TCHAR */ #endif } FILINFO; /* File function return code (FRESULT) */ typedef enum { FR_OK = 0, /* (0) Succeeded */ FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ FR_EXIST, /* (8) Acces denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file shareing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; /*--------------------------------------------------------------*/ /* FatFs module application interface */ FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ FRESULT f_open (FIL*, const TCHAR*, BYTE); /* Open or create a file */ FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ FRESULT f_close (FIL*); /* Close an open file object */ FRESULT f_opendir (DIR*, const TCHAR*); /* Open an existing directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ FRESULT f_stat (const TCHAR*, FILINFO*); /* Get file status */ FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ FRESULT f_getfree (const TCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ FRESULT f_truncate (FIL*); /* Truncate file */ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ FRESULT f_chdrive (BYTE); /* Change current drive */ FRESULT f_chdir (const TCHAR*); /* Change current directory */ FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */ int f_putc (TCHAR, FIL*); /* Put a character to the file */ int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) #define f_tell(fp) ((fp)->fptr) #define f_size(fp) ((fp)->fsize) #ifndef EOF #define EOF (-1) #endif /*--------------------------------------------------------------*/ /* Additional user defined functions */ /* RTC function */ #if !_FS_READONLY DWORD get_fattime (void); #endif /* Unicode support functions */ #if _USE_LFN /* Unicode - OEM code conversion */ WCHAR ff_convert (WCHAR, UINT); /* OEM-Unicode bidirectional conversion */ WCHAR ff_wtoupper (WCHAR); /* Unicode upper-case conversion */ #if _USE_LFN == 3 /* Memory functions */ void* ff_memalloc (UINT); /* Allocate memory block */ void ff_memfree (void*); /* Free memory block */ #endif #endif /* Sync functions */ #if _FS_REENTRANT int ff_cre_syncobj (BYTE, _SYNC_t*);/* Create a sync object */ int ff_req_grant (_SYNC_t); /* Lock sync object */ void ff_rel_grant (_SYNC_t); /* Unlock sync object */ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #endif /*--------------------------------------------------------------*/ /* Flags and offset address */ /* File access control and file status flags (FIL.flag) */ #define FA_READ 0x01 #define FA_OPEN_EXISTING 0x00 #define FA__ERROR 0x80 #if !_FS_READONLY #define FA_WRITE 0x02 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 #define FA_OPEN_ALWAYS 0x10 #define FA__WRITTEN 0x20 #define FA__DIRTY 0x40 #endif /* FAT sub type (FATFS.fs_type) */ #define FS_FAT12 1 #define FS_FAT16 2 #define FS_FAT32 3 /* File attribute bits for directory entry */ #define AM_RDO 0x01 /* Read only */ #define AM_HID 0x02 /* Hidden */ #define AM_SYS 0x04 /* System */ #define AM_VOL 0x08 /* Volume label */ #define AM_LFN 0x0F /* LFN entry */ #define AM_DIR 0x10 /* Directory */ #define AM_ARC 0x20 /* Archive */ #define AM_MASK 0x3F /* Mask of defined bits */ /* Fast seek feature */ #define CREATE_LINKMAP 0xFFFFFFFF /*--------------------------------*/ /* Multi-byte word access macros */ #if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */ #define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) #define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) #define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) #define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) #else /* Use byte-by-byte access to the FAT structure */ #define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) #define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr)) #define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8) #define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24) #endif #ifdef __cplusplus } #endif #endif /* _FATFS */ 根据头文件修改一下
06-17
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值