Home | History | Annotate | Download | only in line_endings
      1 #include <unistd.h>
      2 #include <fcntl.h>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include <stdlib.h>
      6 #include <sys/stat.h>
      7 
      8 #define BUFSIZE (1024*8)
      9 static void to_unix(char* buf);
     10 static void unix_to_dos(char* buf2, const char* buf);
     11 
     12 int usage()
     13 {
     14     fprintf(stderr, "usage: line_endings unix|dos FILES\n"
     15             "\n"
     16             "Convert FILES to either unix or dos line endings.\n");
     17     return 1;
     18 }
     19 
     20 typedef struct Node {
     21     struct Node *next;
     22     char buf[BUFSIZE*2+3];
     23 } Node;
     24 
     25 int
     26 main(int argc, char** argv)
     27 {
     28     enum { UNIX, DOS } ending;
     29     int i;
     30 
     31     if (argc < 2) {
     32         return usage();
     33     }
     34 
     35     if (0 == strcmp("unix", argv[1])) {
     36         ending = UNIX;
     37     }
     38     else if (0 == strcmp("dos", argv[1])) {
     39         ending = DOS;
     40     }
     41     else {
     42         return usage();
     43     }
     44 
     45     for (i=2; i<argc; i++) {
     46         int fd;
     47         int len;
     48 
     49         // force implied
     50         chmod(argv[i], S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
     51 
     52         fd = open(argv[i], O_RDWR);
     53         if (fd < 0) {
     54             fprintf(stderr, "unable to open file for read/write: %s\n", argv[i]);
     55             return 1;
     56         }
     57 
     58         len = lseek(fd, 0, SEEK_END);
     59         lseek(fd, 0, SEEK_SET);
     60 
     61         if (len > 0) {
     62             Node* root = malloc(sizeof(Node));
     63             Node* node = root;
     64             node->buf[0] = 0;
     65 
     66             while (len > 0) {
     67                 node->next = malloc(sizeof(Node));
     68                 node = node->next;
     69                 node->next = NULL;
     70 
     71                 char buf[BUFSIZE+2];
     72                 ssize_t amt;
     73                 ssize_t amt2 = len < BUFSIZE ? len : BUFSIZE;
     74                 amt = read(fd, buf, amt2);
     75                 if (amt != amt2) {
     76                     fprintf(stderr, "unable to read file: %s\n", argv[i]);
     77                     return 1;
     78                 }
     79                 buf[amt2] = '\0';
     80                 to_unix(buf);
     81                 if (ending == UNIX) {
     82                     strcpy(node->buf, buf);
     83                 } else {
     84                     char buf2[(BUFSIZE*2)+3];
     85                     unix_to_dos(buf2, buf);
     86                     strcpy(node->buf, buf2);
     87                 }
     88                 len -= amt2;
     89             }
     90 
     91             (void)ftruncate(fd, 0);
     92             lseek(fd, 0, SEEK_SET);
     93             while (root) {
     94                 ssize_t amt2 = strlen(root->buf);
     95                 if (amt2 > 0) {
     96                     ssize_t amt = write(fd, root->buf, amt2);
     97                     if (amt != amt2) {
     98                         fprintf(stderr, "unable to write file: %s\n", argv[i]);
     99                         return 1;
    100                     }
    101                 }
    102                 node = root;
    103                 root = root->next;
    104                 free(node);
    105             }
    106         }
    107         close(fd);
    108     }
    109     return 0;
    110 }
    111 
    112 void
    113 to_unix(char* buf)
    114 {
    115     char* p = buf;
    116     char* q = buf;
    117     while (*p) {
    118         if (p[0] == '\r' && p[1] == '\n') {
    119             // dos
    120             *q = '\n';
    121             p += 2;
    122             q += 1;
    123         }
    124         else if (p[0] == '\r') {
    125             // old mac
    126             *q = '\n';
    127             p += 1;
    128             q += 1;
    129         }
    130         else {
    131             *q = *p;
    132             p += 1;
    133             q += 1;
    134         }
    135     }
    136     *q = '\0';
    137 }
    138 
    139 void
    140 unix_to_dos(char* buf2, const char* buf)
    141 {
    142     const char* p = buf;
    143     char* q = buf2;
    144     while (*p) {
    145         if (*p == '\n') {
    146             q[0] = '\r';
    147             q[1] = '\n';
    148             q += 2;
    149             p += 1;
    150         } else {
    151             *q = *p;
    152             p += 1;
    153             q += 1;
    154         }
    155     }
    156     *q = '\0';
    157 }
    158 
    159