1
|
1 /*****************************************************************
|
|
2 * SQUID - a library of functions for biological sequence analysis
|
|
3 * Copyright (C) 1992-2002 Washington University School of Medicine
|
|
4 *
|
|
5 * This source code is freely distributed under the terms of the
|
|
6 * GNU General Public License. See the files COPYRIGHT and LICENSE
|
|
7 * for details.
|
|
8 *****************************************************************/
|
|
9
|
|
10
|
|
11 /* file.c
|
|
12 * SRE, Wed Jun 19 11:19:22 1996
|
|
13 *
|
|
14 * File operation utilities, dealing with pathnames, directories,
|
|
15 * and environment variables.
|
|
16 *
|
|
17 * The goal is to have these be platform-independent but they
|
|
18 * currently are UNIX-specific: i.e. this file is currently POSIX compliant
|
|
19 * but it is NOT ANSI C compliant. (The sole offender is getenv().)
|
|
20 *
|
|
21 * RCS $Id: file.c 217 2011-03-19 10:27:10Z andreas $ (Original squid RCS Id: file.c,v 1.8 2002/03/07 03:18:02 eddy Exp)
|
|
22 */
|
|
23
|
|
24 #include <stdio.h>
|
|
25 #include <stdlib.h>
|
|
26 #include <string.h>
|
|
27
|
|
28 #include "squid.h"
|
|
29 #include "sqfuncs.h"
|
|
30
|
|
31 /*
|
|
32 * VMS: #define DIRSLASH ']'
|
|
33 * MacOS: #define DIRSLASH ':'
|
|
34 * DOS: #define DIRSLASH '\\'
|
|
35 *
|
|
36 * The code assumes that '.' is used for file name extensions,
|
|
37 * such as "foo.bar".
|
|
38 */
|
|
39 #define DIRSLASH '/' /* UNIX directory paths have /foo/bar */
|
|
40
|
|
41
|
|
42
|
|
43 /* Function: FileDirname()
|
|
44 *
|
|
45 * Purpose: Returns the path from a filename:
|
|
46 * "/foo/bar/baz" -> "/foo/bar"
|
|
47 * "foo/bar" -> "foo"
|
|
48 * "foo" -> "."
|
|
49 * "/" -> "/"
|
|
50 * i.e. the string will be non-NULL; it will
|
|
51 * contain the string up to but not including the
|
|
52 * last '/' character; returns "." if
|
|
53 * there are no '/' characters, and returns "/"
|
|
54 * if the last slash is the first character.
|
|
55 * Modeled on Tcl's "file dirname" command.
|
|
56 *
|
|
57 * Args: file - name of file "/foo/bar/baz".
|
|
58 *
|
|
59 * Return: ptr to malloc'ed string "/foo/bar".
|
|
60 */
|
|
61 char *
|
|
62 FileDirname(char *file)
|
|
63 {
|
|
64 char *dirname;
|
|
65 char *lastslash;
|
|
66 int len;
|
|
67
|
|
68 lastslash = strrchr(file, DIRSLASH);
|
|
69 len = (lastslash == NULL) ? 0 : (int) (lastslash - file);
|
|
70 dirname = (char *) MallocOrDie (sizeof(char) * (len+2));
|
|
71 if (len > 0) strncpy(dirname, file, len);
|
|
72 else if (*file != DIRSLASH) { *dirname = '.'; len = 1; }
|
|
73 else { *dirname = DIRSLASH; len = 1; }
|
|
74 dirname[len] = '\0';
|
|
75 return dirname;
|
|
76 }
|
|
77
|
|
78
|
|
79 /* Function: FileTail()
|
|
80 *
|
|
81 * Purpose: Return everything after the DIRSLASH:
|
|
82 * "/foo/bar/baz.1" -> "baz.1"
|
|
83 * "foo/bar" -> "bar"
|
|
84 * "foo" -> "foo"
|
|
85 * "/" -> ""
|
|
86 * If noextension is TRUE, removes a trailing ".foo" extension
|
|
87 * too.
|
|
88 *
|
|
89 * Args: file - name of file "/foo/bar/baz.1"
|
|
90 * noextension - TRUE to also remove extensions
|
|
91 *
|
|
92 * Return: ptr to malloc'ed string "baz.1"
|
|
93 */
|
|
94 char *
|
|
95 FileTail(char *file, int noextension)
|
|
96 {
|
|
97 char *tail;
|
|
98 char *lastslash;
|
|
99 char *lastdot;
|
|
100 /* remove directory prefix */
|
|
101 lastslash = strrchr(file, DIRSLASH);
|
|
102 tail = (char *) MallocOrDie (sizeof(char) * (strlen(file)+1));
|
|
103 if (lastslash == NULL) strcpy(tail, file);
|
|
104 else strcpy(tail, lastslash+1);
|
|
105 /* remove trailing suffix */
|
|
106 if (noextension) {
|
|
107 if ((lastdot = strrchr(tail, '.')) != NULL)
|
|
108 *lastdot = '\0';
|
|
109 }
|
|
110
|
|
111 return tail;
|
|
112 }
|
|
113
|
|
114
|
|
115 /* Function: FileSameDirectory()
|
|
116 * Date: SRE, Wed Mar 6 20:03:23 2002 [St. Louis]
|
|
117 *
|
|
118 * Purpose: Given a path to one file, and the
|
|
119 * name of another file in the same directory,
|
|
120 * concat the path from file1 onto file2, and
|
|
121 * return the result. Caller must free the ptr
|
|
122 * that's returned.
|
|
123 *
|
|
124 * Written for SSI - SSI indices contain filenames
|
|
125 * without paths, and we will need to convert that
|
|
126 * to a full path.
|
|
127 *
|
|
128 * Args: file1 - a path to a file, e.g. "/foo/bar/baz.1"
|
|
129 * file2 - a simple filename, e.g. "quux.2"
|
|
130 *
|
|
131 * Returns: path to file2: e.g. "/foo/bar/quux.2"
|
|
132 * Returns NULL if file2 already has a path, and the result
|
|
133 * would be a different place.
|
|
134 */
|
|
135 char *
|
|
136 FileSameDirectory(char *file1, char *file2)
|
|
137 {
|
|
138 char *path;
|
|
139 char *tail;
|
|
140 char *result;
|
|
141 int seems_ok = 1;
|
|
142
|
|
143 path = FileDirname(file1);
|
|
144 tail = FileTail(file2, FALSE);
|
|
145 if (strcmp(file2, tail) != 0) seems_ok = 0; /* ut-oh, file2 *had* a path */
|
|
146 result = FileConcat(path, tail);
|
|
147 if (! seems_ok && strcmp(result, file2) != 0) {
|
|
148 free(result); result = NULL;
|
|
149 }
|
|
150 free(path);
|
|
151 free(tail);
|
|
152 return result;
|
|
153 }
|
|
154
|
|
155 /* Function: FileConcat()
|
|
156 *
|
|
157 * Purpose: Concatenate a directory path and a file name,
|
|
158 * returning a pointer to a malloc'ed string with the
|
|
159 * full filename. This isn't just a string concat,
|
|
160 * because we're careful about the dir slash.
|
|
161 */
|
|
162 char *
|
|
163 FileConcat(char *dir, char *file)
|
|
164 {
|
|
165 char *full;
|
|
166
|
|
167 full = (char *) MallocOrDie (sizeof(char) * (strlen(dir)+strlen(file)+2));
|
|
168 if (*file == DIRSLASH) strcpy(full, file); /* file = "/foo", ignore directory. */
|
|
169 else sprintf(full, "%s%c%s", dir, DIRSLASH, file);
|
|
170 return full;
|
|
171 }
|
|
172
|
|
173
|
|
174 /* Function: FileAddSuffix()
|
|
175 * Date: SRE, Wed Aug 1 11:19:33 2001 [Pasadena]
|
|
176 *
|
|
177 * Purpose: Add a suffix to a filename, return a malloc'ed
|
|
178 * string containing the new filename.sfx name.
|
|
179 * Example:
|
|
180 * FileAddSuffix("genbank", "ssi")
|
|
181 * returns "genbank.ssi".
|
|
182 */
|
|
183 char *
|
|
184 FileAddSuffix(char *filename, char *sfx)
|
|
185 {
|
|
186 char *new;
|
|
187 new = MallocOrDie(strlen(filename) + strlen(sfx) + 2);
|
|
188 sprintf(new, "%s.%s", filename, sfx);
|
|
189 return new;
|
|
190 }
|
|
191
|
|
192 /* Function: EnvFileOpen()
|
|
193 * Date: Sun Feb 12 10:55:29 1995
|
|
194 *
|
|
195 * Purpose: Open a file, given a file name and an environment
|
|
196 * variable that contains a directory path. Files
|
|
197 * are opened read-only. Does not look at current directory
|
|
198 * unless "." is explicitly in the path specified by env.
|
|
199 *
|
|
200 * For instance:
|
|
201 * fp = EnvFileOpen("BLOSUM45", "BLASTMAT", NULL);
|
|
202 * or:
|
|
203 * fp = EnvFileOpen("swiss", "BLASTDB", NULL);
|
|
204 *
|
|
205 * Environment variables may contain a colon-delimited
|
|
206 * list of more than one path; e.g.
|
|
207 * setenv BLASTDB /nfs/databases/foo:/nfs/databases/bar
|
|
208 *
|
|
209 * Sometimes a group of files may be found in
|
|
210 * one directory; for instance, an index file with a
|
|
211 * database. The caller can EnvFileOpen() the main
|
|
212 * file, and ask to get the name of the
|
|
213 * directory back in ret_dir, so it can construct
|
|
214 * the other auxiliary file names and fopen() them. (If it called
|
|
215 * EnvFileOpen(), it might get confused by
|
|
216 * file name clashes and open files in different
|
|
217 * directories.
|
|
218 *
|
|
219 * Args: fname - name of file to open
|
|
220 * env - name of environment variable containing path
|
|
221 * ret_dir - if non-NULL, RETURN: name of dir that was used.
|
|
222 *
|
|
223 * Return: FILE * to open file, or NULL on failure -- same as fopen()
|
|
224 * Caller must free ret_dir if it passed a non-NULL address.
|
|
225 */
|
|
226 FILE *
|
|
227 EnvFileOpen(char *fname, char *env, char **ret_dir)
|
|
228 {
|
|
229 FILE *fp;
|
|
230 char *path;
|
|
231 char *s; /* ptr to indiv element in env list */
|
|
232 char full[1024]; /* constructed file name */
|
|
233
|
|
234 if (env == NULL) return NULL;
|
|
235 if ((path = Strdup(getenv(env))) == NULL) return NULL;
|
|
236
|
|
237 fp = NULL;
|
|
238 s = strtok(path, ":");
|
|
239 while (s != NULL)
|
|
240 {
|
|
241 if (((int) strlen(fname) + (int) strlen(s) + 2) > 1024)
|
|
242 { free(path); return NULL; }
|
|
243 sprintf(full, "%s%c%s", s, DIRSLASH, fname);
|
|
244 if ((fp = fopen(full, "r")) != NULL) break;
|
|
245 s = strtok(NULL, ":");
|
|
246 }
|
|
247
|
|
248 /* Return the path we used, if caller wants it
|
|
249 */
|
|
250 if (ret_dir != NULL) *ret_dir = Strdup(s);
|
|
251 free(path);
|
|
252
|
|
253 return fp;
|
|
254 }
|
|
255
|
|
256
|
|
257 /* Function: FileExists()
|
|
258 *
|
|
259 * Purpose: Return TRUE if filename exists.
|
|
260 * Testing fopen() is the only possible platform-independent test
|
|
261 * I'm aware of.
|
|
262 */
|
|
263 int
|
|
264 FileExists(char *filename)
|
|
265 {
|
|
266 FILE *fp;
|
|
267 if ((fp = fopen(filename, "r"))) { fclose(fp); return TRUE; }
|
|
268 return FALSE;
|
|
269 }
|
|
270
|
|
271
|