]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/apr/file_io/unix/filepath_util.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / apr / file_io / unix / filepath_util.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #define APR_WANT_STRFUNC
19 #define APR_WANT_MEMFUNC
20 #include "apr_want.h"
21
22 #include "apr_errno.h"
23 #include "apr_pools.h"
24 #include "apr_strings.h"
25 #include "apr_tables.h"
26
27 #include "apr_private.h"
28
29 apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts,
30                                           const char *liststr,
31                                           char separator,
32                                           apr_pool_t *p)
33 {
34     char *path, *part, *ptr;
35     char separator_string[2] = { '\0', '\0' };
36     apr_array_header_t *elts;
37     int nelts;
38
39     separator_string[0] = separator;
40     /* Count the number of path elements. We know there'll be at least
41        one even if path is an empty string. */
42     path = apr_pstrdup(p, liststr);
43     for (nelts = 0, ptr = path; ptr != NULL; ++nelts)
44     {
45         ptr = strchr(ptr, separator);
46         if (ptr)
47             ++ptr;
48     }
49
50     /* Split the path into the array. */
51     elts = apr_array_make(p, nelts, sizeof(char*));
52     while ((part = apr_strtok(path, separator_string, &ptr)) != NULL)
53     {
54         if (*part == '\0')      /* Ignore empty path components. */
55             continue;
56
57         *(char**)apr_array_push(elts) = part;
58         path = NULL;            /* For the next call to apr_strtok */
59     }
60
61     *pathelts = elts;
62     return APR_SUCCESS;
63 }
64
65
66 apr_status_t apr_filepath_list_merge_impl(char **liststr,
67                                           apr_array_header_t *pathelts,
68                                           char separator,
69                                           apr_pool_t *p)
70 {
71     apr_size_t path_size = 0;
72     char *path;
73     int i;
74
75     /* This test isn't 100% certain, but it'll catch at least some
76        invalid uses... */
77     if (pathelts->elt_size != sizeof(char*))
78         return APR_EINVAL;
79
80     /* Calculate the size of the merged path */
81     for (i = 0; i < pathelts->nelts; ++i)
82         path_size += strlen(((char**)pathelts->elts)[i]);
83
84     if (path_size == 0)
85     {
86         *liststr = NULL;
87         return APR_SUCCESS;
88     }
89
90     if (i > 0)                  /* Add space for the separators */
91         path_size += (i - 1);
92
93     /* Merge the path components */
94     path = *liststr = apr_palloc(p, path_size + 1);
95     for (i = 0; i < pathelts->nelts; ++i)
96     {
97         /* ### Hmmmm. Calling strlen twice on the same string. Yuck.
98                But is is better than reallocation in apr_pstrcat? */
99         const char *part = ((char**)pathelts->elts)[i];
100         apr_size_t part_size = strlen(part);
101         if (part_size == 0)     /* Ignore empty path components. */
102             continue;
103
104         if (i > 0)
105             *path++ = separator;
106         memcpy(path, part, part_size);
107         path += part_size;
108     }
109     *path = '\0';
110     return APR_SUCCESS;
111 }