/src/server/mysys/mf_dirname.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. |
2 | | Copyright (c) 2009, 2020, MariaDB Corporation. |
3 | | |
4 | | This program is free software; you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation; version 2 of the License. |
7 | | |
8 | | This program is distributed in the hope that it will be useful, |
9 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | | GNU General Public License for more details. |
12 | | |
13 | | You should have received a copy of the GNU General Public License |
14 | | along with this program; if not, write to the Free Software |
15 | | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ |
16 | | |
17 | | #include "mysys_priv.h" |
18 | | #include <m_string.h> |
19 | | |
20 | | /* Functions definied in this file */ |
21 | | |
22 | | size_t dirname_length(const char *name) |
23 | 0 | { |
24 | 0 | register char *pos, *gpos; |
25 | | #ifdef BASKSLASH_MBTAIL |
26 | | CHARSET_INFO *fs= fs_character_set(); |
27 | | #endif |
28 | | #ifdef FN_DEVCHAR |
29 | | if ((pos=(char*)strrchr(name,FN_DEVCHAR)) == 0) |
30 | | #endif |
31 | 0 | pos=(char*) name-1; |
32 | |
|
33 | 0 | gpos= pos++; |
34 | 0 | for ( ; *pos ; pos++) /* Find last FN_LIBCHAR */ |
35 | 0 | { |
36 | | #ifdef BASKSLASH_MBTAIL |
37 | | uint l; |
38 | | if (my_ci_use_mb(fs) && (l= my_ismbchar(fs, pos, pos + 3))) |
39 | | { |
40 | | pos+= l - 1; |
41 | | continue; |
42 | | } |
43 | | #endif |
44 | 0 | if (*pos == FN_LIBCHAR || *pos == '/') |
45 | 0 | gpos=pos; |
46 | 0 | } |
47 | 0 | return (size_t) (gpos+1-(char*) name); |
48 | 0 | } |
49 | | |
50 | | |
51 | | /* |
52 | | Gives directory part of filename. Directory ends with '/' |
53 | | |
54 | | SYNOPSIS |
55 | | dirname_part() |
56 | | to Store directory name here |
57 | | name Original name |
58 | | to_length Store length of 'to' here |
59 | | |
60 | | RETURN |
61 | | # Length of directory part in 'name' |
62 | | */ |
63 | | |
64 | | size_t dirname_part(char *to, const char *name, size_t *to_res_length) |
65 | 0 | { |
66 | 0 | size_t length; |
67 | 0 | DBUG_ENTER("dirname_part"); |
68 | 0 | DBUG_PRINT("enter",("'%s'",name)); |
69 | |
|
70 | 0 | length=dirname_length(name); |
71 | 0 | *to_res_length= (size_t) (convert_dirname(to, name, name+length) - to); |
72 | 0 | DBUG_RETURN(length); |
73 | 0 | } /* dirname */ |
74 | | |
75 | | |
76 | | /* |
77 | | Convert directory name to use under this system |
78 | | |
79 | | SYNPOSIS |
80 | | convert_dirname() |
81 | | to Store result here. Must be at least of size |
82 | | MY_MIN(FN_REFLEN, strlen(from) + 1) to make room |
83 | | for adding FN_LIBCHAR at the end. |
84 | | from Original filename. May be == to |
85 | | from_end Pointer at end of filename (normally end \0) |
86 | | |
87 | | IMPLEMENTATION |
88 | | If Windows converts '/' to '\' |
89 | | Adds a FN_LIBCHAR to end if the result string if there isn't one |
90 | | and the last isn't dev_char. |
91 | | Copies data from 'from' until ASCII(0) for until from == from_end |
92 | | If you want to use the whole 'from' string, just send NullS as the |
93 | | last argument. |
94 | | |
95 | | If the result string is larger than FN_REFLEN -1, then it's cut. |
96 | | |
97 | | RETURN |
98 | | Returns pointer to end \0 in to |
99 | | */ |
100 | | |
101 | | #ifndef FN_DEVCHAR |
102 | 0 | #define FN_DEVCHAR '\0' /* For easier code */ |
103 | | #endif |
104 | | |
105 | | char *convert_dirname(char *to, const char *from, const char *from_end) |
106 | 0 | { |
107 | 0 | char *to_org=to; |
108 | | #ifdef BACKSLASH_MBTAIL |
109 | | CHARSET_INFO *fs= fs_character_set(); |
110 | | #endif |
111 | 0 | DBUG_ENTER("convert_dirname"); |
112 | | |
113 | | /* We use -2 here, becasue we need place for the last FN_LIBCHAR */ |
114 | 0 | if (!from_end || (from_end - from) > FN_REFLEN-2) |
115 | 0 | from_end=from+FN_REFLEN -2; |
116 | |
|
117 | | #if FN_LIBCHAR != '/' |
118 | | { |
119 | | for (; from != from_end && *from ; from++) |
120 | | { |
121 | | if (*from == '/') |
122 | | *to++= FN_LIBCHAR; |
123 | | else |
124 | | { |
125 | | #ifdef BACKSLASH_MBTAIL |
126 | | uint l; |
127 | | if (my_ci_use_mb(fs) && (l= my_ismbchar(fs, from, from + 3))) |
128 | | { |
129 | | memmove(to, from, l); |
130 | | to+= l; |
131 | | from+= l - 1; |
132 | | to_org= to; /* Don't look inside mbchar */ |
133 | | } |
134 | | else |
135 | | #endif |
136 | | { |
137 | | *to++= *from; |
138 | | } |
139 | | } |
140 | | } |
141 | | *to=0; |
142 | | } |
143 | | #else |
144 | | /* This is ok even if to == from, becasue we need to cut the string */ |
145 | 0 | to= strmake(to, from, (size_t) (from_end-from)); |
146 | 0 | #endif |
147 | | |
148 | | /* Add FN_LIBCHAR to the end of directory path */ |
149 | 0 | if (to != to_org && (to[-1] != FN_LIBCHAR && to[-1] != FN_DEVCHAR)) |
150 | 0 | { |
151 | 0 | *to++=FN_LIBCHAR; |
152 | 0 | *to=0; |
153 | 0 | } |
154 | 0 | DBUG_RETURN(to); /* Pointer to end of dir */ |
155 | 0 | } /* convert_dirname */ |