Root/
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 | |
14 | |
15 | #include <stdlib.h> |
16 | #include <stdio.h> |
17 | #include <string.h> |
18 | #include <errno.h> |
19 | #include <sys/stat.h> |
20 | |
21 | #include "dump.h" |
22 | #include "kicad.h" |
23 | #include "geda.h" |
24 | #include "postscript.h" |
25 | #include "gnuplot.h" |
26 | #include "util.h" |
27 | #include "file.h" |
28 | #include "fped.h" |
29 | |
30 | |
31 | /* ----- general helper functions ------------------------------------------ */ |
32 | |
33 | |
34 | char *set_extension(const char *name, const char *ext) |
35 | { |
36 | char *s = stralloc(name); |
37 | char *slash, *dot; |
38 | char *res; |
39 | |
40 | slash = strrchr(s, '/'); |
41 | dot = strrchr(slash ? slash : s, '.'); |
42 | if (dot) |
43 | *dot = 0; |
44 | res = stralloc_printf("%s.%s", s, ext); |
45 | free(s); |
46 | return res; |
47 | } |
48 | |
49 | |
50 | int file_exists(const char *name) |
51 | { |
52 | struct stat st; |
53 | |
54 | if (stat(name, &st) >= 0) |
55 | return 1; |
56 | if (errno == ENOENT) |
57 | return 0; |
58 | perror(name); |
59 | return -1; |
60 | } |
61 | |
62 | |
63 | int save_to(const char *name, int (*fn)(FILE *file, const char *one), |
64 | const char *one) |
65 | { |
66 | FILE *file; |
67 | |
68 | file = fopen(name, "w"); |
69 | if (!file) { |
70 | perror(name); |
71 | return 0; |
72 | } |
73 | if (!fn(file, one)) { |
74 | perror(name); |
75 | return 0; |
76 | } |
77 | if (fclose(file) == EOF) { |
78 | perror(name); |
79 | return 0; |
80 | } |
81 | return 1; |
82 | } |
83 | |
84 | |
85 | void save_with_backup(const char *name, int (*fn)(FILE *file, const char *one), |
86 | const char *one) |
87 | { |
88 | char *s = stralloc(name); |
89 | char *back, *tmp; |
90 | char *slash, *dot; |
91 | int n, res; |
92 | |
93 | /* save to temporary file */ |
94 | |
95 | slash = strrchr(s, '/'); |
96 | if (!slash) { |
97 | tmp = stralloc_printf("~%s", s); |
98 | } else { |
99 | *slash = 0; |
100 | tmp = stralloc_printf("%s/~%s", s, slash+1); |
101 | *slash = '/'; |
102 | } |
103 | |
104 | if (!save_to(tmp, fn, one)) |
105 | return; |
106 | |
107 | /* move existing file out of harm's way */ |
108 | |
109 | dot = strrchr(slash ? slash : s, '.'); |
110 | if (dot) |
111 | *dot = 0; |
112 | n = 0; |
113 | while (1) { |
114 | back = stralloc_printf("%s~%d%s%s", |
115 | s, n, dot ? "." : "", dot ? dot+1 : ""); |
116 | res = file_exists(back); |
117 | if (!res) |
118 | break; |
119 | free(back); |
120 | if (res < 0) |
121 | return; |
122 | n++; |
123 | } |
124 | if (rename(name, back) < 0) { |
125 | if (errno != ENOENT) { |
126 | perror(name); |
127 | free(back); |
128 | return; |
129 | } |
130 | } else { |
131 | fprintf(stderr, "renamed %s to %s\n", name, back); |
132 | } |
133 | free(back); |
134 | |
135 | /* rename to final name */ |
136 | |
137 | if (rename(tmp, name) < 0) { |
138 | perror(name); |
139 | free(tmp); |
140 | return; |
141 | } |
142 | free(tmp); |
143 | |
144 | fprintf(stderr, "saved to %s\n", name); |
145 | } |
146 | |
147 | |
148 | /* ----- application-specific save handlers -------------------------------- */ |
149 | |
150 | |
151 | void save_fpd(void) |
152 | { |
153 | if (save_file_name) { |
154 | save_with_backup(save_file_name, dump, NULL); |
155 | } else { |
156 | if (!dump(stdout, NULL)) |
157 | perror("stdout"); |
158 | } |
159 | } |
160 | |
161 | |
162 | void write_kicad(void) |
163 | { |
164 | char *name; |
165 | |
166 | if (save_file_name) { |
167 | name = set_extension(save_file_name, "mod"); |
168 | save_to(name, kicad, NULL); |
169 | free(name); |
170 | } else { |
171 | if (!kicad(stdout, NULL)) |
172 | perror("stdout"); |
173 | } |
174 | } |
175 | |
176 | void write_geda(void) |
177 | { |
178 | char *name; |
179 | |
180 | if (save_file_name) { |
181 | name = set_extension(save_file_name, "pcb"); |
182 | save_to(name, geda, NULL); |
183 | free(name); |
184 | } else { |
185 | if (!geda(stdout, NULL)) |
186 | perror("stdout"); |
187 | } |
188 | } |
189 | |
190 | |
191 | static void do_write_ps(int (*fn)(FILE *file, const char *one), |
192 | const char *one) |
193 | { |
194 | char *name; |
195 | |
196 | if (save_file_name) { |
197 | name = set_extension(save_file_name, "ps"); |
198 | save_to(name, fn, one); |
199 | free(name); |
200 | } else { |
201 | if (!fn(stdout, one)) |
202 | perror("stdout"); |
203 | } |
204 | } |
205 | |
206 | |
207 | void write_ps(const char *one) |
208 | { |
209 | do_write_ps(postscript, one); |
210 | } |
211 | |
212 | |
213 | void write_ps_fullpage(const char *one) |
214 | { |
215 | do_write_ps(postscript_fullpage, one); |
216 | } |
217 | |
218 | |
219 | void write_gnuplot(const char *one) |
220 | { |
221 | char *name; |
222 | |
223 | if (save_file_name) { |
224 | name = set_extension(save_file_name, "gp"); |
225 | save_to(name, gnuplot, one); |
226 | free(name); |
227 | } else { |
228 | if (!gnuplot(stdout, one)) |
229 | perror("stdout"); |
230 | } |
231 | } |
232 |
Branches:
master