]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Lib/exfat/src/libexfat/lookup.c
3 exFAT file system implementation library.
5 Free exFAT implementation.
6 Copyright (C) 2010-2018 Andrew Nayenko
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 int exfat_opendir(struct exfat
* ef
, struct exfat_node
* dir
,
29 struct exfat_iterator
* it
)
36 rc
= exfat_cache_directory(ef
, dir
);
38 exfat_put_node(ef
, dir
);
42 void exfat_closedir(struct exfat
* ef
, struct exfat_iterator
* it
)
44 exfat_put_node(ef
, it
->parent
);
49 struct exfat_node
* exfat_readdir(struct exfat_iterator
* it
)
51 if (it
->current
== NULL
)
52 it
->current
= it
->parent
->child
;
54 it
->current
= it
->current
->next
;
56 if (it
->current
!= NULL
)
57 return exfat_get_node(it
->current
);
62 static int compare_char(struct exfat
* ef
, uint16_t a
, uint16_t b
)
64 return (int) ef
->upcase
[a
] - (int) ef
->upcase
[b
];
67 static int compare_name(struct exfat
* ef
, const le16_t
* a
, const le16_t
* b
)
69 while (le16_to_cpu(*a
) && le16_to_cpu(*b
))
71 int rc
= compare_char(ef
, le16_to_cpu(*a
), le16_to_cpu(*b
));
77 return compare_char(ef
, le16_to_cpu(*a
), le16_to_cpu(*b
));
80 static int lookup_name(struct exfat
* ef
, struct exfat_node
* parent
,
81 struct exfat_node
** node
, const char* name
, size_t n
)
83 struct exfat_iterator it
;
84 le16_t buffer
[EXFAT_NAME_MAX
+ 1];
89 rc
= utf8_to_utf16(buffer
, name
, EXFAT_NAME_MAX
+ 1, n
);
93 rc
= exfat_opendir(ef
, parent
, &it
);
96 while ((*node
= exfat_readdir(&it
)))
98 if (compare_name(ef
, buffer
, (*node
)->name
) == 0)
100 exfat_closedir(ef
, &it
);
103 exfat_put_node(ef
, *node
);
105 exfat_closedir(ef
, &it
);
109 static size_t get_comp(const char* path
, const char** comp
)
113 *comp
= path
+ strspn(path
, "/"); /* skip leading slashes */
114 end
= strchr(*comp
, '/');
116 return strlen(*comp
);
121 int exfat_lookup(struct exfat
* ef
, struct exfat_node
** node
,
124 struct exfat_node
* parent
;
129 /* start from the root directory */
130 parent
= *node
= exfat_get_node(ef
->root
);
131 for (p
= path
; (n
= get_comp(p
, &p
)); p
+= n
)
133 if (n
== 1 && *p
== '.') /* skip "." component */
135 rc
= lookup_name(ef
, parent
, node
, p
, n
);
138 exfat_put_node(ef
, parent
);
141 exfat_put_node(ef
, parent
);
147 static bool is_last_comp(const char* comp
, size_t length
)
149 const char* p
= comp
+ length
;
151 return get_comp(p
, &p
) == 0;
154 static bool is_allowed(const char* comp
, size_t length
)
158 for (i
= 0; i
< length
; i
++)
176 int exfat_split(struct exfat
* ef
, struct exfat_node
** parent
,
177 struct exfat_node
** node
, le16_t
* name
, const char* path
)
183 memset(name
, 0, (EXFAT_NAME_MAX
+ 1) * sizeof(le16_t
));
184 *parent
= *node
= exfat_get_node(ef
->root
);
185 for (p
= path
; (n
= get_comp(p
, &p
)); p
+= n
)
187 if (n
== 1 && *p
== '.')
189 if (is_last_comp(p
, n
))
191 if (!is_allowed(p
, n
))
193 /* contains characters that are not allowed */
194 exfat_put_node(ef
, *parent
);
197 rc
= utf8_to_utf16(name
, p
, EXFAT_NAME_MAX
+ 1, n
);
200 exfat_put_node(ef
, *parent
);
204 rc
= lookup_name(ef
, *parent
, node
, p
, n
);
205 if (rc
!= 0 && rc
!= -ENOENT
)
207 exfat_put_node(ef
, *parent
);
212 rc
= lookup_name(ef
, *parent
, node
, p
, n
);
215 exfat_put_node(ef
, *parent
);
218 exfat_put_node(ef
, *parent
);
221 exfat_bug("impossible");