From patchwork Tue Sep 11 06:59:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 968440 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="QtfZ98lw"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 428bcs4jFkz9s4s for ; Tue, 11 Sep 2018 17:09:17 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E9E8CC21E76; Tue, 11 Sep 2018 07:06:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id DA38EC21EFC; Tue, 11 Sep 2018 07:00:52 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 74ACFC21EC9; Tue, 11 Sep 2018 07:00:23 +0000 (UTC) Received: from mail-pg1-f195.google.com (mail-pg1-f195.google.com [209.85.215.195]) by lists.denx.de (Postfix) with ESMTPS id E2782C21EFC for ; Tue, 11 Sep 2018 07:00:17 +0000 (UTC) Received: by mail-pg1-f195.google.com with SMTP id d19-v6so11767638pgv.1 for ; Tue, 11 Sep 2018 00:00:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4kbxUPVWkedb8CcqEPt5F1V4tG0kf9B6Ax7XOaTDTyU=; b=QtfZ98lw0FM47AX6q9sHjaojV47aV2BTGd65T9VuWbBnQEQbToUsqsSCHRRc5OuCZ1 2hN2UwpoBCIVZimBTErhjoggie06vOAlR1vRTg9NTqr1sTh8XP2jHdmqZbTIAqQ2GBAZ pOKfc2k7S8a+kQ4JZYp4o72t5uRfgpYYGrkp0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4kbxUPVWkedb8CcqEPt5F1V4tG0kf9B6Ax7XOaTDTyU=; b=jqJRz04pMnpWBt1QRS2+50FqLysoKv8ruuvgcZ38hS3L+ej8YPslZgwH7pXa3Pzh5J WHcEbYhsZCxeIIktxB5Nym/BEeOtdC7fI905TgPf4t0AIDG7gjQNegttc43V1xeGXLSa yX1lOs5UCTjo3syLS/njH91H9xvNxEVCuHANL7oBB1ldKQjaoJApg4TAP4BRiBvs/aLW QROVu2fYdBDwXWycN61oxb670FTsA6re1nvuL6LVKKg2dd+zsCsfKdPKZ2YNJzJ/0MRv 0/ruQTLL1rzko5QWpaLrEQxTDAFWOVLISg0AK6+Ln9k6kOVD63bejkKBoSI2hKaSuDfQ f+Dg== X-Gm-Message-State: APzg51COliiN49I9u6z8q0TthWK6/oZsqLkrz24f6pgJhgQTu0xgG7Jw can3Wt/Fq+svaE3PHtV8cA9ZyA== X-Google-Smtp-Source: ANB0VdaxxifsxBX6X+hRAf3PqDI+TaQKFbJRjQW83U9Wl3uwy0jQn1ETzBhbRVl79y1T3QtT6B0WjA== X-Received: by 2002:a63:4826:: with SMTP id v38-v6mr26767573pga.379.1536649211327; Tue, 11 Sep 2018 00:00:11 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id o21-v6sm26008596pfi.165.2018.09.11.00.00.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Sep 2018 00:00:10 -0700 (PDT) From: "Akashi, Takahiro" To: trini@konsulko.com Date: Tue, 11 Sep 2018 15:59:14 +0900 Message-Id: <20180911065922.19141-19-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180911065922.19141-1-takahiro.akashi@linaro.org> References: <20180911065922.19141-1-takahiro.akashi@linaro.org> Cc: u-boot@lists.denx.de, xypron.glpk@gmx.de, agraf@suse.de Subject: [U-Boot] [PATCH v3 18/26] fs: fat: support unlink X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: AKASHI Takahiro In this patch, unlink support is added to FAT file system. A directory can be deleted only if it is empty. In this implementation, only a directory entry for a short file name will be removed. So entries for a long file name can and should be reclaimed with fsck. Signed-off-by: AKASHI Takahiro --- fs/fat/fat_write.c | 132 +++++++++++++++++++++++++++++++++++++++++++++ fs/fs.c | 3 +- include/fat.h | 1 + 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c index 035469f31c8d..6d3d2d1abb04 100644 --- a/fs/fat/fat_write.c +++ b/fs/fat/fat_write.c @@ -1184,6 +1184,138 @@ int file_fat_write(const char *filename, void *buffer, loff_t offset, return file_fat_write_at(filename, offset, buffer, maxsize, actwrite); } +static int fat_dir_entries(fat_itr *itr) +{ + fat_itr *dirs; + fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata; + /* for FATBUFSIZE */ + int count; + + dirs = malloc_cache_aligned(sizeof(fat_itr)); + if (!dirs) { + debug("Error: allocating memory\n"); + count = -ENOMEM; + goto exit; + } + + /* duplicate fsdata */ + fat_itr_child(dirs, itr); + fsdata = *dirs->fsdata; + + /* allocate local fat buffer */ + fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE); + if (!fsdata.fatbuf) { + debug("Error: allocating memory\n"); + count = -ENOMEM; + goto exit; + } + fsdata.fatbufnum = -1; + dirs->fsdata = &fsdata; + + for (count = 0; fat_itr_next(dirs); count++) + ; + +exit: + free(fsdata.fatbuf); + free(dirs); + return count; +} + +static int delete_dentry(fat_itr *itr) +{ + fsdata *mydata = itr->fsdata; + dir_entry *dentptr = itr->dent; + + /* free cluster blocks */ + clear_fatent(mydata, START(dentptr)); + if (flush_dirty_fat_buffer(mydata) < 0) { + printf("Error: flush fat buffer\n"); + return -EIO; + } + + /* + * update a directory entry + * TODO: + * - long file name support + * - find and mark the "new" first invalid entry as name[0]=0x00 + */ + memset(dentptr, 0, sizeof(*dentptr)); + dentptr->name[0] = 0xe5; + + if (set_cluster(mydata, itr->clust, itr->block, + mydata->clust_size * mydata->sect_size) != 0) { + printf("error: writing directory entry\n"); + return -EIO; + } + + return 0; +} + +int fat_unlink(const char *filename) +{ + fsdata fsdata = { .fatbuf = NULL, }; + fat_itr *itr = NULL; + int n_entries, ret; + char *filename_copy, *dirname, *basename; + + filename_copy = strdup(filename); + split_filename(filename_copy, &dirname, &basename); + + if (!strcmp(dirname, "/") && !strcmp(basename, "")) { + printf("Error: cannot remove root\n"); + ret = -EINVAL; + goto exit; + } + + itr = malloc_cache_aligned(sizeof(fat_itr)); + if (!itr) { + printf("Error: allocating memory\n"); + return -ENOMEM; + } + + ret = fat_itr_root(itr, &fsdata); + if (ret) + goto exit; + + total_sector = fsdata.total_sect; + + ret = fat_itr_resolve(itr, dirname, TYPE_DIR); + if (ret) { + printf("%s: doesn't exist (%d)\n", dirname, ret); + ret = -ENOENT; + goto exit; + } + + if (!find_directory_entry(itr, basename)) { + printf("%s: doesn't exist\n", basename); + ret = -ENOENT; + goto exit; + } + + if (fat_itr_isdir(itr)) { + n_entries = fat_dir_entries(itr); + if (n_entries < 0) { + ret = n_entries; + goto exit; + } + if (n_entries > 2) { + printf("Error: directory is not empty: %d\n", + n_entries); + ret = -EINVAL; + goto exit; + } + } + + ret = delete_dentry(itr); + +exit: + free(fsdata.fatbuf); + free(itr); + free(filename_copy); + + return ret; +} + int fat_mkdir(const char *new_dirname) { dir_entry *retdent; diff --git a/fs/fs.c b/fs/fs.c index ba9a65166c70..adae98d021ee 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -170,16 +170,17 @@ static struct fstype_info fstypes[] = { .read = fat_read_file, #ifdef CONFIG_FAT_WRITE .write = file_fat_write, + .unlink = fat_unlink, .mkdir = fat_mkdir, #else .write = fs_write_unsupported, + .unlink = fs_unlink_unsupported, .mkdir = fs_mkdir_unsupported, #endif .uuid = fs_uuid_unsupported, .opendir = fat_opendir, .readdir = fat_readdir, .closedir = fat_closedir, - .unlink = fs_unlink_unsupported, }, #endif #ifdef CONFIG_FS_EXT4 diff --git a/include/fat.h b/include/fat.h index 97460a3cdff1..ca92a735b4fd 100644 --- a/include/fat.h +++ b/include/fat.h @@ -205,6 +205,7 @@ int fat_read_file(const char *filename, void *buf, loff_t offset, loff_t len, int fat_opendir(const char *filename, struct fs_dir_stream **dirsp); int fat_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); void fat_closedir(struct fs_dir_stream *dirs); +int fat_unlink(const char *filename); int fat_mkdir(const char *dirname); void fat_close(void); #endif /* CONFIG_FS_FAT */