File: fromdos.c

package info (click to toggle)
clisp 1997-12-06-1
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 20,744 kB
  • ctags: 8,390
  • sloc: ansic: 37,808; lisp: 37,255; asm: 6,393; sh: 3,077; objc: 2,481; makefile: 1,174; sed: 96; perl: 14
file content (159 lines) | stat: -rw-r--r-- 4,873 bytes parent folder | download | duplicates (7)
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;
}