1 /*
2 **
3 ** file.c
4 **
5 ** Copyright (C) 1995, 1996, 1997 Johannes Plass
6 ** Copyright (C) 2004 Jose E. Marchesi
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 3 of the License, or
11 ** (at your option) any later version.
12 **
13 ** This program is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ** GNU General Public License for more details.
17 **
18 ** You should have received a copy of the GNU General Public License
19 ** along with GNU gv; see the file COPYING. If not, write to
20 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ** Boston, MA 02111-1307, USA.
22 **
23 ** Author: Johannes Plass (plass@thep.physik.uni-mainz.de)
24 ** Department of Physics
25 ** Johannes Gutenberg-University
26 ** Mainz, Germany
27 **
28 ** Jose E. Marchesi (jemarch@gnu.org)
29 ** GNU Project
30 **
31 ** Changes submitted by Maurizio Loreti distributed on the public
32 ** domain:
33 **
34 ** - Code for handle bzip2 compressed files.
35 **
36 */
37 #include "ac_config.h"
38
39 /*
40 #define MESSAGES
41 */
42 #include "message.h"
43
44 #include <string.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <time.h>
49 #include <ctype.h>
50 #include <errno.h>
51 #include <fcntl.h>
52
53 #include <sys/types.h>
54 #include <sys/stat.h>
55
56 #include "paths.h"
57 #include INC_X11(Intrinsic.h)
58
59 #include "types.h"
60 #include "config.h"
61 #include "file.h"
62 #include "main_resources.h"
63 #include "main_globals.h"
64
65 #ifndef ENODATA
66 #define ENODATA ENOMSG
67 #endif
68
69 /*############################################################*/
70 /* file_getDirOfPath */
71 /*############################################################*/
72
73 char *
file_getDirOfPath(char * path)74 file_getDirOfPath(char *path)
75 {
76 char *dir=NULL;
77 char *pos;
78
79 BEGINMESSAGE(file_getDirOfPath)
80
81 if (path) {
82 dir=XtNewString(path);
83 pos = strrchr(dir,'/');
84 if (pos) { pos++; *pos='\0'; }
85 }
86
87 #ifdef MESSAGES
88 if (!dir) { INFMESSAGE (### Warning: returning NULL) }
89 else { INFSMESSAGE(returning, dir) }
90 #endif
91 ENDMESSAGE(file_getDirOfPath)
92 return(dir);
93 }
94
95 /*############################################################*/
96 /* file_locateFilename */
97 /*############################################################*/
98
99 char *
file_locateFilename(char * path)100 file_locateFilename(char *path)
101 {
102 char *tmp=NULL;
103 BEGINMESSAGE(file_locateFileName)
104 if (path) {
105
106 tmp = strrchr(path,'/');
107
108 if (!tmp) tmp=path;
109 else tmp++;
110 INFSMESSAGE(found,tmp)
111 }
112 ENDMESSAGE(file_locateFilename)
113 return(tmp);
114 }
115
116 /*############################################################*/
117 /* file_getTmpFilename */
118 /* provide some temporary file name */
119 /*############################################################*/
120
121 char *
file_getTmpFilename(const char * baseDirectory,const char * baseFilename,int * filed)122 file_getTmpFilename(const char *baseDirectory, const char *baseFilename, int *filed)
123 {
124 char tempFilename[256];
125 char *tempFilenameP;
126 char tmpNameBuf[256];
127 char *tmpName;
128 char *tmpExt;
129 char *pos;
130 int len;
131
132 BEGINMESSAGE(file_getTmpFilename)
133
134 if (baseDirectory)
135 pos = strrchr(baseDirectory, '/');
136 else
137 pos = NULL;
138 if (pos) {
139 len = pos - baseDirectory;
140 } else {
141 baseDirectory = app_res.scratch_dir;
142 len = strlen(baseDirectory);
143 if (len > 0 && baseDirectory[len-1] == '/')
144 len--;
145 }
146
147 if (!baseFilename) baseFilename= ".";
148 strcpy(tmpNameBuf,baseFilename);
149 pos = file_locateFilename(tmpNameBuf);
150 if (pos) tmpName = pos;
151 else tmpName = tmpNameBuf;
152
153 pos = strrchr(tmpName,'.');
154 if (pos) { *pos='\0'; tmpExt = pos+1; }
155 else tmpExt = "";
156
157 /* Limit filename to 39 characters (excluding dir and .tmp).
158 This is required for VMS, but is also reasonable for Unix. */
159 if (strlen(tmpName)+strlen(tmpExt)>23) {
160 if (strlen(tmpExt)>11) tmpExt[11] = '\0'; /* allow .ps_page_nnn */
161 if (strlen(tmpName)+strlen(tmpExt)>23) tmpName[23-strlen(tmpExt)] = '\0';
162 }
163 {
164 int done = 0;
165 int i=1;
166 do {
167 int fd, l;
168 mode_t oldumask;
169 l = snprintf(tempFilename, sizeof(tempFilename),
170 "%.*s/gv_%s_%s.XXXXXX",
171 len, baseDirectory, tmpName, tmpExt);
172 if (l < 0 || l >= (int)sizeof(tempFilename) )
173 break;
174 file_translateTildeInPath(tempFilename, sizeof(tempFilename));
175 oldumask = umask(0077);
176 fd = mkstemp(tempFilename);
177 umask(oldumask);
178 if (fd < 0)
179 break;
180 if (fd >= 0) {
181 if (filed)
182 *filed = fd;
183 else
184 close(fd);
185 done = 1;
186 }
187 i++;
188 } while (!done && i <= 10000);
189 if (!done) {
190 ENDMESSAGE(file_getTmpFilename)
191 return NULL;
192 }
193 }
194 SMESSAGE(tempFilename)
195 tempFilenameP = XtNewString(tempFilename);
196 ENDMESSAGE(file_getTmpFilename)
197 return(tempFilenameP);
198 }
199
200 /*############################################################*/
201 /* file_translateTildeInPath */
202 /* Replaces tilde in string by user's home directory. */
203 /*############################################################*/
204
file_translateTildeInPath(char * path,size_t s)205 void file_translateTildeInPath(char *path, size_t s)
206 {
207
208 BEGINMESSAGE(file_translateTildeInPath)
209 if (path[0] == '~' && (path[1] == '/' || path[1] == '\0')) {
210 char *home = getenv("HOME");
211
212 if (home != NULL) {
213 size_t pl = strlen(path);
214 size_t hl = strlen(home);
215 if (pl + hl - 1 < s - 1) {
216 memmove(path + hl, path + 1, pl - 1 + 1);
217 memcpy(path, home, hl);
218 }
219 }
220 }
221 ENDMESSAGE(file_translateTildeInPath)
222 }
223
224 /*############################################################*/
225 /* file_fileIsDir */
226 /*############################################################*/
227
file_fileIsDir(char * fn)228 int file_fileIsDir(char *fn)
229 {
230 struct stat s;
231 int r=0;
232 char *c;
233 BEGINMESSAGE(file_fileIsNotUseful)
234 if (fn) {
235 c = strrchr(fn,'/');
236 if (c && (!*(c+1) || isspace(*(c+1)))) r = 1;
237
238 if (!r && !stat(fn,&s) && (S_ISDIR(s.st_mode))) r=1;
239 }
240 IMESSAGE(r)
241 ENDMESSAGE(file_fileIsDir)
242 return(r);
243 }
244
245 /*############################################################*/
246 /* file_fileIsNotUseful */
247 /*############################################################*/
248
249 int
file_fileIsNotUseful(char * fn)250 file_fileIsNotUseful(char *fn)
251 {
252 struct stat s;
253 int r=0;
254 BEGINMESSAGE(file_fileIsNotUseful)
255 if (!fn || stat(fn, &s))
256 r = 1;
257 else if (S_ISDIR(s.st_mode)) {
258 r = 1;
259 errno = EISDIR;
260 } else if (s.st_size == 0) {
261 r = 1;
262 #ifdef EFTYPE
263 errno = EFTYPE;
264 #else
265 errno = ENODATA;
266 #endif
267 }
268 IMESSAGE(r)
269 ENDMESSAGE(file_fileIsNotUseful)
270 return(r);
271 }
272
273 /*############################################################*/
274 /* file_pdfname2psname */
275 /* If the file ends in .pdf, change this to .ps.*/
276 /* Return pointer to temp copy if changed, else to input string. */
277 /*############################################################*/
278
279 char *
file_pdfname2psname(char * name)280 file_pdfname2psname(char *name)
281 {
282 char *e;
283
284 if (!name)
285 {
286 return(name);
287 }
288
289 e = name+strlen(name);
290
291 if ((e-name)-4 >= 0)
292 {
293 e -= 4;
294 if (!strcasecmp(e,".pdf"))
295 {
296 strcpy(e,".ps");
297 }
298 }
299
300 return(name);
301 }
302
303
304 /*############################################################*/
305 /* file_getUsefulName */
306 /*############################################################*/
307
308 char *
file_getUsefulName(char * name)309 file_getUsefulName(char *name)
310 {
311 char *e,*c;
312 String mext,ext;
313
314 BEGINMESSAGE(file_getUsefulName)
315 if (!name) {
316 ENDMESSAGE(file_getUsefulName)
317 return(name);
318 }
319 INFSMESSAGE(in,name)
320
321 c = e = strrchr(name,'.');
322 if (!e) {
323 ENDMESSAGE(file_getUsefulName)
324 return(name);
325 }
326 mext = ext = XtNewString(e);
327 while (*ext) { *ext = tolower(*ext); ext++; }
328 if (!strncmp(mext,".gz",3)) ext = "";
329 else if (!strncmp(mext,".bz2",4)) ext = "";
330 else if (!strncmp(mext,".z",2)) ext = "";
331 else if (!strncmp(mext,".ps",3)) ext = ".ps";
332 else if (!strncmp(mext,".pdf",4)) ext = ".pdf";
333 else ext = e;
334 if (e == name && !(*ext)) {
335 ENDMESSAGE(file_getUsefulName)
336 return(name);
337 }
338 strcpy(mext,ext);
339 ext=mext;
340 while (*ext && *e) *ext++=*e++;
341 strcpy(c,mext);
342 XtFree(mext);
343 INFSMESSAGE(out,name)
344 ENDMESSAGE(file_getUsefulName)
345 return(name);
346 }
347
348