From patchwork Fri Jan 2 00:50:57 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1191 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767315180; bh=Xka6npl9HOhwNJKd9FT0bU+i3BVD1wHwCCqJcpNAPak=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=CWY1EWC/d+G9tSJJluz/Bl0AccrCOH01L4XTNLj7JQdNRokLERqp2aVRXijy/cpun 0Lobkw7TD/dv5XtjUkjuBmAaBNM1g3KCa1Z5E9r2D0VV5/xTUi8IgEoE4yVyCNF3od HdUUU4ES1nUkFRTWk8grvXI0ZIfLoyQLlIr5y4xejySdY4r4z4flMKSdItGZw29VO6 1ujw3YooOwLekd9LauWqznTiVXyJwo2fjNsZE/7o+a1copPPs0XLnF7ndnv97I4Pnc QG0/DEa2prCwFm2uxZcfLO+Ub+VT87Zg4y2qxh0aumNS8/wftL4j1Q3I0pjUlPNo0e iDJUmd/frqITw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id C261A69004 for ; Thu, 1 Jan 2026 17:53:00 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id aLug64ckJhyX for ; Thu, 1 Jan 2026 17:53:00 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767315180; bh=Xka6npl9HOhwNJKd9FT0bU+i3BVD1wHwCCqJcpNAPak=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=CWY1EWC/d+G9tSJJluz/Bl0AccrCOH01L4XTNLj7JQdNRokLERqp2aVRXijy/cpun 0Lobkw7TD/dv5XtjUkjuBmAaBNM1g3KCa1Z5E9r2D0VV5/xTUi8IgEoE4yVyCNF3od HdUUU4ES1nUkFRTWk8grvXI0ZIfLoyQLlIr5y4xejySdY4r4z4flMKSdItGZw29VO6 1ujw3YooOwLekd9LauWqznTiVXyJwo2fjNsZE/7o+a1copPPs0XLnF7ndnv97I4Pnc QG0/DEa2prCwFm2uxZcfLO+Ub+VT87Zg4y2qxh0aumNS8/wftL4j1Q3I0pjUlPNo0e iDJUmd/frqITw== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id A811D68F53 for ; Thu, 1 Jan 2026 17:53:00 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767315178; bh=z4J0kIQeMUc0jUnUtZxslvoAPDIgfK3EV5bWV8O8hR4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=hAunLodLYZxWFt8QMmngroHH39w9IO5msefN97P09yDxFv+Kruz3MUHfdHKm4+5KV NJwZ0FhKpzjNDg6CMwheijOTU4Jo7xpfMM4kHDYJJ6jhMq06uhlF7+GihzHhTpqIm+ cZBDmZCqsJp2QwkDk+fCMXHt/Fe6xVddFFFjvLFKELbpyiV5UBNAuYDoBCllbd8C46 XyQ55DV/mYXnnMhpJBYjCAo8G5rw8m6fKvlUk4QeJJfV3Ss8udWtnm1QdjPgGMNLUh Um6/wiKx5CD/6f18WKDxISwVAsWMmXbV/5+XhQ5Iu5QzqqMJifuDZtmlOhF983+WX6 0JYhxr1WjasVw== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8896268F58; Thu, 1 Jan 2026 17:52:58 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id nLGBvTaJquh3; Thu, 1 Jan 2026 17:52:58 -0700 (MST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1767315172; bh=GBvQCiQojHiX3AwDMt/bqOJZ+Kep8VqGvy74tBPITPc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eAo7IFKQT1zokjC4A8y9DazPooQiQZC6CPuWVXm8jVHW/VpE4eXdHBeI5u8GmoiaG D+/w1TxFGokgafG6XEiVCurhEzFnlfrhNib4DDE76pp7BX19oORdatsWEGAj9lRQJ0 q4A//tp5+W0Npt6sqEHme0slbxZtgl/YAZu3deCu90Dheo6szEWiUzD7GNo7ZJCE5y LxepFxv8NpBum0qoACWvG4y4mz4UaNRf/nIUmsR8xJ97Ij9QevhnkQCoaWXwb6Nc4X f1L2XWFSRyQTtsewddqPHGJ+FRXsIjE/6++dz3sPei8XWHHicuqra4BQg3hcdbqtw1 T8+iXmFmqxhKg== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 5C54F68313; Thu, 1 Jan 2026 17:52:52 -0700 (MST) From: Simon Glass To: U-Boot Concept Date: Thu, 1 Jan 2026 17:50:57 -0700 Message-ID: <20260102005112.552256-28-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260102005112.552256-1-sjg@u-boot.org> References: <20260102005112.552256-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: LQL3OVA7LDM27AYNQ6NLPRCPC2OWDU3H X-Message-ID-Hash: LQL3OVA7LDM27AYNQ6NLPRCPC2OWDU3H X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH v2 27/30] ext4l: Update symlink to replace existing files List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass The ext4l_ln() function returned -EEXIST when creating a symlink where a file already exists. This differs from the old ext4 implementation which deletes any existing file before creating the symlink (like ln -sf behaviour). Update ext4l_ln() to match this behaviour by calling __ext4_unlink() to remove any existing non-directory file before creating the symlink. Directories cannot be replaced with symlinks and return -EISDIR. This allows test_symlink3 to pass. Co-developed-by: Claude Signed-off-by: Simon Glass --- (no changes since v1) fs/ext4l/interface.c | 18 +++++++++++++++--- include/ext4l.h | 5 ++++- test/fs/ext4l.c | 4 ++-- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/fs/ext4l/interface.c b/fs/ext4l/interface.c index c9dd25dd7b4..acd9ba5511e 100644 --- a/fs/ext4l/interface.c +++ b/fs/ext4l/interface.c @@ -1268,9 +1268,21 @@ int ext4l_ln(const char *filename, const char *linkname) return ret; if (dentry->d_inode) { - /* File already exists */ - ret = -EEXIST; - goto out; + /* File already exists - delete it first (like ln -sf) */ + if (S_ISDIR(dentry->d_inode->i_mode)) { + /* Cannot replace a directory with a symlink */ + ret = -EISDIR; + goto out; + } + + ret = __ext4_unlink(dir_dentry->d_inode, &dentry->d_name, + dentry->d_inode, dentry); + if (ret) + goto out; + + /* Release inode to free data blocks */ + iput(dentry->d_inode); + dentry->d_inode = NULL; } /* Create the symlink - filename is what the link points to */ diff --git a/include/ext4l.h b/include/ext4l.h index d0e420c8da2..882a27dad42 100644 --- a/include/ext4l.h +++ b/include/ext4l.h @@ -114,9 +114,12 @@ int ext4l_mkdir(const char *dirname); /** * ext4l_ln() - Create a symbolic link * + * Creates the symlink, replacing any existing file (like ln -sf). + * Refuses to replace a directory. + * * @filename: Path of symlink to create * @target: Target path the symlink points to - * Return: 0 on success, -EEXIST if file already exists, + * Return: 0 on success, -EISDIR if target is a directory, * -ENOTDIR if parent is not a directory, -EROFS if read-only, * negative on other errors */ diff --git a/test/fs/ext4l.c b/test/fs/ext4l.c index 1d46a752f32..c1d10dcc816 100644 --- a/test/fs/ext4l.c +++ b/test/fs/ext4l.c @@ -576,8 +576,8 @@ static int fs_test_ext4l_ln_norun(struct unit_test_state *uts) ut_asserteq(12, actread); ut_asserteq_str("hello world\n", buf); - /* Verify creating duplicate returns -EEXIST */ - ut_asserteq(-EEXIST, ext4l_ln(target, link_name)); + /* Verify creating duplicate succeeds (like ln -sf) */ + ut_assertok(ext4l_ln(target, link_name)); /* Verify creating symlink in non-existent parent returns -ENOENT */ ut_asserteq(-ENOENT, ext4l_ln(target, "/nonexistent/link"));