From 87ba0e2a319653af510fae24a6d2975d3589735b Mon Sep 17 00:00:00 2001 From: chs Date: Thu, 17 Nov 2022 06:40:38 +0000 Subject: [PATCH] Restore backward compatibility of UFS2 with previous NetBSD releases by disabling support in UFS2 for extended attributes (including ACLs). Add a new variant of UFS2 called "UFS2ea" that does support extended attributes. Add new fsck_ffs operations "-c ea" and "-c no-ea" to convert file systems from UFS2 to UFS2ea and vice-versa (both of which delete all existing extended attributes in the process). --- UPDATING | 29 +- distrib/sets/lists/tests/mi | 3 +- sbin/badsect/badsect.c | 6 +- sbin/cgdconfig/cgdconfig.c | 6 +- sbin/clri/clri.c | 6 +- sbin/dump/ffs_inode.c | 10 +- sbin/fsck_ffs/extern.h | 3 +- sbin/fsck_ffs/fsck.h | 6 +- sbin/fsck_ffs/fsck_ffs.8 | 21 +- sbin/fsck_ffs/main.c | 17 +- sbin/fsck_ffs/pass1.c | 22 +- sbin/fsck_ffs/pass5.c | 17 +- sbin/fsck_ffs/setup.c | 48 ++- sbin/fsck_ffs/utilities.c | 16 +- sbin/fsdb/fsdb.8 | 10 +- sbin/fsdb/fsdb.c | 335 +++++++++++++++++++-- sbin/fsdb/fsdbutil.c | 10 +- sbin/fsirand/fsirand.c | 6 +- sbin/newfs/extern.h | 3 +- sbin/newfs/mkfs.c | 6 +- sbin/newfs/newfs.8 | 5 +- sbin/newfs/newfs.c | 11 +- sbin/resize_ffs/resize_ffs.c | 6 +- sbin/scan_ffs/scan_ffs.c | 6 +- sbin/tunefs/tunefs.c | 19 +- sys/arch/hppa/stand/xxboot/readufs_ffs.c | 7 +- sys/arch/sparc/stand/bootblk/bootblk.fth | 5 +- sys/arch/sparc/stand/bootblk/genfth.cf | 3 +- sys/arch/x68k/stand/boot_ufs/readufs_ffs.c | 7 +- sys/lib/libsa/ffsv1.c | 7 +- sys/lib/libsa/ffsv2.c | 7 +- sys/lib/libsa/lfsv1.c | 4 +- sys/lib/libsa/lfsv2.c | 4 +- sys/lib/libsa/ufs.c | 46 ++- sys/ufs/ffs/ffs_balloc.c | 6 +- sys/ufs/ffs/ffs_extattr.c | 8 +- sys/ufs/ffs/ffs_vfsops.c | 25 +- sys/ufs/ffs/fs.h | 4 +- sys/ufs/ufs/ufs_bmap.c | 6 +- sys/ufs/ufs/ufsmount.h | 3 +- tests/fs/ffs/t_extattr.c | 8 +- tests/sbin/fsck_ffs/Makefile | 4 +- tests/sbin/fsck_ffs/t_extattr.sh | 197 ++++++++++++ usr.sbin/dumpfs/dumpfs.c | 9 +- usr.sbin/fstyp/ufs.c | 10 +- usr.sbin/installboot/ffs.c | 6 +- usr.sbin/makefs/ffs.c | 7 +- usr.sbin/makefs/ffs.h | 3 +- usr.sbin/makefs/ffs/ffs_balloc.c | 7 +- usr.sbin/makefs/ffs/mkfs.c | 11 +- usr.sbin/makefs/makefs.8 | 4 +- usr.sbin/quot/quot.c | 8 +- usr.sbin/quotacheck/quotacheck.c | 10 +- usr.sbin/sysinst/label.c | 6 +- 54 files changed, 908 insertions(+), 151 deletions(-) create mode 100644 tests/sbin/fsck_ffs/t_extattr.sh diff --git a/UPDATING b/UPDATING index 3f7ca4e60fda..16ec5c20567d 100644 --- a/UPDATING +++ b/UPDATING @@ -1,4 +1,4 @@ -$NetBSD: UPDATING,v 1.334 2022/11/12 02:20:15 mrg Exp $ +$NetBSD: UPDATING,v 1.335 2022/11/17 06:40:38 chs Exp $ This file (UPDATING) is intended to be a brief reference to recent changes that might cause problems in the build process, and a guide for @@ -19,6 +19,33 @@ See also: BUILDING, build.sh, Makefile. Recent changes: ^^^^^^^^^^^^^^^ +20221116: + + The addition to NetBSD's version of UFS2 of support for extended + attributes broke backward compatibility with previous releases + of NetBSD, so UFS2 has been restored to being compatible with + previous NetBSD releases by disabling extended attributes. + (Note that ACLs are implemented as extended attributes, so + this changes disables ACLs as well.) + + Support for UFS2 with extended attributes is now available in a new + UFS variant called UFS2ea. If you have created extended attributes + in an original UFS2 file system then "fsck -p" will now fail due to + the unexpected presence of extended attributes and "fsck -y" will + remove all extended attributes. If you wish to preserve extended + attributes rather than delete them, there is a utility to convert + a UFS2 file system to UFS2ea and leave extended attributes in place, + but this should be used with caution since it will preserve any + extended attributes that have been corrupted by the backward + incompatibility too. + + If you wish to use a UFS2ea file system as your root file system, + then you will need to update your boot loader to a version that + supports UFS2ea. + + For more information, see: + https://wiki.netbsd.org/features/UFS2ea + 20221111: The new libdrm import worsened the conflict issues for the kdump/ktruss ioctl, and i915 now conflicts with base, and has diff --git a/distrib/sets/lists/tests/mi b/distrib/sets/lists/tests/mi index e14eac2e338a..0bf1eabfc74a 100644 --- a/distrib/sets/lists/tests/mi +++ b/distrib/sets/lists/tests/mi @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1230 2022/11/10 06:13:58 blymn Exp $ +# $NetBSD: mi,v 1.1231 2022/11/17 06:40:38 chs Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -4354,6 +4354,7 @@ ./usr/tests/sbin/fsck_ffs/Kyuafile tests-sbin-tests compattestfile,atf,kyua ./usr/tests/sbin/fsck_ffs/t_check_quotas tests-sbin-tests compattestfile,atf ./usr/tests/sbin/fsck_ffs/t_enable_quotas tests-sbin-tests compattestfile,atf +./usr/tests/sbin/fsck_ffs/t_extattr tests-sbin-tests compattestfile,atf ./usr/tests/sbin/gpt tests-sbin-tests compattestfile,atf ./usr/tests/sbin/gpt/Atffile tests-sbin-tests compattestfile,atf ./usr/tests/sbin/gpt/Kyuafile tests-sbin-tests compattestfile,atf,kyua diff --git a/sbin/badsect/badsect.c b/sbin/badsect/badsect.c index fc3eed76dff1..04a486045c4c 100644 --- a/sbin/badsect/badsect.c +++ b/sbin/badsect/badsect.c @@ -1,4 +1,4 @@ -/* $NetBSD: badsect.c,v 1.34 2016/09/05 01:09:57 sevan Exp $ */ +/* $NetBSD: badsect.c,v 1.35 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1981, 1983, 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1981, 1983, 1993\ #if 0 static char sccsid[] = "@(#)badsect.c 8.2 (Berkeley) 5/4/95"; #else -__RCSID("$NetBSD: badsect.c,v 1.34 2016/09/05 01:09:57 sevan Exp $"); +__RCSID("$NetBSD: badsect.c,v 1.35 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -151,11 +151,13 @@ main(int argc, char *argv[]) rdfs(sblock_try[i], SBLOCKSIZE, fs); switch (fs->fs_magic) { case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC: break; case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC_SWAPPED: diff --git a/sbin/cgdconfig/cgdconfig.c b/sbin/cgdconfig/cgdconfig.c index 207fb601bb4a..9a634ef37e22 100644 --- a/sbin/cgdconfig/cgdconfig.c +++ b/sbin/cgdconfig/cgdconfig.c @@ -1,4 +1,4 @@ -/* $NetBSD: cgdconfig.c,v 1.60 2022/09/13 10:14:32 riastradh Exp $ */ +/* $NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $ */ /*- * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc. @@ -33,7 +33,7 @@ #ifndef lint __COPYRIGHT("@(#) Copyright (c) 2002, 2003\ The NetBSD Foundation, Inc. All rights reserved."); -__RCSID("$NetBSD: cgdconfig.c,v 1.60 2022/09/13 10:14:32 riastradh Exp $"); +__RCSID("$NetBSD: cgdconfig.c,v 1.61 2022/11/17 06:40:38 chs Exp $"); #endif #ifdef HAVE_ARGON2 @@ -1207,8 +1207,10 @@ verify_ffs(int fd) switch (u.fs.fs_magic) { case FS_UFS1_MAGIC: case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: case FS_UFS1_MAGIC_SWAPPED: case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: return 0; default: continue; diff --git a/sbin/clri/clri.c b/sbin/clri/clri.c index db78dc5191e2..d208563ae6a7 100644 --- a/sbin/clri/clri.c +++ b/sbin/clri/clri.c @@ -1,4 +1,4 @@ -/* $NetBSD: clri.c,v 1.24 2015/08/30 05:23:17 mlelstv Exp $ */ +/* $NetBSD: clri.c,v 1.25 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1990, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1990, 1993\ #if 0 static char sccsid[] = "@(#)clri.c 8.3 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: clri.c,v 1.24 2015/08/30 05:23:17 mlelstv Exp $"); +__RCSID("$NetBSD: clri.c,v 1.25 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -107,11 +107,13 @@ main(int argc, char *argv[]) sbp = (struct fs *)sblock; switch(sbp->fs_magic) { case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: is_ufs2 = 1; /*FALLTHROUGH*/ case FS_UFS1_MAGIC: break; case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: is_ufs2 = 1; /*FALLTHROUGH*/ case FS_UFS1_MAGIC_SWAPPED: diff --git a/sbin/dump/ffs_inode.c b/sbin/dump/ffs_inode.c index 42b25f255b2a..d5b8b0213774 100644 --- a/sbin/dump/ffs_inode.c +++ b/sbin/dump/ffs_inode.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_inode.c,v 1.23 2019/03/01 16:42:11 christos Exp $ */ +/* $NetBSD: ffs_inode.c,v 1.24 2022/11/17 06:40:38 chs Exp $ */ /*- * Copyright (c) 1980, 1991, 1993, 1994 @@ -36,7 +36,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\ #endif /* not lint */ #ifndef lint -__RCSID("$NetBSD: ffs_inode.c,v 1.23 2019/03/01 16:42:11 christos Exp $"); +__RCSID("$NetBSD: ffs_inode.c,v 1.24 2022/11/17 06:40:38 chs Exp $"); #endif /* not lint */ #include @@ -83,11 +83,17 @@ fs_read_sblock(char *superblock) rawread(sblock_try[i], (char *)superblock, MAXBSIZE); switch(sblock->fs_magic) { + case FS_UFS2EA_MAGIC: + sblock->fs_magic = FS_UFS2_MAGIC; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC: is_ufs2 = 1; /*FALLTHROUGH*/ case FS_UFS1_MAGIC: break; + case FS_UFS2EA_MAGIC_SWAPPED: + sblock->fs_magic = FS_UFS2_MAGIC_SWAPPED; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC_SWAPPED: is_ufs2 = 1; /*FALLTHROUGH*/ diff --git a/sbin/fsck_ffs/extern.h b/sbin/fsck_ffs/extern.h index 0e552bf12bd5..49fd8824b841 100644 --- a/sbin/fsck_ffs/extern.h +++ b/sbin/fsck_ffs/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.27 2011/06/09 19:57:52 christos Exp $ */ +/* $NetBSD: extern.h,v 1.28 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1994 James A. Jegers @@ -42,6 +42,7 @@ void clri(struct inodesc *, const char *, int); int cmpsblks(const struct fs *, struct fs *); int cmpsblks42(const struct fs *, struct fs *); int cmpsblks44(const struct fs *, struct fs *); +void cvt_magic(struct fs *); union dinode * getnextinode(ino_t); void direrror(ino_t, const char *); int dirscan(struct inodesc *); diff --git a/sbin/fsck_ffs/fsck.h b/sbin/fsck_ffs/fsck.h index 47c68c49e655..40bd9194e00b 100644 --- a/sbin/fsck_ffs/fsck.h +++ b/sbin/fsck_ffs/fsck.h @@ -1,4 +1,4 @@ -/* $NetBSD: fsck.h,v 1.55 2020/04/18 12:54:38 jdolecek Exp $ */ +/* $NetBSD: fsck.h,v 1.56 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -166,6 +166,7 @@ extern struct fs *sblocksave; sb_oldfscompat_write(sblk.b_un.b_fs, sblocksave); \ if (needswap) \ ffs_sb_swap(sblk.b_un.b_fs, sblk.b_un.b_fs); \ + cvt_magic(sblk.b_un.b_fs); \ sblk.b_dirty = 1; \ } while (0) #define cgdirty() do {copyback_cg(&cgblk); cgblk.b_dirty = 1;} while (0) @@ -280,12 +281,15 @@ extern int zflag; /* zero unused directory space */ extern int cvtlevel; /* convert to newer file system format */ extern int doinglevel1; /* converting to new cylinder group format */ extern int doinglevel2; /* converting to new inode format */ +extern int doing2ea; /* converting UFS2 to UFS2ea */ +extern int doing2noea; /* converting UFS2ea to UFS2 */ extern int newinofmt; /* filesystem has new inode format */ extern char usedsoftdep; /* just fix soft dependency inconsistencies */ extern int preen; /* just fix normal inconsistencies */ extern int quiet; /* Don't print anything if clean */ extern int forceimage; /* file system is an image file */ extern int is_ufs2; /* we're dealing with an UFS2 filesystem */ +extern int is_ufs2ea; /* is the variant that supports exattrs */ extern int markclean; /* mark file system clean when done */ extern char havesb; /* superblock has been read */ extern char skipclean; /* skip clean file systems if preening */ diff --git a/sbin/fsck_ffs/fsck_ffs.8 b/sbin/fsck_ffs/fsck_ffs.8 index 71aa1f575b2f..d182e3c020dd 100644 --- a/sbin/fsck_ffs/fsck_ffs.8 +++ b/sbin/fsck_ffs/fsck_ffs.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: fsck_ffs.8,v 1.51 2019/05/05 14:59:06 christos Exp $ +.\" $NetBSD: fsck_ffs.8,v 1.52 2022/11/17 06:40:38 chs Exp $ .\" .\" Copyright (c) 1980, 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -205,7 +205,23 @@ option to .Xr newfs 8 . .El .Pp -Note that FFSv2 file systems are always level 4. +Note that FFSv2 file systems always have the features of FFSv1 level 4. +.Pp +FFSv2 file systems have separate conversion options: +.Bl -tag -width 3n -offset indent +.It ea +Convert the file system to the format which supports extended attributes +(and access control lists). +After this conversion is performed, the file system will no longer be +recognized at all by releases prior to +.Nx 10.0 . +.It no-ea +Convert the file system to the format which does not support extended attributes +(or access control lists). +This will remove any existing extended attributes, and the file system +will become recognizable to releases prior to +.Nx 10.0 . +.El .Pp In interactive mode, .Nm @@ -227,6 +243,7 @@ in the second line) and the file system level .Dq ( fslevel in the sixth line). +.Pp .It Fl d Print debugging output. .It Fl F diff --git a/sbin/fsck_ffs/main.c b/sbin/fsck_ffs/main.c index 08dea23c3bbc..aa9c1f7f2f3b 100644 --- a/sbin/fsck_ffs/main.c +++ b/sbin/fsck_ffs/main.c @@ -1,4 +1,4 @@ -/* $NetBSD: main.c,v 1.89 2020/04/06 09:54:24 martin Exp $ */ +/* $NetBSD: main.c,v 1.90 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1986, 1993\ #if 0 static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/14/95"; #else -__RCSID("$NetBSD: main.c,v 1.89 2020/04/06 09:54:24 martin Exp $"); +__RCSID("$NetBSD: main.c,v 1.90 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -102,11 +102,14 @@ int zflag; int cvtlevel; int doinglevel1; int doinglevel2; +int doing2ea; +int doing2noea; int newinofmt; char usedsoftdep; int preen; int forceimage; int is_ufs2; +int is_ufs2ea; int markclean; char havesb; char skipclean; @@ -194,6 +197,14 @@ main(int argc, char *argv[]) case 'c': skipclean = 0; + if (strcmp(optarg, "ea") == 0) { + doing2ea = 1; + break; + } + if (strcmp(optarg, "no-ea") == 0) { + doing2noea = 1; + break; + } cvtlevel = argtoi('c', "conversion level", optarg, 10); if (cvtlevel > 4) { cvtlevel = 4; @@ -201,7 +212,7 @@ main(int argc, char *argv[]) cvtlevel); } break; - + case 'd': debug++; break; diff --git a/sbin/fsck_ffs/pass1.c b/sbin/fsck_ffs/pass1.c index 2434de8bee51..e10c7a6a5e90 100644 --- a/sbin/fsck_ffs/pass1.c +++ b/sbin/fsck_ffs/pass1.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass1.c,v 1.59 2020/04/19 19:37:06 christos Exp $ */ +/* $NetBSD: pass1.c,v 1.60 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)pass1.c 8.6 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: pass1.c,v 1.59 2020/04/19 19:37:06 christos Exp $"); +__RCSID("$NetBSD: pass1.c,v 1.60 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -423,7 +423,23 @@ checkinode(ino_t inumber, struct inodesc *idesc) else idesc->id_type = ADDR; (void)ckinode(dp, idesc); - if (is_ufs2 && iswap32(dp->dp2.di_extsize) > 0) { + if (is_ufs2 && (!is_ufs2ea || doing2noea) && + (iswap32(dp->dp2.di_extsize) != 0 || + iswap64(dp->dp2.di_extb[0]) != 0 || + iswap64(dp->dp2.di_extb[1]) != 0)) { + pfatal("NON-ZERO EXTATTR FIELDS"); + if (!reply("CLEAR EXTATTR FIELDS AND SET PERMS TO 0")) { + markclean = 0; + return; + } + dp = ginode(inumber); + dp->dp2.di_extsize = iswap32(0); + dp->dp2.di_extb[0] = iswap64(0); + dp->dp2.di_extb[1] = iswap64(0); + dp->dp2.di_mode &= ~07777; + inodirty(); + } + if (is_ufs2ea && iswap32(dp->dp2.di_extsize) > 0) { int ret, offset; idesc->id_type = ADDR; ndb = howmany(iswap32(dp->dp2.di_extsize), sblock->fs_bsize); diff --git a/sbin/fsck_ffs/pass5.c b/sbin/fsck_ffs/pass5.c index 8e48e225cb85..7b9a6946b72c 100644 --- a/sbin/fsck_ffs/pass5.c +++ b/sbin/fsck_ffs/pass5.c @@ -1,4 +1,4 @@ -/* $NetBSD: pass5.c,v 1.54 2013/06/23 22:03:34 dholland Exp $ */ +/* $NetBSD: pass5.c,v 1.55 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)pass5.c 8.9 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: pass5.c,v 1.54 2013/06/23 22:03:34 dholland Exp $"); +__RCSID("$NetBSD: pass5.c,v 1.55 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -223,11 +223,13 @@ pass5(void) * write back the superblock to the spare at this * cylinder group. */ - if ((cvtlevel && sblk.b_dirty) || doswap) { + if ((cvtlevel && sblk.b_dirty) || doswap || doing2ea || doing2noea) { bwrite(fswritefd, sblk.b_un.b_buf, FFS_FSBTODB(sblock, cgsblock(sblock, c)), sblock->fs_sbsize); } else { + int alt_ufs2ea = 0; + /* * Read in the current alternate superblock, * and compare it to the master. If it's @@ -242,10 +244,15 @@ pass5(void) sblock->fs_sbsize); if (needswap) ffs_sb_swap(asblk.b_un.b_fs, altsblock); + if (altsblock->fs_magic == FS_UFS2EA_MAGIC) { + altsblock->fs_magic = FS_UFS2_MAGIC; + alt_ufs2ea = 1; + } } sb_oldfscompat_write(sblock, sblocksave); - if ((asblk.b_errs || cmpsblks(sblock, altsblock)) && - dofix(&idesc[3], + if ((asblk.b_errs || cmpsblks(sblock, altsblock) || + is_ufs2ea != alt_ufs2ea) && + dofix(&idesc[3], "ALTERNATE SUPERBLK(S) ARE INCORRECT")) { bwrite(fswritefd, sblk.b_un.b_buf, FFS_FSBTODB(sblock, cgsblock(sblock, c)), diff --git a/sbin/fsck_ffs/setup.c b/sbin/fsck_ffs/setup.c index 75dd6d2d4599..2ccbe0d8beae 100644 --- a/sbin/fsck_ffs/setup.c +++ b/sbin/fsck_ffs/setup.c @@ -1,4 +1,4 @@ -/* $NetBSD: setup.c,v 1.103 2020/04/17 09:42:27 jdolecek Exp $ */ +/* $NetBSD: setup.c,v 1.104 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)setup.c 8.10 (Berkeley) 5/9/95"; #else -__RCSID("$NetBSD: setup.c,v 1.103 2020/04/17 09:42:27 jdolecek Exp $"); +__RCSID("$NetBSD: setup.c,v 1.104 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -718,7 +718,8 @@ detect_byteorder(struct fs *fs, int sblockoff) fs->fs_magic == FS_UFS1_MAGIC_SWAPPED)) /* Likely to be the first alternate of a fs with 64k blocks */ return -1; - if (fs->fs_magic == FS_UFS1_MAGIC || fs->fs_magic == FS_UFS2_MAGIC) { + if (fs->fs_magic == FS_UFS1_MAGIC || fs->fs_magic == FS_UFS2_MAGIC || + fs->fs_magic == FS_UFS2EA_MAGIC) { #ifndef NO_FFS_EI if (endian == 0 || BYTE_ORDER == endian) { needswap = 0; @@ -732,7 +733,8 @@ detect_byteorder(struct fs *fs, int sblockoff) } #ifndef NO_FFS_EI else if (fs->fs_magic == FS_UFS1_MAGIC_SWAPPED || - fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) { + fs->fs_magic == FS_UFS2_MAGIC_SWAPPED || + fs->fs_magic == FS_UFS2EA_MAGIC_SWAPPED) { if (endian == 0 || BYTE_ORDER != endian) { needswap = 1; doswap = do_blkswap = do_dirswap = 0; @@ -746,6 +748,29 @@ detect_byteorder(struct fs *fs, int sblockoff) return -1; } +/* Update on-disk fs->fs_magic if we are converting */ +void +cvt_magic(struct fs *fs) +{ + + if (is_ufs2ea || doing2ea) { + if (fs->fs_magic == FS_UFS2_MAGIC) { + fs->fs_magic = FS_UFS2EA_MAGIC; + } + if (fs->fs_magic == FS_UFS2_MAGIC_SWAPPED) { + fs->fs_magic = FS_UFS2EA_MAGIC_SWAPPED; + } + } + if (doing2noea) { + if (fs->fs_magic == FS_UFS2EA_MAGIC) { + fs->fs_magic = FS_UFS2_MAGIC; + } + if (fs->fs_magic == FS_UFS2EA_MAGIC_SWAPPED) { + fs->fs_magic = FS_UFS2_MAGIC_SWAPPED; + } + } +} + /* * Possible superblock locations ordered from most to least likely. */ @@ -811,9 +836,15 @@ readsb(int listerr) memmove(sblock, sblk.b_un.b_fs, SBLOCKSIZE); if (needswap) ffs_sb_swap(sblk.b_un.b_fs, sblock); - + if (sblock->fs_magic == FS_UFS2EA_MAGIC) { + is_ufs2ea = 1; + sblock->fs_magic = FS_UFS2_MAGIC; + } is_ufs2 = sblock->fs_magic == FS_UFS2_MAGIC; + /* change on-disk magic if asked */ + cvt_magic(fs); + /* * run a few consistency checks of the super block */ @@ -845,6 +876,11 @@ readsb(int listerr) memmove(altsblock, asblk.b_un.b_fs, sblock->fs_sbsize); if (needswap) ffs_sb_swap(asblk.b_un.b_fs, altsblock); + if (altsblock->fs_magic == FS_UFS2EA_MAGIC) { + altsblock->fs_magic = FS_UFS2_MAGIC; + } + /* change on-disk magic if asked */ + cvt_magic(asblk.b_un.b_fs); if (cmpsblks(sblock, altsblock)) { if (debug) { uint32_t *nlp, *olp, *endlp; @@ -873,7 +909,7 @@ out: sb_oldfscompat_read(sblock, &sblocksave); /* Now we know the SB is valid, we can write it back if needed */ - if (doswap) { + if (doswap || doing2ea || doing2noea) { sbdirty(); dirty(&asblk); } diff --git a/sbin/fsck_ffs/utilities.c b/sbin/fsck_ffs/utilities.c index 2b53dcb99935..35b21b7549cd 100644 --- a/sbin/fsck_ffs/utilities.c +++ b/sbin/fsck_ffs/utilities.c @@ -1,4 +1,4 @@ -/* $NetBSD: utilities.c,v 1.66 2020/04/17 09:42:27 jdolecek Exp $ */ +/* $NetBSD: utilities.c,v 1.67 2022/11/17 06:40:38 chs Exp $ */ /* * Copyright (c) 1980, 1986, 1993 @@ -34,7 +34,7 @@ #if 0 static char sccsid[] = "@(#)utilities.c 8.6 (Berkeley) 5/19/95"; #else -__RCSID("$NetBSD: utilities.c,v 1.66 2020/04/17 09:42:27 jdolecek Exp $"); +__RCSID("$NetBSD: utilities.c,v 1.67 2022/11/17 06:40:38 chs Exp $"); #endif #endif /* not lint */ @@ -324,6 +324,18 @@ ckfini(int noint) "\n***** FILE SYSTEM MARKED CLEAN *****\n"); } } + if (doing2ea) { + printf("ENABLING EXTATTR SUPPORT\n"); + is_ufs2ea = 1; + sbdirty(); + flush(fswritefd, &sblk); + } + if (doing2noea) { + printf("DISABLING EXTATTR SUPPORT\n"); + is_ufs2ea = 0; + sbdirty(); + flush(fswritefd, &sblk); + } if (debug) printf("cache missed %ld of %ld (%d%%)\n", diskreads, totalreads, (int)(diskreads * 100 / totalreads)); diff --git a/sbin/fsdb/fsdb.8 b/sbin/fsdb/fsdb.8 index d4b557b6b5fa..405edddb18fc 100644 --- a/sbin/fsdb/fsdb.8 +++ b/sbin/fsdb/fsdb.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: fsdb.8,v 1.27 2021/05/29 16:51:25 christos Exp $ +.\" $NetBSD: fsdb.8,v 1.28 2022/11/17 06:40:38 chs Exp $ .\" .\" Copyright (c) 1996, 2017 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -35,7 +35,7 @@ .Nd FFS debugging/editing tool .Sh SYNOPSIS .Nm -.Op Fl dFn +.Op Fl dFnN .Fl f Ar fsname .Sh DESCRIPTION .Nm @@ -74,6 +74,12 @@ The .Fl n option disables writing to the device, preventing any changes from being made to the filesystem. +.Pp +The +.Fl N +option causes the superblock not to be marked dirty when +.Nm +exits. .Sh COMMANDS Besides the built-in .Xr editline 3 diff --git a/sbin/fsdb/fsdb.c b/sbin/fsdb/fsdb.c index 741f73800549..bb2628b52eda 100644 --- a/sbin/fsdb/fsdb.c +++ b/sbin/fsdb/fsdb.c @@ -1,4 +1,4 @@ -/* $NetBSD: fsdb.c,v 1.52 2021/05/29 16:51:25 christos Exp $ */ +/* $NetBSD: fsdb.c,v 1.53 2022/11/17 06:40:38 chs Exp $ */ /*- * Copyright (c) 1996, 2017 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #ifndef lint -__RCSID("$NetBSD: fsdb.c,v 1.52 2021/05/29 16:51:25 christos Exp $"); +__RCSID("$NetBSD: fsdb.c,v 1.53 2022/11/17 06:40:38 chs Exp $"); #endif /* not lint */ #include @@ -51,6 +51,7 @@ __RCSID("$NetBSD: fsdb.c,v 1.52 2021/05/29 16:51:25 christos Exp $"); #include #include #include +#include #include #include @@ -91,13 +92,17 @@ int bflag; int debug; int zflag; int cvtlevel; +int eaflag; int doinglevel1; int doinglevel2; +int doing2ea; +int doing2noea; int newinofmt; char usedsoftdep; int preen; int forceimage; int is_ufs2; +int is_ufs2ea; int markclean; char havesb; char skipclean; @@ -137,6 +142,7 @@ static int scannames(struct inodesc *); static int dolookup(char *); static int chinumfunc(struct inodesc *); static int chnamefunc(struct inodesc *); +static int chreclenfunc(struct inodesc *); static int dotime(char *, int64_t *, int32_t *); static void print_blks32(int32_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); static void print_blks64(int64_t *buf, int size, uint64_t *blknum, struct wrinfo *wrp); @@ -160,7 +166,7 @@ ino_t curinum; static void usage(void) { - errx(1, "usage: %s [-dFn] -f ", getprogname()); + errx(1, "usage: %s [-dFfNn] ", getprogname()); } /* * We suck in lots of fsck code, and just pick & choose the stuff we want. @@ -173,11 +179,12 @@ main(int argc, char *argv[]) { int ch, rval; char *fsys = NULL; + bool makedirty = true; forceimage = 0; debug = 0; isappleufs = 0; - while ((ch = getopt(argc, argv, "dFf:n")) != -1) { + while ((ch = getopt(argc, argv, "dFf:Nn")) != -1) { switch (ch) { case 'd': debug++; @@ -188,6 +195,9 @@ main(int argc, char *argv[]) case 'f': fsys = optarg; break; + case 'N': + makedirty = false; + break; case 'n': nflag++; break; @@ -195,6 +205,10 @@ main(int argc, char *argv[]) usage(); } } + argc -= optind; + argv += optind; + if (fsys == NULL) + fsys = argv[0]; if (fsys == NULL) usage(); endian = 0; @@ -205,6 +219,10 @@ main(int argc, char *argv[]) rval = cmdloop(); if (nflag) exit(rval); + if (!makedirty) { + ckfini(1); + exit(rval); + } sblock->fs_clean = 0; /* mark it dirty */ sbdirty(); markclean = 0; @@ -245,6 +263,15 @@ CMDFUNC(chatime); /* Change atime */ CMDFUNC(chbirthtime); /* Change birthtime */ CMDFUNC(chinum); /* Change inode # of dirent */ CMDFUNC(chname); /* Change dirname of dirent */ +CMDFUNC(chreclen); /* Change reclen of dirent */ +CMDFUNC(chextsize); /* Change extsize */ +CMDFUNC(chblocks); /* Change blocks */ +CMDFUNC(chdb); /* Change direct block pointer */ +CMDFUNC(chib); /* Change indirect block pointer */ +CMDFUNC(chextb); /* Change extattr block pointer */ +CMDFUNC(chfreelink); /* Change freelink pointer */ +CMDFUNC(iptrs); /* print raw block pointers for active inode */ +CMDFUNC(saveea); /* Save extattrs */ static struct cmdtable cmds[] = { {"help", "Print out help", 1, 1, helpfn}, @@ -261,13 +288,14 @@ static struct cmdtable cmds[] = { {"linkcount", "Set link count to COUNT", 2, 2, linkcount}, {"ls", "List current inode as directory", 1, 1, ls}, {"blks", "List current inode's data blocks", 1, 1, blks}, - {"saveblks", "Save current inode's data blocks", 2, 2, blks}, + {"saveblks", "Save current inode's data blocks to FILE", 2, 2, blks}, {"findblk", "Find inode owning disk block(s)", 2, 33, findblk}, {"rm", "Remove NAME from current inode directory", 2, 2, rm}, {"del", "Remove NAME from current inode directory", 2, 2, rm}, {"ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln}, {"chinum", "Change dir entry number INDEX to INUM", 3, 3, chinum}, {"chname", "Change dir entry number INDEX to NAME", 3, 3, chname}, + {"chreclen", "Change dir entry number INDEX to RECLEN", 3, 3, chreclen}, {"chtype", "Change type of current inode to TYPE", 2, 2, newtype}, {"chmod", "Change mode of current inode to MODE", 2, 2, chmode}, {"chown", "Change owner of current inode to OWNER", 2, 2, chowner}, @@ -276,11 +304,19 @@ static struct cmdtable cmds[] = { {"chflags", "Change flags of current inode to FLAGS", 2, 2, chaflags}, {"chgen", "Change generation number of current inode to GEN", 2, 2, chgen}, + { "chextsize", "Change extsize of current inode to EXTSIZE", 2, 2, chextsize }, + { "chblocks", "Change blocks of current inode to BLOCKS", 2, 2, chblocks }, + { "chdb", "Change db pointer N of current inode to BLKNO", 3, 3, chdb }, + { "chib", "Change ib pointer N of current inode to BLKNO", 3, 3, chib }, + { "chextb", "Change extb pointer N of current inode to BLKNO", 3, 3, chextb }, + { "chfreelink", "Change freelink of current inode to FREELINK", 2, 2, chfreelink }, + { "iptrs", "Print raw block pointers of current inode", 1, 1, iptrs }, {"mtime", "Change mtime of current inode to MTIME", 2, 2, chmtime}, {"ctime", "Change ctime of current inode to CTIME", 2, 2, chctime}, {"atime", "Change atime of current inode to ATIME", 2, 2, chatime}, {"birthtime", "Change atime of current inode to BIRTHTIME", 2, 2, chbirthtime}, + {"saveea", "Save current inode's extattr blocks to FILE", 2, 2, saveea}, {"quit", "Exit", 1, 1, quit}, {"q", "Exit", 1, 1, quit}, {"exit", "Exit", 1, 1, quit}, @@ -491,6 +527,7 @@ static const char *typename[] = { "whiteout", }; +static int diroff; static int slot; static int @@ -498,10 +535,11 @@ scannames(struct inodesc *idesc) { struct direct *dirp = idesc->id_dirp; - printf("slot %d ino %d reclen %d: %s, `%.*s'\n", - slot++, iswap32(dirp->d_ino), iswap16(dirp->d_reclen), - typename[dirp->d_type], + printf("slot %d off %d ino %d reclen %d: %s, `%.*s'\n", + slot++, diroff, iswap32(dirp->d_ino), iswap16(dirp->d_reclen), + typename[dirp->d_type], dirp->d_namlen, dirp->d_name); + diroff += dirp->d_reclen; return (KEEPON); } @@ -511,6 +549,7 @@ CMDFUNC(ls) checkactivedir(); /* let it go on anyway */ slot = 0; + diroff = 0; idesc.id_number = curinum; idesc.id_func = scannames; idesc.id_type = DATA; @@ -524,16 +563,18 @@ CMDFUNC(ls) CMDFUNC(blks) { uint64_t blkno = 0; - int i, type; + int i; struct wrinfo wrinfo, *wrp = NULL; + bool saveblks; - if (strcmp(argv[0], "saveblks") == 0) { + saveblks = strcmp(argv[0], "saveblks") == 0; + if (saveblks) { wrinfo.fd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0644); if (wrinfo.fd == -1) { warn("unable to create file %s", argv[1]); return 0; } - wrinfo.size = DIP(curinode, size); + wrinfo.size = iswap64(DIP(curinode, size)); wrinfo.written_size = 0; wrp = &wrinfo; } @@ -541,12 +582,6 @@ CMDFUNC(blks) warnx("no current inode"); return 0; } - type = iswap16(DIP(curinode, mode)) & IFMT; - if (type != IFDIR && type != IFREG) { - warnx("inode %llu not a file or directory", - (unsigned long long)curinum); - return 0; - } if (is_ufs2) { printf("I=%llu %lld blocks\n", (unsigned long long)curinum, (long long)(iswap64(curinode->dp2.di_blocks))); @@ -564,6 +599,11 @@ CMDFUNC(blks) for (i = 0; i < UFS_NIADDR; i++) print_indirblks64(iswap64(curinode->dp2.di_ib[i]), i, &blkno, wrp); + printf("Extattr blocks:\n"); + blkno = 0; + if (saveblks) + wrinfo.size += iswap32(curinode->dp2.di_extsize); + print_blks64(curinode->dp2.di_extb, UFS_NXADDR, &blkno, wrp); } else { for (i = 0; i < UFS_NIADDR; i++) print_indirblks32(iswap32(curinode->dp1.di_ib[i]), i, @@ -827,7 +867,7 @@ static int writefileblk(struct wrinfo *wrp, uint64_t blk) { char buf[MAXBSIZE]; - long long size; + long long size, rsize; size = wrp->size - wrp->written_size; if (size > sblock->fs_bsize) @@ -837,7 +877,8 @@ writefileblk(struct wrinfo *wrp, uint64_t blk) return -1; } - if (bread(fsreadfd, buf, FFS_FSBTODB(sblock, blk), size) != 0) + rsize = roundup(size, DEV_BSIZE); + if (bread(fsreadfd, buf, FFS_FSBTODB(sblock, blk), rsize) != 0) return -1; if (write(wrp->fd, buf, size) != size) return -1; @@ -1154,6 +1195,53 @@ CMDFUNC(chname) } } +static int +chreclenfunc(struct inodesc *idesc) +{ + struct direct *dirp = idesc->id_dirp; + + if (slotcount++ == desired) { + dirp->d_reclen = iswap16(idesc->id_parent); + return STOP | ALTERED | FOUND; + } + return KEEPON; +} + +CMDFUNC(chreclen) +{ + char *cp; + uint32_t reclen; + struct inodesc idesc; + + slotcount = 0; + if (!checkactivedir()) + return 1; + + desired = strtoul(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + printf("invalid slot number `%s'\n", argv[1]); + return 1; + } + reclen = strtoul(argv[2], &cp, 0); + if (reclen >= UINT16_MAX) { + printf("invalid reclen `%s'\n", argv[2]); + return 1; + } + + idesc.id_number = curinum; + idesc.id_func = chreclenfunc; + idesc.id_fix = IGNORE; + idesc.id_type = DATA; + idesc.id_parent = reclen; /* XXX convenient hiding place */ + + if (ckinode(curinode, &idesc) & FOUND) + return 0; + else { + warnx("no %sth slot in current directory", argv[1]); + return 1; + } +} + static struct typemap { const char *typename; int typebits; @@ -1162,6 +1250,9 @@ static struct typemap { { "dir", IFDIR }, { "socket", IFSOCK }, { "fifo", IFIFO }, + {"link", IFLNK}, + {"chr", IFCHR}, + {"blk", IFBLK}, }; CMDFUNC(newtype) @@ -1217,13 +1308,13 @@ CMDFUNC(chmode) CMDFUNC(chlen) { - long len; + off_t len; char *cp; if (!checkactive()) return 1; - len = strtol(argv[1], &cp, 0); + len = strtoull(argv[1], &cp, 0); if (cp == argv[1] || *cp != '\0' || len < 0) { warnx("bad length '%s'", argv[1]); return 1; @@ -1281,6 +1372,160 @@ CMDFUNC(chgen) return 0; } +CMDFUNC(chextsize) +{ + uint32_t extsize; + char *cp; + + if (!is_ufs2) + return 1; + if (!checkactive()) + return 1; + + extsize = strtol(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad extsize `%s'", argv[1]); + return 1; + } + + curinode->dp2.di_extsize = extsize; + inodirty(); + printactive(); + return 0; +} + +CMDFUNC(chblocks) +{ + uint64_t blocks; + char *cp; + + if (!checkactive()) + return 1; + + blocks = strtoll(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad blocks `%s'", argv[1]); + return 1; + } + + DIP_SET(curinode, blocks, blocks); + inodirty(); + printactive(); + return 0; +} + +CMDFUNC(chdb) +{ + unsigned int idx; + daddr_t bno; + char *cp; + + if (!checkactive()) + return 1; + + idx = strtoull(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad pointer idx `%s'", argv[1]); + return 1; + } + bno = strtoll(argv[2], &cp, 0); + if (cp == argv[2] || *cp != '\0') { + warnx("bad block number `%s'", argv[2]); + return 1; + } + if (idx >= UFS_NDADDR) { + warnx("pointer index %d is out of range", idx); + return 1; + } + + DIP_SET(curinode, db[idx], bno); + inodirty(); + printactive(); + return 0; +} + +CMDFUNC(chib) +{ + unsigned int idx; + daddr_t bno; + char *cp; + + if (!checkactive()) + return 1; + + idx = strtoull(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad pointer idx `%s'", argv[1]); + return 1; + } + bno = strtoll(argv[2], &cp, 0); + if (cp == argv[2] || *cp != '\0') { + warnx("bad block number `%s'", argv[2]); + return 1; + } + if (idx >= UFS_NIADDR) { + warnx("pointer index %d is out of range", idx); + return 1; + } + + DIP_SET(curinode, ib[idx], bno); + inodirty(); + printactive(); + return 0; +} + +CMDFUNC(chextb) +{ + unsigned int idx; + daddr_t bno; + char *cp; + + if (!checkactive()) + return 1; + + idx = strtoull(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad pointer idx `%s'", argv[1]); + return 1; + } + bno = strtoll(argv[2], &cp, 0); + if (cp == argv[2] || *cp != '\0') { + warnx("bad block number `%s'", argv[2]); + return 1; + } + if (idx >= UFS_NXADDR) { + warnx("pointer index %d is out of range", idx); + return 1; + } + + curinode->dp2.di_extb[idx] = bno; + inodirty(); + printactive(); + return 0; +} + +CMDFUNC(chfreelink) +{ +#if 0 + ino_t freelink; + char *cp; + + if (!checkactive()) + return 1; + + freelink = strtoll(argv[1], &cp, 0); + if (cp == argv[1] || *cp != '\0') { + warnx("bad freelink `%s'", argv[1]); + return 1; + } + + DIP_SET(curinode, freelink, freelink); + inodirty(); + printactive(); +#endif + return 0; +} + CMDFUNC(linkcount) { int lcnt; @@ -1418,6 +1663,8 @@ CMDFUNC(chmtime) int64_t rsec; int32_t nsec; + if (!checkactive()) + return 1; if (dotime(argv[1], &rsec, &nsec)) return 1; DIP_SET(curinode, mtime, rsec); @@ -1432,6 +1679,8 @@ CMDFUNC(chatime) int64_t rsec; int32_t nsec; + if (!checkactive()) + return 1; if (dotime(argv[1], &rsec, &nsec)) return 1; DIP_SET(curinode, atime, rsec); @@ -1446,6 +1695,8 @@ CMDFUNC(chctime) int64_t rsec; int32_t nsec; + if (!checkactive()) + return 1; if (dotime(argv[1], &rsec, &nsec)) return 1; DIP_SET(curinode, ctime, rsec); @@ -1464,6 +1715,8 @@ CMDFUNC(chbirthtime) warnx("birthtime can only be set in ufs2"); return 1; } + if (!checkactive()) + return 1; if (dotime(argv[1], &rsec, &nsec)) return 1; @@ -1473,3 +1726,43 @@ CMDFUNC(chbirthtime) printactive(); return 0; } + +CMDFUNC(iptrs) +{ + int i; + + if (!checkactive()) + return 1; + for (i = 0; i < UFS_NDADDR; i++) + printf("di_db %d %ju\n", i, DIP(curinode, db[i])); + for (i = 0; i < UFS_NIADDR; i++) + printf("di_ib %d %ju\n", i, DIP(curinode, ib[i])); + if (is_ufs2) + for (i = 0; i < UFS_NXADDR; i++) + printf("di_extb %d %ju\n", i, curinode->dp2.di_extb[i]); + return 0; +} + +CMDFUNC(saveea) +{ + struct wrinfo wrinfo; + uint64_t blkno = 0; + + if (!is_ufs2) { + warnx("dumping extattrs is only supported for ufs2"); + return 1; + } + if (!checkactive()) + return 1; + + wrinfo.fd = open(argv[1], O_WRONLY | O_TRUNC | O_CREAT, 0644); + if (wrinfo.fd == -1) { + warn("unable to create file %s", argv[1]); + return 0; + } + + wrinfo.size = iswap32(curinode->dp2.di_extsize); + wrinfo.written_size = 0; + print_blks64(curinode->dp2.di_extb, UFS_NXADDR, &blkno, &wrinfo); + return 0; +} diff --git a/sbin/fsdb/fsdbutil.c b/sbin/fsdb/fsdbutil.c index 8c5eb1702b30..ffa962043b0c 100644 --- a/sbin/fsdb/fsdbutil.c +++ b/sbin/fsdb/fsdbutil.c @@ -1,4 +1,4 @@ -/* $NetBSD: fsdbutil.c,v 1.23 2021/05/29 16:51:25 christos Exp $ */ +/* $NetBSD: fsdbutil.c,v 1.24 2022/11/17 06:40:38 chs Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #ifndef lint -__RCSID("$NetBSD: fsdbutil.c,v 1.23 2021/05/29 16:51:25 christos Exp $"); +__RCSID("$NetBSD: fsdbutil.c,v 1.24 2022/11/17 06:40:38 chs Exp $"); #endif /* not lint */ #include @@ -95,11 +95,13 @@ printstat(const char *cp, ino_t inum, union dinode *dp) time_t t; char *p; uint64_t size, blocks; + uint32_t extsize; uint16_t mode; uint32_t rdev; uint32_t uid, gid; size = iswap64(DIP(dp, size)); + extsize = is_ufs2 ? iswap32(dp->dp2.di_extsize) : 0; blocks = is_ufs2 ? iswap64(DIP(dp, blocks)) : iswap32(DIP(dp, blocks)); mode = iswap16(DIP(dp, mode)); rdev = iswap32(DIP(dp, rdev)); @@ -139,8 +141,8 @@ printstat(const char *cp, ino_t inum, union dinode *dp) puts("fifo"); break; } - printf("I=%llu MODE=%o SIZE=%llu", (unsigned long long)inum, mode, - (unsigned long long)size); + printf("I=%llu MODE=%o SIZE=%llu EXTSIZE=%u", (unsigned long long)inum, + mode, (unsigned long long)size, extsize); t = is_ufs2 ? iswap64(dp->dp2.di_mtime) : iswap32(dp->dp1.di_mtime); p = ctime(&t); printf("\n\t MTIME=%15.15s %4.4s [%d nsec]", &p[4], &p[20], diff --git a/sbin/fsirand/fsirand.c b/sbin/fsirand/fsirand.c index d4a376ae4f90..8ca27f70f2f2 100644 --- a/sbin/fsirand/fsirand.c +++ b/sbin/fsirand/fsirand.c @@ -1,4 +1,4 @@ -/* $NetBSD: fsirand.c,v 1.32 2013/10/19 01:09:58 christos Exp $ */ +/* $NetBSD: fsirand.c,v 1.33 2022/11/17 06:40:39 chs Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include #ifndef lint -__RCSID("$NetBSD: fsirand.c,v 1.32 2013/10/19 01:09:58 christos Exp $"); +__RCSID("$NetBSD: fsirand.c,v 1.33 2022/11/17 06:40:39 chs Exp $"); #endif /* lint */ #include @@ -95,11 +95,13 @@ getsblock(int fd, const char *name, struct fs *fs) switch(fs->fs_magic) { case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC: break; case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC_SWAPPED: diff --git a/sbin/newfs/extern.h b/sbin/newfs/extern.h index 159d0380de7f..62282378f31f 100644 --- a/sbin/newfs/extern.h +++ b/sbin/newfs/extern.h @@ -1,4 +1,4 @@ -/* $NetBSD: extern.h,v 1.19 2020/04/18 12:54:38 jdolecek Exp $ */ +/* $NetBSD: extern.h,v 1.20 2022/11/17 06:40:39 chs Exp $ */ /* * Copyright (c) 1997 Christos Zoulas. All rights reserved. @@ -31,6 +31,7 @@ void mkfs(const char *, int, int, mode_t, uid_t, gid_t); extern int mfs; /* run as the memory based filesystem */ extern int Nflag; /* run mkfs without writing file system */ extern int Oflag; /* format as an 4.3BSD file system */ +extern int eaflag; /* use UFS2ea fs_magic */ extern int verbosity; /* amount of printf() output */ extern int64_t fssize; /* file system size */ extern int sectorsize; /* bytes/sector */ diff --git a/sbin/newfs/mkfs.c b/sbin/newfs/mkfs.c index 1ccaf4b08498..e7064447a9ec 100644 --- a/sbin/newfs/mkfs.c +++ b/sbin/newfs/mkfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkfs.c,v 1.131 2022/01/01 10:32:28 msaitoh Exp $ */ +/* $NetBSD: mkfs.c,v 1.132 2022/11/17 06:40:39 chs Exp $ */ /* * Copyright (c) 1980, 1989, 1993 @@ -73,7 +73,7 @@ #if 0 static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; #else -__RCSID("$NetBSD: mkfs.c,v 1.131 2022/01/01 10:32:28 msaitoh Exp $"); +__RCSID("$NetBSD: mkfs.c,v 1.132 2022/11/17 06:40:39 chs Exp $"); #endif #endif /* not lint */ @@ -745,6 +745,8 @@ mkfs(const char *fsys, int fi, int fo, memset(iobuf + sizeof(sblock), 0, i - sizeof(sblock)); if (needswap) ffs_sb_swap(&sblock, (struct fs *)iobuf); + if (eaflag) + ((struct fs *)iobuf)->fs_magic = FS_UFS2EA_MAGIC; if ((sblock.fs_old_flags & FS_FLAGS_UPDATED) == 0) memset(iobuf + offsetof(struct fs, fs_old_postbl_start), 0xff, 256); diff --git a/sbin/newfs/newfs.8 b/sbin/newfs/newfs.8 index a6072de89641..1f50e51f4e0c 100644 --- a/sbin/newfs/newfs.8 +++ b/sbin/newfs/newfs.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: newfs.8,v 1.85 2019/04/13 19:29:27 maya Exp $ +.\" $NetBSD: newfs.8,v 1.86 2022/11/17 06:40:39 chs Exp $ .\" .\" Copyright (c) 1983, 1987, 1991, 1993, 1994 .\" The Regents of the University of California. All rights reserved. @@ -229,9 +229,10 @@ or This is the default. .It 2 FFSv2; enhanced Fast File System, suited for more than 1 Terabyte capacity. -.\" Supports access control lists. This is also known as .Sq UFS2 . +.It 2ea +FFSv2 plus support for extended attributes and access control lists. .El See .Xr fsck_ffs 8 diff --git a/sbin/newfs/newfs.c b/sbin/newfs/newfs.c index a635f2343f7d..1a5d1cf424e5 100644 --- a/sbin/newfs/newfs.c +++ b/sbin/newfs/newfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: newfs.c,v 1.117 2022/04/16 18:15:20 andvar Exp $ */ +/* $NetBSD: newfs.c,v 1.118 2022/11/17 06:40:39 chs Exp $ */ /* * Copyright (c) 1983, 1989, 1993, 1994 @@ -78,7 +78,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\ #if 0 static char sccsid[] = "@(#)newfs.c 8.13 (Berkeley) 5/1/95"; #else -__RCSID("$NetBSD: newfs.c,v 1.117 2022/04/16 18:15:20 andvar Exp $"); +__RCSID("$NetBSD: newfs.c,v 1.118 2022/11/17 06:40:39 chs Exp $"); #endif #endif /* not lint */ @@ -207,6 +207,7 @@ int mfs; /* run as the memory based filesystem */ int Gflag; /* allow garbage parameters (for testing) */ int Nflag; /* run without writing file system */ int Oflag = 1; /* format as an 4.3BSD file system */ +int eaflag; /* use UFS2ea fs_magic */ int verbosity; /* amount of printf() output */ #define DEFAULT_VERBOSITY 3 /* 4 is traditional behavior */ int64_t fssize; /* file system size */ @@ -315,6 +316,10 @@ main(int argc, char *argv[]) verbosity = DEFAULT_VERBOSITY; break; case 'O': + if (strcmp(optarg, "2ea") == 0) { + eaflag = 1; + optarg[1] = 0; + } Oflag = strsuftoi64("format", optarg, 0, 2, NULL); break; case 'S': @@ -862,7 +867,7 @@ struct help_strings { { NEWFS, "-I \t\tdo not check that the file system type is '4.2BSD'" }, { BOTH, "-N \t\tdo not create file system, just print out " "parameters" }, - { NEWFS, "-O N\t\tfilesystem format: 0 => 4.3BSD, 1 => FFSv1, 2 => FFSv2" }, + { NEWFS, "-O N\t\tfilesystem format: 0 => 4.3BSD, 1 => FFSv1, 2 => FFSv2, 2ea => FFSv2 with extattrs" }, { NEWFS, "-S secsize\tsector size" }, #ifdef COMPAT { NEWFS, "-T disktype\tdisk type" }, diff --git a/sbin/resize_ffs/resize_ffs.c b/sbin/resize_ffs/resize_ffs.c index 49c8e1286ee0..99be25b6715b 100644 --- a/sbin/resize_ffs/resize_ffs.c +++ b/sbin/resize_ffs/resize_ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: resize_ffs.c,v 1.56 2022/04/08 10:17:53 andvar Exp $ */ +/* $NetBSD: resize_ffs.c,v 1.57 2022/11/17 06:40:39 chs Exp $ */ /* From sources sent on February 17, 2003 */ /*- * As its sole author, I explicitly place this code in the public @@ -36,7 +36,7 @@ */ #include -__RCSID("$NetBSD: resize_ffs.c,v 1.56 2022/04/08 10:17:53 andvar Exp $"); +__RCSID("$NetBSD: resize_ffs.c,v 1.57 2022/11/17 06:40:39 chs Exp $"); #include #include @@ -2227,12 +2227,14 @@ main(int argc, char **argv) readat(where / DEV_BSIZE, oldsb, SBLOCKSIZE); switch (oldsb->fs_magic) { case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC: needswap = 0; break; case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC_SWAPPED: diff --git a/sbin/scan_ffs/scan_ffs.c b/sbin/scan_ffs/scan_ffs.c index 8110c3efc977..4a4b0f21d547 100644 --- a/sbin/scan_ffs/scan_ffs.c +++ b/sbin/scan_ffs/scan_ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: scan_ffs.c,v 1.35 2022/01/20 14:45:14 christos Exp $ */ +/* $NetBSD: scan_ffs.c,v 1.36 2022/11/17 06:40:39 chs Exp $ */ /* * Copyright (c) 2005-2007 Juan Romero Pardines @@ -33,7 +33,7 @@ #include #ifndef lint -__RCSID("$NetBSD: scan_ffs.c,v 1.35 2022/01/20 14:45:14 christos Exp $"); +__RCSID("$NetBSD: scan_ffs.c,v 1.36 2022/11/17 06:40:39 chs Exp $"); #endif /* not lint */ #include @@ -128,7 +128,9 @@ ffs_checkver(struct sblockinfo *sbi) sbi->ffs->fs_size = sbi->ffs->fs_old_size; return FSTYPE_FFSV1; case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: return FSTYPE_FFSV2; default: return FSTYPE_NONE; diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index ea46a5537885..7487bd8bf2b7 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -1,4 +1,4 @@ -/* $NetBSD: tunefs.c,v 1.55 2021/09/18 03:05:20 christos Exp $ */ +/* $NetBSD: tunefs.c,v 1.56 2022/11/17 06:40:39 chs Exp $ */ /* * Copyright (c) 1983, 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1993\ #if 0 static char sccsid[] = "@(#)tunefs.c 8.3 (Berkeley) 5/3/95"; #else -__RCSID("$NetBSD: tunefs.c,v 1.55 2021/09/18 03:05:20 christos Exp $"); +__RCSID("$NetBSD: tunefs.c,v 1.56 2022/11/17 06:40:39 chs Exp $"); #endif #endif /* not lint */ @@ -81,6 +81,7 @@ int fi; long dev_bsize = 512; int needswap = 0; int is_ufs2 = 0; +int extattr = 0; off_t sblockloc; int userquota = 0; int groupquota = 0; @@ -361,7 +362,9 @@ main(int argc, char *argv[]) if (aflag) { name = "ACLs"; if (strcmp(avalue, "enable") == 0) { - if (sblock.fs_flags & FS_NFS4ACLS) { + if (is_ufs2 && !extattr) { + warnx("%s not supported by this fs", name); + } else if (sblock.fs_flags & FS_NFS4ACLS) { warnx("%s remains unchanged as enabled", name); } else if (sblock.fs_flags & FS_POSIX1EACLS) { warnx("%s and POSIX.1e ACLs are mutually " @@ -384,7 +387,9 @@ main(int argc, char *argv[]) if (pflag) { name = "POSIX1e ACLs"; if (strcmp(pvalue, "enable") == 0) { - if (sblock.fs_flags & FS_POSIX1EACLS) { + if (is_ufs2 && !extattr) { + warnx("%s not supported by this fs", name); + } else if (sblock.fs_flags & FS_POSIX1EACLS) { warnx("%s remains unchanged as enabled", name); } else if (sblock.fs_flags & FS_NFS4ACLS) { warnx("%s and ACLs are mutually " @@ -657,11 +662,17 @@ getsb(struct fs *fs, const char *file) errx(5, "cannot find filesystem superblock"); bread(sblock_try[i] / dev_bsize, (char *)fs, SBLOCKSIZE, file); switch(fs->fs_magic) { + case FS_UFS2EA_MAGIC: + extattr = 1; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC: is_ufs2 = 1; /*FALLTHROUGH*/ case FS_UFS1_MAGIC: break; + case FS_UFS2EA_MAGIC_SWAPPED: + extattr = 1; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC_SWAPPED: is_ufs2 = 1; /*FALLTHROUGH*/ diff --git a/sys/arch/hppa/stand/xxboot/readufs_ffs.c b/sys/arch/hppa/stand/xxboot/readufs_ffs.c index 11d542d037ae..392b8354a443 100644 --- a/sys/arch/hppa/stand/xxboot/readufs_ffs.c +++ b/sys/arch/hppa/stand/xxboot/readufs_ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: readufs_ffs.c,v 1.1 2014/02/24 07:23:43 skrll Exp $ */ +/* $NetBSD: readufs_ffs.c,v 1.2 2022/11/17 06:40:39 chs Exp $ */ /* from Id: readufs_ffs.c,v 1.8 2004/06/12 04:26:39 itohy Exp */ /* @@ -66,7 +66,7 @@ try_ffs(void) break; #endif #ifdef USE_UFS2 - if (magic == FS_UFS2_MAGIC) { + if (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) { #ifdef USE_UFS1 fsi.ufstype = UFSTYPE_UFS2; #endif @@ -81,7 +81,8 @@ try_ffs(void) */ fsi_ffs.magic = magic; #ifdef DEBUG_WITH_STDIO - printf("FFS: detected UFS%d format\n", (magic == FS_UFS2_MAGIC) + 1); + printf("FFS: detected UFS%d format\n", + (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) + 1); #endif /* This partition looks like an FFS. */ diff --git a/sys/arch/sparc/stand/bootblk/bootblk.fth b/sys/arch/sparc/stand/bootblk/bootblk.fth index 0107053a9c99..184b16859ec6 100644 --- a/sys/arch/sparc/stand/bootblk/bootblk.fth +++ b/sys/arch/sparc/stand/bootblk/bootblk.fth @@ -1,4 +1,4 @@ -\ $NetBSD: bootblk.fth,v 1.16 2021/07/24 21:31:36 andvar Exp $ +\ $NetBSD: bootblk.fth,v 1.17 2022/11/17 06:40:39 chs Exp $ \ \ IEEE 1275 Open Firmware Boot Block \ @@ -624,6 +624,7 @@ create cur-blockno -1 l, -1 l, \ Current disk block. fs_magic l@ case fs1_magic_value of init-ffs-v1 true endof fs2_magic_value of init-ffs-v2 true endof + fs2ea_magic_value of init-ffs-v2 true endof false swap \ Return false endcase ; @@ -890,7 +891,7 @@ create cur-blockno -1 l, -1 l, \ Current disk block. : do-boot ( bootfile -- ) ." NetBSD IEEE 1275 Multi-FS Bootblock" cr - ." Version $NetBSD: bootblk.fth,v 1.16 2021/07/24 21:31:36 andvar Exp $" cr + ." Version $NetBSD: bootblk.fth,v 1.17 2022/11/17 06:40:39 chs Exp $" cr boot-path load-file ( -- load-base ) dup 0<> if " init-program " evaluate then ; diff --git a/sys/arch/sparc/stand/bootblk/genfth.cf b/sys/arch/sparc/stand/bootblk/genfth.cf index 8c2cf1f8451a..2bde08ee2e59 100644 --- a/sys/arch/sparc/stand/bootblk/genfth.cf +++ b/sys/arch/sparc/stand/bootblk/genfth.cf @@ -1,4 +1,4 @@ -# $NetBSD: genfth.cf,v 1.9 2013/06/10 10:26:22 hannken Exp $ +# $NetBSD: genfth.cf,v 1.10 2022/11/17 06:40:39 chs Exp $ # # Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -158,6 +158,7 @@ member d_name define fs1_magic_value FS_UFS1_MAGIC define fs2_magic_value FS_UFS2_MAGIC +define fs2ea_magic_value FS_UFS2EA_MAGIC define fs_42postblfmt FS_42POSTBLFMT define fs_44inodefmt FS_44INODEFMT define ndaddr UFS_NDADDR diff --git a/sys/arch/x68k/stand/boot_ufs/readufs_ffs.c b/sys/arch/x68k/stand/boot_ufs/readufs_ffs.c index 61f8116f0319..5ef632825a48 100644 --- a/sys/arch/x68k/stand/boot_ufs/readufs_ffs.c +++ b/sys/arch/x68k/stand/boot_ufs/readufs_ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: readufs_ffs.c,v 1.14 2013/06/23 02:06:05 dholland Exp $ */ +/* $NetBSD: readufs_ffs.c,v 1.15 2022/11/17 06:40:39 chs Exp $ */ /* from Id: readufs_ffs.c,v 1.6 2003/04/08 09:19:32 itohy Exp */ /* @@ -69,7 +69,7 @@ try_ffs(void) } #endif #ifdef USE_UFS2 - if (magic == FS_UFS2_MAGIC) { + if (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) { #ifdef USE_UFS1 fsi.ufstype = UFSTYPE_UFS2; #endif @@ -84,7 +84,8 @@ try_ffs(void) */ fsi_ffs.magic = magic; #ifdef DEBUG_WITH_STDIO - printf("FFS: detected UFS%d format\n", (magic == FS_UFS2_MAGIC) + 1); + printf("FFS: detected UFS%d format\n", + (magic == FS_UFS2_MAGIC || magic == FS_UFS2EA_MAGIC) + 1); #endif /* This partition looks like an FFS. */ diff --git a/sys/lib/libsa/ffsv1.c b/sys/lib/libsa/ffsv1.c index c3197c669d16..779bc2fdafa8 100644 --- a/sys/lib/libsa/ffsv1.c +++ b/sys/lib/libsa/ffsv1.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffsv1.c,v 1.9 2022/04/24 06:52:59 mlelstv Exp $ */ +/* $NetBSD: ffsv1.c,v 1.10 2022/11/17 06:40:39 chs Exp $ */ #define LIBSA_FFSv1 @@ -17,9 +17,4 @@ #define ufs_indp_swap bswap32 #define indp_t int32_t -#define FS_MAGIC FS_UFS1_MAGIC - -/* #define FSMOD "wapbl/ufs/ffs" */ -#define FSMOD NULL - #include "ufs.c" diff --git a/sys/lib/libsa/ffsv2.c b/sys/lib/libsa/ffsv2.c index 90b7cae30a12..390b3763046a 100644 --- a/sys/lib/libsa/ffsv2.c +++ b/sys/lib/libsa/ffsv2.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffsv2.c,v 1.9 2022/04/24 06:52:59 mlelstv Exp $ */ +/* $NetBSD: ffsv2.c,v 1.10 2022/11/17 06:40:39 chs Exp $ */ #define LIBSA_FFSv2 @@ -17,9 +17,4 @@ #define ufs_indp_swap bswap64 #define indp_t int64_t -#define FS_MAGIC FS_UFS2_MAGIC - -/* #define FSMOD "wapbl/ufs/ffs" */ -#define FSMOD NULL - #include "ufs.c" diff --git a/sys/lib/libsa/lfsv1.c b/sys/lib/libsa/lfsv1.c index 1c361c23bd82..825c457a2c21 100644 --- a/sys/lib/libsa/lfsv1.c +++ b/sys/lib/libsa/lfsv1.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfsv1.c,v 1.15 2021/05/27 06:54:44 mrg Exp $ */ +/* $NetBSD: lfsv1.c,v 1.16 2022/11/17 06:40:39 chs Exp $ */ #define LIBSA_LFS #define REQUIRED_LFS_VERSION 1 @@ -25,8 +25,6 @@ #define dblksize(a, b, c) lfs_dblksize((a), (b), (c)) #define FSBTODB(fs, daddr) (daddr) /* LFSv1 uses sectors for addresses */ -#define FS_MAGIC LFS_MAGIC - #define FSMOD "lfs" #include "lib/libsa/ufs.c" diff --git a/sys/lib/libsa/lfsv2.c b/sys/lib/libsa/lfsv2.c index 0eb0583854b8..089f763d8753 100644 --- a/sys/lib/libsa/lfsv2.c +++ b/sys/lib/libsa/lfsv2.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfsv2.c,v 1.15 2021/05/27 06:54:44 mrg Exp $ */ +/* $NetBSD: lfsv2.c,v 1.16 2022/11/17 06:40:40 chs Exp $ */ #define LIBSA_LFS #define REQUIRED_LFS_VERSION 2 @@ -29,8 +29,6 @@ #define dblksize(a, b, c) lfs_dblksize((a), (b), (c)) #define FSBTODB(a, b) LFS_FSBTODB((a), (b)) -#define FS_MAGIC LFS_MAGIC - #define FSMOD "lfs" #include "lib/libsa/ufs.c" diff --git a/sys/lib/libsa/ufs.c b/sys/lib/libsa/ufs.c index adf464e6d79f..5641c5f018a8 100644 --- a/sys/lib/libsa/ufs.c +++ b/sys/lib/libsa/ufs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs.c,v 1.86 2022/04/29 07:42:07 rin Exp $ */ +/* $NetBSD: ufs.c,v 1.87 2022/11/17 06:40:40 chs Exp $ */ /*- * Copyright (c) 1993 @@ -156,9 +156,6 @@ typedef uint32_t ino32_t; #ifndef FSBTODB #define FSBTODB(fs, indp) FFS_FSBTODB(fs, indp) #endif -#ifndef FS_MAGIC -#define FS_MAGIC FS_UFS1_MAGIC -#endif #ifndef UFS_NINDIR #define UFS_NINDIR FFS_NINDIR #endif @@ -214,17 +211,54 @@ static int search_directory(const char *, int, struct open_file *, ino32_t *); static void ffs_oldfscompat(FS *); #endif +#ifdef LIBSA_FFSv1 static __inline__ bool ffs_is_magic(FS *fs) { - return fs->fs_magic == FS_MAGIC; + return fs->fs_magic == FS_UFS1_MAGIC; } +static __inline__ bool +ffs_is_magic_swapped(FS *fs) +{ + return fs->fs_magic == bswap32(FS_UFS1_MAGIC); +} +#endif + +#ifdef LIBSA_FFSv2 +static __inline__ bool +ffs_is_magic(FS *fs) +{ + return fs->fs_magic == FS_UFS2_MAGIC || fs->fs_magic == FS_UFS2EA_MAGIC; +} + +static __inline__ bool +ffs_is_magic_swapped(FS *fs) +{ + return fs->fs_magic == bswap32(FS_UFS2_MAGIC) || + fs->fs_magic == bswap32(FS_UFS2EA_MAGIC); +} +#endif + +#ifdef LIBSA_LFS +static __inline__ bool +ffs_is_magic(FS *fs) +{ + return fs->fs_magic == LFS_MAGIC; +} + +static __inline__ bool +ffs_is_magic_swapped(FS *fs) +{ + return fs->fs_magic == bswap32(LFS_MAGIC); +} +#endif + static __inline__ void ffs_fix_magic_swapped(struct file *fp, FS *fs) { #ifdef LIBSA_FFS_EI - fp->f_swapped = fs->fs_magic == bswap32(FS_MAGIC); + fp->f_swapped = ffs_is_magic_swapped(fs); if (fp->f_swapped) { ffs_sb_swap(fs, fs); diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index fb52b993f6f1..954d7f1de4a7 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_balloc.c,v 1.65 2020/09/05 16:30:13 riastradh Exp $ */ +/* $NetBSD: ffs_balloc.c,v 1.66 2022/11/17 06:40:40 chs Exp $ */ /* * Copyright (c) 2002 Networks Associates Technology, Inc. @@ -41,7 +41,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.65 2020/09/05 16:30:13 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_balloc.c,v 1.66 2022/11/17 06:40:40 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -543,6 +543,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t off, int size, kauth_cred_t cred, const int needswap = UFS_FSNEEDSWAP(fs); UVMHIST_FUNC("ffs_balloc"); UVMHIST_CALLED(ubchist); + KASSERT((ump->um_flags & UFS_EA) != 0 || (flags & IO_EXT) == 0); + lbn = ffs_lblkno(fs, off); size = ffs_blkoff(fs, off) + size; if (size > fs->fs_bsize) diff --git a/sys/ufs/ffs/ffs_extattr.c b/sys/ufs/ffs/ffs_extattr.c index 41ba849c1d89..7c4728275ba9 100644 --- a/sys/ufs/ffs/ffs_extattr.c +++ b/sys/ufs/ffs/ffs_extattr.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_extattr.c,v 1.8 2021/12/14 11:06:50 chs Exp $ */ +/* $NetBSD: ffs_extattr.c,v 1.9 2022/11/17 06:40:40 chs Exp $ */ /*- * SPDX-License-Identifier: (BSD-2-Clause-FreeBSD AND BSD-3-Clause) @@ -66,7 +66,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_extattr.c,v 1.8 2021/12/14 11:06:50 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_extattr.c,v 1.9 2022/11/17 06:40:40 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -464,6 +464,9 @@ ffs_open_ea(struct vnode *vp, kauth_cred_t cred) int error; ip = VTOI(vp); + if ((ip->i_ump->um_flags & UFS_EA) == 0) { + return EOPNOTSUPP; + } ffs_lock_ea(vp); if (ip->i_ea_area != NULL) { @@ -497,6 +500,7 @@ ffs_close_ea(struct vnode *vp, int commit, kauth_cred_t cred) struct ufs2_dinode *dp; ip = VTOI(vp); + KASSERT((ip->i_ump->um_flags & UFS_EA) != 0); if (commit) KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE); diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 181a38d826db..f39f29ad6023 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vfsops.c,v 1.377 2022/11/10 10:53:29 hannken Exp $ */ +/* $NetBSD: ffs_vfsops.c,v 1.378 2022/11/17 06:40:40 chs Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.377 2022/11/10 10:53:29 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.378 2022/11/17 06:40:40 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -845,6 +845,15 @@ ffs_reload(struct mount *mp, kauth_cred_t cred, struct lwp *l) brelse(bp, 0); + /* Allow converting from UFS2 to UFS2EA but not vice versa. */ + if (newfs->fs_magic == FS_UFS2EA_MAGIC) { + ump->um_flags |= UFS_EA; + newfs->fs_magic = FS_UFS2_MAGIC; + } else { + if ((ump->um_flags & UFS_EA) != 0) + return EINVAL; + } + if ((newfs->fs_magic != FS_UFS1_MAGIC) && (newfs->fs_magic != FS_UFS2_MAGIC)) { kmem_free(newfs, fs_sbsize); @@ -1217,6 +1226,13 @@ ffs_mountfs(struct vnode *devvp, struct mount *mp, struct lwp *l) * size to read the superblock. Once read, we swap the whole * superblock structure. */ + if (fs->fs_magic == FS_UFS2EA_MAGIC) { + ump->um_flags |= UFS_EA; + fs->fs_magic = FS_UFS2_MAGIC; + } else if (fs->fs_magic == FS_UFS2EA_MAGIC_SWAPPED) { + ump->um_flags |= UFS_EA; + fs->fs_magic = FS_UFS2_MAGIC_SWAPPED; + } if (fs->fs_magic == FS_UFS1_MAGIC) { fs_sbsize = fs->fs_sbsize; fstype = UFS1; @@ -2375,6 +2391,11 @@ ffs_sbupdate(struct ufsmount *mp, int waitfor) memcpy(bp->b_data, fs, fs->fs_sbsize); ffs_oldfscompat_write((struct fs *)bp->b_data, mp); + if (mp->um_flags & UFS_EA) { + struct fs *bfs = (struct fs *)bp->b_data; + KASSERT(bfs->fs_magic == FS_UFS2_MAGIC); + bfs->fs_magic = FS_UFS2EA_MAGIC; + } #ifdef FFS_EI if (mp->um_flags & UFS_NEEDSWAP) ffs_sb_swap((struct fs *)bp->b_data, (struct fs *)bp->b_data); diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index ca92949e7095..da0bf60cd1ae 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -1,4 +1,4 @@ -/* $NetBSD: fs.h,v 1.69 2021/09/18 03:05:20 christos Exp $ */ +/* $NetBSD: fs.h,v 1.70 2022/11/17 06:40:40 chs Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -398,8 +398,10 @@ struct fs { */ #define FS_UFS1_MAGIC 0x011954 /* UFS1 fast file system magic number */ #define FS_UFS2_MAGIC 0x19540119 /* UFS2 fast file system magic number */ +#define FS_UFS2EA_MAGIC 0x19012038 /* UFS2 with extattrs */ #define FS_UFS1_MAGIC_SWAPPED 0x54190100 #define FS_UFS2_MAGIC_SWAPPED 0x19015419 +#define FS_UFS2EA_MAGIC_SWAPPED 0x38200119 #define FS_OKAY 0x7c269d38 /* superblock checksum */ #define FS_42INODEFMT -1 /* 4.2BSD inode format */ #define FS_44INODEFMT 2 /* 4.4BSD inode format */ diff --git a/sys/ufs/ufs/ufs_bmap.c b/sys/ufs/ufs/ufs_bmap.c index 96e57032da3b..7709dcf2b0ca 100644 --- a/sys/ufs/ufs/ufs_bmap.c +++ b/sys/ufs/ufs/ufs_bmap.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_bmap.c,v 1.53 2020/04/20 03:57:02 christos Exp $ */ +/* $NetBSD: ufs_bmap.c,v 1.54 2022/11/17 06:40:40 chs Exp $ */ /* * Copyright (c) 1989, 1991, 1993 @@ -37,7 +37,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ufs_bmap.c,v 1.53 2020/04/20 03:57:02 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_bmap.c,v 1.54 2022/11/17 06:40:40 chs Exp $"); #include #include @@ -191,7 +191,7 @@ ufs_bmaparray(struct vnode *vp, daddr_t bn, daddr_t *bnp, struct indir *ap, } return (0); } else if (bn < 0 && bn >= -UFS_NXADDR) { - KASSERT(ump->um_fstype == UFS2); + KASSERT(ump->um_fstype == UFS2 && (ump->um_flags & UFS_EA) != 0); daddr = ufs_rw64(ip->i_ffs2_extb[-1 - bn], UFS_MPNEEDSWAP(ump)); *bnp = blkptrtodb(ump, daddr); if (*bnp == 0) diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h index 86b3968b90a9..aa190ad7ef33 100644 --- a/sys/ufs/ufs/ufsmount.h +++ b/sys/ufs/ufs/ufsmount.h @@ -1,4 +1,4 @@ -/* $NetBSD: ufsmount.h,v 1.43 2015/03/27 17:27:56 riastradh Exp $ */ +/* $NetBSD: ufsmount.h,v 1.44 2022/11/17 06:40:40 chs Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -163,6 +163,7 @@ struct ufs_ops { #define UFS_ISAPPLEUFS 0x02 /* filesystem is Apple UFS */ #define UFS_QUOTA 0x04 /* filesystem has QUOTA (v1) */ #define UFS_QUOTA2 0x08 /* filesystem has QUOTA2 */ +#define UFS_EA 0x10 /* UFS2 with extattrs */ /* * Filesystem types diff --git a/tests/fs/ffs/t_extattr.c b/tests/fs/ffs/t_extattr.c index 6fe2281d190e..89c73394a0a6 100644 --- a/tests/fs/ffs/t_extattr.c +++ b/tests/fs/ffs/t_extattr.c @@ -1,4 +1,4 @@ -/* $NetBSD: t_extattr.c,v 1.2 2020/04/12 23:52:20 christos Exp $ */ +/* $NetBSD: t_extattr.c,v 1.3 2022/11/17 06:40:40 chs Exp $ */ /*- * Copyright (c) 2020 The NetBSD Foundation, Inc. @@ -29,7 +29,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -__RCSID("$NetBSD: t_extattr.c,v 1.2 2020/04/12 23:52:20 christos Exp $"); +__RCSID("$NetBSD: t_extattr.c,v 1.3 2022/11/17 06:40:40 chs Exp $"); #include #include @@ -78,8 +78,8 @@ check_list(const char *buf, ssize_t nr) } } -// Make it ffsv2 -const char *newfs = "newfs -O 2 -F -s 10000 " IMGNAME; +// Make it ffsv2 with extattrs +const char *newfs = "newfs -O 2ea -F -s 10000 " IMGNAME; #define FAKEBLK "/dev/formula1" static void diff --git a/tests/sbin/fsck_ffs/Makefile b/tests/sbin/fsck_ffs/Makefile index 0f279911912f..b0e4abe54d98 100644 --- a/tests/sbin/fsck_ffs/Makefile +++ b/tests/sbin/fsck_ffs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.2 2011/03/06 17:08:41 bouyer Exp $ +# $NetBSD: Makefile,v 1.3 2022/11/17 06:40:40 chs Exp $ .include @@ -9,4 +9,6 @@ TESTS_SH+= ${name} TESTS_SH_SRC_${name}= quotas_common.sh ${name}.sh .endfor +TESTS_SH+= t_extattr + .include diff --git a/tests/sbin/fsck_ffs/t_extattr.sh b/tests/sbin/fsck_ffs/t_extattr.sh new file mode 100644 index 000000000000..699c096f7973 --- /dev/null +++ b/tests/sbin/fsck_ffs/t_extattr.sh @@ -0,0 +1,197 @@ +# $NetBSD: t_extattr.sh,v 1.1 2022/11/17 06:40:40 chs Exp $ +# +# Copyright (c) 2021 The NetBSD Foundation, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +VND=vnd0 +BDEV=/dev/${VND}a +CDEV=/dev/r${VND}a +IMG=fsimage +MNT=mnt + +atf_test_case fsck_extattr_enable cleanup +atf_test_case fsck_extattr_enable_corrupted cleanup +atf_test_case fsck_extattr_disable cleanup + +cleanup() +{ + echo in cleanup + umount -f ${MNT} > /dev/null 2>&1 || true + vnconfig -u ${VND} > /dev/null 2>&1 || true +} + +fsck_extattr_enable_head() +{ + atf_set "descr" "Checks fsck_ffs enabling extattrs" +} + +fsck_extattr_enable_body() +{ + atf_check mkdir -p ${MNT} + + atf_check -o ignore newfs -O2 -s 4m -F ${IMG} + atf_check vnconfig ${VND} ${IMG} + + # Verify that extattrs are disabled. + atf_check -o ignore -e 'match:POSIX1e ACLs not supported by this fs' \ + tunefs -p enable ${CDEV} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check touch ${MNT}/file + atf_check -s exit:1 -e ignore setextattr user name1 value1 ${MNT}/file + atf_check umount ${MNT} + + # Enable extattrs. + atf_check -o 'match:ENABLING EXTATTR SUPPORT' \ + fsck_ffs -c ea ${CDEV} + + # Verify that extattrs are now enabled. + atf_check -o 'match:POSIX1e ACLs set' -e ignore \ + tunefs -p enable ${CDEV} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check touch ${MNT}/file + atf_check setextattr user testname testvalue ${MNT}/file + atf_check -o 'match:testvalue' getextattr user testname ${MNT}/file + atf_check umount ${MNT} + atf_check vnconfig -u ${VND} +} + +fsck_extattr_enable_cleanup() +{ + cleanup +} + +fsck_extattr_enable_corrupted_head() +{ + atf_set "descr" "Checks fsck_ffs enabling extattrs with corruption" +} + +fsck_extattr_enable_corrupted_body() +{ + atf_check mkdir -p ${MNT} + + # Create an fs with extattrs enabled and set an extattr on the test file. + atf_check -o ignore newfs -O2ea -b 8k -f 1k -s 4m -F ${IMG} + atf_check vnconfig ${VND} ${IMG} + + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check touch ${MNT}/file + atf_check setextattr user testname testvalue ${MNT}/file + atf_check -o 'match:testvalue' getextattr user testname ${MNT}/file + atf_check umount ${MNT} + + # Find the location and size of the extattr block. + extb0=$(printf 'cd file\niptrs\n' | fsdb -n $CDEV | grep 'di_extb 0' | + awk '{print $3}') + extsize=$(printf 'cd file\n' | fsdb -n $CDEV | grep EXTSIZE | tail -1 | + awk '{print $4}' | sed 's,.*=,,') + atf_check [ $extb0 != 0 ] + atf_check [ $extsize != 0 ] + + # Recreate the fs with extattrs disabled and set the extattr block + # size/location of the new test file to the same values as the old + # test file. This simulates extattrs having been created in a + # UFS2-non-ea file system before UFS2ea was invented. + atf_check -o ignore newfs -O2 -b 8k -f 1k -s 4m -F ${IMG} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check touch ${MNT}/file + atf_check umount ${MNT} + printf "cd file\nchextb 0 $extb0\n" | fsdb -N $CDEV + printf "cd file\nchextsize $extsize\n" | fsdb -N $CDEV + + # Convert to enable extattrs. + atf_check -o 'match:CLEAR EXTATTR FIELDS' \ + -o 'match:ENABLING EXTATTR SUPPORT' \ + fsck_ffs -y -c ea ${CDEV} + + # Verify that the test file does not have the extattr. + atf_check -o ignore fsck -n ${CDEV} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check -s exit:1 -e 'match:Attribute not found' \ + getextattr user testname ${MNT}/file + atf_check umount ${MNT} + atf_check vnconfig -u ${VND} +} + +fsck_extattr_enable_corrupted_cleanup() +{ + cleanup +} + +fsck_extattr_disable_head() +{ + atf_set "descr" "Checks fsck_ffs disabling extattrs" +} + +fsck_extattr_disable_body() +{ + atf_check mkdir -p ${MNT} + + # Create an fs with extattrs enabled and set an extattr on the test file. + atf_check -o ignore newfs -O2ea -b 8k -f 1k -s 4m -F ${IMG} + atf_check vnconfig ${VND} ${IMG} + + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check touch ${MNT}/file + atf_check setextattr user testname testvalue ${MNT}/file + atf_check -o 'match:testvalue' getextattr user testname ${MNT}/file + atf_check umount ${MNT} + + # Convert to disable extattrs. + atf_check -o 'match:CLEAR EXTATTR FIELDS' \ + -o 'match:DISABLING EXTATTR SUPPORT' \ + fsck_ffs -y -c no-ea ${CDEV} + + # Verify that the test file does not have the test extattr. + atf_check -o ignore fsck -n ${CDEV} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check -s exit:1 -e 'match:getextattr: mnt/file: failed: Operation not supported' \ + getextattr user testname ${MNT}/file + atf_check umount ${MNT} + + # Convert to enable extattrs again. + atf_check -o 'match:ENABLING EXTATTR SUPPORT' \ + fsck_ffs -y -c ea ${CDEV} + + # Verify that the test extattr is still gone. + atf_check -o ignore fsck -n ${CDEV} + atf_check mount -t ffs ${BDEV} ${MNT} + atf_check -s exit:1 -e 'match:Attribute not found' \ + getextattr user testname ${MNT}/file + atf_check umount ${MNT} + + atf_check vnconfig -u ${VND} +} + +fsck_extattr_disable_cleanup() +{ + cleanup +} + +atf_init_test_cases() +{ + atf_add_test_case fsck_extattr_enable + atf_add_test_case fsck_extattr_enable_corrupted + atf_add_test_case fsck_extattr_disable +} diff --git a/usr.sbin/dumpfs/dumpfs.c b/usr.sbin/dumpfs/dumpfs.c index 881bf8f6a1f4..2797a9e35839 100644 --- a/usr.sbin/dumpfs/dumpfs.c +++ b/usr.sbin/dumpfs/dumpfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: dumpfs.c,v 1.65 2021/09/18 03:05:20 christos Exp $ */ +/* $NetBSD: dumpfs.c,v 1.66 2022/11/17 06:40:40 chs Exp $ */ /* * Copyright (c) 1983, 1992, 1993 @@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1992, 1993\ #if 0 static char sccsid[] = "@(#)dumpfs.c 8.5 (Berkeley) 4/29/95"; #else -__RCSID("$NetBSD: dumpfs.c,v 1.65 2021/09/18 03:05:20 christos Exp $"); +__RCSID("$NetBSD: dumpfs.c,v 1.66 2022/11/17 06:40:40 chs Exp $"); #endif #endif /* not lint */ @@ -192,11 +192,13 @@ dumpfs(const char *name) if (read(fd, &afs, SBLOCKSIZE) != SBLOCKSIZE) continue; switch(afs.fs_magic) { + case FS_UFS2EA_MAGIC: case FS_UFS2_MAGIC: is_ufs2 = 1; break; case FS_UFS1_MAGIC: break; + case FS_UFS2EA_MAGIC_SWAPPED: case FS_UFS2_MAGIC_SWAPPED: is_ufs2 = 1; needswap = 1; @@ -294,7 +296,8 @@ print_superblock(struct fs *fs, uint16_t *opostbl, time_t t; int32_t fsflags; - printf("format\tFFSv%d\n", is_ufs2+1); + printf("format\tFFSv%d%s\n", is_ufs2+1, + fs->fs_magic == FS_UFS2EA_MAGIC ? "ea" : ""); #if BYTE_ORDER == LITTLE_ENDIAN if (needswap) #else diff --git a/usr.sbin/fstyp/ufs.c b/usr.sbin/fstyp/ufs.c index fb8a2868b601..0607b9607146 100644 --- a/usr.sbin/fstyp/ufs.c +++ b/usr.sbin/fstyp/ufs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ufs.c,v 1.1 2018/01/09 03:31:15 christos Exp $ */ +/* $NetBSD: ufs.c,v 1.2 2022/11/17 06:40:40 chs Exp $ */ /*- * Copyright (c) 2017 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@ * SUCH DAMAGE. */ #include -__RCSID("$NetBSD: ufs.c,v 1.1 2018/01/09 03:31:15 christos Exp $"); +__RCSID("$NetBSD: ufs.c,v 1.2 2022/11/17 06:40:40 chs Exp $"); #include #include @@ -67,6 +67,12 @@ fstyp_ufs(FILE *fp, char *label, size_t labelsize) fs = (struct fs *)read_buf(fp, superblock, SBLOCKSIZE); if (fs == NULL) continue; + + if (fs->fs_magic == FS_UFS2EA_MAGIC) + fs->fs_magic = FS_UFS2_MAGIC; + else if (fs->fs_magic == FS_UFS2EA_MAGIC_SWAPPED) + fs->fs_magic = FS_UFS2_MAGIC_SWAPPED; + /* * Check for magic. We also need to check if file system size * is equal to providers size, because sysinstall(8) used to diff --git a/usr.sbin/installboot/ffs.c b/usr.sbin/installboot/ffs.c index ac122925ea51..46f55179ba68 100644 --- a/usr.sbin/installboot/ffs.c +++ b/usr.sbin/installboot/ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs.c,v 1.32 2013/06/23 02:06:06 dholland Exp $ */ +/* $NetBSD: ffs.c,v 1.33 2022/11/17 06:40:40 chs Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #include #if !defined(__lint) -__RCSID("$NetBSD: ffs.c,v 1.32 2013/06/23 02:06:06 dholland Exp $"); +__RCSID("$NetBSD: ffs.c,v 1.33 2022/11/17 06:40:40 chs Exp $"); #endif /* !__lint */ #include @@ -502,6 +502,7 @@ ffs_match_common(ib_params *params, off_t offset) continue; switch (fs->fs_magic) { case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC: @@ -512,6 +513,7 @@ ffs_match_common(ib_params *params, off_t offset) break; #ifndef FFS_NO_SWAP case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: is_ufs2 = 1; /* FALLTHROUGH */ case FS_UFS1_MAGIC_SWAPPED: diff --git a/usr.sbin/makefs/ffs.c b/usr.sbin/makefs/ffs.c index 5875c5c95cf6..333d508ab3d0 100644 --- a/usr.sbin/makefs/ffs.c +++ b/usr.sbin/makefs/ffs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs.c,v 1.72 2022/04/09 10:05:35 riastradh Exp $ */ +/* $NetBSD: ffs.c,v 1.73 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright (c) 2001 Wasabi Systems, Inc. @@ -71,7 +71,7 @@ #include #if defined(__RCSID) && !defined(__lint) -__RCSID("$NetBSD: ffs.c,v 1.72 2022/04/09 10:05:35 riastradh Exp $"); +__RCSID("$NetBSD: ffs.c,v 1.73 2022/11/17 06:40:41 chs Exp $"); #endif /* !__lint */ #include @@ -180,6 +180,8 @@ ffs_prep_opts(fsinfo_t *fsopts) 0, 0, "Optimization (time|space)" }, { 'l', "label", ffs_opts->label, OPT_STRARRAY, 1, sizeof(ffs_opts->label), "UFS label" }, + { 'e', "extattr", &ffs_opts->extattr, OPT_INT32, + 0, 1, "extattr support" }, { .name = NULL } }; @@ -194,6 +196,7 @@ ffs_prep_opts(fsinfo_t *fsopts) ffs_opts->avgfilesize= -1; ffs_opts->avgfpdir= -1; ffs_opts->version = 1; + ffs_opts->extattr = 1; fsopts->fs_specific = ffs_opts; fsopts->fs_options = copy_opts(ffs_options); diff --git a/usr.sbin/makefs/ffs.h b/usr.sbin/makefs/ffs.h index 79223bd54dd8..0b8d6eef7e8c 100644 --- a/usr.sbin/makefs/ffs.h +++ b/usr.sbin/makefs/ffs.h @@ -1,4 +1,4 @@ -/* $NetBSD: ffs.h,v 1.2 2011/10/09 21:33:43 christos Exp $ */ +/* $NetBSD: ffs.h,v 1.3 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright (c) 2001-2003 Wasabi Systems, Inc. @@ -60,6 +60,7 @@ typedef struct { int avgfilesize; /* expected average file size */ int avgfpdir; /* expected # of files per directory */ int version; /* filesystem version (1 = FFS, 2 = UFS2) */ + int extattr; /* use UFS2ea magic */ int maxbsize; /* maximum extent size */ int maxblkspercg; /* max # of blocks per cylinder group */ /* XXX: support `old' file systems ? */ diff --git a/usr.sbin/makefs/ffs/ffs_balloc.c b/usr.sbin/makefs/ffs/ffs_balloc.c index bf1350470772..84d1d5ff10d1 100644 --- a/usr.sbin/makefs/ffs/ffs_balloc.c +++ b/usr.sbin/makefs/ffs/ffs_balloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_balloc.c,v 1.21 2015/03/29 05:52:59 agc Exp $ */ +/* $NetBSD: ffs_balloc.c,v 1.22 2022/11/17 06:40:41 chs Exp $ */ /* From NetBSD: ffs_balloc.c,v 1.25 2001/08/08 08:36:36 lukem Exp */ /* @@ -38,7 +38,7 @@ #include #if defined(__RCSID) && !defined(__lint) -__RCSID("$NetBSD: ffs_balloc.c,v 1.21 2015/03/29 05:52:59 agc Exp $"); +__RCSID("$NetBSD: ffs_balloc.c,v 1.22 2022/11/17 06:40:41 chs Exp $"); #endif /* !__lint */ #include @@ -74,7 +74,8 @@ static int ffs_balloc_ufs2(struct inode *, off_t, int, struct buf **); int ffs_balloc(struct inode *ip, off_t offset, int bufsize, struct buf **bpp) { - if (ip->i_fs->fs_magic == FS_UFS2_MAGIC) + if (ip->i_fs->fs_magic == FS_UFS2_MAGIC || + ip->i_fs->fs_magic == FS_UFS2EA_MAGIC) return ffs_balloc_ufs2(ip, offset, bufsize, bpp); else return ffs_balloc_ufs1(ip, offset, bufsize, bpp); diff --git a/usr.sbin/makefs/ffs/mkfs.c b/usr.sbin/makefs/ffs/mkfs.c index 6bfb9644d6c7..95e61dfb880c 100644 --- a/usr.sbin/makefs/ffs/mkfs.c +++ b/usr.sbin/makefs/ffs/mkfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: mkfs.c,v 1.40 2022/04/02 19:16:49 mlelstv Exp $ */ +/* $NetBSD: mkfs.c,v 1.41 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright (c) 2002 Networks Associates Technology, Inc. @@ -48,7 +48,7 @@ static char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; #else #ifdef __RCSID -__RCSID("$NetBSD: mkfs.c,v 1.40 2022/04/02 19:16:49 mlelstv Exp $"); +__RCSID("$NetBSD: mkfs.c,v 1.41 2022/11/17 06:40:41 chs Exp $"); #endif #endif #endif /* not lint */ @@ -109,6 +109,7 @@ union { #define writebuf wb.pad static int Oflag; /* format as an 4.3BSD file system */ +static int extattr; /* use UFS2ea magic */ static int64_t fssize; /* file system size */ static int sectorsize; /* bytes/sector */ static int fsize; /* fragment size */ @@ -148,6 +149,7 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp) ffs_opt_t *ffs_opts = fsopts->fs_specific; Oflag = ffs_opts->version; + extattr = ffs_opts->extattr; fssize = fsopts->size / fsopts->sectorsize; sectorsize = fsopts->sectorsize; fsize = ffs_opts->fsize; @@ -296,7 +298,10 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp) sblock.fs_old_postblformat = 1; sblock.fs_old_nrpos = 1; } else { - sblock.fs_magic = FS_UFS2_MAGIC; + if (extattr) + sblock.fs_magic = FS_UFS2EA_MAGIC; + else + sblock.fs_magic = FS_UFS2_MAGIC; #if 0 /* XXX makefs is used for small filesystems. */ sblock.fs_sblockloc = SBLOCK_UFS2; #else diff --git a/usr.sbin/makefs/makefs.8 b/usr.sbin/makefs/makefs.8 index 529fbc43eef7..83934adb08e6 100644 --- a/usr.sbin/makefs/makefs.8 +++ b/usr.sbin/makefs/makefs.8 @@ -1,4 +1,4 @@ -.\" $NetBSD: makefs.8,v 1.70 2022/04/06 13:39:06 wiz Exp $ +.\" $NetBSD: makefs.8,v 1.71 2022/11/17 06:40:41 chs Exp $ .\" .\" Copyright (c) 2001-2003 Wasabi Systems, Inc. .\" All rights reserved. @@ -304,6 +304,8 @@ Expected number of files per directory. Block size. .It Sy density Bytes per inode. +.It Sy extattr +UFS2 with extended attributes. .It Sy extent Maximum extent size. .It Sy fsize diff --git a/usr.sbin/quot/quot.c b/usr.sbin/quot/quot.c index 72ca41e8f2e7..d89c1904b0ab 100644 --- a/usr.sbin/quot/quot.c +++ b/usr.sbin/quot/quot.c @@ -1,4 +1,4 @@ -/* $NetBSD: quot.c,v 1.34 2016/07/28 08:24:58 martin Exp $ */ +/* $NetBSD: quot.c,v 1.35 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright (C) 1991, 1994 Wolfgang Solfrank. @@ -33,7 +33,7 @@ #include #ifndef lint -__RCSID("$NetBSD: quot.c,v 1.34 2016/07/28 08:24:58 martin Exp $"); +__RCSID("$NetBSD: quot.c,v 1.35 2022/11/17 06:40:41 chs Exp $"); #endif /* not lint */ #include @@ -569,10 +569,12 @@ quot(const char *name, const char *mp) fs = (struct fs *)superblock; if (fs->fs_magic != FS_UFS1_MAGIC && - fs->fs_magic != FS_UFS2_MAGIC) + fs->fs_magic != FS_UFS2_MAGIC && + fs->fs_magic != FS_UFS2EA_MAGIC) continue; if (fs->fs_magic == FS_UFS2_MAGIC + || fs->fs_magic == FS_UFS2EA_MAGIC || fs->fs_old_flags & FS_FLAGS_UPDATED) { /* Not the main superblock */ if (fs->fs_sblockloc != sbloc) diff --git a/usr.sbin/quotacheck/quotacheck.c b/usr.sbin/quotacheck/quotacheck.c index 12cec5145287..db221f99385c 100644 --- a/usr.sbin/quotacheck/quotacheck.c +++ b/usr.sbin/quotacheck/quotacheck.c @@ -1,4 +1,4 @@ -/* $NetBSD: quotacheck.c,v 1.49 2015/06/16 23:04:14 christos Exp $ */ +/* $NetBSD: quotacheck.c,v 1.50 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright (c) 1980, 1990, 1993 @@ -42,7 +42,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1990, 1993\ #if 0 static char sccsid[] = "@(#)quotacheck.c 8.6 (Berkeley) 4/28/95"; #else -__RCSID("$NetBSD: quotacheck.c,v 1.49 2015/06/16 23:04:14 christos Exp $"); +__RCSID("$NetBSD: quotacheck.c,v 1.50 2022/11/17 06:40:41 chs Exp $"); #endif #endif /* not lint */ @@ -367,6 +367,9 @@ chkquota(const char *type, const char *fsname, const char *mntpt, void *v, bread(sblock_try[i], (char *)&sblock, SBLOCKSIZE); switch (sblock.fs_magic) { #ifdef HAVE_UFSv2 + case FS_UFS2EA_MAGIC: + sblock.fs_magic = FS_UFS2_MAGIC; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC: is_ufs2 = 1; /*FALLTHROUGH*/ @@ -374,6 +377,9 @@ chkquota(const char *type, const char *fsname, const char *mntpt, void *v, case FS_UFS1_MAGIC: break; #ifdef HAVE_UFSv2 + case FS_UFS2EA_MAGIC_SWAPPED: + sblock.fs_magic = FS_UFS2_MAGIC_SWAPPED; + /*FALLTHROUGH*/ case FS_UFS2_MAGIC_SWAPPED: is_ufs2 = 1; /*FALLTHROUGH*/ diff --git a/usr.sbin/sysinst/label.c b/usr.sbin/sysinst/label.c index 013bfe60b90e..31db8b6a42ac 100644 --- a/usr.sbin/sysinst/label.c +++ b/usr.sbin/sysinst/label.c @@ -1,4 +1,4 @@ -/* $NetBSD: label.c,v 1.41 2022/06/21 15:46:10 martin Exp $ */ +/* $NetBSD: label.c,v 1.42 2022/11/17 06:40:41 chs Exp $ */ /* * Copyright 1997 Jonathan Stone @@ -36,7 +36,7 @@ #include #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: label.c,v 1.41 2022/06/21 15:46:10 martin Exp $"); +__RCSID("$NetBSD: label.c,v 1.42 2022/11/17 06:40:41 chs Exp $"); #endif #include @@ -2023,7 +2023,9 @@ get_last_mounted(int fd, daddr_t partstart, uint *fs_type, uint *fs_sub_type, *fs_sub_type = 1; continue; case FS_UFS2_MAGIC: + case FS_UFS2EA_MAGIC: case FS_UFS2_MAGIC_SWAPPED: + case FS_UFS2EA_MAGIC_SWAPPED: /* Check we have the main superblock */ if (SB->fs_sblockloc == *sbp) { mnt = (const char *)SB->fs_fsmnt;