Skip to content
Browse files

Add some devfs code that's been sitting in my local tree for a while.

devfsd(8) is now the first daemon to be started after init(8). It tracks
device insertion (will eventually track removal) and devfs mounts.

Currently, we can mount multiple device file systems and have device
special files pushed into the mounts automatically, though, the device
special files aren't created with the correct major/minor number pairs
yet.

More work to come soon.
  • Loading branch information...
1 parent 2ad592d commit 664207d69ba85e3e0e8a3d87a718733e8134df95 mjf committed Feb 18, 2008
Showing with 30,061 additions and 442 deletions.
  1. +4,132 −0 distrib/sets/lists/base/mi
  2. +12,571 −0 distrib/sets/lists/comp/mi
  3. +351 −0 distrib/sets/lists/etc/mi
  4. +5,097 −0 distrib/sets/lists/man/mi
  5. +627 −0 etc/Makefile
  6. +3 −1 etc/defaults/rc.conf
  7. 0 sbin/devfsd/test.cfg → etc/devfsd.conf
  8. +2 −2 etc/rc.d/Makefile
  9. +30 −0 etc/rc.d/devfsd
  10. +2 −1 etc/rc.d/wdogctl
  11. +2 −1 sbin/Makefile
  12. +5 −3 sbin/devfsd/Makefile
  13. +81 −0 sbin/devfsd/devfsd.8
  14. +290 −61 sbin/devfsd/devfsd.c
  15. +73 −38 sbin/devfsd/devfsd.h
  16. +131 −39 sbin/devfsd/devfsd_dev.c
  17. +82 −0 sbin/devfsd/devfsd_mount.c
  18. +161 −18 sbin/devfsd/devfsd_rule.c
  19. +3 −3 sbin/devfsd/pathnames.h
  20. +17 −0 sbin/mount_devfs/Makefile
  21. +134 −0 sbin/mount_devfs/mount_devfs.8
  22. +212 −0 sbin/mount_devfs/mount_devfs.c
  23. +5 −1 sys/conf/files
  24. +2 −1 sys/conf/majors
  25. +4 −4 sys/dev/Makefile
  26. +8 −0 sys/dev/dctl/Makefile
  27. +557 −0 sys/dev/dctl/dctl.c
  28. +39 −0 sys/dev/dctl/dctl.h
  29. +125 −0 sys/dev/dctl/dctlio.h
  30. +47 −0 sys/dev/dctl/dctlvar.h
  31. +4 −0 sys/dev/dctl/files.dctl
  32. +0 −7 sys/fs/devfs/Makefile
  33. +8 −0 sys/fs/devfs/README
  34. +20 −0 sys/fs/devfs/TODO
  35. +494 −30 sys/fs/devfs/devfs.h
  36. +245 −0 sys/fs/devfs/devfs_comm.c
  37. +38 −0 sys/fs/devfs/devfs_comm.h
  38. +170 −0 sys/fs/devfs/devfs_fifoops.c
  39. +130 −0 sys/fs/devfs/devfs_fifoops.h
  40. +321 −0 sys/fs/devfs/devfs_pool.c
  41. +148 −0 sys/fs/devfs/devfs_pool.h
  42. +171 −0 sys/fs/devfs/devfs_specops.c
  43. +131 −0 sys/fs/devfs/devfs_specops.h
  44. +1,347 −0 sys/fs/devfs/devfs_subr.c
  45. +400 −73 sys/fs/devfs/devfs_vfsops.c
  46. +1,496 −153 sys/fs/devfs/devfs_vnops.c
  47. +130 −0 sys/fs/devfs/devfs_vnops.h
  48. +6 −1 sys/fs/devfs/files.devfs
  49. +2 −1 sys/sys/device.h
  50. +2 −1 sys/sys/mount.h
  51. +5 −3 sys/sys/vnode.h
