Subject: hard links not metalogged correctly
To: None <tech-toolchain@netbsd.org>
From: Jukka Salmi <j+nbsd@2005.salmi.ch>
List: tech-toolchain
Date: 07/08/2005 17:07:10
--uh9ZiVrAOUUm9fzH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hello,
install(1) currently does not metalog hard links correctly; e.g. syss?tat
entries from my /etc/mtree/set.base look like
./usr/bin/systat type=file mode=02555 uname=root gname=kmem sha1=...
./usr/bin/sysstat type=file mode=0555 sha1=...
Obviously, only the first entry is correct:
$ ls -li /usr/bin/sys*tat
107653 -r-xr-sr-x 2 root kmem 96480 Jul 7 15:43 /usr/bin/sysstat
107653 -r-xr-sr-x 2 root kmem 96480 Jul 7 15:43 /usr/bin/systat
$ mtree -e -p / -f /etc/mtree/set.base
[...]
usr/bin/sysstat:
gid (0, 2)
permissions (0555, 02555)
Two questions about makelink() from src/usr.bin/xinstall/xinstall.c:
- The mode being metalogged for hard links is the mode of the source link
masked with 0777 - shouldn't this be 07777? I.e. why are e.g. the s[ug]id
bits cleared? That's why the mode of entries like the sysstat entry above
is logged wrong (even when running privleged).
- Why are owner, group and fflags ignored?
To fix the problem for privileged installs seems to be easy: just use the
source link's owner, group, permissions, etc.; see attached patch.
For unprivileged installs it's probably more difficult: the source link
is possibly installed with "wrong" owner, group, etc. I see two possible
solutions: either read the METALOG to determine the information about the
source link (probably a bad idea...), or simply pass the information to
install(1) on invocation, as it's done if a regular file is installed,
and don't ignore it when metalogging (see patch).
With the patch applied, install can be used as
$ install -U -M $log -l h -o $owner -g $group -m $mode ... $dest $link
However, I'm not sure about how to implement this in bsd.links.mk; how
do I determine the mode logged for the source link? And how about owner
and group? BINOWN and BINGRP?
Comments are appreciated!
Cheers, Jukka
P.S.: there's a bug in xinstall.c: if more than one flag is specified
(install -f flag1,flag2,...), only the last one is used; that's because
string_to_flags() modifies the pointer and uses strsep(3) on it. Maybe
this should be fixed in src/bin/ls/stat_flags.c, but I didn't check if
any other programs depend on this behaviour. It's probably easier to just
restore the string (see patch).
--
bashian roulette:
$ ((RANDOM%6)) || rm -rf ~
--uh9ZiVrAOUUm9fzH
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="xinstall.c.diff"
Index: xinstall.c
===================================================================
RCS file: /cvsroot/src/usr.bin/xinstall/xinstall.c,v
retrieving revision 1.91
diff -u -p -r1.91 xinstall.c
--- xinstall.c 11 Jun 2005 22:59:05 -0000 1.91
+++ xinstall.c 8 Jul 2005 14:49:53 -0000
@@ -270,8 +270,9 @@ main(int argc, char *argv[])
if ((dostrip || dolink) && dodir)
usage();
- /* strip and flags make no sense with links */
- if ((dostrip || fflags) && dolink)
+ /* strip and flags make no sense with links, but allow flags if
+ running unprivileged */
+ if ((dostrip || (fflags && !dounpriv)) && dolink)
usage();
/* must have at least two arguments, except when creating directories */
@@ -310,6 +311,8 @@ main(int argc, char *argv[])
if (fflags && !dounpriv) {
if (string_to_flags(&fflags, &fileflags, NULL))
errx(1, "%s: invalid flag", fflags);
+ /* restore fflags since string_to_flags() changed it */
+ fflags = flags_to_string(fileflags, "-");
iflags |= SETFLAGS;
}
#endif
@@ -468,15 +471,26 @@ makelink(char *from_name, char *to_name)
char *oowner, *ogroup, *offlags;
char *dres;
+ if (!dounpriv) {
/* XXX: use underlying perms */
- omode = mode;
- mode = (to_sb.st_mode & 0777);
- oowner = owner;
- owner = NULL;
- ogroup = group;
- group = NULL;
- offlags = fflags;
- fflags = NULL;
+ omode = mode;
+ mode = (to_sb.st_mode & 07777);
+ oowner = owner;
+ owner = (char *)user_from_uid(
+ to_sb.st_uid, 0);
+ ogroup = group;
+ group = (char *)group_from_gid(
+ to_sb.st_gid, 0);
+ offlags = fflags;
+ fflags = NULL;
+#if ! HAVE_NBTOOL_CONFIG_H
+ fflags = flags_to_string(
+ to_sb.st_flags, "-");
+ if (strcmp(fflags, "-") == 0)
+ fflags = NULL;
+#endif
+ }
+
switch (digesttype) {
case DIGEST_MD5:
dres = MD5File(from_name, NULL);
@@ -492,10 +506,13 @@ makelink(char *from_name, char *to_name)
}
metadata_log(to_name, "file", NULL, NULL, dres);
free(dres);
- mode = omode;
- owner = oowner;
- group = ogroup;
- fflags = offlags;
+
+ if (!dounpriv) {
+ mode = omode;
+ owner = oowner;
+ group = ogroup;
+ fflags = offlags;
+ }
}
return;
}
--uh9ZiVrAOUUm9fzH--