d4eb5b560cd7871578137e120c5aae3f784a708b
[yaz-moved-to-github.git] / src / tpath.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2008 Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file tpath.c
7  * \brief File Path utilities
8  */
9
10 #if HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <yaz/tpath.h>
19 #include <yaz/log.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #if HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25
26 FILE *yaz_path_fopen(const char *path, const char *name, const char *mode)
27 {
28     return yaz_fopen (path, name, mode, 0);
29 }
30
31 int yaz_fclose (FILE *f)
32 {
33     return fclose (f);
34 }
35
36
37 size_t yaz_filepath_comp(const char **path_p, const char **comp)
38 {
39     const char *path = *path_p;
40     size_t len;
41     const char *path_sep;
42
43     /* somewhat dirty since we have to consider Windows
44      * drive letters..
45      */
46     if (path[0] && strchr ("/\\.", path[0]))
47         path_sep = strchr (path+1, ':');
48     else if (path[0] && path[1])
49         path_sep = strchr (path+2, ':');
50     else
51         path_sep = 0;
52     
53     if (path_sep)
54     {
55         len = path_sep - path;
56         *path_p = path + len + 1;
57     }
58     else
59     {
60         len = strlen(path);
61         *path_p = path + len;
62     }
63     *comp = path;
64     return len;
65 }
66
67 char *yaz_filepath_resolve(const char *fname, const char *path,
68                            const char *base, char *fullpath)
69 {
70     for(;;)
71     {
72         struct stat stat_buf;
73         size_t slen = 0;
74        
75         *fullpath = '\0';
76         if (path)
77         {
78             const char *comp;
79             size_t len = 0;
80
81             len = yaz_filepath_comp(&path, &comp);
82             if (!len)
83                 break;
84
85             if (!strchr ("/\\", *comp) && base)
86             {
87                 /* yes: make base the first part */
88                 strcpy (fullpath, base);
89                 slen = strlen(fullpath);
90                 fullpath[slen++] = '/';
91             }
92             memcpy (fullpath+slen, comp, len);
93             slen += len;
94             if (slen > 0 && !strchr("/\\", fullpath[slen-1]))
95                 fullpath[slen++] = '/';
96         }
97         strcpy (fullpath+slen, fname);
98         if (stat(fullpath, &stat_buf) == 0)
99             return fullpath;
100         if (!path)
101             break;
102     }
103     return 0;
104 }
105
106 FILE *yaz_fopen(const char *path, const char *fname, const char *mode,
107                 const char *base)
108 {
109     char fullpath[1024];
110
111     if (!yaz_filepath_resolve(fname, path, base, fullpath))
112         return 0; /* failure */
113     return fopen(fullpath, mode);
114 }
115
116 int yaz_is_abspath (const char *p)
117 {
118     if (*p == '/')
119         return 1;
120 #ifdef WIN32
121     if (*p == '\\')
122         return 1;
123     if (*p && p[1] == ':' && isalpha(*p))
124         return 1;
125 #endif
126     return 0;
127 }
128 /*
129  * Local variables:
130  * c-basic-offset: 4
131  * indent-tabs-mode: nil
132  * End:
133  * vim: shiftwidth=4 tabstop=8 expandtab
134  */
135