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