write() 未定义行为

write() undefined behavior

我有这段代码,我在其中收到服务器响应,检查它是否成功,如果是 - 在请求的路径下创建文件,然后将响应主体写入文件:

我正在使用以下 URL 进行测试:

http://neverssl.com/index.html

所以这意味着我需要创建一个名为 neverssl.com 的文件夹,其中包含一个 index.html 文件.

我正在使用以下方法创建文件:

//full_path = "http://neverssl.com/index.html"
int create_file_under_path(char *full_path) {
    int fd, path_len = (int) strlen(full_path);
    char *curr_path = calloc(path_len + 1, 1);
    char *token = strtok(full_path, "/");
    strncpy(curr_path, token, path_len);
    while (token) {
        if (path_len == strlen(curr_path))
            break;
        if (access(curr_path, F_OK) != 0) {//The folder doesn't exist
            if (mkdir(curr_path, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
                perror("mkdir failed\n");
                return -1;
            }
        }
        token = strtok(NULL, "/");
        strcat(curr_path, "/");
        strncat(curr_path, token, strlen(token));
    }
    if ((fd = open(curr_path, O_CREAT | O_WRONLY, 0700)) == -1) {
        perror("failed to open file\n");
        return -1;
    }
    free(curr_path);
    return fd;
}

然后我使用 write 系统调用写入它,如下所示:

if ((fd = create_file_under_path(url->full_path)) == -1) {
                            free_URL(url);
                            free(buf);
                            exit(EXIT_FAILURE);
}
if (write(fd, buf + header_size, tot_read - header_size) != (buf_size - header_size)) {
                            perror("write:\n");
                            exit(EXIT_FAILURE);
}

10 次中有 9 次一切正常,但有时即使创建了文件夹和文件,write 也会失败并显示以下消息:No such file or directory。 发生这种情况时我打印了 FD,它应该是 4。

我不知道如何进一步调试它,我会提供帮助!

这是一个例子,你可以看到文件存在,fd确实是4,即使如此它进入if语句:

write(fd, buf + header_size, tot_read - header_size) != (buf_size - header_size)

来自man 3p write

   Upon successful completion, these functions shall return the number of bytes actually  written  to  the  file  associated  with
   fildes.  This number shall never be greater than nbyte.  Otherwise, -1 shall be returned and errno set to indicate the error.

Only when write() == -1 then errno is set, otherwise it is irrelevant - left from some other operation. write() 返回的数字可能小于请求的字节数。

您必须编写一个小循环,在其中遍历要写入的字节。到时候,考虑处理 errno == EAGAIN.