目标文件和源文件不匹配 - C

Destination and Source file don't match - C

我一直在试图找出我的测试仪失败的原因,它说目标文件和源文件不匹配。 link 测试人员:https://github.com/ShiraWolf/hwOP.git
输出要求和测试:
它必须输出以下类型的消息之一(精确且区分大小写):

或者各种参数之一解析错误,如上例所述。

我的代码:

/*
 * ex1.c
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAX_BUFFER_SIZE 65536
#define DESTINATION_FILE_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH

extern int opterr, optind;

void exit_with_usage(const char *message) {
    fprintf(stderr, "%s\n", message);
    fprintf(stderr, "Usage:\n\tex1 [-f] BUFFER_SIZE SOURCE DEST\n");
    exit(EXIT_FAILURE);
}

void copy_file(const char *source_file, const char *dest_file, int buffer_size, int force_flag) {
    /*
     * Copy source_file content to dest_file, buffer_size bytes at a time.
     * If force_flag is true, then also overwrite dest_file. Otherwise print error, and exit.
     *
     * TODO:
     *  1. Open source_file for reading
     *  2. Open dest_file for writing (Hint: is force_flag true?)
     *  3. Loop reading from source and writing to the destination buffer_size bytes each time
     *  4. Close source_file and dest_file
     *
     *  ALWAYS check the return values of syscalls for errors!
     *  If an error was found, use perror(3) to print it with a message, and then exit(EXIT_FAILURE)
     */
    int c = 0;
    int sourcef = 0;
    int destf = 0;
    sourcef = open(source_file, O_RDONLY);
    if (sourcef == -1) {
        perror("Unable to open source file for reading");
        exit(EXIT_FAILURE);
    }
    destf = open(dest_file, O_WRONLY |O_CREAT | O_EXCL, 00700);
    if (destf == -1) {
        if (force_flag) {
            destf = open(dest_file, O_WRONLY, 00700);
            if (destf == -1) {
                if (close(sourcef) == -1) {
                    perror("couldn't close source file");
                    exit(EXIT_FAILURE);
                }
                perror("Unable to open destination for writing");
                exit(EXIT_FAILURE);
            }
        } else {
            perror("Unable to open destination for writing");
            exit(EXIT_FAILURE);
        }
    }
    char *buffer = malloc(sizeof(char) * buffer_size);
    while ((c = read(sourcef, buffer, buffer_size)) != 0) {
        if (c == -1) {
            perror("couldn't read from source file");
            if (close(sourcef) == -1) {
                perror("couldn't close source file after reading has failed");
                exit(EXIT_FAILURE);
            }
            if (close(destf) == -1) {
                perror("couldn't close dest file after reading has failed");
                exit(EXIT_FAILURE);
            }
            exit(EXIT_FAILURE);
        }

        c = write(destf, buffer, buffer_size);
        if (c == -1) {
            perror("couldn't write to source file");
            if (close(sourcef) == -1) {
                perror("couldn't close source file after writing has failed");
                exit(EXIT_FAILURE);
            }
            if (close(destf) == -1) {
                 perror("couldn't close dest file after writing has failed");
                 exit(EXIT_FAILURE);
            }
            exit(EXIT_FAILURE);
        }
    }
    free(buffer);

    if (close(sourcef) == -1) {
        perror("couldn't close source file");
        exit(EXIT_FAILURE);
    }
    if (close(destf) == -1) {
        perror("couldn't close dest file");
        exit(EXIT_FAILURE);
    }
    printf("File %s was copied to %s\n", source_file, dest_file);
    exit(EXIT_SUCCESS);
}

void parse_arguments (
        int argc, char **argv,
        char **source_file, char **dest_file, int *buffer_size, int *force_flag) {
    /*
     * parses command line arguments and set the arguments required for copy_file
     */
    int option_character;

    opterr = 0; /* Prevent getopt() from printing an error message to stderr */

    while ((option_character = getopt(argc, argv, "f")) != -1) {
        switch (option_character) {
        case 'f':
            *force_flag = 1;
            break;
        default:  /* '?' */
            exit_with_usage("Unknown option specified");
        }
    }

    if (argc - optind != 3) {
        exit_with_usage("Invalid number of arguments");
    } else {
        *source_file = argv[argc - 2];
        *dest_file = argv[argc - 1];
        *buffer_size = atoi(argv[argc - 3]);

        if (strlen(*source_file) == 0 || strlen(*dest_file) == 0) {
            exit_with_usage("Invalid source / destination file name");
        } else if (*buffer_size < 1 || *buffer_size > MAX_BUFFER_SIZE) {
            exit_with_usage("Invalid buffer size");
        }
    }
}

int main(int argc, char **argv) {
    int force_flag = 0; /* force flag default: false */
    char *source_file = NULL;
    char *dest_file = NULL;
    int buffer_size = MAX_BUFFER_SIZE;

    parse_arguments(argc, argv, &source_file, &dest_file, &buffer_size, &force_flag);

    copy_file(source_file, dest_file, buffer_size, force_flag);

    return EXIT_SUCCESS;
}

谁能看出我的错误在哪里?

c = write(destf, buffer, buffer_size); 未使用正确的大小:您应该写入 c 字节并将写入的计数存储到单独的变量 nwritten 并继续尝试写入更多字节直到 [=已写入 12=] 个字节或 write return 0-1.

这是复制循环的修改版本:

    while ((c = read(sourcef, buffer, buffer_size)) != 0) {
        if (c == -1) {
            perror("Unable to read from source file");
            if (close(sourcef) == -1) {
                perror("Unable to close source file");
                exit(EXIT_FAILURE);
            }
            if (close(destf) == -1) {
                perror("Unable to close destination file");
                exit(EXIT_FAILURE);
            }
            exit(EXIT_FAILURE);
        }
        int towrite = c;
        int pos = 0;
        while (towrite > 0) {
            int nwritten = write(destf, buffer + pos, towrite);
            if (nwritten <= 0) {
                perror("Unable to write to destination file");
                if (close(sourcef) == -1) {
                    perror("Unable to close source file");
                    exit(EXIT_FAILURE);
                }
                if (close(destf) == -1) {
                    perror("Unable to close destination file");
                    exit(EXIT_FAILURE);
                }
                exit(EXIT_FAILURE);
            }
            pos += nwritten;
            towrite -= nwritten;
        }
    }

另请注意,其他错误消息与规范不同。