dos2unix.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * dos2unix for BusyBox
  3. *
  4. * dos2unix '\n' convertor 0.5.0
  5. * based on Unix2Dos 0.9.0 by Peter Hanecak (made 19.2.1997)
  6. * Copyright 1997,.. by Peter Hanecak <hanecak@megaloman.sk>.
  7. * All rights reserved.
  8. *
  9. * dos2unix filters reading input from stdin and writing output to stdout.
  10. * Without arguments it reverts the format (e.i. if source is in UNIX format,
  11. * output is in DOS format and vice versa).
  12. *
  13. * This program is free software; you can redistribute it and/or
  14. * modify it under the terms of the GNU General Public License
  15. * as published by the Free Software Foundation; either version 2
  16. * of the License, or (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  26. *
  27. * See the COPYING file for license information.
  28. */
  29. #include <string.h>
  30. #include <getopt.h>
  31. #include <unistd.h>
  32. #include <stdint.h>
  33. #include <fcntl.h>
  34. #include <sys/time.h>
  35. #include "busybox.h"
  36. #define CT_AUTO 0
  37. #define CT_UNIX2DOS 1
  38. #define CT_DOS2UNIX 2
  39. /* We are making a lame pseudo-random string generator here. in
  40. * convert(), each pass through the while loop will add more and more
  41. * stuff into value, which is _supposed_ to wrap. We don't care about
  42. * it being accurate. We care about it being messy, since we then mod
  43. * it by the sizeof(letters) and then use that as an index into letters
  44. * to pick a random letter to add to out temporary file. */
  45. typedef unsigned long int bb_uint64_t;
  46. static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  47. // if fn is NULL then input is stdin and output is stdout
  48. static int convert(char *fn, int ConvType)
  49. {
  50. int c, fd;
  51. struct timeval tv;
  52. char tempFn[BUFSIZ];
  53. static bb_uint64_t value=0;
  54. FILE *in = stdin, *out = stdout;
  55. if (fn != NULL) {
  56. in = bb_xfopen(fn, "rw");
  57. safe_strncpy(tempFn, fn, sizeof(tempFn));
  58. c = strlen(tempFn);
  59. tempFn[c] = '.';
  60. while(1) {
  61. /* tempFn is BUFSIZ so the last addressable spot it BUFSIZ-1.
  62. * The loop increments by 2. So this must check for BUFSIZ-3. */
  63. if (c >=BUFSIZ-3)
  64. bb_error_msg_and_die("unique name not found");
  65. /* Get some semi random stuff to try and make a
  66. * random filename based (and in the same dir as)
  67. * the input file... */
  68. gettimeofday (&tv, NULL);
  69. value += ((bb_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
  70. tempFn[++c] = letters[value % 62];
  71. tempFn[c+1] = '\0';
  72. value /= 62;
  73. if ((fd = open(tempFn, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0 ) {
  74. continue;
  75. }
  76. out = fdopen(fd, "w+");
  77. if (!out) {
  78. close(fd);
  79. remove(tempFn);
  80. continue;
  81. }
  82. break;
  83. }
  84. }
  85. while ((c = fgetc(in)) != EOF) {
  86. if (c == '\r') {
  87. if ((ConvType == CT_UNIX2DOS) && (fn != NULL)) {
  88. // file is alredy in DOS format so it is not necessery to touch it
  89. remove(tempFn);
  90. if (fclose(in) < 0 || fclose(out) < 0) {
  91. bb_perror_nomsg();
  92. return -2;
  93. }
  94. return 0;
  95. }
  96. if (!ConvType)
  97. ConvType = CT_DOS2UNIX;
  98. break;
  99. }
  100. if (c == '\n') {
  101. if ((ConvType == CT_DOS2UNIX) && (fn != NULL)) {
  102. // file is alredy in UNIX format so it is not necessery to touch it
  103. remove(tempFn);
  104. if ((fclose(in) < 0) || (fclose(out) < 0)) {
  105. bb_perror_nomsg();
  106. return -2;
  107. }
  108. return 0;
  109. }
  110. if (!ConvType) {
  111. ConvType = CT_UNIX2DOS;
  112. }
  113. if (ConvType == CT_UNIX2DOS) {
  114. fputc('\r', out);
  115. }
  116. fputc('\n', out);
  117. break;
  118. }
  119. fputc(c, out);
  120. }
  121. if (c != EOF)
  122. while ((c = fgetc(in)) != EOF) {
  123. if (c == '\r')
  124. continue;
  125. if (c == '\n') {
  126. if (ConvType == CT_UNIX2DOS)
  127. fputc('\r', out);
  128. fputc('\n', out);
  129. continue;
  130. }
  131. fputc(c, out);
  132. }
  133. if (fn != NULL) {
  134. if (fclose(in) < 0 || fclose(out) < 0) {
  135. bb_perror_nomsg();
  136. remove(tempFn);
  137. return -2;
  138. }
  139. /* Assume they are both on the same filesystem (which
  140. * should be true since we put them into the same directory
  141. * so we _should_ be ok, but you never know... */
  142. if (rename(tempFn, fn) < 0) {
  143. bb_perror_msg("unable to rename '%s' as '%s'", tempFn, fn);
  144. return -1;
  145. }
  146. }
  147. return 0;
  148. }
  149. int dos2unix_main(int argc, char *argv[])
  150. {
  151. int ConvType = CT_AUTO;
  152. int o;
  153. //See if we are supposed to be doing dos2unix or unix2dos
  154. if (argv[0][0]=='d') {
  155. ConvType = CT_DOS2UNIX;
  156. }
  157. if (argv[0][0]=='u') {
  158. ConvType = CT_UNIX2DOS;
  159. }
  160. // process parameters
  161. while ((o = getopt(argc, argv, "du")) != EOF) {
  162. switch (o) {
  163. case 'd':
  164. ConvType = CT_UNIX2DOS;
  165. break;
  166. case 'u':
  167. ConvType = CT_DOS2UNIX;
  168. break;
  169. default:
  170. bb_show_usage();
  171. }
  172. }
  173. if (optind < argc) {
  174. while(optind < argc)
  175. if ((o = convert(argv[optind++], ConvType)) < 0)
  176. break;
  177. }
  178. else
  179. o = convert(NULL, ConvType);
  180. return o;
  181. }