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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
/* Conversion utility CR/LF -> NL */
/* multiple files, in place, restores write date */
/* Bruno Haible 23.1.1994 */
/* Make: gcc -O2 -fomit-frame-pointer -N -o fromdos fromdos.c */
#include <sys/types.h>
#include <unistd.h> /* open, read, write, close, lseek, ftruncate */
#include <fcntl.h> /* O_RDONLY, O_RDWR */
#include <sys/stat.h> /* fstat */
#include <sys/time.h> /* struct timeval, utimes */
#include <errno.h> /* EINTR, perror */
#define CR 13
#define LF 10
#define NL 10
#define BUFLEN 4096
int full_read (int fd, char* buf, size_t nbyte);
int full_write (int fd, char* buf, size_t nbyte);
int main (int argc, char* argv[])
{ int i;
for (i=1; i<argc; i++)
{ char* filename = argv[i];
/* open filename twice so that there is no need to lseek */
int rfd = open(filename,O_RDONLY);
if (rfd<0) { perror(filename); goto next; }
{struct stat statbuf;
if (fstat(rfd,&statbuf)<0) { perror(filename); goto next; }
{ int wfd = open(filename,O_RDWR);
if (wfd<0) { perror(filename); close(rfd); goto next; }
{ char buffer[BUFLEN];
char* bufend = &buffer[BUFLEN];
register char* srcptr = &buffer[0];
register char* destptr;
while (1) /* srcptr is either &buffer[0] or &buffer[1] here */
{ register int count = full_read(rfd,srcptr,bufend-srcptr);
if (count < 0)
{ perror(filename); close(wfd); close(rfd); goto next; }
if (count == 0) break; /* EOF */
count += (srcptr - &buffer[0]);
destptr = srcptr = &buffer[0];
do /* srcptr + count remains constant, destptr<=srcptr, count>0 */
{ if (*srcptr == CR)
{ if (count > 1)
{ if (srcptr[1] == LF)
{ *destptr++ = NL; srcptr += 2; count -= 2; }
else
{ *destptr++ = *srcptr++; count--; }
}
else
break; /* CR at the end of the buffer -> finish loop */
}
else
{ *destptr++ = *srcptr++; count--; }
}
while (count > 0);
/* count = 0 or = 1 here */
if (full_write(wfd,buffer,destptr-buffer) < 0)
{ perror(filename); close(wfd); close(rfd); goto next; }
if (count > 0)
{ buffer[0] = *srcptr; srcptr = &buffer[1]; }
else
{ srcptr = &buffer[0]; }
}
if (srcptr!=buffer)
{ if (full_write(wfd,buffer,srcptr-buffer) < 0)
{ perror(filename); close(wfd); close(rfd); goto next; }
}
}
{ off_t length = lseek(wfd,0,SEEK_CUR);
if (length < 0)
{ perror(filename); close(wfd); close(rfd); goto next; }
if (ftruncate(wfd,length) < 0)
{ perror(filename); close(wfd); close(rfd); goto next; }
}
close(wfd);
}
close(rfd);
/* reset the access and modification times */
{ struct timeval tv[2];
tv[0].tv_sec = statbuf.st_atime; tv[0].tv_usec = 0;
tv[1].tv_sec = statbuf.st_mtime; tv[1].tv_usec = 0;
if (utimes(filename,tv) < 0) { perror(filename); goto next; }
}
}
next: ;
}
exit(0);
}
/* On POSIX systems, read() and write() may return partial results without
failing. Redefine the functions read() and write() such that they retry
whenever a partial result is received or the system call is interrupted
by a signal.
The function full_read and full_write behave like BSD read() and write():
on success, they return nbyte;
on EOF, they return 0;
on failure, they return a negative value and set errno.
*/
int full_read (fd, buf, nbyte)
int fd;
char *buf;
size_t nbyte;
{
register int retval;
size_t done = 0;
while (nbyte > 0)
{
retval = read (fd, buf, nbyte);
if (retval == 0)
break;
else if (retval < 0)
{
#ifdef EINTR
if (errno != EINTR)
#endif
return retval;
}
else
{
buf += retval;
done += (size_t) retval;
nbyte -= (size_t) retval;
}
}
return done;
}
int full_write (fd, buf, nbyte)
int fd;
char *buf;
size_t nbyte;
{
register int retval;
size_t done = 0;
while (nbyte > 0)
{
retval = write (fd, buf, nbyte);
if (retval == 0)
break;
else if (retval < 0)
{
#ifdef EINTR
if (errno != EINTR)
#endif
return retval;
}
else
{
buf += retval;
done += (size_t) retval;
nbyte -= (size_t) retval;
}
}
return done;
}
|