mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-12-17 17:16:19 +00:00
Experimental Linux GUI based on web browser
This commit is contained in:
224
LinuxGUI/Ventoy2Disk/Lib/exfat/src/libexfat/lookup.c
Normal file
224
LinuxGUI/Ventoy2Disk/Lib/exfat/src/libexfat/lookup.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
lookup.c (02.09.09)
|
||||
exFAT file system implementation library.
|
||||
|
||||
Free exFAT implementation.
|
||||
Copyright (C) 2010-2018 Andrew Nayenko
|
||||
|
||||
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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "exfat.h"
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int exfat_opendir(struct exfat* ef, struct exfat_node* dir,
|
||||
struct exfat_iterator* it)
|
||||
{
|
||||
int rc;
|
||||
|
||||
exfat_get_node(dir);
|
||||
it->parent = dir;
|
||||
it->current = NULL;
|
||||
rc = exfat_cache_directory(ef, dir);
|
||||
if (rc != 0)
|
||||
exfat_put_node(ef, dir);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void exfat_closedir(struct exfat* ef, struct exfat_iterator* it)
|
||||
{
|
||||
exfat_put_node(ef, it->parent);
|
||||
it->parent = NULL;
|
||||
it->current = NULL;
|
||||
}
|
||||
|
||||
struct exfat_node* exfat_readdir(struct exfat_iterator* it)
|
||||
{
|
||||
if (it->current == NULL)
|
||||
it->current = it->parent->child;
|
||||
else
|
||||
it->current = it->current->next;
|
||||
|
||||
if (it->current != NULL)
|
||||
return exfat_get_node(it->current);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int compare_char(struct exfat* ef, uint16_t a, uint16_t 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)
|
||||
{
|
||||
while (le16_to_cpu(*a) && le16_to_cpu(*b))
|
||||
{
|
||||
int rc = compare_char(ef, le16_to_cpu(*a), le16_to_cpu(*b));
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
return compare_char(ef, le16_to_cpu(*a), le16_to_cpu(*b));
|
||||
}
|
||||
|
||||
static int lookup_name(struct exfat* ef, struct exfat_node* parent,
|
||||
struct exfat_node** node, const char* name, size_t n)
|
||||
{
|
||||
struct exfat_iterator it;
|
||||
le16_t buffer[EXFAT_NAME_MAX + 1];
|
||||
int rc;
|
||||
|
||||
*node = NULL;
|
||||
|
||||
rc = utf8_to_utf16(buffer, name, EXFAT_NAME_MAX + 1, n);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
rc = exfat_opendir(ef, parent, &it);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
while ((*node = exfat_readdir(&it)))
|
||||
{
|
||||
if (compare_name(ef, buffer, (*node)->name) == 0)
|
||||
{
|
||||
exfat_closedir(ef, &it);
|
||||
return 0;
|
||||
}
|
||||
exfat_put_node(ef, *node);
|
||||
}
|
||||
exfat_closedir(ef, &it);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static size_t get_comp(const char* path, const char** comp)
|
||||
{
|
||||
const char* end;
|
||||
|
||||
*comp = path + strspn(path, "/"); /* skip leading slashes */
|
||||
end = strchr(*comp, '/');
|
||||
if (end == NULL)
|
||||
return strlen(*comp);
|
||||
else
|
||||
return end - *comp;
|
||||
}
|
||||
|
||||
int exfat_lookup(struct exfat* ef, struct exfat_node** node,
|
||||
const char* path)
|
||||
{
|
||||
struct exfat_node* parent;
|
||||
const char* p;
|
||||
size_t n;
|
||||
int rc;
|
||||
|
||||
/* start from the root directory */
|
||||
parent = *node = exfat_get_node(ef->root);
|
||||
for (p = path; (n = get_comp(p, &p)); p += n)
|
||||
{
|
||||
if (n == 1 && *p == '.') /* skip "." component */
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_last_comp(const char* comp, size_t length)
|
||||
{
|
||||
const char* p = comp + length;
|
||||
|
||||
return get_comp(p, &p) == 0;
|
||||
}
|
||||
|
||||
static bool is_allowed(const char* comp, size_t 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** parent,
|
||||
struct exfat_node** node, le16_t* name, const char* path)
|
||||
{
|
||||
const char* p;
|
||||
size_t n;
|
||||
int rc;
|
||||
|
||||
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 (is_last_comp(p, n))
|
||||
{
|
||||
if (!is_allowed(p, n))
|
||||
{
|
||||
/* contains characters that are not allowed */
|
||||
exfat_put_node(ef, *parent);
|
||||
return -ENOENT;
|
||||
}
|
||||
rc = utf8_to_utf16(name, p, EXFAT_NAME_MAX + 1, n);
|
||||
if (rc != 0)
|
||||
{
|
||||
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_bug("impossible");
|
||||
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user