View
4,132 distrib/sets/lists/base/mi
4,132 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
12,571 distrib/sets/lists/comp/mi
12,571 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
351 distrib/sets/lists/etc/mi
@@ -0,0 +1,351 @@
+# $NetBSD: mi,v 1.197.2.2 2008/02/18 22:07:01 mjf Exp $
+#
+# Note: end-user configuration files that are moved to another location
+# should not be marked "obsolete"; they should just be removed from
+# the set list, a custom fix should be added to postinstall(8), and
+# an item should be added to src/UPDATING for MKUPDATE=yes users.
+# This is an exception to the general rule that moved/removed files
+# are marked as "obsolete", because we don't want to arbitrarily
+# remove end-user configuration files.
+#
+./.cshrc etc-util-etc
+./.profile etc-util-etc
+./dev/MAKEDEV etc-sys-etc
+./dev/MAKEDEV.local etc-sys-etc
+./dev/MAKEDEV.subr etc-obsolete obsolete
+./etc/atf/NetBSD.conf etc-atf-etc
+./etc/atf/atf-run.hooks etc-atf-etc
+./etc/audit-packages.conf etc-util-etc
+./etc/bootptab etc-bootserver-etc
+./etc/changelist etc-sys-etc
+./etc/csh.cshrc etc-util-etc
+./etc/csh.login etc-util-etc
+./etc/csh.logout etc-util-etc
+./etc/bluetooth etc-sys-etc
+./etc/bluetooth/bluetooth.conf etc-obsolete obsolete
+./etc/bluetooth/btdevctl.conf etc-sys-etc
+./etc/bluetooth/btuartd.conf etc-sys-etc
+./etc/bluetooth/hosts etc-sys-etc
+./etc/bluetooth/protocols etc-sys-etc
+./etc/daily etc-sys-etc
+./etc/daily.conf etc-sys-etc
+./etc/default etc-obsolete obsolete
+./etc/default/daily.conf etc-obsolete obsolete
+./etc/default/monthly.conf etc-obsolete obsolete
+./etc/default/rc.conf etc-obsolete obsolete
+./etc/default/security.conf etc-obsolete obsolete
+./etc/default/weekly.conf etc-obsolete obsolete
+./etc/defaults/daily.conf etc-sys-defaults
+./etc/defaults/monthly.conf etc-sys-defaults
+./etc/defaults/pf.boot.conf etc-pf-defaults pf
+./etc/defaults/rc.conf etc-sys-defaults
+./etc/defaults/security.conf etc-sys-defaults
+./etc/defaults/weekly.conf etc-sys-defaults
+./etc/devfsd.conf etc-sysutil-etc
+./etc/dhclient-script etc-obsolete obsolete
+./etc/disktab etc-sysutil-etc
+./etc/dm.conf etc-games-etc
+./etc/dumpdates etc-sysutil-etc
+./etc/envsys.conf etc-sysutil-etc
+./etc/floppytab etc-sysutil-etc
+./etc/fstab.nfs etc-obsolete obsolete
+./etc/fstab.sd etc-obsolete obsolete
+./etc/fstab.sd0 etc-obsolete obsolete
+./etc/fstab.sd1 etc-obsolete obsolete
+./etc/fstab.sd2 etc-obsolete obsolete
+./etc/fstab.sd3 etc-obsolete obsolete
+./etc/fstab.sd4 etc-obsolete obsolete
+./etc/fstab.sd5 etc-obsolete obsolete
+./etc/fstab.sd6 etc-obsolete obsolete
+./etc/fstab.sd7 etc-obsolete obsolete
+./etc/fstab.tmp etc-obsolete obsolete
+./etc/fstab.wd etc-obsolete obsolete
+./etc/ftpchroot etc-netutil-etc
+./etc/ftpusers etc-netutil-etc
+./etc/gettytab etc-sysutil-etc
+./etc/group etc-sys-etc
+./etc/hosts etc-net-etc
+./etc/hosts.equiv etc-netutil-etc
+./etc/hosts.lpd etc-lpr-etc
+./etc/inetd.conf etc-netutil-etc
+./etc/iscsi/auths etc-iscsi-etc iscsi
+./etc/iscsi/targets etc-iscsi-etc iscsi
+./etc/lkm.conf etc-sys-etc
+./etc/localtime etc-sys-etc
+./etc/locate.conf etc-sys-etc
+./etc/login.conf etc-sys-etc
+./etc/mail.rc etc-mail-etc
+./etc/mail/aliases etc-postfix-etc postfix
+./etc/mailer.conf etc-mailwrapper-etc
+./etc/man.conf etc-man-etc
+./etc/master.passwd etc-sys-etc
+./etc/moduli etc-secsh-etc crypto
+./etc/monthly etc-sys-etc
+./etc/monthly.conf etc-sys-etc
+./etc/motd etc-sys-etc
+./etc/mrouted.conf etc-router-etc
+./etc/mtree/NetBSD.dist etc-sys-etc
+./etc/mtree/set.etc etc-sys-etc
+./etc/mtree/special etc-sys-etc
+./etc/named.conf etc-bind-etc
+./etc/namedb/127 etc-bind-etc
+./etc/namedb/localhost etc-bind-etc
+./etc/namedb/loopback.v6 etc-bind-etc
+./etc/namedb/root.cache etc-bind-etc
+./etc/netconfig etc-net-etc
+./etc/networks etc-net-etc
+./etc/newsyslog.conf etc-sysutil-etc
+./etc/nsswitch.conf etc-net-etc
+./etc/ntp.conf etc-ntp-etc
+./etc/obsolete/base etc-obsolete obsolete
+./etc/obsolete/comp etc-obsolete obsolete
+./etc/obsolete/etc etc-obsolete obsolete
+./etc/obsolete/games etc-obsolete obsolete
+./etc/obsolete/man etc-obsolete obsolete
+./etc/obsolete/misc etc-obsolete obsolete
+./etc/obsolete/text etc-obsolete obsolete
+./etc/pam.d/README etc-sys-etc
+./etc/pam.d/display_manager etc-sys-etc
+./etc/pam.d/ftpd etc-sys-etc
+./etc/pam.d/gdm etc-sys-etc
+./etc/pam.d/imap etc-sys-etc
+./etc/pam.d/kde etc-sys-etc
+./etc/pam.d/login etc-sys-etc
+./etc/pam.d/other etc-sys-etc
+./etc/pam.d/passwd etc-sys-etc
+./etc/pam.d/pop3 etc-sys-etc
+./etc/pam.d/ppp etc-sys-etc
+./etc/pam.d/rexecd etc-sys-etc
+./etc/pam.d/rsh etc-sys-etc
+./etc/pam.d/sshd etc-sys-etc
+./etc/pam.d/su etc-sys-etc
+./etc/pam.d/system etc-sys-etc
+./etc/pam.d/telnetd etc-sys-etc
+./etc/pam.d/xdm etc-sys-etc
+./etc/pam.d/xserver etc-sys-etc
+./etc/passwd etc-sys-etc
+./etc/passwd.conf etc-sys-etc
+./etc/pf.conf etc-pf-etc pf
+./etc/pf.os etc-pf-etc pf
+./etc/phones etc-sys-etc
+./etc/postfix/README etc-postfix-etc postfix
+./etc/postfix/main.cf etc-postfix-etc postfix
+./etc/postfix/master.cf etc-postfix-etc postfix
+./etc/postfix/post-install etc-postfix-etc postfix
+./etc/postfix/postfix-files etc-postfix-etc postfix
+./etc/postfix/postfix-script etc-postfix-etc postfix
+./etc/postinstall etc-obsolete obsolete
+./etc/powerd/scripts/acadapter etc-sysutil-etc
+./etc/powerd/scripts/hotkey_button etc-sysutil-etc
+./etc/powerd/scripts/lid_switch etc-sysutil-etc
+./etc/powerd/scripts/power_button etc-sysutil-etc
+./etc/powerd/scripts/reset_button etc-sysutil-etc
+./etc/powerd/scripts/sensor_battery etc-sysutil-etc
+./etc/powerd/scripts/sensor_drive etc-sysutil-etc
+./etc/powerd/scripts/sensor_fan etc-sysutil-etc
+./etc/powerd/scripts/sensor_indicator etc-sysutil-etc
+./etc/powerd/scripts/sensor_power etc-sysutil-etc
+./etc/powerd/scripts/sensor_resistance etc-sysutil-etc
+./etc/powerd/scripts/sensor_temperature etc-sysutil-etc
+./etc/powerd/scripts/sensor_voltage etc-sysutil-etc
+./etc/powerd/scripts/sleep_button etc-sysutil-etc
+./etc/primes etc-obsolete obsolete
+./etc/printcap etc-lpr-etc
+./etc/profile etc-util-etc
+./etc/protocols etc-net-etc
+./etc/pwd.db etc-sys-etc
+./etc/rbootd.conf etc-bootserver-etc
+./etc/rc etc-sys-rc
+./etc/rc.conf etc-sys-rc
+./etc/rc.d/DAEMON etc-sys-rc
+./etc/rc.d/LOGIN etc-sys-rc
+./etc/rc.d/NETWORK etc-obsolete obsolete
+./etc/rc.d/NETWORKING etc-sys-rc
+./etc/rc.d/SERVERS etc-sys-rc
+./etc/rc.d/accounting etc-sys-rc
+./etc/rc.d/altqd etc-router-rc
+./etc/rc.d/amd etc-amd-rc
+./etc/rc.d/apmd etc-sys-rc
+./etc/rc.d/bootconf.sh etc-sys-rc
+./etc/rc.d/bootparams etc-bootserver-rc
+./etc/rc.d/btconfig etc-sys-rc
+./etc/rc.d/btcontrol etc-obsolete obsolete
+./etc/rc.d/btdevctl etc-sys-rc
+./etc/rc.d/bthcid etc-sys-rc
+./etc/rc.d/btuartd etc-sys-rc
+./etc/rc.d/ccd etc-sys-rc
+./etc/rc.d/cgd etc-sys-rc
+./etc/rc.d/cleartmp etc-sys-rc
+./etc/rc.d/cron etc-cron-rc
+./etc/rc.d/devfsd etc-sys-rc
+./etc/rc.d/dhclient etc-dhclient-rc
+./etc/rc.d/dhcpd etc-dhcpd-rc
+./etc/rc.d/dhcrelay etc-dhcpd-rc
+./etc/rc.d/dmesg etc-sys-rc
+./etc/rc.d/downinterfaces etc-sys-rc
+./etc/rc.d/envsys etc-sys-rc
+./etc/rc.d/fixsb etc-obsolete obsolete
+./etc/rc.d/fsck etc-sys-rc
+./etc/rc.d/fsck.sh etc-obsolete obsolete
+./etc/rc.d/ftpd etc-net-rc
+./etc/rc.d/hostapd etc-net-rc
+./etc/rc.d/gated etc-obsolete obsolete
+./etc/rc.d/identd etc-net-rc
+./etc/rc.d/ifwatchd etc-net-rc
+./etc/rc.d/inetd etc-net-rc
+./etc/rc.d/ipfilter etc-ipf-rc
+./etc/rc.d/ipfs etc-ipf-rc
+./etc/rc.d/ipmon etc-ipf-rc
+./etc/rc.d/ipnat etc-ipf-rc
+./etc/rc.d/ipsec etc-net-rc
+./etc/rc.d/irdaattach etc-sys-rc
+./etc/rc.d/iscsi_target etc-iscsi-rc
+./etc/rc.d/isdnd etc-isdn-rc
+./etc/rc.d/kdc etc-krb5-rc
+./etc/rc.d/kerberos etc-obsolete obsolete
+./etc/rc.d/ldconfig etc-sys-rc
+./etc/rc.d/lkm1 etc-sys-rc
+./etc/rc.d/lkm2 etc-sys-rc
+./etc/rc.d/lkm3 etc-sys-rc
+./etc/rc.d/local etc-sys-rc
+./etc/rc.d/lpd etc-lpr-rc
+./etc/rc.d/mixerctl etc-audio-rc
+./etc/rc.d/mopd etc-bootserver-rc
+./etc/rc.d/motd etc-sys-rc
+./etc/rc.d/mountall etc-sys-rc
+./etc/rc.d/mountcritlocal etc-sys-rc
+./etc/rc.d/mountcritremote etc-sys-rc
+./etc/rc.d/mountd etc-nfsserver-rc
+./etc/rc.d/moused etc-sysutil-rc
+./etc/rc.d/mrouted etc-router-rc
+./etc/rc.d/named etc-bind-rc
+./etc/rc.d/ndbootd etc-bootserver-rc
+./etc/rc.d/network etc-net-rc
+./etc/rc.d/newsyslog etc-sys-rc
+./etc/rc.d/nfsd etc-nfsserver-rc
+./etc/rc.d/nfslocking etc-nfsserver-rc
+./etc/rc.d/ntpd etc-ntp-rc
+./etc/rc.d/ntpdate etc-ntp-rc
+./etc/rc.d/perusertmp etc-sys-rc
+./etc/rc.d/pf etc-net-rc
+./etc/rc.d/pf_boot etc-net-rc
+./etc/rc.d/pflogd etc-net-rc
+./etc/rc.d/poffd etc-sys-rc
+./etc/rc.d/postfix etc-postfix-rc
+./etc/rc.d/powerd etc-sysutil-rc
+./etc/rc.d/ppp etc-ppp-rc
+./etc/rc.d/pwcheck etc-sys-rc
+./etc/rc.d/quota etc-sys-rc
+./etc/rc.d/racoon etc-net-rc
+./etc/rc.d/raidframe etc-sys-rc
+./etc/rc.d/raidframeparity etc-sys-rc
+./etc/rc.d/rarpd etc-bootserver-rc
+./etc/rc.d/rbootd etc-bootserver-rc
+./etc/rc.d/root etc-sys-rc
+./etc/rc.d/route6d etc-router-rc
+./etc/rc.d/routed etc-router-rc
+./etc/rc.d/rpcbind etc-rpcbind-rc
+./etc/rc.d/rtadvd etc-net-rc
+./etc/rc.d/rtclocaltime etc-sys-rc
+./etc/rc.d/rtsold etc-net-rc
+./etc/rc.d/rwho etc-net-rc
+./etc/rc.d/savecore etc-sys-rc
+./etc/rc.d/screenblank etc-sys-rc
+./etc/rc.d/sdpd etc-sys-rc
+./etc/rc.d/securelevel etc-sys-rc
+./etc/rc.d/sshd etc-secsh-rc
+./etc/rc.d/staticroute etc-sys-rc
+./etc/rc.d/swap1 etc-sys-rc
+./etc/rc.d/swap2 etc-sys-rc
+./etc/rc.d/sysctl etc-sys-rc
+./etc/rc.d/sysdb etc-sys-rc
+./etc/rc.d/syslogd etc-sys-rc
+./etc/rc.d/systemfs etc-obsolete obsolete
+./etc/rc.d/timed etc-timed-rc
+./etc/rc.d/tpctl etc-sys-rc
+./etc/rc.d/ttys etc-sys-rc
+./etc/rc.d/veriexec etc-sys-rc
+./etc/rc.d/virecover etc-sys-rc
+./etc/rc.d/wdogctl etc-sysutil-rc
+./etc/rc.d/wpa_supplicant etc-net-rc
+./etc/rc.d/wscons etc-sys-rc
+./etc/rc.d/wsmoused etc-sys-rc
+./etc/rc.d/xdm etc-x11-rc
+./etc/rc.d/xfs etc-x11-rc
+./etc/rc.d/xntpd etc-obsolete obsolete
+./etc/rc.d/ypbind etc-nis-rc
+./etc/rc.d/yppasswdd etc-nis-rc
+./etc/rc.d/ypserv etc-nis-rc
+./etc/rc.d/ypset etc-obsolete obsolete
+./etc/rc.lkm etc-sys-rc
+./etc/rc.local etc-sys-rc
+./etc/rc.shutdown etc-sys-rc
+./etc/rc.subr etc-sys-rc
+./etc/rc.wscons etc-obsolete obsolete
+./etc/release-info etc-obsolete obsolete
+./etc/remote etc-sys-etc
+./etc/rmt etc-sysutil-etc
+./etc/rpc etc-net-etc
+./etc/security etc-sys-etc
+./etc/security.conf etc-sys-etc
+./etc/services etc-net-etc
+./etc/shells etc-sys-etc
+./etc/shrc etc-util-etc
+./etc/skel/.cshrc etc-sys-etc
+./etc/skel/.login etc-sys-etc
+./etc/skel/.logout etc-sys-etc
+./etc/skel/.profile etc-sys-etc
+./etc/skel/.shrc etc-sys-etc
+./etc/skeykeys etc-sys-etc
+./etc/spamd.conf etc-obsolete obsolete
+./etc/spwd.db etc-sys-etc
+./etc/ssh/ssh_config etc-secsh-etc crypto
+./etc/ssh/ssh_known_hosts etc-secsh-etc crypto
+./etc/ssh/sshd_config etc-secsh-etc crypto
+./etc/sysctl.conf etc-sys-etc
+./etc/syslog.conf etc-sys-etc
+./etc/ttys etc-sys-etc
+./etc/weekly etc-sys-etc
+./etc/weekly.conf etc-sys-etc
+./etc/wscons.conf etc-sys-etc
+./root/.cshrc etc-root-root
+./root/.klogin etc-root-root
+./root/.login etc-root-root
+./root/.profile etc-root-root
+./root/.shrc etc-root-root
+./var/at/at.deny etc-cron-root
+./var/crash/minfree etc-sys-root
+./var/cron/tabs/root etc-cron-root
+./var/db/locate.database etc-sys-root
+./var/games/atc_score etc-games-scores
+./var/games/battlestar.log etc-games-scores
+./var/games/cfscores etc-games-scores
+./var/games/criblog etc-games-scores
+./var/games/hackdir/record etc-games-scores
+./var/games/larn/llog12.0 etc-games-scores
+./var/games/larn/lscore12.0 etc-games-scores
+./var/games/larn/playerids etc-games-scores
+./var/games/phantasia/characs etc-games-scores
+./var/games/phantasia/scoreboard etc-games-scores
+./var/games/robots_roll etc-games-scores
+./var/games/rogue.scores etc-games-scores
+./var/games/saillog etc-games-scores
+./var/games/snake.log etc-games-scores
+./var/games/snakerawscores etc-games-scores
+./var/games/tetris.scores etc-games-scores
+./var/log/authlog etc-sys-log
+./var/log/cron etc-cron-log
+./var/log/lastlog etc-sys-log
+./var/log/lastlogx etc-sys-log
+./var/log/lpd-errs etc-lpr-log
+./var/log/maillog etc-sendmail-log
+./var/log/messages etc-sys-log
+./var/log/secure etc-sys-log
+./var/log/wtmp etc-sys-log
+./var/log/wtmpx etc-sys-log
+./var/log/xferlog etc-netutil-log
+./var/msgs/bounds etc-sysutil-log
+./var/run/utmp etc-sys-log
+./var/run/utmpx etc-sys-log
+./var/yp/Makefile.main etc-nis-root yp
+./var/yp/Makefile.yp etc-nis-root yp
View
5,097 distrib/sets/lists/man/mi
5,097 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
627 etc/Makefile
@@ -0,0 +1,627 @@
+# $NetBSD: Makefile,v 1.348.4.2 2008/02/18 22:07:01 mjf Exp $
+# from: @(#)Makefile 8.7 (Berkeley) 5/25/95
+
+# Environment variables without default values:
+# DESTDIR must be set before anything in this file will work.
+# RELEASEDIR is where the tarred up stuff for a snapshot or
+# release will be placed.
+#
+# Environment variables with default values:
+# LOCALTIME will set the default local time for the system you
+# build; it determines what /etc/localtime is symlink'd to.
+# KERNSRCDIR points to kernel source; it is set by default to ../sys,
+# but can be overridden.
+# KERNOBJDIR is the kernel build directory, it defaults to
+# ${KERNSRCDIR}/arch/${MACHINE}/compile, but can be overridden.
+# KERNCONFDIR is where the configuration files for kernels are found;
+# default is ${KERNSRCDIR}/arch/${MACHINE}/conf but can be overridden.
+# MKCRYPTO; if not `no', install crypto-related configuration
+# MKPOSTFIX; if not `no', install postfix configuration
+# MKUNPRIVED; if not `no', allow non-root installs.
+# MKUPDATE; if not `no', don't do a 'make clean' before kernel compile
+#
+# Targets:
+# distribution: makes a full NetBSD distribution in DESTDIR. If
+# INSTALL_DONE is set, it will not do a `make install.'
+# if DISTRIBUTION_DONE is set, it will not do anything.
+# distrib-dirs: creates an empty NetBSD directory tree in DESTDIR.
+# Called by distribution.
+# snapshot: calls distribution, above, and then tars up the files
+# into a release(7) format in RELEASEDIR/${RELEASEMACHINEDIR}.
+# Any port-dependent stuff for this target is found in
+# etc.${MACHINE}/Makefile.inc.
+# release: a synonym for `snapshot'
+#
+
+# For MK* vars
+.include <bsd.own.mk>
+
+.include <bsd.sys.mk> # for HOST_SH
+.include <bsd.kernobj.mk> # For KERNSRCDIR, KERNOBJDIR, ...
+.include <bsd.endian.mk> # For TARGET_ENDIANNESS
+
+.MAKEOVERRIDES+= USETOOLS
+
+TZDIR= /usr/share/zoneinfo
+LOCALTIME?= UTC
+CKSUM?= ${TOOL_CKSUM}
+MAKESUMS= MAKE=${MAKE:Q} CKSUM=${CKSUM:Q} ${HOST_SH} ${NETBSDSRCDIR}/distrib/sets/makesums
+DISTRIBVER!= ${HOST_SH} ${NETBSDSRCDIR}/sys/conf/osrelease.sh
+
+# Flags for creating ISO CDROM image
+# mkisofs is expected to be in $PATH, install via pkgsrc/sysutils/cdrtools
+# Note: At least mkisofs 2.0 should be used.
+#
+.if !defined(MKISOFS)
+MKISOFS!= (which mkisofs || echo true)
+.endif
+DISTRIBREV!= ${HOST_SH} ${KERNSRCDIR}/conf/osrelease.sh -s
+# ISO 9660 volume ID. Note that this can only contain [A-Z0-9_].
+ISO_VOLID!= echo NETBSD_${DISTRIBREV} | tr a-z A-Z
+MKISOFS_FLAGS+= -J -l -hide-joliet-trans-tbl -r -T \
+ -V ${ISO_VOLID} \
+ -publisher "The NetBSD Project" \
+ -m "${RELEASEDIR}/${RELEASEMACHINEDIR}/installation/cdrom"
+.if ${MKISOFS_FLAGS:N-v}
+MKISOFS_FLAGS+= -quiet
+.endif
+
+
+# MD Makefile.inc may append MD targets to BIN[123]. Make sure all
+# are empty, to preserve the old semantics of setting them below with "+=".
+#
+BIN1=
+BIN2=
+BIN3=
+
+# Directories to build in ${RELEASEDIR}/${RELEASEMACHINEDIR}.
+# MD Makefile.inc files can add to this.
+# NOTE: Parent directories must be listed before subdirectories.
+#
+INSTALLATION_DIRS= binary binary/sets binary/kernel installation
+
+.if exists(etc.${RELEASEMACHINE}/Makefile.inc)
+.include "etc.${RELEASEMACHINE}/Makefile.inc"
+.endif
+
+# -rw-r--r--
+BINOWN= root
+BINGRP= wheel
+UTMPGRP= utmp
+BIN1+= audit-packages.conf bootptab changelist csh.cshrc csh.login \
+ csh.logout daily daily.conf devfsd.conf dm.conf envsys.conf \
+ floppytab ftpchroot \
+ ftpusers gettytab group hosts hosts.lpd inetd.conf lkm.conf \
+ locate.conf login.conf mailer.conf man.conf monthly monthly.conf \
+ mrouted.conf named.conf netconfig networks newsyslog.conf \
+ nsswitch.conf ntp.conf passwd.conf phones printcap profile protocols \
+ rbootd.conf rc rc.conf rc.lkm rc.local rc.subr rc.shutdown remote rpc \
+ security security.conf services shells shrc sysctl.conf syslog.conf \
+ weekly weekly.conf wscons.conf
+
+# Use machine-specific disktab if it exists, or the MI one otherwise
+.if exists(etc.${MACHINE}/disktab)
+BIN1+= etc.${MACHINE}/disktab
+.else
+BIN1+= disktab
+.endif
+
+.if exists(etc.${MACHINE}/ld.so.conf)
+BIN1+= etc.${MACHINE}/ld.so.conf
+.endif
+
+.if exists(etc.${MACHINE}/ttyaction)
+BIN1+= etc.${MACHINE}/ttyaction
+.endif
+
+# -rw-rw-r--
+.if !empty(DISTRIBVER:M*.99.*)
+BIN2+= motd.current
+FILESNAME_motd.current= motd
+.elif !empty(DISTRIBVER:M*BETA*)
+BIN2+= motd.beta
+FILESNAME_motd.beta= motd
+.elif !empty(DISTRIBVER:M*RC*)
+BIN2+= motd.rc
+FILESNAME_motd.rc= motd
+.elif !empty(DISTRIBVER:M*STABLE*)
+BIN2+= motd.stable
+FILESNAME_motd.stable= motd
+.else
+BIN2+= motd
+.endif
+
+# -rw-------
+BIN3+= hosts.equiv
+
+SYSPKG= etc
+ETC_PKG=-T etc_pkg
+BASE_PKG=-T base_pkg
+ETC_INSTALL_FILE=cd ${.CURDIR} && ${INSTALL_FILE} ${ETC_PKG}
+ETC_INSTALL_OBJ_FILE=cd ${.OBJDIR} && ${INSTALL_FILE} ${ETC_PKG}
+
+.if ${TARGET_ENDIANNESS} == "1234"
+PWD_MKDB_ENDIAN= -L
+.elif ${TARGET_ENDIANNESS} == "4321"
+PWD_MKDB_ENDIAN= -B
+.else
+PWD_MKDB_ENDIAN=
+.endif
+
+
+# distribution --
+# Build a distribution
+#
+distribution: .PHONY .MAKE check_DESTDIR distrib-dirs
+.if !defined(DISTRIBUTION_DONE)
+.if !defined(INSTALL_DONE)
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR} include _DISTRIB=
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR} install _DISTRIB=
+.endif # !INSTALL_DONE
+ ${MAKEDIRTARGET} . install-etc-files
+.if ${MKX11} != "no"
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/x11 distribution
+.endif
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/distrib/sets makesetfiles
+.endif # !DISTRIBUTION_DONE
+
+
+CLEANFILES+= MAKEDEV
+MAKEDEV: .EXEC
+ ${_MKTARGET_CREATE}
+ MACHINE=${MACHINE:Q} MACHINE_ARCH=${MACHINE_ARCH:Q} \
+ NETBSDSRCDIR=${NETBSDSRCDIR:Q} \
+ awk -f ${.CURDIR}/MAKEDEV.awk ${.CURDIR}/MAKEDEV.tmpl > ${.TARGET}
+
+RELEASEVARS= BSDOBJDIR BSDSRCDIR BUILDID \
+ DESTDIR EXTERNAL_TOOLCHAIN HAVE_GCC HAVE_GDB \
+ INSTALLWORLDDIR \
+ KERNARCHDIR KERNCONFDIR KERNOBJDIR KERNSRCDIR \
+ MACHINE MACHINE_ARCH MAKE MAKECONF MAKEFLAGS \
+ MAKEOBJDIR MAKEOBJDIRPREFIX MAKEVERBOSE \
+ MKBFD MKCATPAGES \
+ MKCRYPTO MKCRYPTO_IDEA MKCRYPTO_MDC2 MKCRYPTO_RC5 MKCVS \
+ MKDEBUG MKDEBUGLIB MKDOC MKDYNAMICROOT \
+ MKGCC MKGCCCMDS MKGDB \
+ MKHESIOD MKHOSTOBJ MKHTML MKIEEEFP MKINET6 MKINFO MKIPFILTER \
+ MKKERBEROS MKLINKLIB MKLINT \
+ MKMAN MKMANZ MKNLS MKOBJ MKOBJDIRS \
+ MKPAM MKPF MKPIC MKPICINSTALL MKPICLIB MKPOSTFIX MKPROFILE \
+ MKSHARE MKSKEY MKSOFTFLOAT MKSTATICLIB \
+ MKUNPRIVED MKUPDATE MKX11 MKYP \
+ NBUILDJOBS NETBSDSRCDIR \
+ NOCLEANDIR NODISTRIBDIRS NOINCLUDES \
+ OBJMACHINE \
+ RELEASEDIR TOOLCHAIN_MISSING TOOLDIR \
+ USETOOLS USR_OBJMACHINE \
+ X11SRCDIR
+
+params: .PHONY
+.for var in ${RELEASEVARS}
+.if defined(${var})
+ @printf "%20s = '%-s'\n" ${var} ${${var}:Q}
+.else
+ @printf "%20s = (undefined)\n" ${var}
+.endif
+.endfor
+
+CLEANFILES+= etc-release
+etc-release: .EXEC .MAKE
+ ${_MKTARGET_CREATE}
+ @( echo "NetBSD ${DISTRIBVER}/${MACHINE}"; \
+ echo ; \
+ cat ${NETBSDSRCDIR}/sys/conf/copyright; \
+ echo ; \
+ echo "Build settings:"; \
+ printf "%20s %s\n" "Build date" "$$(date -u)"; \
+ printf "%20s %s\n" "Built by" "$${USER-root}@$$(hostname)"; \
+ echo ; \
+ (cd ${.CURDIR}; ${MAKE} ${MFLAGS} -j1 params); \
+ ) >${.OBJDIR}/${.TARGET}
+
+install-etc-release: .PHONY etc-release
+ ${_MKMSG_INSTALL} etc/release
+ ${ETC_INSTALL_OBJ_FILE} -o ${BINOWN} -g ${BINGRP} -m 444 \
+ etc-release ${DESTDIR}/etc/release
+
+
+FILESDIR= /etc
+CONFIGFILES=
+CONFIGSYMLINKS=
+
+.for file in ${BIN1}
+CONFIGFILES+= ${file}
+FILESMODE_${file:T}= 644
+.endfor
+
+.for file in ${BIN2}
+CONFIGFILES+= ${file}
+FILESMODE_${file:T}= 664
+.endfor
+
+.for file in ${BIN3}
+CONFIGFILES+= ${file}
+FILESMODE_${file:T}= 600
+.endfor
+
+.if (${MKPOSTFIX} != "no")
+CONFIGFILES+= aliases
+FILESDIR_aliases= /etc/mail
+FILESMODE_aliases= 644
+.endif
+
+CONFIGFILES+= MAKEDEV.local
+FILESDIR_MAKEDEV.local= /dev
+FILESMODE_MAKEDEV.local=${BINMODE}
+
+CONFIGFILES+= crontab
+FILESDIR_crontab= /var/cron/tabs
+FILESNAME_crontab= root
+FILESMODE_crontab= 600
+
+CONFIGFILES+= minfree
+FILESDIR_minfree= /var/crash
+FILESMODE_minfree= 600
+
+CONFIGSYMLINKS+= ${TZDIR}/${LOCALTIME} /etc/localtime \
+ /usr/sbin/rmt /etc/rmt
+
+
+# install-etc-files --
+# Install etc (config) files; not performed by "make build"
+#
+install-etc-files: .PHONY .MAKE check_DESTDIR MAKEDEV
+ ${_MKMSG_INSTALL} ${DESTDIR}/etc/master.passwd
+ ${ETC_INSTALL_FILE} -o root -g wheel -m 600 \
+ master.passwd ${DESTDIR}/etc
+ ${TOOL_PWD_MKDB} -p ${PWD_MKDB_ENDIAN} -d ${DESTDIR}/ \
+ ${DESTDIR}/etc/master.passwd
+.if ${MKUNPRIVED} != "no"
+ ( \
+ for metaent in passwd pwd.db spwd.db; do \
+ echo "./etc/$${metaent} type=file mode=0644 uname=root gname=wheel tags=etc_pkg"; \
+ done; \
+ ) | ${METALOG.add}
+.endif # MKUNPRIVED != no
+ ${_MKMSG_INSTALL} ${DESTDIR}/etc/ttys
+ ${ETC_INSTALL_OBJ_FILE} -o ${BINOWN} -g ${BINGRP} -m 644 \
+ ${.CURDIR}/etc.${MACHINE}/ttys ${DESTDIR}/etc
+ ${_MKMSG_INSTALL} ${DESTDIR}/dev/MAKEDEV
+ ${ETC_INSTALL_OBJ_FILE} -o ${BINOWN} -g ${BINGRP} -m 555 \
+ MAKEDEV ${DESTDIR}/dev
+.for owner group mode file in \
+ ${BINOWN} operator 664 /etc/dumpdates \
+ ${BINOWN} operator 600 /etc/skeykeys \
+ root wheel 600 /var/at/at.deny \
+ nobody ${BINGRP} 664 /var/db/locate.database \
+ ${BINOWN} ${BINGRP} 600 /var/log/authlog \
+ root wheel 600 /var/log/cron \
+ ${BINOWN} ${UTMPGRP} 664 /var/log/lastlog \
+ ${BINOWN} ${UTMPGRP} 664 /var/log/lastlogx \
+ ${BINOWN} ${BINGRP} 640 /var/log/lpd-errs \
+ ${BINOWN} ${BINGRP} 600 /var/log/maillog \
+ ${BINOWN} ${BINGRP} 644 /var/log/messages \
+ ${BINOWN} ${BINGRP} 600 /var/log/secure \
+ ${BINOWN} ${UTMPGRP} 664 /var/log/wtmp \
+ ${BINOWN} ${UTMPGRP} 664 /var/log/wtmpx \
+ ${BINOWN} ${BINGRP} 600 /var/log/xferlog \
+ daemon staff 664 /var/msgs/bounds \
+ ${BINOWN} ${UTMPGRP} 664 /var/run/utmp \
+ ${BINOWN} ${UTMPGRP} 664 /var/run/utmpx \
+ games games 664 /var/games/atc_score \
+ games games 664 /var/games/battlestar.log \
+ games games 664 /var/games/cfscores \
+ games games 664 /var/games/criblog \
+ games games 660 /var/games/hackdir/perm \
+ games games 660 /var/games/hackdir/record \
+ games games 664 /var/games/larn/llog12.0 \
+ games games 664 /var/games/larn/lscore12.0 \
+ games games 664 /var/games/larn/playerids \
+ games games 664 /var/games/robots_roll \
+ games games 664 /var/games/rogue.scores \
+ games games 664 /var/games/saillog \
+ games games 664 /var/games/snakerawscores \
+ games games 664 /var/games/snake.log \
+ games games 664 /var/games/tetris.scores
+ ${_MKMSG_INSTALL} ${DESTDIR}${file}
+ ${ETC_INSTALL_FILE} -o ${owner} -g ${group} -m ${mode} \
+ /dev/null ${DESTDIR}${file}
+.endfor
+.for subdir in . atf defaults bluetooth iscsi mtree namedb pam.d powerd rc.d root skel ssh
+ ${MAKEDIRTARGET} ${subdir} configinstall
+.endfor
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.bin/mail configinstall
+.if (${MKPF} != "no")
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.sbin/pf configinstall
+.endif
+.if (${MKCRYPTO} != "no")
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/usr.bin/ssh configinstall
+.endif
+.if (${MKPOSTFIX} != "no")
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/gnu/usr.sbin/postfix configinstall
+.endif
+
+
+# install-obsolete-lists --
+# Install var/db/obsolete set lists; this is performed by "make build"
+#
+OBSOLETE.dir= ${.OBJDIR}/obsolete.dir
+OBSOLETE.files= base comp etc games man misc tests text
+.if ${MKX11} != "no"
+OBSOLETE.files+= xbase xcomp xetc xfont xserver
+.endif
+
+install-obsolete-lists: .PHONY .MAKE
+ mkdir -p ${OBSOLETE.dir}
+.if ${MKX11} != "no"
+ (cd ${NETBSDSRCDIR}/distrib/sets && \
+ MAKE=${MAKE:Q} ${HOST_SH} ./makeobsolete -b -t ${OBSOLETE.dir})
+.else
+ (cd ${NETBSDSRCDIR}/distrib/sets && \
+ MAKE=${MAKE:Q} ${HOST_SH} ./makeobsolete -t ${OBSOLETE.dir})
+.endif
+.for file in ${OBSOLETE.files}
+ ${_MKMSG_INSTALL} ${DESTDIR}/var/db/obsolete/${file}
+ ${ETC_INSTALL_FILE} -o ${BINOWN} -g ${BINGRP} -m 644 \
+ ${OBSOLETE.dir}/${file} ${DESTDIR}/var/db/obsolete
+.endfor
+
+
+# distrib-dirs --
+# Populate $DESTDIR with directories needed by NetBSD
+#
+.if ${MKUNPRIVED} == "no"
+TOOL_MTREE.unpriv=
+.else
+TOOL_MTREE.unpriv= -W
+.endif
+
+distrib-dirs: .PHONY check_DESTDIR
+.if !defined(DISTRIBUTION_DONE) # {
+# XXX: If METALOG=${DESTDIR}/METALOG (as is normal), and if ${DESTDIR}
+# does not yet exist (as often happens), then the INSTALL_DIR command
+# immediately below will create ${DESTDIR} but will fail to register
+# an entry for "." in the metalog. We ignore the problem, because the
+# TOOL_MTREE commands a little further below will soon register an entry
+# for "." in the metalog.
+ ${INSTALL_DIR} -o root -g wheel -m 755 ${BASE_PKG} ${DESTDIR}
+# XXX: It would be nice if a single mtree invocation could both
+# append to the metalog and do real work. Instead, we have to
+# repeat the command twice in slightly different ways.
+ ${TOOL_MTREE} -def ${.CURDIR}/mtree/NetBSD.dist -N ${.CURDIR} \
+ -p ${DESTDIR}/ -U ${TOOL_MTREE.unpriv}
+.if ${MKUNPRIVED} != "no" # {
+ ${TOOL_MTREE} -def ${.CURDIR}/mtree/NetBSD.dist -N ${.CURDIR} \
+ -p ${DESTDIR}/ -C -k all | \
+ awk '/ optional/ {next} // {print}' | ${METALOG.add}
+.endif # MKUNPRIVED # }
+.endif # DISTRIBUTION_DONE # }
+
+# release, snapshot --
+# Build a full distribution including kernels & install media.
+#
+release snapshot: .PHONY .MAKE check_DESTDIR check_RELEASEDIR snap_md_post
+ ${MAKEDIRTARGET} ${NETBSDSRCDIR}/distrib/sets sets
+ ${MAKESUMS} -A -t ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/sets \
+ ${KERNEL_SETS:@.SETS.@kern-${.SETS.}.tgz@}
+ ${MAKESUMS} -t ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/kernel '*.gz'
+
+
+# iso-image --
+# Standalone target to create a CDROM image after the release
+# was composed. Should be run after "make release" in src and xsrc.
+# The do-iso-image is to be called from etc.$MACHINE/Makefile.inc
+#
+# Note: At least mkisofs 2.0 should be used.
+#
+CDROM_NAME_ADD?=
+CDROM.image?=${RELEASEDIR}/iso/${MACHINE}cd.iso
+CDROM.dir= ${.OBJDIR}/cdrom.dir
+CDROM.pathlist= ${.OBJDIR}/cdrom.pathlist
+
+iso-image:
+
+.if ${MKISOFS} != true
+do-iso-image: .PHONY check_DESTDIR check_RELEASEDIR iso-image-md-post
+ ${MAKESUMS} -t ${RELEASEDIR}/iso/ '*.iso'
+ @echo "iso-image created as: ${CDROM.image}"
+.else
+do-iso-image:
+ @echo iso-image: mkisofs not found
+.endif
+
+iso-image-setup: .PHONY check_RELEASEDIR
+ rm -f ${CDROM.pathlist}
+.for extra in README SOURCE_DATE source
+.if exists(${RELEASEDIR}/${extra})
+ echo "${extra}=${RELEASEDIR}/${extra}" >> ${CDROM.pathlist}
+.endif
+.endfor
+ echo "${MACHINE}/=${RELEASEDIR}/${RELEASEMACHINEDIR}/" >> ${CDROM.pathlist}
+ mkdir -p ${CDROM.dir}
+ mkdir -p ${RELEASEDIR}/${RELEASEMACHINEDIR}/installation/cdrom
+
+# iso-image-mi --
+# Create the image after the MD operations have completed.
+#
+iso-image-mi: .PHONY check_DESTDIR check_RELEASEDIR iso-image-md-pre
+ @if ! ${MKISOFS} --version; then \
+ echo "install pkgsrc/sysutils/cdrtools and run 'make iso-image'." ; \
+ false; \
+ fi
+ ${MKISOFS} ${MKISOFS_FLAGS} -graft-points -path-list ${CDROM.pathlist} \
+ -o ${CDROM.image} ${CDROM.dir}
+
+# iso-image-md-pre --
+# Setup ${CDROM.dir} to produce a bootable CD image.
+# Overridden by etc.$MACHINE/Makefile.inc
+#
+iso-image-md-pre: .PHONY check_DESTDIR check_RELEASEDIR iso-image-setup
+# (empty -- look in the machine-dependent Makefile.inc)
+
+# iso-image-md-post --
+# Fixup the CD-image to be bootable.
+# Overridden by etc.$MACHINE/Makefile.inc
+#
+iso-image-md-post: .PHONY check_DESTDIR check_RELEASEDIR iso-image-mi
+# (empty -- look in the machine-dependent Makefile.inc)
+
+
+# snap_pre --
+# Create ${RELEASEDIR} and necessary subdirectories.
+#
+snap_pre: .PHONY check_DESTDIR check_RELEASEDIR distribution
+ ${INSTALL} -d -m 755 ${RELEASEDIR}
+.if ${MKUPDATE} == "no"
+# Could be a mount point, ignore the errors
+ -/bin/rm -rf ${RELEASEDIR}/${RELEASEMACHINEDIR}
+.endif
+ ${INSTALL} -d -m 755 ${RELEASEDIR}/${RELEASEMACHINEDIR}
+.for dir in ${INSTALLATION_DIRS}
+ ${INSTALL} -d -m 755 ${RELEASEDIR}/${RELEASEMACHINEDIR}/${dir}
+.endfor
+
+# snap_post --
+# Build the install media and notes from distrib
+#
+snap_post: .PHONY .MAKE build_kernelsets build_releasekernels
+.if ${MKUPDATE} == "no"
+ cd ${NETBSDSRCDIR}/distrib && ${MAKE} cleandir
+.endif
+ cd ${NETBSDSRCDIR}/distrib && ${MAKE} depend && ${MAKE} && \
+ ${MAKE} release
+
+# build kernels --
+# This target builds the kernels specified by each port.
+# A port may specify the following kernels:
+#
+# KERNEL_SETS The list of kernels that will be
+# packaged into sets, named
+# kern-${kernel}.tgz. These kernels
+# are also placed in the binary/kernel
+# area of the release package as
+# netbsd-${kernel}.gz.
+#
+# EXTRA_KERNELS Additional kernels to place in the
+# binary/kernel area of the release
+# package as netbsd-${kernel}.gz, but
+# which are not placed into sets. This
+# allows a port to provide e.g. a netbootable
+# installation kernel containing a ramdisk.
+#
+# BUILD_KERNELS Additional kernels to build which are
+# not placed into sets nor into the
+# binary/kernel area of the release
+# package. These are typically kernels
+# that are built for inclusion only in
+# installation disk/CD-ROM/tape images.
+#
+# A port may also specify KERNEL_SUFFIXES, which is an optional list
+# of filename suffixes for kernels to include in the kernel sets and
+# in the binary/kernel area of the release package (e.g. "netbsd" vs.
+# "netbsd.ecoff" and "netbsd.srec"). It is not an error if kernels
+# with these suffixes do not exist in the kernel build directory.
+#
+#
+# A list of all the kernels to build, which can be overridden from
+# external sources (such as make(1)'s environment or command line)
+#
+ALL_KERNELS?= ${KERNEL_SETS} ${EXTRA_KERNELS} ${BUILD_KERNELS}
+
+GETKERNELAWK= awk '/^config/ {print $$2; found=1} \
+ END{ if (found == 0) print "netbsd"; }'
+
+build_kernels: .PHONY
+# Configure & compile kernels listed in ${ALL_KERNELS}
+#
+# The 'sync' is so that all writes during the build are pushed back
+# to the disk. Not having it causes problems on some host systems
+# (e.g. Linux) when building on NFS.
+#
+.if !defined(KERNELS_DONE) # {
+.for configfile in ${ALL_KERNELS} # {
+build_kernels: kern-${configfile}
+kern-${configfile}: .PHONY .MAKE
+ cd ${KERNCONFDIR} && ${TOOL_CONFIG} -s ${KERNSRCDIR} \
+ -b ${KERNOBJDIR}/${configfile:C/.*\///} ${configfile}
+.if ${MKUPDATE} == "no"
+ cd ${KERNOBJDIR}/${configfile:C/.*\///} && ${MAKE} distclean
+.endif
+ cd ${KERNOBJDIR}/${configfile:C/.*\///} && ${MAKE} depend && ${MAKE}
+ sync
+.endfor # ALL_KERNELS # }
+.endif # KERNELS_DONE # }
+
+build_kernelsets: .PHONY
+# Create kernel sets from ${KERNEL_SETS} into
+# ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/sets
+#
+.for configfile in ${KERNEL_SETS} # {
+build_kernelsets: kernset-${configfile}
+kernset-${configfile}: .PHONY build_kernels snap_pre
+ @ kernlist=`${GETKERNELAWK} ${KERNCONFDIR}/${configfile}`; \
+ kerndir=${KERNOBJDIR}/${configfile:C/.*\///}; \
+ kernsuffixes="${KERNEL_SUFFIXES:S/^/./}"; \
+ kern_tgz=${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/sets/kern-${configfile}.tgz; \
+ pax_cmd="GZIP=-9 ${TOOL_PAX} -O -zw -M -N ${NETBSDSRCDIR}/etc -f $${kern_tgz}"; \
+ cd $${kerndir} && { \
+ kernels=; newest=; \
+ for kernel in $${kernlist}; do \
+ for s in "" $${kernsuffixes}; do \
+ ks="$${kernel}$${s}"; \
+ [ -f $${ks} ] || continue; \
+ kernels="$${kernels} $${ks}"; \
+ [ -z "$${newest}" -o $${ks} -nt "$${newest}" ] && \
+ newest=$${ks}; \
+ done; \
+ done; \
+ [ $${kern_tgz} -nt "$${newest}" ] || { \
+ echo "echo $${kernels} | $${pax_cmd}"; \
+ ( echo "/set uname=${BINOWN} gname=${BINGRP}"; \
+ echo ". type=dir optional"; \
+ for kernel in $${kernels}; do \
+ echo "./$${kernel} type=file"; \
+ done ) | eval $${pax_cmd}; \
+ } \
+ }
+.endfor # KERNEL_SETS # }
+
+build_releasekernels: .PHONY
+# Build kernel.gz from ${KERNEL_SETS} ${EXTRA_KERNELS} into
+# ${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/kernel
+#
+.for configfile in ${KERNEL_SETS} ${EXTRA_KERNELS} # {
+build_releasekernels: releasekern-${configfile}
+releasekern-${configfile}: .PHONY build_kernels snap_pre
+ @ kernlist=`${GETKERNELAWK} ${KERNCONFDIR}/${configfile:C/.*\///}`; \
+ kerndir=${KERNOBJDIR}/${configfile:C/.*\///}; \
+ kernsuffixes="${KERNEL_SUFFIXES:S/^/./}"; \
+ cd $${kerndir} && { \
+ for kernel in $${kernlist}; do \
+ for s in "" $${kernsuffixes}; do \
+ ks="$${kernel}$${s}"; \
+ [ ! -f $${ks} ] && continue; \
+ knl_gz="${RELEASEDIR}/${RELEASEMACHINEDIR}/binary/kernel/$${ks}-${configfile:C/.*\///}.gz"; \
+ [ $${knl_gz} -nt $${ks} ] && continue; \
+ echo "gzip -c -9 < $${kerndir}/$${ks} > $${knl_gz}"; \
+ gzip -c -9 < $${ks} > $${knl_gz}; \
+ done; \
+ done; \
+ }
+.endfor # KERNEL_SETS EXTRA_KERNELS # }
+
+# snap_md_post --
+# Machine dependent distribution media operations.
+# Overridden by etc.$MACHINE/Makefile.inc
+#
+snap_md_post: .PHONY check_DESTDIR check_RELEASEDIR snap_post
+# (empty -- look in the machine-dependent Makefile.inc)
+
+
+clean:
+ -rm -rf ${CDROM.dir} ${CDROM.pathlist} ${OBSOLETE.dir}
+
+.include <bsd.prog.mk>
+
+test:
+ @echo ${OBSOLETE.files}
View
4 etc/defaults/rc.conf
@@ -1,4 +1,4 @@
-# $NetBSD: rc.conf,v 1.90 2007/08/27 10:59:05 pavel Exp $
+# $NetBSD: rc.conf,v 1.90.6.1 2008/02/18 22:07:01 mjf Exp $
#
# /etc/defaults/rc.conf --
# default configuration of /etc/rc.conf
@@ -303,6 +303,8 @@ wdogctl=NO # watchdog timer control
irdaattach=NO # attach serial lines to IrDA
irdaattach_flags="tty00"
+devfsd=YES devfsd_flags="" # devfs daemon
+
# Configuration of "wscons" console driver virtual screens.
#
wscons=NO wscons_flags="" # setup wscons from wscons.conf
View
0 sbin/devfsd/test.cfg → etc/devfsd.conf 100644 → 100755
File renamed without changes.
View
4 etc/rc.d/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.66 2007/07/14 21:20:31 ad Exp $
+# $NetBSD: Makefile,v 1.66.8.1 2008/02/18 22:07:01 mjf Exp $
.include <bsd.own.mk>
@@ -12,7 +12,7 @@ CONFIGFILES=\
accounting altqd amd apmd \
bootconf.sh bootparams btconfig btdevctl bthcid btuartd \
ccd cgd cleartmp cron \
- dhclient dhcpd dhcrelay dmesg downinterfaces envsys \
+ devfsd dhclient dhcpd dhcrelay dmesg downinterfaces envsys \
fsck ftpd \
hostapd \
identd ifwatchd inetd ipfilter ipfs ipmon ipnat ipsec \
View
30 etc/rc.d/devfsd
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# $NetBSD: devfsd,v 1.1.2.1 2008/02/18 22:07:01 mjf Exp $
+#
+
+# BEFORE: disks
+# PROVIDE: devs
+
+# The devfsd is configured VERY early, so that /dev can be populated
+# with device special nodes.
+
+$_rc_subr_loaded . /etc/rc.subr
+
+name="devfsd"
+rcvar=$name
+
+start_cmd="devfsd_start"
+stop_cmd="devfsd_stop"
+status_cmd="devfsd_status"
+
+extra_commands="status"
+
+devfsd_start()
+{
+ echo "Starting devfsd."
+ /sbin/devfsd ${devfsd_flags}
+}
+
+load_rc_config $name
+run_rc_command "$1"
View
3 etc/rc.d/wdogctl
@@ -1,9 +1,10 @@
#!/bin/sh
#
-# $NetBSD: wdogctl,v 1.2 2004/08/13 18:08:03 mycroft Exp $
+# $NetBSD: wdogctl,v 1.2.22.1 2008/02/18 22:07:01 mjf Exp $
#
# BEFORE: disks
+# REQUIRE: devs
# The watchdog is configured VERY early, so that any problems that
# occur during the bootstrap process are protected by the watchdog.
View
3 sbin/Makefile
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.107.2.2 2008/02/18 21:04:16 mjf Exp $
+# $NetBSD: Makefile,v 1.107.2.3 2008/02/18 22:07:01 mjf Exp $
# @(#)Makefile 8.5 (Berkeley) 3/31/94
# Not ported: XNSrouted enpload scsiformat startslip
@@ -26,6 +26,7 @@ SUBDIR+= newfs_msdos fsck_msdos
SUBDIR+= newfs_sysvbfs
SUBDIR+= mount_ados
SUBDIR+= mount_cd9660
+SUBDIR+= mount_devfs
SUBDIR+= mount_efs
SUBDIR+= mount_ext2fs
SUBDIR+= mount_fdesc
View
8 sbin/devfsd/Makefile
@@ -1,11 +1,13 @@
-# $NetBSD: Makefile,v 1.1.2.1 2007/12/08 22:05:04 mjf Exp $
+# $NetBSD: Makefile,v 1.1.2.2 2008/02/18 22:07:02 mjf Exp $
PROG= devfsd
-SRCS= devfsd.c devfsd_dev.c devfsd_rule.c
+SRCS= devfsd.c devfsd_dev.c devfsd_mount.c devfsd_rule.c
MAN= devfsd.8
DPADD= ${LIBUTIL}
-LDADD= -lutil
+LDADD= -lutil -lprop
+
+CFLAGS=-g
WARNS= 4
View
81 sbin/devfsd/devfsd.8
@@ -0,0 +1,81 @@
+.\" $NetBSD: devfsd.8,v 1.1.2.1 2008/02/18 22:07:02 mjf Exp $
+.\"
+.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Matt Fleming.
+.\"
+.\" 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.
+.\"
+.Dd December 8, 2007
+.Dt DEVFSD 8
+.Sh NAME
+.Nm devfsd
+.Nd Create device special files in a device file system
+.Sh SYNOPSIS
+.Nm
+.Op Fl iv
+.Sh DESCRIPTION
+.Nm
+is a daemon that controls the device special
+nodes in a
+.Tn devfs
+file system.
+.Nm
+is started at boot time and monitors device insertion
+and removal via the
+.Xr dctl 4
+device driver. When a device is attached
+to the system is it run against rules specifed in the
+config file. If no config file is specified
+.Pa /etc/devfsd.conf
+is used. See
+.Xr devfsd.conf 5 .
+.Nm
+interacts with the kernel via
+.Xr dctl 4
+in order to create device special files.
+The options are as follows:
+.Bl -tag
+Read rules from the specified configuration file.
+.It Fl i
+Set the default visibility of device special nodes to invisible.
+.It Fl v
+Set the default visibility of device special nodes to visible.
+.El
+.Sh FILES
+.Pa /etc/devfsd.conf
+.Sh SEE ALSO
+.Xr dctl 4 ,
+.Xr devfsd.conf 5
+.Sh HISTORY
+The
+.Nm
+daemon first appeared in
+.Nx 5.0 .
+.Sh AUTHORS
+The
+.Nm
+daemon was implemented by
+.An Matt Fleming.
+
View
351 sbin/devfsd/devfsd.c
@@ -1,7 +1,7 @@
-/* $NetBSD: devfsd.c,v 1.1.2.1 2007/12/08 22:05:04 mjf Exp $ */
+/* $NetBSD: devfsd.c,v 1.1.2.2 2008/02/18 22:07:02 mjf Exp $ */
/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -36,42 +36,50 @@
#include <sys/errno.h>
#include <sys/ioctl.h>
-#include <sys/dev/dctlvar.h>
+#include <dev/dctl/dctlio.h>
#include <err.h>
+#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "devfsd.h"
#include "pathnames.h"
-#define A_CNT(x) (sizeof((x)) / sizeof((x)[0]))
-
extern struct rlist_head rule_list;
extern struct dlist_head dev_list;
-static void init(void);
-static int update(void);
-static bool device_found(device_t);
+static int init(void);
+static int update(struct devfs_dev *, struct dctl_msg *);
+static void device_found(struct devfs_dev *);
+static void device_create_nodes(struct devfs_dev *);
+static void push_nodes(struct devfs_dev *, struct devfs_mount *);
+static void mount_found(struct devfs_mount *);
+static void mount_disappear(struct devfs_mount *);
static bool rule_match(struct devfs_rule *, struct devfs_dev *);
static void usage(void);
-/* kevent(2) stuff */
-static struct kevent *allocevchange(int);
-static int wait_for_events(struct kevent *, size_t, int);
-static void read_dctl(struct kevent *);
-
/* can userland see device nodes? */
static int default_visibility = DEVFS_VISIBLE;
+/* kqueue stuff */
+static struct kevent *allocevchange(void);
+static int wait_for_events(struct kevent *, size_t);
+static void dispatch_read_dctl(struct kevent *);
+static int fkq;
+static int dctl_fd;
+
+#define A_CNT(x) (sizeof((x)) / sizeof((x)[0]))
+
int
main(int argc, char **argv)
{
- int ch, fd, fkq;
+ int ch;
struct kevent events[16], *ev;
(void)setlocale(LC_ALL, "");
@@ -96,64 +104,245 @@ main(int argc, char **argv)
* Read the config file and construct a list of rules in the global
* rule list, 'rule_list'.
*/
- if (rule_parsefile(_PATH_TEST_CONFIG) != 0)
- err(EXIT_FAILURE, "%s: could not parse\n", _PATH_TEST_CONFIG);
+ if (rule_parsefile(_PATH_CONFIG) != 0)
+ err(EXIT_FAILURE, "%s: could not parse\n", _PATH_CONFIG);
- if ((fd = open(_PATH_DCTL, O_RDWR, 0)) < 0)
+ if ((dctl_fd = open(_PATH_DCTL, O_RDONLY, 0)) < 0)
err(EXIT_FAILURE, "%s: could not open", _PATH_DCTL);
- if (daemon(0, 0) != 0)
+ /* Don't close stdin/stdout/stderr when we goto bg
+ if (daemon(0, 1) != 0)
err(EXIT_FAILURE, "could not demonize");
+ */
- if ((fkq = kqueue() < 0))
+ if ((fkq = kqueue()) < 0)
err(EXIT_FAILURE, "cannot create event queue");
- ev = allocevchange(fkq);
- EV_SET(ev, fd, EVFILT_READ, EV_ADD, 0, 0, (intptr_t) read_dctl);
+ ev = allocevchange();
+ EV_SET(ev, dctl_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
+ (intptr_t) dispatch_read_dctl);
+ /* Handle events from the device driver */
for (;;) {
void (*handler)(struct kevent *);
int i, rv;
-
- rv = wait_for_events(events, A_CNT(events), fkq);
+ rv = wait_for_events(events, A_CNT(events));
if (rv == 0)
continue;
-
if (rv < 0) {
- warnx("kqueue failed\n");
+ warnx("kevent() failed");
continue;
}
-
for (i = 0; i < rv; i++) {
handler = (void *) events[i].udata;
(*handler)(&events[i]);
- }
+ }
}
-
return 0;
}
+/*
+ * Dispatch routine for reading /dev/dctl
+ */
static void
+dispatch_read_dctl(struct kevent *ev)
+{
+ ssize_t rv;
+ int fd = ev->ident;
+ struct dctl_msg msg;
+ struct devfs_dev *de;
+ struct devfs_mount *dmp;
+
+ memset(&msg, 0, sizeof(msg));
+
+ rv = ioctl(fd, DCTL_IOC_NEXTEVENT, &msg);
+ if (rv >= 0) {
+ switch(msg.d_type) {
+ case DCTL_NEW_DEVICE:
+ printf("dctl: new device %s\n",
+ msg.d_kdev.k_name);
+ de = dev_create(&msg.d_kdev, msg.d_dc);
+ if (de == NULL) {
+ warnx("could not internalize device\n");
+ return;
+ }
+
+ /*
+ * We need to create special files for this
+ * device on all devfs file systems (whether
+ * they are visible or not in a file system is
+ * not our concern, they still need to be
+ * attached to it).
+ */
+ device_create_nodes(de);
+
+ /*
+ * Run rules against our device and it's
+ * nodes.
+ */
+ device_found(de);
+
+ /*
+ * Push the new nodes into their respective
+ * file systems at once!
+ */
+ push_nodes(de, NULL);
+ break;
+ case DCTL_UPDATE_NODE_ATTR:
+ printf("dctl: updated device attrs\n");
+ de = dev_lookup(msg.d_sn);
+ if (de == NULL) {
+ warnx("could not find device to update\n");
+ return;
+ }
+ if (update(de, &msg) == -1)
+ warnx("your changes will be lost on reboot\n");
+ break;
+
+ case DCTL_UPDATE_NODE_NAME:
+ printf("dctl: filename for node updated\n");
+ break;
+
+ case DCTL_NEW_MOUNT:
+ printf("dctl: new devfs mount: %s\n",
+ msg.d_mp.m_pathname);
+
+ dmp = mount_create(msg.d_mc,
+ msg.d_mp.m_pathname, msg.d_mp.m_visibility);
+
+ if (dmp == NULL) {
+ warnx("failed to internalize mount\n");
+ return;
+ }
+
+ mount_found(dmp);
+ break;
+ case DCTL_UNMOUNT:
+ dmp = mount_lookup(msg.d_mc);
+
+ if (dmp == NULL) {
+ warnx("unknown mount removed\n");
+ return;
+ }
+
+ printf("dctl: devfs mount gone: %s\n",
+ dmp->m_pathname);
+
+ mount_disappear(dmp);
+ mount_destroy(dmp);
+
+ break;
+ case DCTL_REMOVED_DEVICE:
+ printf("dctl: device removed: %s\n",
+ msg.d_kdev.k_name);
+ break;
+ }
+ } else if (rv < 0 && errno != EINTR) {
+ /*
+ * /dev/dctl has croaked. Disable the event
+ * so it won't bother us again.
+ */
+ struct kevent *cev = allocevchange();
+ EV_SET(cev, fd, EVFILT_READ, EV_DISABLE,
+ 0, 0, (intptr_t) dispatch_read_dctl);
+ }
+}
+
+/*
+ * Dispatch routine for writing /dev/dctl
+ *
+ * If 'dmp' is NULL we push these nodes in to _ALL_ device file systems.
+ */
+static void
+push_nodes(struct devfs_dev *dev, struct devfs_mount *dmp)
+{
+ int rv;
+ struct dctl_msg msg;
+ struct devfs_node *node;
+
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+
+ if (dmp != NULL) {
+ /* Ensure we push nodes into the correct fs */
+ if (node->n_cookie.sc_mount != dmp->m_id)
+ continue;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.d_sn = node->n_cookie;
+ msg.d_attr = node->n_attr;
+ printf("creating node: %s\n",
+ msg.d_attr.d_component.in_pthcmp.d_filename);
+
+ rv = ioctl(dctl_fd, DCTL_IOC_CREATENODE, &msg);
+
+ if (rv < 0)
+ warn("could not push node into devfs");
+ }
+}
+
+static int
init(void)
{
+ int error = 0;
+
rule_init();
dev_init();
+
+ return error;
}
/*
* The attributes of some devices have changed (mode/permissions) so we
* must update the corresponding device in the device list and rule
* in the rules list. Then update the config file to reflect this.
*
- * XXX: We call this function before going back to wait for kevent()
+ * NOTE: We handle filename updates, i.e. mv(1), differently from other
+ * attribute updates, i.e. chmod(1). This is because in the future we
+ * may do radically different things for either case. Right now they're
+ * pretty much the same, though.
*/
static int
-update(void)
+update(struct devfs_dev *dev, struct dctl_msg *msg)
{
- /* TODO: Reconstruct rules for devices into proplib objects */
+ struct devfs_node *node;
+
+ /* Figure out which node for this device is being updated */
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+ if (NODE_COOKIE_MATCH(node->n_cookie, msg->d_sn))
+ break;
+ }
+
+ if (node == NULL) {
+ warnx("node not on device node list\n");
+ return -1;
+ }
+
+ if (msg->d_type != DCTL_UPDATE_NODE_ATTR &&
+ msg->d_type != DCTL_UPDATE_NODE_NAME) {
+ warnx("%s: node not being updated\n",
+ node->n_attr.d_component.out_pthcmp.d_pthcmp);
+ return -1;
+ }
- if (rule_writefile(_PATH_TEST_CONFIG) != 0) {
- err(1, "%s: could not write to file", _PATH_TEST_CONFIG);
+ /*
+ * XXX: The simplest way I can think of doing this is just by
+ * letting the current attributes overwrite whatever we have for
+ * this entry in dev_list, because _we_ specified the attributes
+ * originally and anything that has changed needs to persist.
+ * It also seems sensible to rebuild the rules based on the
+ * new values (old rules that differ will therefore be discarded),
+ * this way we don't have a two rules in the config file that
+ * contradict each other.
+ */
+ node->n_attr = msg->d_attr;
+
+ /* construct new rules for dev->d_dev */
+ rule_rebuild_attr(dev);
+
+ if (rule_writefile(_PATH_CONFIG) != 0) {
+ warnx("%s: could not write to file", _PATH_CONFIG);
return -1;
}
@@ -163,28 +352,74 @@ update(void)
/*
* We've learnt about a new device from /dev/dctl so run it against our
* list of rules and apply any rules that are found to match.
- *
- * Returns true if we successfully created and installed the device on the
- * lists, false otherwise.
*/
-static bool
-device_found(device_t kernel_dev)
+static void
+device_found(struct devfs_dev *dev)
{
- struct devfs_dev *dev;
struct devfs_rule *rule;
- if ((dev = dev_create(kernel_dev, default_visibility)) == NULL)
- return false;
-
SLIST_FOREACH(rule, &rule_list, r_next) {
if (rule_match(rule, dev)) {
/* got a match: apply rule-specific attrs */
dev_apply_rule(dev, rule);
}
}
SLIST_INSERT_HEAD(&dev_list, dev, d_next);
+}
+
+static void
+device_create_nodes(struct devfs_dev *dev)
+{
+ struct devfs_mount *dmp;
+ SLIST_FOREACH(dmp, &mount_list, m_next)
+ dev_add_node(dev, dmp);
+}
+
+/*
+ * For every device we must now create a new node for that
+ * device for this devfs mount
+ */
+static void
+mount_found(struct devfs_mount *dmp)
+{
+ int error;
+ struct devfs_dev *dev;
+ struct devfs_node *node;
+ struct rule2dev *r2d;
+
+ SLIST_FOREACH(dev, &dev_list, d_next) {
+ if ((error = dev_add_node(dev, dmp)) != 0) {
+ warnx("could not add node to device");
+ continue;
+ }
+
+ /* This node has just been placed at the head */
+ node = SLIST_FIRST(&dev->d_node_head);
+ TAILQ_FOREACH(r2d, &dev->d_pairing, r_next_rule)
+ dev_apply_rule_node(node, dmp, r2d->r_rule);
- return true;
+ printf("Pushing nodes to kernel from daemon: %s\n", dmp->m_pathname);
+ push_nodes(dev, dmp);
+ }
+}
+
+/*
+ * This devfs mount is about to be destroy and disappear
+ * from the system. We must reap all device nodes that are
+ * associated with it.
+ */
+void
+mount_disappear(struct devfs_mount *dmp)
+{
+ struct devfs_dev *dev;
+ struct devfs_node *node;
+
+ SLIST_FOREACH(dev, &dev_list, d_next) {
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+ if (node->n_cookie.sc_mount != dmp->m_id)
+ continue;
+ }
+ }
}
/*
@@ -193,50 +428,44 @@ device_found(device_t kernel_dev)
*
* XXX: Find some way to implement subsystem specific matching functions.
* For example, we should be able to match a network adapter by its
- * MAC address.
+ * MAC address. This probably needs to be an ioctl for the dctl driver.
*/
static bool
rule_match(struct devfs_rule *rule, struct devfs_dev *dev)
{
return false;
}
-void
+static void
usage(void)
{
(void)fprintf(stderr,
"usage: %s [-iv]\n", getprogname());
- exit(1);
+ exit(EXIT_FAILURE);
}
static struct kevent changebuf[8];
static int nchanges;
static struct kevent *
-allocevchange(int fkq)
-{
-
- if (nchanges == A_CNT(changebuf)) {
+allocevchange(void)
+{
+ if (nchanges == A_CNT(changebuf)) {
/* XXX Error handling could be improved. */
- (void) wait_for_events(NULL, 0, fkq);
+ (void) wait_for_events(NULL, 0);
}
- return (&changebuf[nchanges++]);
+ return &changebuf[nchanges++];
}
static int
-wait_for_events(struct kevent *events, size_t nevents, int fkq)
+wait_for_events(struct kevent *events, size_t nevents)
{
int rv;
rv = kevent(fkq, nchanges ? changebuf : NULL, nchanges,
- events, nevents, NULL);
+ events, nevents, NULL);
nchanges = 0;
- return (rv);
-}
-
-static void
-read_dctl(struct kevent *ev)
-{
-}
+ return rv;
+}
View
111 sbin/devfsd/devfsd.h
@@ -1,7 +1,7 @@
-/* $NetBSD: devfsd.h,v 1.1.2.1 2007/12/08 22:05:04 mjf Exp $ */
+/* $NetBSD: devfsd.h,v 1.1.2.2 2008/02/18 22:07:02 mjf Exp $ */
/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -36,8 +36,12 @@
#include <sys/types.h>
#include <sys/device.h>
#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/condvar.h>
+#include <sys/statvfs.h>
#include <prop/proplib.h>
+#include <dev/dctl/dctlio.h>
/*
* A rule can be broken into two parts:
@@ -59,11 +63,10 @@ struct devfs_rule {
const char *r_name; /* rule name */
SLIST_ENTRY(devfs_rule) r_next; /* next rule in list */
- /*
- * This is used by the devfs_dev structure to keep track of which
- * rules have been applied to a device.
- */
- SLIST_ENTRY(devfs_rule) r_dev_next;
+ TAILQ_HEAD(,rule2dev) r_pairing;
+
+ /* which devfs mount this rule should be applied to */
+ const char r_mntpath[_VFS_MNAMELEN];
/*
* How to match.
@@ -77,10 +80,10 @@ struct devfs_rule {
/*
* Attributes to set.
*/
- const char *r_filename; /* filename to use */
+ char *r_filename; /* filename to use */
mode_t r_mode;
- uid_t r_owner; /* owner */
- gid_t r_group;
+ uid_t r_uid; /* owner */
+ gid_t r_gid;
int r_flags; /* see below */
};
@@ -89,41 +92,73 @@ struct devfs_rule {
* userland */
#define DEVFS_RULE_ATTR_UNSET 0xdeadbeef /* attribute is not set */
+#define ATTR_ISSET(x) (x != DEVFS_RULE_ATTR_UNSET)
+
SLIST_HEAD(rlist_head, devfs_rule) rule_list;
-int rule_parsefile(const char *);
-int rule_writefile(const char *);
-int rule_init(void);
+struct devfs_node {
+ SLIST_ENTRY(devfs_node) n_next;
+ struct dctl_specnode_attr n_attr;
+ struct dctl_node_cookie n_cookie; /* cookie to uniquely identify node */
+};
-/*
- * This is the devfsd daemon's internal representation of a device. This
- * data structure is used to create a device special file for this device.
+/*
+ * This structure is our understanding of a device that is connected
+ * to the system. Each device has a unique cookie that allows dctl(4)
+ * to understand what device we're talking about when we request some
+ * action for a device.
*
- * We also keep some extra information such as whether or not the device
- * is the boot device.
- */
-
-struct devfs_dev {
- device_t d_dev;
- SLIST_ENTRY(devfs_dev) d_next; /* next device in list */
- char d_filename[MAXPATHLEN]; /* filename to use */
- mode_t d_mode;
- uid_t d_owner;
- gid_t d_group;
- int d_flags;
-
- /*
- * We maintain a list of rules that have been applied to this device.
- */
- SLIST_HEAD(, devfs_rule) d_rule_head;
+ * Because there can be multiple devfs mounts on the system we need to
+ * keep track of all the different special nodes in use for this device.
+ * We keep a list of all device special nodes for this device in the
+ * 'd_node_head' member.
+ */
+struct devfs_dev {
+ intptr_t d_cookie; /* cookie for this device */
+ char d_kname[16]; /* device driver name */
+ SLIST_ENTRY(devfs_dev) d_next; /* next device in list */
+ SLIST_HEAD(, devfs_node) d_node_head; /* nodes for this device */
+ TAILQ_HEAD(, rule2dev) d_pairing;
};
SLIST_HEAD(dlist_head, devfs_dev) dev_list;
-int dev_init(void);
-const char *device_xname(device_t);
-struct devfs_dev *dev_create(device_t, int);
-void dev_apply_rule(struct devfs_dev *, struct devfs_rule *);
-void dev_destroy(struct devfs_dev *);
+/*
+ * This is allows us to pair up devices with rules that have
+ * been applied to that it and also pair up rules with devices.
+ * This is a many-to-many relationship.
+ */
+struct rule2dev {
+ TAILQ_ENTRY(rule2dev) r_next_rule;
+ TAILQ_ENTRY(rule2dev) r_next_dev;
+ struct devfs_rule *r_rule;
+ struct devfs_dev *r_dev;
+};
+
+struct devfs_mount {
+ char m_pathname[_VFS_MNAMELEN];
+ int32_t m_id;
+ int m_visibility;
+ SLIST_ENTRY(devfs_mount) m_next;
+};
+SLIST_HEAD(mlist_head, devfs_mount) mount_list;
+
+int rule_parsefile(const char *);
+int rule_writefile(const char *);
+int rule_init(void);
+int rule_rebuild_attr(struct devfs_dev *);
+
+int dev_init(void);
+struct devfs_dev *dev_create(struct dctl_kerndev *, intptr_t);
+void dev_apply_rule(struct devfs_dev *, struct devfs_rule *);
+void dev_apply_rule_node(struct devfs_node *, struct devfs_mount *,
+ struct devfs_rule *);
+void dev_destroy(struct devfs_dev *);
+struct devfs_dev *dev_lookup(struct dctl_node_cookie);
+int dev_add_node(struct devfs_dev *, struct devfs_mount *);
+
+struct devfs_mount *mount_create(int32_t, const char *, int);
+struct devfs_mount *mount_lookup(int32_t);
+void mount_destroy(struct devfs_mount *);
#endif /* _DEVFSD_H_ */
View
170 sbin/devfsd/devfsd_dev.c
@@ -1,7 +1,7 @@
-/* $NetBSD: devfsd_dev.c,v 1.1.2.1 2007/12/08 22:05:05 mjf Exp $ */
+/* $NetBSD: devfsd_dev.c,v 1.1.2.2 2008/02/18 22:07:02 mjf Exp $ */
/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -53,31 +53,70 @@ dev_init(void)
return 0;
}
-/*
- * Create a new devfsd device and fill it with default attributes.
- */
struct devfs_dev *
-dev_create(device_t kernel_dev, int visibility)
+dev_create(struct dctl_kerndev *kerndev, intptr_t cookie)
{
- struct devfs_dev *dev;
+ struct devfs_dev *ddev;
- if ((dev = (struct devfs_dev *)malloc(sizeof(dev))) == NULL)
+ if ((ddev = malloc(sizeof(*ddev))) == NULL) {
+ warn("could not alloc memory for dev\n");
return NULL;
+ }
+
+ ddev->d_cookie = cookie;
+
+ strlcpy(ddev->d_kname, kerndev->k_name, sizeof(ddev->d_kname));
+
+ SLIST_INIT(&ddev->d_node_head);
+ TAILQ_INIT(&ddev->d_pairing);
+
+ return ddev;
+}
+
+int
+dev_add_node(struct devfs_dev *dev, struct devfs_mount *dmp)
+{
+ size_t len;
+ struct devfs_node *dnode;
+ char *d_filename;
+
+ if ((dnode = malloc(sizeof(*dnode))) == NULL)
+ return -1;
/* Fill in default attributes */
- dev->d_dev = kernel_dev;
+ dnode->n_attr.d_mode = 0644;
+ dnode->n_attr.d_uid = 0; /* root */
+ dnode->n_attr.d_gid = 0; /* wheel */
+ dnode->n_attr.d_flags = dmp->m_visibility;
+
+ /*
+ * By default, we use the driver name for the node
+ * (this may be overridden later with a rule).
+ */
+ len = strlen(dev->d_kname) + 1;
+ d_filename = malloc(len);
+ strlcpy(d_filename, dev->d_kname, len);
- strlcpy(dev->d_filename, device_xname(kernel_dev),
- sizeof(dev->d_filename));
+ dnode->n_attr.d_component.in_pthcmp.d_filename = d_filename;
- dev->d_mode = 0644;
- dev->d_owner = 0; /* root */
- dev->d_group = 0; /* wheel */
- dev->d_flags = visibility;
+ dnode->n_cookie.sc_dev = (intptr_t) dev->d_cookie;
+ dnode->n_cookie.sc_mount = dmp->m_id;
- SLIST_INIT(&dev->d_rule_head);
+ SLIST_INSERT_HEAD(&dev->d_node_head, dnode, n_next);
- return dev;
+ return 0;
+}
+
+int
+dev_del_node(struct devfs_dev *dev, struct devfs_mount *dmp)
+{
+ struct devfs_node *node;
+
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+ if (node->n_cookie.sc_mount != dmp->m_id)
+ continue;
+ }
+ return 0;
}
/*
@@ -88,6 +127,7 @@ dev_destroy(struct devfs_dev *dev)
{
bool removed = false;
struct devfs_dev *tmp_dev;
+ struct devfs_node *node;
SLIST_FOREACH(tmp_dev, &dev_list, d_next) {
if (tmp_dev == dev) {
@@ -103,43 +143,95 @@ dev_destroy(struct devfs_dev *dev)
return;
}
+ /* Free all nodes allocated for this device */
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+ SLIST_REMOVE(&dev->d_node_head, node, devfs_node, n_next);
+ free(node);
+ }
+
+ /*
+ * TODO: Must remove this device from every rule's list of devices
+ */
+
free(dev);
}
/*
* We have already matched this rule against this device, so apply
- * the rule to the device node.
+ * the rule to the appropriate device nodes.
*/
void
-dev_apply_rule(struct devfs_dev *d, struct devfs_rule *r)
+dev_apply_rule(struct devfs_dev *dd, struct devfs_rule *r)
{
- if (r->r_filename != NULL)
- strlcpy(d->d_filename, r->r_filename, sizeof(d->d_filename));
-
- if (r->r_mode != DEVFS_RULE_ATTR_UNSET)
- d->d_mode = r->r_mode;
-
- if (r->r_owner != DEVFS_RULE_ATTR_UNSET)
- d->d_owner = r->r_owner;
+ struct rule2dev *rd;
+ struct devfs_node *node;
+ struct devfs_mount *dmp;
- if (r->r_group != DEVFS_RULE_ATTR_UNSET)
- d->d_group = r->r_group;
+ if ((rd = malloc(sizeof(*rd))) == NULL) {
+ warn("could not allocate rule2dev structure");
+ return;
+ }
- d->d_flags = r->r_flags;
+ SLIST_FOREACH(node, &dd->d_node_head, n_next) {
+ /*
+ * Check if this rule should be applied to nodes on
+ * this node's mount path.
+ */
+ dmp = mount_lookup(node->n_cookie.sc_mount);
+ dev_apply_rule_node(node, dmp, r);
+ }
/*
- * Add this device to the list of devices this rule applies
- * to
+ * Add this device to the rule's devices list and add this rule
+ * to the device's rules list. See devfsd.h for more information.
+ *
+ * XXX: Adding the rules and devices to the appropriate lists is always
+ * done, even if no nodes were actually matched, a new node may be
+ * created for this device where this rule does apply.
*/
- SLIST_INSERT_HEAD(&d->d_rule_head, r, r_dev_next);
+ rd->r_rule = r;
+ rd->r_dev = dd;
+ TAILQ_INSERT_TAIL(&dd->d_pairing, rd, r_next_rule);
+ TAILQ_INSERT_TAIL(&r->r_pairing, rd, r_next_dev);
}
-/*
- * XXX: this is a userland definition of device_xname and as such will break
- * if the kernel version of device_xname changes.
+/*
+ * Apply a rule to a devfs node.
*/
-const char *
-device_xname(device_t d)
+void
+dev_apply_rule_node(struct devfs_node *node, struct devfs_mount *dmp,
+ struct devfs_rule *r)
+{
+ if (strncmp(r->r_mntpath,
+ dmp->m_pathname, sizeof(r->r_mntpath)) != 0)
+ return;
+
+ if (r->r_filename != NULL)
+ strlcpy(node->n_attr.d_component.out_pthcmp.d_pthcmp,
+ r->r_filename,
+ sizeof(node->n_attr.d_component.out_pthcmp.d_pthcmp));
+
+ if (r->r_mode != DEVFS_RULE_ATTR_UNSET)
+ node->n_attr.d_mode = r->r_mode;
+
+ if (r->r_uid != DEVFS_RULE_ATTR_UNSET)
+ node->n_attr.d_uid = r->r_uid;
+
+ if (r->r_gid != DEVFS_RULE_ATTR_UNSET)
+ node->n_attr.d_gid = r->r_gid;
+
+ node->n_attr.d_flags = r->r_flags;
+}
+
+struct devfs_dev *
+dev_lookup(struct dctl_node_cookie c)
{
- return d->dv_xname;
+ struct devfs_dev *dev;
+
+ SLIST_FOREACH(dev, &dev_list, d_next) {
+ /* Found */
+ if (c.sc_dev == dev->d_cookie)
+ break;
+ }
+ return dev;
}
View
82 sbin/devfsd/devfsd_mount.c
@@ -0,0 +1,82 @@
+/* $NetBSD: devfsd_mount.c,v 1.1.2.1 2008/02/18 22:07:02 mjf Exp $ */
+
+/*-
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Fleming.
+ *
+ * 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.
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "devfsd.h"
+
+extern struct mlist_head mount_list;
+
+/*
+ * Create a new devfs_mount structure and add it to the list
+ * of all mounts.
+ */
+struct devfs_mount *
+mount_create(int32_t cookie, const char *mountpath, int visibility)
+{
+ struct devfs_mount *dmp;
+
+ if ((dmp = malloc(sizeof(*dmp))) == NULL)
+ return NULL;
+
+ strlcpy(dmp->m_pathname, mountpath, sizeof(dmp->m_pathname));
+ dmp->m_id = cookie;
+ dmp->m_visibility = visibility;
+ SLIST_INSERT_HEAD(&mount_list, dmp, m_next);
+
+ return dmp;
+}
+
+struct devfs_mount *
+mount_lookup(int32_t cookie)
+{
+ struct devfs_mount *dmp;
+
+ SLIST_FOREACH(dmp, &mount_list, m_next) {
+ if (dmp->m_id == cookie)
+ break;
+ }
+ return dmp;
+}
+
+void
+mount_destroy(struct devfs_mount *dmp)
+{
+ SLIST_REMOVE(&mount_list, dmp, devfs_mount, m_next);
+ free(dmp);
+}
View
179 sbin/devfsd/devfsd_rule.c
@@ -1,7 +1,7 @@
-/* $NetBSD: devfsd_rule.c,v 1.1.2.1 2007/12/08 22:05:05 mjf Exp $ */
+/* $NetBSD: devfsd_rule.c,v 1.1.2.2 2008/02/18 22:07:02 mjf Exp $ */
/*-
- * Copyright (c) 2007 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -54,10 +54,20 @@
extern struct rlist_head rule_list;
-static int handle_match(const char *, const char *, struct devfs_rule *);
-static int handle_attributes(const char *, const char *, struct devfs_rule *);
+struct attrs_handled {
+ int file_handled;
+ int m_handled;
+ int u_handled;
+ int g_handled;
+ int flags_handled;
+};
+
+static int handle_match(const char *, char *, struct devfs_rule *);
+static int handle_attributes(const char *, char *, struct devfs_rule *);
static int handle_dict(prop_dictionary_t, const char *, struct devfs_rule *);
static prop_dictionary_t construct_rule(struct devfs_rule *);
+/*static void rule_store_attributes(struct devfs_rule *rule,
+ struct dctl_specnode_attr *di, struct attrs_handled *ah, int store);*/
int
rule_init(void)
@@ -119,7 +129,7 @@ rule_parsefile(const char *filename)
return -1;
}
- sr->r_mode = sr->r_owner = sr->r_group = DEVFS_RULE_ATTR_UNSET;
+ sr->r_mode = sr->r_uid = sr->r_gid = DEVFS_RULE_ATTR_UNSET;
rule = prop_dictionary_get_keysym(dict, obj1);
if (rule == NULL) {
@@ -168,7 +178,8 @@ handle_dict(prop_dictionary_t d, const char *section, struct devfs_rule *sr)
prop_object_t obj;
prop_string_t key;
prop_object_t value;
- const char *key_string, *value_string;
+ const char *key_string;
+ char *value_string;
if ((iter = prop_dictionary_iterator(d)) == NULL)
return -1;
@@ -177,7 +188,7 @@ handle_dict(prop_dictionary_t d, const char *section, struct devfs_rule *sr)
key = prop_dictionary_get_keysym(d, obj);
key_string = prop_dictionary_keysym_cstring_nocopy(obj);
value = prop_dictionary_get(d, key_string);
- value_string = prop_string_cstring_nocopy(value);
+ value_string = prop_string_cstring(value);
if (!strncmp(section, "match", strlen("match")))
error = handle_match(key_string, value_string, sr);
@@ -199,7 +210,7 @@ handle_dict(prop_dictionary_t d, const char *section, struct devfs_rule *sr)
* Handler function for match dictionaries. Step 4.
*/
static int
-handle_match(const char *key, const char *value, struct devfs_rule *sr)
+handle_match(const char *key, char *value, struct devfs_rule *sr)
{
if (!strncmp(key, "label", strlen("label"))) {
sr->r_label = value;
@@ -221,16 +232,16 @@ handle_match(const char *key, const char *value, struct devfs_rule *sr)
* Handler function for attribute dictionaries. Step 4.
*/
static int
-handle_attributes(const char *key, const char *value, struct devfs_rule *sr)
+handle_attributes(const char *key, char *value, struct devfs_rule *sr)
{
if (!strncmp(key, "filename", strlen("filename"))) {
sr->r_filename = value;
} else if (!strncmp(key, "mode", strlen("mode"))) {
sr->r_mode = strtoul(value, (char **)NULL, 8);
- } else if (!strncmp(key, "uid", strlen("owner"))) {
- sr->r_owner = atoi(value);
- } else if (!strncmp(key, "gid", strlen("group"))) {
- sr->r_group = atoi(value);
+ } else if (!strncmp(key, "uid", strlen("uid"))) {
+ sr->r_uid = atoi(value);
+ } else if (!strncmp(key, "gid", strlen("gid"))) {
+ sr->r_gid = atoi(value);
} else if (!strncmp(key, "visibility", strlen("visibility"))) {
if (!strncmp(value, "visibile", strlen("visibile"))) {
sr->r_flags &= ~DEVFS_INVISIBLE;
@@ -337,7 +348,8 @@ construct_rule(struct devfs_rule *dr)
} else if (dr->r_drivername != NULL) {
tmp_string =
prop_string_create_cstring_nocopy(dr->r_drivername);
- if (prop_dictionary_set(tmp1, "drivername", tmp_string) != true){
+ if (prop_dictionary_set(tmp1, "drivername",
+ tmp_string) != true) {
error = 1;
goto out;
}
@@ -373,8 +385,8 @@ construct_rule(struct devfs_rule *dr)
}
}
- if (dr->r_owner != DEVFS_RULE_ATTR_UNSET) {
- if (snprintf(buf, 11, "%u", dr->r_owner) > 10) {
+ if (dr->r_uid != DEVFS_RULE_ATTR_UNSET) {
+ if (snprintf(buf, 11, "%u", dr->r_uid) > 10) {
errx(1, "uid too large\n");
error = 1;
goto out;
@@ -389,8 +401,8 @@ construct_rule(struct devfs_rule *dr)
}
}
- if (dr->r_group != DEVFS_RULE_ATTR_UNSET) {
- if (snprintf(buf, 11, "%u", dr->r_group) > 10) {
+ if (dr->r_gid != DEVFS_RULE_ATTR_UNSET) {
+ if (snprintf(buf, 11, "%u", dr->r_gid) > 10) {
errx(1, "gid too large\n");
error = 1;
goto out;
@@ -411,3 +423,134 @@ construct_rule(struct devfs_rule *dr)
out:
return (error) ? NULL : rule;
}
+
+/*
+ * Rebuild the attributes section of a rule. If a rule already specified
+ * one of the attributes and that attribute has changed then replace the
+ * value of the attribute in that rule. If no rule currently exists to
+ * handle the leftover attributes of 'di' then we create a new rule that
+ * contains their values.
+ */
+int
+rule_rebuild_attr(struct devfs_dev *dev)
+{
+ /*
+ struct devfs_rule *rule, *new_rule;
+ struct dctl_specnode_attr *di = &dev->d_dev;
+ struct attrs_handled ah;
+ struct devfs_node *node;
+ struct rule2dev *rd;
+ char *mntpath;
+ struct devfs_mount *dmp;
+
+ ah.file_handled = (di->d_filename == NULL) ? 0 : 1;
+ ah.m_handled = ATTR_ISSET(di->d_mode);
+ ah.u_handled = ATTR_ISSET(di->d_uid);
+ ah.g_handled = ATTR_ISSET(di->d_gid);
+ ah.flags_handled = ATTR_ISSET(di->d_flags);
+ */
+
+ /* existing rules */
+
+ /*
+ * TODO: Figure out how to update rules and deal with multiple
+ * mount points. For example, if I chmod a special node in /priv_dev
+ * do I want a rule creating for that mount only? Or for all mounts?
+ TAILQ_FOREACH(rd, &dev->d_pairing, r_next_rule) {
+ mntpath = rd->r_rule->r_mntpath;
+
+ SLIST_FOREACH(node, &dev->d_node_head, n_next) {
+ */
+ /*
+ * Determine if this rule has been applied to
+ * this node. The only reason that this rule _hasnt_
+ * been applied to this node is if the rule is
+ * associated with a specific mount point.
+ */
+ /*
+ if (mntpath[0] != '\0') {
+ dmp = mount_lookup(node.n_cookie.sc_mount);
+ if (strcmp(mntpath, dmp->m_pathname) != 0)
+ continue;
+ }
+
+ rule_store_attributes(rule, &node.n_attr, &ah, 0);
+ }
+ }
+ */
+
+ /* Now find all attributes that weren't taken care of */
+ /*
+ if (ah.file_handled != 0 || ah.m_handled != 0 || ah.u_handled != 0
+ || ah.g_handled != 0 || ah.flags_handled != 0) {
+
+ new_rule = malloc(sizeof(*new_rule));
+ if (new_rule == NULL) {
+ warn("could not fully rebuild rule attributes\n");
+ return -1;
+ }
+ rule_store_attributes(new_rule, &node.n_attr, &ah, 1);
+ }
+ */
+
+ return 0;
+}
+
+/*