#include <unistd.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/stat.h> #define BUFSIZE (1024*8) static void to_unix(char* buf); static void unix_to_dos(char* buf2, const char* buf); int usage() { fprintf(stderr, "usage: line_endings unix|dos FILES\n" "\n" "Convert FILES to either unix or dos line endings.\n"); return 1; } typedef struct Node { struct Node *next; char buf[BUFSIZE*2+3]; } Node; int main(int argc, char** argv) { enum { UNIX, DOS } ending; int i; if (argc < 2) { return usage(); } if (0 == strcmp("unix", argv[1])) { ending = UNIX; } else if (0 == strcmp("dos", argv[1])) { ending = DOS; } else { return usage(); } for (i=2; i<argc; i++) { int fd; int len; // force implied chmod(argv[i], S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); fd = open(argv[i], O_RDWR); if (fd < 0) { fprintf(stderr, "unable to open file for read/write: %s\n", argv[i]); return 1; } len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); if (len > 0) { Node* root = malloc(sizeof(Node)); Node* node = root; node->buf[0] = 0; while (len > 0) { node->next = malloc(sizeof(Node)); node = node->next; node->next = NULL; char buf[BUFSIZE+2]; ssize_t amt; ssize_t amt2 = len < BUFSIZE ? len : BUFSIZE; amt = read(fd, buf, amt2); if (amt != amt2) { fprintf(stderr, "unable to read file: %s\n", argv[i]); return 1; } buf[amt2] = '\0'; to_unix(buf); if (ending == UNIX) { strcpy(node->buf, buf); } else { char buf2[(BUFSIZE*2)+3]; unix_to_dos(buf2, buf); strcpy(node->buf, buf2); } len -= amt2; } (void)ftruncate(fd, 0); lseek(fd, 0, SEEK_SET); while (root) { ssize_t amt2 = strlen(root->buf); if (amt2 > 0) { ssize_t amt = write(fd, root->buf, amt2); if (amt != amt2) { fprintf(stderr, "unable to write file: %s\n", argv[i]); return 1; } } node = root; root = root->next; free(node); } } close(fd); } return 0; } void to_unix(char* buf) { char* p = buf; char* q = buf; while (*p) { if (p[0] == '\r' && p[1] == '\n') { // dos *q = '\n'; p += 2; q += 1; } else if (p[0] == '\r') { // old mac *q = '\n'; p += 1; q += 1; } else { *q = *p; p += 1; q += 1; } } *q = '\0'; } void unix_to_dos(char* buf2, const char* buf) { const char* p = buf; char* q = buf2; while (*p) { if (*p == '\n') { q[0] = '\r'; q[1] = '\n'; q += 2; p += 1; } else { *q = *p; p += 1; q += 1; } } *q = '\0'; }