OSDN Git Service

Fixed rename(): replace target if it exists.
authorresver <resver@60bc1c72-a15a-11de-b98f-4500b42dc123>
Sun, 7 Feb 2010 07:26:10 +0000 (07:26 +0000)
committerresver <resver@60bc1c72-a15a-11de-b98f-4500b42dc123>
Sun, 7 Feb 2010 07:26:10 +0000 (07:26 +0000)
git-svn-id: http://exfat.googlecode.com/svn/trunk@120 60bc1c72-a15a-11de-b98f-4500b42dc123

libexfat/exfat.h
libexfat/lookup.c
libexfat/node.c

index 3ae96ad..95575c5 100644 (file)
@@ -120,8 +120,8 @@ void exfat_closedir(struct exfat* ef, struct exfat_iterator* it);
 struct exfat_node* exfat_readdir(struct exfat* ef, struct exfat_iterator* it);
 int exfat_lookup(struct exfat* ef, struct exfat_node** node,
                const char* path);
-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);
 
 off_t exfat_c2o(const struct exfat* ef, cluster_t cluster);
 cluster_t exfat_next_cluster(const struct exfat* ef,
index c800e61..1841082 100644 (file)
@@ -85,6 +85,8 @@ static int lookup_name(struct exfat* ef, struct exfat_node* parent,
        le16_t buffer[EXFAT_NAME_MAX + 1];
        int rc;
 
+       *node = NULL;
+
        rc = utf8_to_utf16(buffer, name, EXFAT_NAME_MAX, n);
        if (rc != 0)
                return rc;
@@ -153,43 +155,49 @@ static int is_allowed(const char* comp, size_t length)
        return strcspn(comp, "/\\:*?\"<>|") >= length;
 }
 
-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;
 
-       parent = *node = exfat_get_node(ef->root);
+       *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);
                        if (rc != 0)
-                               exfat_put_node(ef, parent);
-                       return rc;
+                       {
+                               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;
                }
-               exfat_put_node(ef, parent);
-               parent = *node;
+               if (lookup_name(ef, *parent, node, p, n) != 0)
+               {
+                       exfat_put_node(ef, *parent);
+                       return -ENOENT;
+               }
+               exfat_put_node(ef, *parent);
+               *parent = *node;
        }
-       exfat_put_node(ef, *node);
-       return -EEXIST;
+       exfat_bug("impossible");
 }
index c9cee45..c50b47c 100644 (file)
@@ -687,14 +687,21 @@ static int write_entry(struct exfat* ef, struct exfat_node* dir,
 static int create(struct exfat* ef, const char* path, uint16_t attrib)
 {
        struct exfat_node* dir;
+       struct exfat_node* existing;
        cluster_t cluster = EXFAT_CLUSTER_BAD;
        off_t offset = -1;
        le16_t name[EXFAT_NAME_MAX + 1];
        int rc;
 
-       rc = exfat_split(ef, &dir, name, path);
+       rc = exfat_split(ef, &dir, &existing, name, path);
        if (rc != 0)
                return rc;
+       if (existing != NULL)
+       {
+               exfat_put_node(ef, existing);
+               exfat_put_node(ef, dir);
+               return -EEXIST;
+       }
 
        rc = find_slot(ef, dir, &cluster, &offset,
                        2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));
@@ -787,6 +794,7 @@ static void rename_entry(struct exfat* ef, struct exfat_node* dir,
 int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
 {
        struct exfat_node* node;
+       struct exfat_node* existing;
        struct exfat_node* dir;
        cluster_t cluster = EXFAT_CLUSTER_BAD;
        off_t offset = -1;
@@ -798,12 +806,36 @@ int exfat_rename(struct exfat* ef, const char* old_path, const char* new_path)
                return rc;
 
        memset(name, 0, (EXFAT_NAME_MAX + 1) * sizeof(le16_t));
-       rc = exfat_split(ef, &dir, name, new_path);
+       rc = exfat_split(ef, &dir, &existing, name, new_path);
        if (rc != 0)
        {
                exfat_put_node(ef, node);
                return rc;
        }
+       if (existing != NULL)
+       {
+               if (existing->flags & EXFAT_ATTRIB_DIR)
+               {
+                       if (node->flags & EXFAT_ATTRIB_DIR)
+                               rc = exfat_rmdir(ef, existing);
+                       else
+                               rc = -ENOTDIR;
+               }
+               else
+               {
+                       if (!(node->flags & EXFAT_ATTRIB_DIR))
+                               rc = exfat_unlink(ef, existing);
+                       else
+                               rc = -EISDIR;
+               }
+               exfat_put_node(ef, existing);
+               if (rc != 0)
+               {
+                       exfat_put_node(ef, dir);
+                       exfat_put_node(ef, node);
+                       return rc;
+               }
+       }
 
        rc = find_slot(ef, dir, &cluster, &offset,
                        2 + DIV_ROUND_UP(utf16_length(name), EXFAT_ENAME_MAX));