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 
usage()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
main(int argc,char ** argv)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
to_unix(char * buf)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
unix_to_dos(char * buf2,const char * buf)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