node.c (09.10.09)
exFAT file system implementation library.
- Copyright (C) 2010-2012 Andrew Nayenko
+ Free exFAT implementation.
+ Copyright (C) 2010-2013 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"
{
if (--node->references < 0)
{
- char buffer[EXFAT_NAME_MAX + 1];
- exfat_get_name(node, buffer, EXFAT_NAME_MAX);
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
+ exfat_get_name(node, buffer, sizeof(buffer) - 1);
exfat_bug("reference counter of `%s' is below zero", buffer);
}
if (node->flags & EXFAT_ATTRIB_UNLINKED)
{
/* free all clusters and node structure itself */
- exfat_truncate(ef, node, 0);
+ exfat_truncate(ef, node, 0, true);
free(node);
}
if (ef->cmap.dirty)
*/
if (real_size != (*node)->size)
{
- char buffer[EXFAT_NAME_MAX + 1];
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
- exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
+ exfat_get_name(*node, buffer, sizeof(buffer) - 1);
exfat_error("`%s' real size does not equal to size "
"(%"PRIu64" != %"PRIu64")", buffer,
real_size, (*node)->size);
}
if (actual_checksum != reference_checksum)
{
- char buffer[EXFAT_NAME_MAX + 1];
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
- exfat_get_name(*node, buffer, EXFAT_NAME_MAX);
+ exfat_get_name(*node, buffer, sizeof(buffer) - 1);
exfat_error("`%s' has invalid checksum (0x%hx != 0x%hx)",
buffer, actual_checksum, reference_checksum);
goto error;
goto error;
}
if (utf16_to_utf8(ef->label, label->name,
- sizeof(ef->label), EXFAT_ENAME_MAX) != 0)
+ sizeof(ef->label) - 1, EXFAT_ENAME_MAX) != 0)
goto error;
break;
node->flags &= ~EXFAT_ATTRIB_CACHED;
if (node->references != 0)
{
- char buffer[EXFAT_NAME_MAX + 1];
- exfat_get_name(node, buffer, EXFAT_NAME_MAX);
+ char buffer[UTF8_BYTES(EXFAT_NAME_MAX) + 1];
+ exfat_get_name(node, buffer, sizeof(buffer) - 1);
exfat_warn("non-zero reference counter (%d) for `%s'",
node->references, buffer);
}
reset_cache(ef, ef->root);
}
-void next_entry(struct exfat* ef, const struct exfat_node* parent,
+static void next_entry(struct exfat* ef, const struct exfat_node* parent,
cluster_t* cluster, off_t* offset)
{
*offset += sizeof(struct exfat_entry);
new_size = CLUSTER_SIZE(*ef->sb);
if (new_size == dir->size)
return 0;
- rc = exfat_truncate(ef, dir, new_size);
+ rc = exfat_truncate(ef, dir, new_size, true);
if (rc != 0)
return rc;
return 0;
{
return exfat_truncate(ef, dir,
DIV_ROUND_UP(asize + difference, CLUSTER_SIZE(*ef->sb))
- * CLUSTER_SIZE(*ef->sb));
+ * CLUSTER_SIZE(*ef->sb), true);
}
static int find_slot(struct exfat* ef, struct exfat_node* dir,
if (rc != 0)
return 0;
/* directories always have at least one cluster */
- rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb));
+ rc = exfat_truncate(ef, node, CLUSTER_SIZE(*ef->sb), true);
if (rc != 0)
{
delete(ef, node);
exfat_put_node(ef, node);
return rc;
}
+
+ /* check that target is not a subdirectory of the source */
+ if (node->flags & EXFAT_ATTRIB_DIR)
+ {
+ struct exfat_node* p;
+
+ for (p = dir; p; p = p->parent)
+ if (node == p)
+ {
+ if (existing != NULL)
+ exfat_put_node(ef, existing);
+ exfat_put_node(ef, dir);
+ exfat_put_node(ef, node);
+ return -EINVAL;
+ }
+ }
+
if (existing != NULL)
{
/* remove target if it's not the same node as source */
exfat_pwrite(ef->dev, &entry, sizeof(struct exfat_entry_label),
co2o(ef, cluster, offset));
+ strcpy(ef->label, label);
return 0;
}