]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - pool_path.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / pool_path.c
1 /* -*-pgsql-c-*- */
2 /*
3  *
4  * $Header: /cvsroot/pgpool/pgpool-II/pool_path.c,v 1.2.2.1 2009/08/22 04:19:49 t-ishii Exp $
5  *
6  * pgpool: a language independent connection pool server for PostgreSQL
7  * written by Tatsuo Ishii
8  *
9  * Portions Copyright (c) 2003-2008,    PgPool Global Development Group
10  * Portions Copyright (c) 2004, PostgreSQL Global Development Group
11  *
12  * Permission to use, copy, modify, and distribute this software and
13  * its documentation for any purpose and without fee is hereby
14  * granted, provided that the above copyright notice appear in all
15  * copies and that both that copyright notice and this permission
16  * notice appear in supporting documentation, and that the name of the
17  * author not be used in advertising or publicity pertaining to
18  * distribution of the software without specific, written prior
19  * permission. The author makes no representations about the
20  * suitability of this software for any purpose.  It is provided "as
21  * is" without express or implied warranty.
22  *
23  * pool_path.c.: small functions to manipulate paths
24  *
25  */
26
27 #include "pool_type.h"
28 #include "pool_path.h"
29 #include <stdio.h>
30 #include <string.h>
31
32 static void trim_directory(char *path);
33 static void trim_trailing_separator(char *path);
34
35 /*
36  * get_parent_directory
37  *
38  * Modify the given string in-place to name the parent directory of the
39  * named file.
40  */
41 void get_parent_directory(char *path)
42 {
43         trim_directory(path);
44 }
45
46
47 /*
48  *  trim_directory
49  *
50  *  Trim trailing directory from path, that is, remove any trailing slashes,
51  *  the last pathname component, and the slash just ahead of it --- but never
52  *  remove a leading slash.
53  */
54 static void trim_directory(char *path)
55 {
56         char *p;
57
58         if (path[0] == '\0')
59                 return;
60
61         /* back up over trailing slash(es) */
62         for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--);
63
64         /* back up over directory name */
65         for (; !IS_DIR_SEP(*p) && p > path; p--);
66
67         /* if multiple slashes before directory name, remove 'em all */
68         for (; p > path && IS_DIR_SEP(*(p - 1)); p--);
69
70         /* don't erase a leading slash */
71         if (p == path && IS_DIR_SEP(*p))
72                 p++;
73
74         *p = '\0';
75 }
76
77
78 /*
79  * join_path_components - join two path components, inserting a slash
80  *
81  * ret_path is the output area (must be of size MAXPGPATH)
82  *
83  * ret_path can be the same as head, but not the same as tail.
84  */
85 void join_path_components(char *ret_path, const char *head, const char *tail)
86 {
87         if (ret_path != head)
88                 StrNCpy(ret_path, head, MAXPGPATH);
89
90         /*
91          * Remove any leading "." and ".." in the tail component,
92          * adjusting head as needed.
93          */
94         for (;;)
95         {
96                 if (tail[0] == '.' && IS_DIR_SEP(tail[1]))
97                 {
98                         tail += 2;
99                 }
100                 else if (tail[0] == '.' && tail[1] == '\0')
101                 {
102                         tail += 1;
103                         break;
104                 }
105                 else if (tail[0] == '.' && tail[1] == '.' && IS_DIR_SEP(tail[2]))
106                 {
107                         trim_directory(ret_path);
108                         tail += 3;
109                 }
110                 else if (tail[0] == '.' && tail[1] == '.' && tail[2] == '\0')
111                 {
112                         trim_directory(ret_path);
113                         tail += 2;
114                         break;
115                 }
116                 else
117                         break;
118         }
119
120         if (*tail)
121                 snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path), "/%s", tail);
122 }
123
124
125 /*
126  *  Clean up path by:
127  *      o  remove trailing slash
128  *      o  remove duplicate adjacent separators
129  *      o  remove trailing '.'
130  *      o  process trailing '..' ourselves
131  */
132 void canonicalize_path(char *path)
133 {
134         char *p, *to_p;
135         bool was_sep = false;
136
137         /*
138          * Removing the trailing slash on a path means we never get ugly
139          * double trailing slashes.
140          */
141         trim_trailing_separator(path);
142
143         /*
144          *  Remove duplicate adjacent separators
145          */
146         p = path;
147         to_p = p;
148         for (; *p; p++, to_p++)
149         {
150                 /* Handle many adjacent slashes, like "/a///b" */
151                 while (*p == '/' && was_sep)
152                         p++;
153                 if (to_p != p)
154                         *to_p = *p;
155                 was_sep = (*p == '/');
156         }
157         *to_p = '\0';
158
159         /*
160          * Remove any trailing uses of "." and process ".." ourselves
161          */
162         for (;;)
163         {
164                 int len = strlen(path);
165
166                 if (len > 2 && strcmp(path + len - 2, "/.") == 0)
167                         trim_directory(path);
168                 else if (len > 3 && strcmp(path + len - 3, "/..") == 0)
169                 {
170                         trim_directory(path);
171                         trim_directory(path);
172                         /* remove directory above */
173                 }
174                 else
175                         break;
176         }
177 }
178
179
180 /*
181  *  trim_trailing_separator
182  *
183  * trim off trailing slashes, but not a leading slash
184  */
185 static void trim_trailing_separator(char *path)
186 {
187         char *p;
188
189         p = path + strlen(path);
190         if (p > path)
191                 for (p--; p > path && IS_DIR_SEP(*p); p--)
192                         *p = '\0';
193 }