lookup.c (02.09.09)
exFAT file system implementation library.
- Copyright (C) 2009, 2010 Andrew Nayenko
+ Free exFAT implementation.
+ Copyright (C) 2010-2017 Andrew Nayenko
- This program is free software: you can redistribute it and/or modify
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
+ the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "exfat.h"
static int compare_char(struct exfat* ef, uint16_t a, uint16_t b)
{
- if (a >= ef->upcase_chars || b >= ef->upcase_chars)
- return (int) a - (int) b;
-
- return (int) le16_to_cpu(ef->upcase[a]) - (int) le16_to_cpu(ef->upcase[b]);
+ return (int) ef->upcase[a] - (int) ef->upcase[b];
}
static int compare_name(struct exfat* ef, const le16_t* a, const le16_t* b)
le16_t buffer[EXFAT_NAME_MAX + 1];
int rc;
- rc = utf8_to_utf16(buffer, name, EXFAT_NAME_MAX, n);
+ *node = NULL;
+
+ rc = utf8_to_utf16(buffer, name, EXFAT_NAME_MAX + 1, n);
if (rc != 0)
return rc;
struct exfat_node* parent;
const char* p;
size_t n;
+ int rc;
/* start from the root directory */
parent = *node = exfat_get_node(ef->root);
{
if (n == 1 && *p == '.') /* skip "." component */
continue;
- if (lookup_name(ef, parent, node, p, n) != 0)
+ rc = lookup_name(ef, parent, node, p, n);
+ if (rc != 0)
{
exfat_put_node(ef, parent);
- return -ENOENT;
+ return rc;
}
exfat_put_node(ef, parent);
parent = *node;
return 0;
}
-static int is_last_comp(const char* comp, size_t length)
+static bool is_last_comp(const char* comp, size_t length)
{
const char* p = comp + length;
return get_comp(p, &p) == 0;
}
-static int is_allowed(const char* comp, size_t length)
+static bool is_allowed(const char* comp, size_t length)
{
- return strcspn(comp, "/\\:*?\"<>|") >= length;
+ size_t i;
+
+ for (i = 0; i < length; i++)
+ switch (comp[i])
+ {
+ case 0x01 ... 0x1f:
+ case '/':
+ case '\\':
+ case ':':
+ case '*':
+ case '?':
+ case '"':
+ case '<':
+ case '>':
+ case '|':
+ return false;
+ }
+ return true;
}
-int exfat_split(struct exfat* ef, struct exfat_node** node, le16_t* name,
- const char* path)
+int exfat_split(struct exfat* ef, struct exfat_node** parent,
+ struct exfat_node** node, le16_t* name, const char* path)
{
- struct exfat_node* parent;
const char* p;
size_t n;
+ int rc;
- parent = *node = exfat_get_node(ef->root);
+ memset(name, 0, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
+ *parent = *node = exfat_get_node(ef->root);
for (p = path; (n = get_comp(p, &p)); p += n)
{
if (n == 1 && *p == '.')
continue;
- if (lookup_name(ef, parent, node, p, n) != 0)
+ if (is_last_comp(p, n))
{
- int rc;
-
- if (!is_last_comp(p, n))
- {
- /* this is not the last component of the path */
- exfat_put_node(ef, parent);
- return -ENOENT;
- }
if (!is_allowed(p, n))
{
/* contains characters that are not allowed */
- exfat_put_node(ef, parent);
+ exfat_put_node(ef, *parent);
return -ENOENT;
}
- *node = parent;
- rc = utf8_to_utf16(name, p, EXFAT_NAME_MAX, n);
+ rc = utf8_to_utf16(name, p, EXFAT_NAME_MAX + 1, n);
if (rc != 0)
- exfat_put_node(ef, parent);
+ {
+ exfat_put_node(ef, *parent);
+ return rc;
+ }
+
+ rc = lookup_name(ef, *parent, node, p, n);
+ if (rc != 0 && rc != -ENOENT)
+ {
+ exfat_put_node(ef, *parent);
+ return rc;
+ }
+ return 0;
+ }
+ rc = lookup_name(ef, *parent, node, p, n);
+ if (rc != 0)
+ {
+ exfat_put_node(ef, *parent);
return rc;
}
- exfat_put_node(ef, parent);
- parent = *node;
+ exfat_put_node(ef, *parent);
+ *parent = *node;
}
- exfat_put_node(ef, *node);
- return -EEXIST;
+ exfat_bug("impossible");
}