summaryrefslogtreecommitdiff
path: root/command/dd.c
blob: d628f9f085a22a781c5dabeb4eb03293c8fa69b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
 *  file: dd.c
 *  command: dd
 *  author: Tyler Murphy
 */

#include "command.h"
#include "lslib.h"

#include <stdlib.h>

/**
 * Help function for dd
 */
static void help(void) {
    printf("Usage: dd [if=FILE] [of=FILE] [bs=N] [count=N]\n\n");
    printf("Copy a file with converting and formatting\n\n");
    printf("\tif=FILE\t\tRead from FILE instead of stdin\n");
    printf("\tof=FILE\t\tWrite to FILE instead of stdout\n");
    printf("\tbs=N\t\tRead and write N bytes at a time\n");
    printf("\tcount=N\t\tCopy only N input blocks\n");
}

/**
* Copys a file with converting and formatting
*/
COMMAND(dd_main) {

    FILE* in_file = stdin; /* the file to copy from */
    FILE* out_file = stdout; /* the file to copy to */
    int bs = 1024; /* the default bs */
    int count = -1; /* amount of bs's to copy, if negative go until EOF */
    int i;
    char* buffer; /* buffer to hold copy data */
    size_t read;

    /* parse arguments and only check for --help */
    parse_help(argc, argv, help);

    /* dd doesnt use standard arguments, parse though each argument and match each arg */
    for (i = 0; i < argc; i++) {
        if (prefix("if=", argv[i])) { /* sets the input file */
            char* path = argv[i] + 3; /* get data after = */
            in_file = get_file(path, "rb");
        } else if (prefix("of=", argv[i])) { /* sets the output file */
            char* path = argv[i] + 3; /* get data after = */
            out_file = get_file(path, "wb");
        } else if (prefix("bs=", argv[i])) { /* sets the blocksize */
            char* str = argv[i] + 3; /* get data after = */
            bs = get_blkm(str);
            if (bs < 1) { /* cannot have a negative bs */
                error("block size must be greater than 0");
            }
        } else if (prefix("count=", argv[i])) { /* sets the count of bs to do */
            char* str = argv[i] + 6; /* get data after = */
            count = get_number(str);
            if (count < 1) {
                error("count must be greather than 0");
            }
        } else { /* error and exit since arg is invalid */
            error("unkown option %s", argv[i]);
        }
    }

    /* allocate buffer of set bs */
    buffer = xalloc(bs);
    
    /* read data until EOF from and to buf */
    while ((read = fread(buffer, 1, bs, in_file)) != 0) {
        fwrite(buffer, 1, read, out_file);
        if (--count, count == 0) break;
    }

    /* cleanup */
    free(buffer);
    fclose(in_file);
    fclose(out_file);

    return EXIT_SUCCESS;
}