Imported Upstream version 2.8.4
[platform/upstream/man-db.git] / src / filenames.c
1 /*
2  * filenames.c: compose and dissect man page file names
3  *
4  * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
5  * Copyright (C) 2001, 2002 Colin Watson.
6  *
7  * This file is part of man-db.
8  *
9  * man-db is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * man-db is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with man-db; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif /* HAVE_CONFIG_H */
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31
32 #include "xvasprintf.h"
33
34 #include "gettext.h"
35 #define _(String) gettext (String)
36
37 #include "manconfig.h"
38
39 #include "error.h"
40
41 #include "db_storage.h"
42
43 #include "filenames.h"
44
45 static void gripe_bogus_manpage (const char *manpage)
46 {
47         if (quiet < 2)
48                 error (0, 0, _("warning: %s: ignoring bogus filename"),
49                        manpage);
50 }                 
51
52 char *make_filename (const char *path, const char *name,
53                      struct mandata *in, const char *type)
54 {
55         static char *file;
56
57         if (!name)
58                 name = in->name;    /* comes from dblookup(), so non-NULL */
59
60         file = xasprintf ("%s/%s%s/%s.%s", path, type, in->sec, name, in->ext);
61
62         if (in->comp && *in->comp != '-')       /* Is there an extension? */
63                 file = appendstr (file, ".", in->comp, NULL);
64
65         debug ("Checking physical location: %s\n", file);
66         if (!CAN_ACCESS (file, R_OK)) {
67                 free (file);
68                 return NULL;
69         }
70
71         return file;
72 }
73
74 /* Fill in a mandata structure with information about a file name.
75  * file is the name to examine. info points to the structure to be filled
76  * in. req_name is the page name that was requested.
77  * 
78  * Returns either a pointer to the buffer which the fields in info point
79  * into, to be freed by the caller, or NULL on error. The buffer will
80  * contain either three or four null-terminated strings: the directory name,
81  * the base of the file name in that directory, the section extension, and
82  * optionally the compression extension (if COMP_SRC is defined).
83  * 
84  * Only the fields name, ext, sec, and comp are filled in by this function.
85  * name is only set if it differs from req_name; otherwise it remains at
86  * NULL.
87  */
88 char *filename_info (const char *file, struct mandata *info,
89                      const char *req_name)
90 {
91         char *manpage = xstrdup (file);
92         char *slash = strrchr (manpage, '/');
93         char *base_name;
94
95         memset (info, 0, sizeof (struct mandata));
96
97 #ifdef COMP_SRC
98         struct compression *comp;
99 #endif
100
101         if (slash) {
102                 *slash = '\0';                  /* strip '/base_name' */
103                 base_name = slash + 1;
104         } else
105                 base_name = manpage;
106
107         /* Bogus files either have (i) no period, ie no extension, (ii)
108            a compression extension, but no sectional extension, (iii)
109            a missmatch between the section they are under and the
110            sectional part of their extension. */
111
112 #ifdef COMP_SRC
113         comp = comp_info (base_name, 1);
114         if (comp) {
115                 info->comp = comp->ext;
116                 *(base_name + strlen (comp->stem)) = '\0';
117                 free (comp->stem);
118         } else
119                 info->comp = NULL;
120 #else /* !COMP_SRC */   
121         info->comp = NULL;
122 #endif /* COMP_SRC */
123
124         {
125                 char *ext = strrchr (base_name, '.');
126                 if (!ext) {
127                         /* no section extension */
128                         gripe_bogus_manpage (file);
129                         free (manpage);
130                         return NULL;
131                 }
132                 *ext++ = '\0';                  /* set section ext */
133                 info->ext = ext;
134                 if (!*info->ext) {
135                         /* zero-length section extension */
136                         gripe_bogus_manpage (file);
137                         free (manpage);
138                         return NULL;
139                 }
140         }
141
142         info->sec = strrchr (manpage, '/') + 4; /* set section name */
143
144         if (strlen (info->sec) >= 1 && strlen (info->ext) >= 1 &&
145             info->sec[0] != info->ext[0]) {
146                 /* mismatch in section */
147                 gripe_bogus_manpage (file);
148                 free (manpage);
149                 return NULL;
150         }
151
152         if (req_name && !STREQ (base_name, req_name))
153                 info->name = xstrdup (base_name);
154         else
155                 info->name = NULL;
156
157         return manpage;
158 }