file.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /*
  2. * file.c - File handling
  3. *
  4. * Written 2009-2012 by Werner Almesberger
  5. * Copyright 2009-2012 by Werner Almesberger
  6. * Copyright 2016, Erich Heinzle (gEDA additions)
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <errno.h>
  17. #include <sys/stat.h>
  18. #include "dump.h"
  19. #include "kicad.h"
  20. #include "geda.h"
  21. #include "postscript.h"
  22. #include "gnuplot.h"
  23. #include "util.h"
  24. #include "file.h"
  25. #include "fped.h"
  26. /* ----- general helper functions ------------------------------------------ */
  27. char *set_extension(const char *name, const char *ext)
  28. {
  29. char *s = stralloc(name);
  30. char *slash, *dot;
  31. char *res;
  32. slash = strrchr(s, '/');
  33. dot = strrchr(slash ? slash : s, '.');
  34. if (dot)
  35. *dot = 0;
  36. res = stralloc_printf("%s.%s", s, ext);
  37. free(s);
  38. return res;
  39. }
  40. int file_exists(const char *name)
  41. {
  42. struct stat st;
  43. if (stat(name, &st) >= 0)
  44. return 1;
  45. if (errno == ENOENT)
  46. return 0;
  47. perror(name);
  48. return -1;
  49. }
  50. int save_to(const char *name, int (*fn)(FILE *file, const char *one),
  51. const char *one)
  52. {
  53. FILE *file;
  54. file = fopen(name, "w");
  55. if (!file) {
  56. perror(name);
  57. return 0;
  58. }
  59. if (!fn(file, one)) {
  60. perror(name);
  61. return 0;
  62. }
  63. if (fclose(file) == EOF) {
  64. perror(name);
  65. return 0;
  66. }
  67. return 1;
  68. }
  69. void save_with_backup(const char *name, int (*fn)(FILE *file, const char *one),
  70. const char *one)
  71. {
  72. char *s = stralloc(name);
  73. char *back, *tmp;
  74. char *slash, *dot;
  75. int n, res;
  76. /* save to temporary file */
  77. slash = strrchr(s, '/');
  78. if (!slash) {
  79. tmp = stralloc_printf("~%s", s);
  80. } else {
  81. *slash = 0;
  82. tmp = stralloc_printf("%s/~%s", s, slash+1);
  83. *slash = '/';
  84. }
  85. if (!save_to(tmp, fn, one))
  86. return;
  87. /* move existing file out of harm's way */
  88. dot = strrchr(slash ? slash : s, '.');
  89. if (dot)
  90. *dot = 0;
  91. n = 0;
  92. while (1) {
  93. back = stralloc_printf("%s~%d%s%s",
  94. s, n, dot ? "." : "", dot ? dot+1 : "");
  95. res = file_exists(back);
  96. if (!res)
  97. break;
  98. free(back);
  99. if (res < 0)
  100. return;
  101. n++;
  102. }
  103. if (rename(name, back) < 0) {
  104. if (errno != ENOENT) {
  105. perror(name);
  106. free(back);
  107. return;
  108. }
  109. } else {
  110. fprintf(stderr, "renamed %s to %s\n", name, back);
  111. }
  112. free(back);
  113. /* rename to final name */
  114. if (rename(tmp, name) < 0) {
  115. perror(name);
  116. free(tmp);
  117. return;
  118. }
  119. free(tmp);
  120. fprintf(stderr, "saved to %s\n", name);
  121. }
  122. /* ----- application-specific save handlers -------------------------------- */
  123. void save_fpd(void)
  124. {
  125. if (save_file_name) {
  126. save_with_backup(save_file_name, dump, NULL);
  127. } else {
  128. if (!dump(stdout, NULL))
  129. perror("stdout");
  130. }
  131. }
  132. void write_kicad(void)
  133. {
  134. char *name;
  135. if (save_file_name) {
  136. name = set_extension(save_file_name, "mod");
  137. save_to(name, kicad, NULL);
  138. free(name);
  139. } else {
  140. if (!kicad(stdout, NULL))
  141. perror("stdout");
  142. }
  143. }
  144. void write_geda(void)
  145. {
  146. char *name;
  147. if (save_file_name) {
  148. name = set_extension(save_file_name, "pcb");
  149. save_to(name, geda, NULL);
  150. free(name);
  151. } else {
  152. if (!geda(stdout, NULL))
  153. perror("stdout");
  154. }
  155. }
  156. static void do_write_ps(int (*fn)(FILE *file, const char *one),
  157. const char *one)
  158. {
  159. char *name;
  160. if (save_file_name) {
  161. name = set_extension(save_file_name, "ps");
  162. save_to(name, fn, one);
  163. free(name);
  164. } else {
  165. if (!fn(stdout, one))
  166. perror("stdout");
  167. }
  168. }
  169. void write_ps(const char *one)
  170. {
  171. do_write_ps(postscript, one);
  172. }
  173. void write_ps_fullpage(const char *one)
  174. {
  175. do_write_ps(postscript_fullpage, one);
  176. }
  177. void write_gnuplot(const char *one)
  178. {
  179. char *name;
  180. if (save_file_name) {
  181. name = set_extension(save_file_name, "gp");
  182. save_to(name, gnuplot, one);
  183. free(name);
  184. } else {
  185. if (!gnuplot(stdout, one))
  186. perror("stdout");
  187. }
  188. }