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