From 1adecf7a539cc262f3f61af37f1469f558daabd3 Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Tue, 16 Aug 2011 23:47:53 +0000 Subject: Add ZFSD, a ZFS fault management daemon. This daemon has the following features: o When a vdev for an active pool is inserted into the system, it will re-integrate it with the pool. o When an unlabeled or inactive disk is inserted into the same physical location as a missing member of a pool with the "autoreplace" attribute set, the inserted disk will be used to replace the missing disk. o When the cumulative soft-error count for a vdev exceeds 50 errors, the vdev will be marked degraded, alerting users to a potential problem. The error counts are persisted across reboots. The daemon is written to be easily extended for more advanced fault management policies and to handle new features such as spare pool management. cddl/sbin/zfsd/zpool_list.cc: cddl/sbin/zfsd/zpool_list.h: ZpoolList is a standard container allowing filtering and iteration of imported ZFS pool information. cddl/sbin/zfsd/callout.cc: cddl/sbin/zfsd/callout.h: Timer services built on top of the POSIX interval timer API. cddl/sbin/zfsd/vdev.cc: cddl/sbin/zfsd/vdev.h: Wrapper class used to provide easy access to Vdev nvlist data. cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: Daemon main, devctl socket handling, and global application state exported through the ZfsDaemon singleton. cddl/sbin/zfsd/case_file.cc: cddl/sbin/zfsd/case_file.h: CaseFile objects aggregate vdev faults that may require ZFSD action in order to maintain the health of a ZFS pool. They also handle serialization/deserialization of fault data to persistent storage. cddl/sbin/zfsd/vdev_iterator.cc: cddl/sbin/zfsd/vdev_iterator.h: Helper class for traversing and finding vdev objects within a pool configuration. cddl/sbin/zfsd/dev_ctl_event.cc: cddl/sbin/zfsd/dev_ctl_event.h: Class hierarchy used to express events received via the devctl API. cddl/sbin/zfsd/zfsd_exception.cc: cddl/sbin/zfsd/zfsd_exception.h: Definition of exceptions explicitly thrown by ZFSD. cddl/sbin/zfsd/Makefile: cddl/sbin/Makefile: Add zfsd to the build. etc/rc.d/zfsd: Rc script for ZFSD. etc/defaults/rc.conf: ZFSD defaults, just like ZFS, to being disabled. etc/mtree/BSD.root.dist: Create the etc/zfs/cases directory used to store persistent fault data. Sponsored by: Spectra Logic Corporation --- etc/defaults/rc.conf | 4 ++++ etc/mtree/BSD.root.dist | 2 ++ etc/rc.d/zfsd | 17 +++++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 etc/rc.d/zfsd (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index d467eaac6c1e..fe37697d593b 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -59,6 +59,10 @@ rc_conf_files="/etc/rc.conf /etc/rc.conf.local" # ZFS support zfs_enable="NO" # Set to YES to automatically mount ZFS file systems +# ZFSD support +zfsd_enable="NO" # Set to YES to automatically start the ZFS fault + # management daemon. + gptboot_enable="YES" # GPT boot success/failure reporting. # Experimental - test before enabling diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index a6cba2474491..86372d854711 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -65,6 +65,8 @@ ssl .. zfs + cases + .. .. .. lib diff --git a/etc/rc.d/zfsd b/etc/rc.d/zfsd new file mode 100644 index 000000000000..3167a22505b2 --- /dev/null +++ b/etc/rc.d/zfsd @@ -0,0 +1,17 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: zfsd +# REQUIRE: devd zfs +# KEYWORD: nojail shutdown + +. /etc/rc.subr + +name="zfsd" +rcvar=`set_rcvar` +command="/sbin/${name}" + +load_rc_config $name +run_rc_command "$1" -- cgit v1.3 From 320256b84995912ef863a8338b065dfc66924d76 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 17 Nov 2011 08:57:39 +0000 Subject: Install zfsd rc.d script. --- etc/rc.d/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index fc09cafc4bb6..486bb10d2904 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -40,7 +40,7 @@ FILES= DAEMON FILESYSTEMS LOGIN NETWORKING SERVERS \ watchdogd wpa_supplicant \ ypbind yppasswdd ypserv \ ypset ypupdated ypxfrd \ - zfs zvol + zfs zfsd zvol .if ${MK_IPX} != "no" FILES+= ipxrouted -- cgit v1.3 From 31b1be9cfaa47f92ec450ce3817b80b345951eec Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Mon, 14 Oct 2013 22:58:48 +0000 Subject: Extract devctl event processing support out of zfsd and into a new library: libdevctl. etc/mtree/BSD.include.dist: Add the /usr/include/devctl directory to the base system. lib/Makefile: lib/libdevctl/Makefile: Build support for the new library. lib/libdevctl/consumer.cc: lib/libdevctl/consumer.h: cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: New class, DevCtl::Consumer, from functionality extracted from ZfsDaemon, which can connect to devd, parse an event stream, and invoke event handlers. lib/libdevctl/event.cc: lib/libdevctl/event.h: cddl/sbin/zfsd/dev_ctl_event.cc: cddl/sbin/zfsd/dev_ctl_event.h: Strip Zfsd specific event handling from Zfsd's event classes to create DevCtl::Event, DevCtl::DevfsEvent, and DevCtl::ZfsEvent. lib/libdevctl/event_buffer.cc: lib/libdevctl/event_buffer.h: cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: DevCtl::EventBuffer: buffer for incoming devctl stream used to parse/extract individual event strings. lib/libdevctl/event_factory.cc: lib/libdevctl/event_factory.h: cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: DevCtl::EventFactory: Method map for converting event strings to Devctl::Event objects. lib/libdevctl/exception.cc: lib/libdevctl/exception.h: cddl/sbin/zfsd/zfsd_exception.cc: cddl/sbin/zfsd/zfsd_exception.h: DevCtl::Exception and DevCtl::ParseException, the exceptions which are thrown by this library. lib/libdevctl/guid.cc: lib/libdevctl/guid.h: cddl/sbin/zfsd/guid.cc: cddl/sbin/zfsd/guid.h: DevCtl::Guid: Helper routines for dealing with 64bit GUIDs such as found in Zfs pools and vdevs. lib/libdevctl/reader.cc: lib/libdevctl/reader.h: cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: DevCtl::Reader class hierarchy. Used to direct a Consumer to an event stream (e.g. from devd or a local/saved file). cddl/sbin/zfsd/zfsd_event.cc: cddl/sbin/zfsd/zfsd_event.h: Zfsd specialization of DevCtl::Event types. cddl/sbin/zfsd/zfsd_exception.cc: cddl/sbin/zfsd/zfsd_exception.h: Zfsd specific exception types, now derived from DevCtl::Excpetion. cddl/sbin/zfsd/Makefile: cddl/sbin/zfsd/callout.cc: cddl/sbin/zfsd/callout.h: cddl/sbin/zfsd/case_file.cc: cddl/sbin/zfsd/case_file.h: cddl/sbin/zfsd/vdev.cc: cddl/sbin/zfsd/vdev.h: cddl/sbin/zfsd/vdev_iterator.cc: cddl/sbin/zfsd/vdev_iterator.h: cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd.h: cddl/sbin/zfsd/zfsd_event.cc: cddl/sbin/zfsd/zfsd_event.h: cddl/sbin/zfsd/zfsd_exception.cc: cddl/sbin/zfsd/zfsd_exception.h: cddl/sbin/zfsd/zfsd_main.cc: cddl/sbin/zfsd/zpool_list.cc: cddl/sbin/zfsd/zpool_list.h: Miscelaneuous refactoring to support using libdevctl instead of local implementation. cddl/sbin/zfsd/Makefile: cddl/sbin/zfsd/Makefile.common: tools/regression/zfsd/Makefile: Export common build information for zfsd and its unit tests to a "Makefile.common". Submitted by: gibbs Approved by: ken (mentor) Sponsored by: Spectra Logic Corporation --- cddl/sbin/zfsd/Makefile | 41 +-- cddl/sbin/zfsd/Makefile.common | 43 +++ cddl/sbin/zfsd/callout.cc | 13 + cddl/sbin/zfsd/callout.h | 10 +- cddl/sbin/zfsd/case_file.cc | 91 +++-- cddl/sbin/zfsd/case_file.h | 52 +-- cddl/sbin/zfsd/dev_ctl_event.cc | 731 --------------------------------------- cddl/sbin/zfsd/dev_ctl_event.h | 525 ---------------------------- cddl/sbin/zfsd/guid.cc | 78 ----- cddl/sbin/zfsd/guid.h | 137 -------- cddl/sbin/zfsd/vdev.cc | 15 + cddl/sbin/zfsd/vdev.h | 47 +-- cddl/sbin/zfsd/vdev_iterator.cc | 14 +- cddl/sbin/zfsd/vdev_iterator.h | 15 +- cddl/sbin/zfsd/zfsd.cc | 540 +++++++---------------------- cddl/sbin/zfsd/zfsd.h | 398 +++------------------ cddl/sbin/zfsd/zfsd_event.cc | 369 ++++++++++++++++++++ cddl/sbin/zfsd/zfsd_event.h | 146 ++++++++ cddl/sbin/zfsd/zfsd_exception.cc | 32 +- cddl/sbin/zfsd/zfsd_exception.h | 29 +- cddl/sbin/zfsd/zfsd_main.cc | 14 + cddl/sbin/zfsd/zpool_list.cc | 21 ++ cddl/sbin/zfsd/zpool_list.h | 17 +- etc/mtree/BSD.include.dist | 2 + lib/Makefile | 1 + lib/libdevctl/Makefile | 23 ++ lib/libdevctl/consumer.cc | 246 +++++++++++++ lib/libdevctl/consumer.h | 171 +++++++++ lib/libdevctl/event.cc | 513 +++++++++++++++++++++++++++ lib/libdevctl/event.h | 366 ++++++++++++++++++++ lib/libdevctl/event_buffer.cc | 216 ++++++++++++ lib/libdevctl/event_buffer.h | 188 ++++++++++ lib/libdevctl/event_factory.cc | 96 +++++ lib/libdevctl/event_factory.h | 94 +++++ lib/libdevctl/exception.cc | 123 +++++++ lib/libdevctl/exception.h | 166 +++++++++ lib/libdevctl/guid.cc | 82 +++++ lib/libdevctl/guid.h | 143 ++++++++ lib/libdevctl/reader.cc | 99 ++++++ lib/libdevctl/reader.h | 136 ++++++++ share/mk/bsd.libnames.mk | 1 + 41 files changed, 3646 insertions(+), 2398 deletions(-) create mode 100644 cddl/sbin/zfsd/Makefile.common delete mode 100644 cddl/sbin/zfsd/dev_ctl_event.cc delete mode 100644 cddl/sbin/zfsd/dev_ctl_event.h delete mode 100644 cddl/sbin/zfsd/guid.cc delete mode 100644 cddl/sbin/zfsd/guid.h create mode 100644 cddl/sbin/zfsd/zfsd_event.cc create mode 100644 cddl/sbin/zfsd/zfsd_event.h create mode 100644 lib/libdevctl/Makefile create mode 100644 lib/libdevctl/consumer.cc create mode 100644 lib/libdevctl/consumer.h create mode 100644 lib/libdevctl/event.cc create mode 100644 lib/libdevctl/event.h create mode 100644 lib/libdevctl/event_buffer.cc create mode 100644 lib/libdevctl/event_buffer.h create mode 100644 lib/libdevctl/event_factory.cc create mode 100644 lib/libdevctl/event_factory.h create mode 100644 lib/libdevctl/exception.cc create mode 100644 lib/libdevctl/exception.h create mode 100644 lib/libdevctl/guid.cc create mode 100644 lib/libdevctl/guid.h create mode 100644 lib/libdevctl/reader.cc create mode 100644 lib/libdevctl/reader.h (limited to 'etc') diff --git a/cddl/sbin/zfsd/Makefile b/cddl/sbin/zfsd/Makefile index 82df7d493a4e..58caefb77a0e 100644 --- a/cddl/sbin/zfsd/Makefile +++ b/cddl/sbin/zfsd/Makefile @@ -1,44 +1,7 @@ # $FreeBSD$ -PROG_CXX= zfsd -SRCS= callout.cc \ - case_file.cc \ - dev_ctl_event.cc \ - guid.cc \ - vdev.cc \ - vdev_iterator.cc \ - zfsd.cc \ - zfsd_exception.cc \ - zpool_list.cc \ - zfsd_main.cc - -NO_MAN= YES - -WARNS?= 1 - -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common -INCFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include -INCFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem -INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libumem/common -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common -INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair -INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs -INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common -INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs -INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys +.include "Makefile.common" -CFLAGS= -Wall -g -DNEED_SOLARIS_BOOLEAN ${INCFLAGS} - -DPADD= ${LIBZFS} ${LIBUTIL} ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} \ - ${LIBNVPAIR} ${LIBUUTIL} -LDADD= -lzfs -lutil -lgeom -lbsdxml -lsbuf -lnvpair -luutil - -cscope: - find ${.CURDIR} -type f -a \( -name "*.[ch]" -o -name "*.cc" \) \ - > ${.CURDIR}/cscope.files - cd ${.CURDIR} && cscope -buq ${INCFLAGS} +PROG_CXX= zfsd .include diff --git a/cddl/sbin/zfsd/Makefile.common b/cddl/sbin/zfsd/Makefile.common new file mode 100644 index 000000000000..65fecb5c5f23 --- /dev/null +++ b/cddl/sbin/zfsd/Makefile.common @@ -0,0 +1,43 @@ +# $FreeBSD$ + +SRCS= callout.cc \ + case_file.cc \ + zfsd_event.cc \ + vdev.cc \ + vdev_iterator.cc \ + zfsd.cc \ + zfsd_exception.cc \ + zpool_list.cc \ + zfsd_main.cc + +NO_MAN= YES + +WARNS?= 3 + +# Ignore warnings about Solaris specific pragmas. +IGNORE_PRAGMA= YES + +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common +INCFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include +INCFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem +INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/head +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libuutil/common +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libumem/common +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzfs/common +INCFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libnvpair +INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs +INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common +INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs +INCFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys + +CFLAGS= -g -DNEED_SOLARIS_BOOLEAN ${INCFLAGS} + +DPADD= ${LIBDEVCTL} ${LIBZFS} ${LIBUTIL} ${LIBGEOM} ${LIBBSDXML} ${LIBSBUF} \ + ${LIBNVPAIR} ${LIBUUTIL} +LDADD= -ldevctl -lzfs -lutil -lgeom -lbsdxml -lsbuf -lnvpair -luutil + +cscope: + find ${.CURDIR} -type f -a \( -name "*.[ch]" -o -name "*.cc" \) \ + > ${.CURDIR}/cscope.files + cd ${.CURDIR} && cscope -buq ${INCFLAGS} diff --git a/cddl/sbin/zfsd/callout.cc b/cddl/sbin/zfsd/callout.cc index b15995964766..1f1735cdcb36 100644 --- a/cddl/sbin/zfsd/callout.cc +++ b/cddl/sbin/zfsd/callout.cc @@ -37,10 +37,23 @@ * timer services built on top of the POSIX interval timer. */ +#include + #include #include +#include +#include +#include + +#include +#include +#include +#include +#include + #include "callout.h" +#include "vdev_iterator.h" #include "zfsd.h" #include "zfsd_exception.h" diff --git a/cddl/sbin/zfsd/callout.h b/cddl/sbin/zfsd/callout.h index 897bcea62f54..83732dd3c7a6 100644 --- a/cddl/sbin/zfsd/callout.h +++ b/cddl/sbin/zfsd/callout.h @@ -34,15 +34,17 @@ * \file callout.h * * \brief Interface for timer based callback services. + * + * Header requirements: + * + * #include + * + * #include */ #ifndef _CALLOUT_H_ #define _CALLOUT_H_ -#include - -#include - /** * \brief Type of the function callback from a Callout. */ diff --git a/cddl/sbin/zfsd/case_file.cc b/cddl/sbin/zfsd/case_file.cc index 15deaabc71e5..a3442473bc83 100644 --- a/cddl/sbin/zfsd/case_file.cc +++ b/cddl/sbin/zfsd/case_file.cc @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Spectra Logic Corporation + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,11 @@ * across reboots. For now, this is just a log of soft errors which we * accumulate in order to mark a device as degraded. */ +#include +#include + +#include + #include #include #include @@ -46,12 +51,31 @@ #include #include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "callout.h" +#include "zfsd_event.h" #include "case_file.h" #include "vdev.h" +#include "vdev_iterator.h" #include "zfsd.h" #include "zfsd_exception.h" #include "zpool_list.h" +__FBSDID("$FreeBSD$"); + /*============================ Namespace Control =============================*/ using std::auto_ptr; using std::hex; @@ -60,26 +84,43 @@ using std::stringstream; using std::setfill; using std::setw; +using DevCtl::Event; +using DevCtl::EventBuffer; +using DevCtl::EventFactory; +using DevCtl::EventList; +using DevCtl::Guid; +using DevCtl::IstreamReader; +using DevCtl::ParseException; + /*-------------------------- File-scoped classes ----------------------------*/ /** * \brief Functor that operators on STL collections of CaseFiles + * * Selectively calls ReEvaluate on the casefile, based on its pool GUID. */ class CaseFileReEvaluator : public std::unary_function { public: - CaseFileReEvaluator(Guid guid, const ZfsEvent &event) : - m_poolGUID(guid), m_event(event) {}; - void operator() (CaseFile *casefile) { - if (m_poolGUID == casefile->PoolGUID()) - casefile->ReEvaluate(m_event); - } + CaseFileReEvaluator(Guid guid, const ZfsEvent &event); + + void operator() (CaseFile *casefile); + private: Guid m_poolGUID; - const ZfsEvent &m_event; + const ZfsEvent &m_event; }; +CaseFileReEvaluator::CaseFileReEvaluator(Guid guid, const ZfsEvent &event) + : m_poolGUID(guid), m_event(event) +{ +} +void +CaseFileReEvaluator::operator() (CaseFile *casefile) +{ + if (m_poolGUID == casefile->PoolGUID()) + casefile->ReEvaluate(m_event); +} /*--------------------------------- CaseFile ---------------------------------*/ //- CaseFile Static Data ------------------------------------------------------- @@ -88,7 +129,6 @@ const string CaseFile::s_caseFilePath = "/etc/zfs/cases"; const timeval CaseFile::s_removeGracePeriod = { 60 /*sec*/, 0 /*usec*/}; //- CaseFile Static Public Methods --------------------------------------------- - CaseFile * CaseFile::Find(Guid poolGUID, Guid vdevGUID) { @@ -509,7 +549,7 @@ CaseFile::ActivateSpare() { } void -CaseFile::RegisterCallout(const DevCtlEvent &event) +CaseFile::RegisterCallout(const Event &event) { timeval now, countdown, elapsed, timestamp, zero, remaining; @@ -594,13 +634,13 @@ CaseFile::Log() zpool_state_to_name(VdevState(), VDEV_AUX_NONE)); if (m_tentativeEvents.size() != 0) { syslog(LOG_INFO, "\t=== Tentative Events ===\n"); - for (DevCtlEventList::iterator event(m_tentativeEvents.begin()); + for (EventList::iterator event(m_tentativeEvents.begin()); event != m_tentativeEvents.end(); event++) (*event)->Log(LOG_INFO); } if (m_events.size() != 0) { syslog(LOG_INFO, "\t=== Events ===\n"); - for (DevCtlEventList::iterator event(m_events.begin()); + for (EventList::iterator event(m_events.begin()); event != m_events.end(); event++) (*event)->Log(LOG_INFO); } @@ -738,7 +778,7 @@ CaseFile::~CaseFile() void CaseFile::PurgeEvents() { - for (DevCtlEventList::iterator event(m_events.begin()); + for (EventList::iterator event(m_events.begin()); event != m_events.end(); event++) delete *event; @@ -748,7 +788,7 @@ CaseFile::PurgeEvents() void CaseFile::PurgeTentativeEvents() { - for (DevCtlEventList::iterator event(m_tentativeEvents.begin()); + for (EventList::iterator event(m_tentativeEvents.begin()); event != m_tentativeEvents.end(); event++) delete *event; @@ -756,12 +796,12 @@ CaseFile::PurgeTentativeEvents() } void -CaseFile::SerializeEvList(const DevCtlEventList events, int fd, +CaseFile::SerializeEvList(const EventList events, int fd, const char* prefix) const { if (events.empty()) return; - for (DevCtlEventList::const_iterator curEvent = events.begin(); + for (EventList::const_iterator curEvent = events.begin(); curEvent != events.end(); curEvent++) { const string &eventString((*curEvent)->GetEventString()); @@ -816,7 +856,7 @@ CaseFile::DeSerialize(ifstream &caseStream) * call ExtractEvent * continue */ - DevCtlEventList* destEvents; + EventList* destEvents; string tentFlag("tentative "); string line; std::stringbuf lineBuf; @@ -832,8 +872,9 @@ CaseFile::DeSerialize(ifstream &caseStream) } fakeDevdSocket << line; fakeDevdSocket << '\n'; + const EventFactory &factory(ZfsDaemon::Get().GetFactory()); while (eventBuffer.ExtractEvent(evString)) { - DevCtlEvent *event(DevCtlEvent::CreateEvent(evString)); + Event *event(Event::CreateEvent(factory, evString)); if (event != NULL) { destEvents->push_back(event); RegisterCallout(*event); @@ -993,23 +1034,29 @@ CaseFile::Replace(const char* vdev_type, const char* path) { } /* Does the argument event refer to a checksum error? */ -static bool IsChecksumEvent(const DevCtlEvent* const event){ +static bool +IsChecksumEvent(const Event* const event) +{ return ("ereport.fs.zfs.checksum" == event->Value("type")); } /* Does the argument event refer to an IO error? */ -static bool IsIOEvent(const DevCtlEvent* const event){ +static bool +IsIOEvent(const Event* const event) +{ return ("ereport.fs.zfs.io" == event->Value("type")); } bool -CaseFile::ShouldDegrade() const { +CaseFile::ShouldDegrade() const +{ return (std::count_if(m_events.begin(), m_events.end(), IsChecksumEvent) > ZFS_DEGRADE_IO_COUNT); } bool -CaseFile::ShouldFault() const { +CaseFile::ShouldFault() const +{ return (std::count_if(m_events.begin(), m_events.end(), IsIOEvent) > ZFS_DEGRADE_IO_COUNT); } diff --git a/cddl/sbin/zfsd/case_file.h b/cddl/sbin/zfsd/case_file.h index 3c757647849a..489645cb85f7 100644 --- a/cddl/sbin/zfsd/case_file.h +++ b/cddl/sbin/zfsd/case_file.h @@ -37,18 +37,17 @@ * * CaseFile objects aggregate vdev faults that may require ZFSD action * in order to maintain the health of a ZFS pool. + * + * Header requirements: + * + * #include + * + * #include "callout.h" + * #include "zfsd_event.h" */ #ifndef _CASE_FILE_H_ #define _CASE_FILE_H_ -#include -#include - -#include - -#include "callout.h" -#include "dev_ctl_event.h" - /*=========================== Forward Declarations ===========================*/ class CaseFile; class Vdev; @@ -95,7 +94,7 @@ public: * \return If found, a pointer to a valid CaseFile object. * Otherwise NULL. */ - static CaseFile *Find(Guid poolGUID, Guid vdevGUID); + static CaseFile *Find(DevCtl::Guid poolGUID, DevCtl::Guid vdevGUID); /** * \brief Find a CaseFile object by a vdev's current/last known @@ -114,7 +113,8 @@ public: * \param poolGUID Only reevaluate cases for this pool * \param event Try to consume this event with the casefile */ - static void ReEvaluateByGuid(Guid poolGUID, const ZfsEvent &event); + static void ReEvaluateByGuid(DevCtl::Guid poolGUID, + const ZfsEvent &event); /** * \brief Create or return an existing active CaseFile for the @@ -145,8 +145,8 @@ public: */ static void PurgeAll(); - Guid PoolGUID() const; - Guid VdevGUID() const; + DevCtl::Guid PoolGUID() const; + DevCtl::Guid VdevGUID() const; vdev_state VdevState() const; const string &PoolGUIDString() const; const string &VdevGUIDString() const; @@ -171,6 +171,7 @@ public: /** * \brief Update this CaseFile in light of the provided ZfsEvent. + * * Must be virtual so it can be overridden in the unit tests * * \param event The ZfsEvent to evaluate. @@ -182,7 +183,7 @@ public: /** * \brief Register an itimer callout for the given event, if necessary */ - virtual void RegisterCallout(const DevCtlEvent &event); + virtual void RegisterCallout(const DevCtl::Event &event); /** * \brief Close a case if it is no longer relevant. @@ -289,7 +290,7 @@ protected: * \param prefix If not NULL, this prefix will be prepended to * every event in the file. */ - void SerializeEvList(const DevCtlEventList events, int fd, + void SerializeEvList(const DevCtl::EventList events, int fd, const char* prefix=NULL) const; /** @@ -327,7 +328,6 @@ protected: * \param path The file system path to the new vdev * * \return true iff the replacement was successful - * */ bool Replace(const char* vdev_type, const char* path); @@ -351,35 +351,35 @@ protected: * \brief A list of soft error events counted against the health of * a vdev. */ - DevCtlEventList m_events; + DevCtl::EventList m_events; /** * \brief A list of soft error events waiting for a grace period * expiration before being counted against the health of * a vdev. */ - DevCtlEventList m_tentativeEvents; + DevCtl::EventList m_tentativeEvents; - Guid m_poolGUID; - Guid m_vdevGUID; - vdev_state m_vdevState; - string m_poolGUIDString; - string m_vdevGUIDString; - string m_vdevPhysPath; + DevCtl::Guid m_poolGUID; + DevCtl::Guid m_vdevGUID; + vdev_state m_vdevState; + string m_poolGUIDString; + string m_vdevGUIDString; + string m_vdevPhysPath; /** * \brief Callout activated when a grace period */ - Callout m_tentativeTimer; + Callout m_tentativeTimer; }; -inline Guid +inline DevCtl::Guid CaseFile::PoolGUID() const { return (m_poolGUID); } -inline Guid +inline DevCtl::Guid CaseFile::VdevGUID() const { return (m_vdevGUID); diff --git a/cddl/sbin/zfsd/dev_ctl_event.cc b/cddl/sbin/zfsd/dev_ctl_event.cc deleted file mode 100644 index 57d44721bd90..000000000000 --- a/cddl/sbin/zfsd/dev_ctl_event.cc +++ /dev/null @@ -1,731 +0,0 @@ -/*- - * Copyright (c) 2011 Spectra Logic Corporation - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - */ - -/** - * \file dev_ctl_event.cc - * - * Implementation of the class hierarchy used to express events - * received via the devctl API. - */ -#include -#include -#include -#include -#include -#include -#include - -#include "case_file.h" -#include "dev_ctl_event.h" -#include "vdev.h" -#include "zfsd.h" -#include "zfsd_exception.h" -#include "zpool_list.h" - -/*============================ Namespace Control =============================*/ -using std::cerr; -using std::cout; -using std::endl; -using std::stringstream; - -/*=========================== Class Implementations ==========================*/ -/*------------------------------ ParseException ------------------------------*/ -//- ParseException Public Methods ---------------------------------------------- -string -ParseException::ToString() const -{ - stringstream result; - - result << "Parsing "; - - switch (Type()) { - case INVALID_FORMAT: - result << "invalid format "; - break; - case DISCARDED_EVENT_TYPE: - result << "discarded event "; - break; - case UNKNOWN_EVENT_TYPE: - result << "unknown event "; - break; - default: - break; - } - result << "exception on buffer: \'"; - if (GetOffset() == 0) { - result << m_parsedBuffer << '\'' << endl; - } else { - string markedBuffer(m_parsedBuffer); - - markedBuffer.insert(GetOffset(), ""); - result << markedBuffer << '\'' << endl; - } - - return (result.str()); -} - -void -ParseException::Log() const -{ - int priority(LOG_ERR); - - if (Type() == DISCARDED_EVENT_TYPE) - priority = LOG_INFO; - - syslog(priority, "%s", ToString().c_str()); -} - -/*-------------------------------- DevCtlEvent -------------------------------*/ -//- DevCtlEvent Static Protected Data ------------------------------------------ -const string DevCtlEvent::s_theEmptyString; - -DevCtlEvent::EventTypeRecord DevCtlEvent::s_typeTable[] = -{ - { DevCtlEvent::NOTIFY, "Notify" }, - { DevCtlEvent::NOMATCH, "No Driver Match" }, - { DevCtlEvent::ATTACH, "Attach" }, - { DevCtlEvent::DETACH, "Detach" } -}; - -DevCtlEvent::EventFactoryRecord DevCtlEvent::s_factoryTable[] = -{ - { DevCtlEvent::NOTIFY, "DEVFS", &DevfsEvent::DevfsEventFactory }, - { DevCtlEvent::NOTIFY, "ZFS", &ZfsEvent::ZfsEventFactory} -}; - -DevCtlEvent::EventFactoryRegistry DevCtlEvent::s_factoryRegistry; - -//- DevCtlEvent Static Public Methods ------------------------------------------ -void -DevCtlEvent::Init() -{ - EventFactoryRecord *rec(s_factoryTable); - EventFactoryRecord *lastRec(s_factoryTable - + NUM_ELEMENTS(s_factoryTable) - 1); - - for (; rec <= lastRec; rec++) { - EventFactoryKey key(rec->m_type, rec->m_subsystem); - - s_factoryRegistry[key] = rec->m_method; - } -} - -DevCtlEvent * -DevCtlEvent::CreateEvent(const string &eventString) -{ - NVPairMap &nvpairs(*new NVPairMap); - Type type(static_cast(eventString[0])); - - try { - ParseEventString(type, eventString, nvpairs); - } catch (const ParseException &exp) { - if (exp.GetType() == ParseException::INVALID_FORMAT) - exp.Log(); - return (NULL); - } - - /* - * Allow entries in our table for events with no system specified. - * These entries should specify the string "none". - */ - NVPairMap::iterator system_item(nvpairs.find("system")); - if (system_item == nvpairs.end()) - nvpairs["system"] = "none"; - - EventFactoryKey key(type, nvpairs["system"]); - EventFactoryRegistry::iterator foundMethod(s_factoryRegistry.find(key)); - if (foundMethod == s_factoryRegistry.end()) { - syslog(LOG_INFO, "DevCtlEvent::CreateEvent: unhandled event %s", - eventString.c_str()); - return (NULL); - } - return ((foundMethod->second)(type, nvpairs, eventString)); -} - -const char * -DevCtlEvent::TypeToString(DevCtlEvent::Type type) -{ - EventTypeRecord *rec(s_typeTable); - EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1); - - for (; rec <= lastRec; rec++) { - if (rec->m_type == type) - return (rec->m_typeName); - } - return ("Unknown"); -} - -//- DevCtlEvent Public Methods ------------------------------------------------- -const string & -DevCtlEvent::Value(const string &varName) const -{ - NVPairMap::const_iterator item(m_nvPairs.find(varName)); - if (item == m_nvPairs.end()) - return (s_theEmptyString); - - return (item->second); -} - -bool -DevCtlEvent::Contains(const string &varName) const -{ - return (m_nvPairs.find(varName) != m_nvPairs.end()); -} - -string -DevCtlEvent::ToString() const -{ - stringstream result; - - NVPairMap::const_iterator devName(m_nvPairs.find("device-name")); - if (devName != m_nvPairs.end()) - result << devName->second << ": "; - - NVPairMap::const_iterator systemName(m_nvPairs.find("system")); - if (systemName != m_nvPairs.end() - && systemName->second != "none") - result << systemName->second << ": "; - - result << TypeToString(GetType()) << ' '; - - for (NVPairMap::const_iterator curVar = m_nvPairs.begin(); - curVar != m_nvPairs.end(); curVar++) { - if (curVar == devName || curVar == systemName) - continue; - - result << ' ' - << curVar->first << "=" << curVar->second; - } - result << endl; - - return (result.str()); -} - -void -DevCtlEvent::Print() const -{ - cout << ToString() << std::flush; -} - -void -DevCtlEvent::Log(int priority) const -{ - syslog(priority, "%s", ToString().c_str()); -} - -//- DevCtlEvent Virtual Public Methods ----------------------------------------- -DevCtlEvent::~DevCtlEvent() -{ - delete &m_nvPairs; -} - -bool -DevCtlEvent::Process() const -{ - return (false); -} - -timeval -DevCtlEvent::GetTimestamp() const -{ - timeval tv_timestamp; - struct tm tm_timestamp; - - if (!Contains("timestamp")) { - throw ZfsdException("Event contains no timestamp: %s", - m_eventString.c_str()); - } - strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp); - tv_timestamp.tv_sec = mktime(&tm_timestamp); - tv_timestamp.tv_usec = 0; - return (tv_timestamp); -} - - -//- DevCtlEvent Protected Methods ---------------------------------------------- -DevCtlEvent::DevCtlEvent(Type type, NVPairMap &map, const string &eventString) - : m_type(type), - m_nvPairs(map), - m_eventString(eventString) -{ -} - -DevCtlEvent::DevCtlEvent(const DevCtlEvent &src) - : m_type(src.m_type), - m_nvPairs(*new NVPairMap(src.m_nvPairs)), - m_eventString(src.m_eventString) -{ -} - -void -DevCtlEvent::ParseEventString(DevCtlEvent::Type type, - const string &eventString, - NVPairMap& nvpairs) -{ - size_t start; - size_t end; - - switch (type) { - case ATTACH: - case DETACH: - - /* - * \ - * at \ - * on - * - * Handle all data that doesn't conform to the - * "name=value" format, and let the generic parser - * below handle the rest. - * - * Type is a single char. Skip it. - */ - start = 1; - end = eventString.find_first_of(" \t\n", start); - if (end == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, start); - - nvpairs["device-name"] = eventString.substr(start, end - start); - - start = eventString.find(" on ", end); - if (end == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, start); - start += 4; - end = eventString.find_first_of(" \t\n", start); - nvpairs["parent"] = eventString.substr(start, end); - break; - case NOTIFY: - break; - case NOMATCH: - throw ParseException(ParseException::DISCARDED_EVENT_TYPE, - eventString); - default: - throw ParseException(ParseException::UNKNOWN_EVENT_TYPE, - eventString); - } - - /* Process common "key=value" format. */ - for (start = 1; start < eventString.length(); start = end + 1) { - - /* Find the '=' in the middle of the key/value pair. */ - end = eventString.find('=', start); - if (end == string::npos) - break; - - /* - * Find the start of the key by backing up until - * we hit whitespace or '!' (event type "notice"). - * Due to the devctl format, all key/value pair must - * start with one of these two characters. - */ - start = eventString.find_last_of("! \t\n", end); - if (start == string::npos) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, end); - start++; - string key(eventString.substr(start, end - start)); - - /* - * Walk forward from the '=' until either we exhaust - * the buffer or we hit whitespace. - */ - start = end + 1; - if (start >= eventString.length()) - throw ParseException(ParseException::INVALID_FORMAT, - eventString, end); - end = eventString.find_first_of(" \t\n", start); - if (end == string::npos) - end = eventString.length() - 1; - string value(eventString.substr(start, end - start)); - - nvpairs[key] = value; - } -} - -/*-------------------------------- DevfsEvent --------------------------------*/ -//- DevfsEvent Static Public Methods ------------------------------------------- -DevCtlEvent * -DevfsEvent::DevfsEventFactory(DevCtlEvent::Type type, NVPairMap &nvPairs, - const string &eventString) -{ - return (new DevfsEvent(type, nvPairs, eventString)); -} - -//- DevfsEvent Static Protected Methods ---------------------------------------- -bool -DevfsEvent::IsDiskDev(const string &devName) -{ - static const char *diskDevNames[] = - { - "da", - "ada" - }; - - const char **diskName(diskDevNames); - const char **lastDiskName(diskDevNames - + NUM_ELEMENTS(diskDevNames) - 1); - size_t find_start = devName.rfind('/'); - if (find_start == string::npos) { - find_start = 0; - } else { - /* Just after the last '/'. */ - find_start++; - } - - for (; diskName <= lastDiskName; diskName++) { - - size_t loc(devName.find(*diskName, find_start)); - if (loc == find_start) { - size_t prefixLen(strlen(*diskName)); - - if (devName.length() - find_start >= prefixLen - && isdigit(devName[find_start + prefixLen])) - return (true); - } - } - - return (false); -} - -bool -DevfsEvent::IsWholeDev(const string &devName) -{ - string::const_iterator i(devName.begin()); - - size_t start = devName.rfind('/'); - if (start == string::npos) { - start = 0; - } else { - /* Just after the last '/'. */ - start++; - } - i += start; - - /* alpha prefix followed only by digits. */ - for (; i < devName.end() && !isdigit(*i); i++) - ; - - if (i == devName.end()) - return (false); - - for (; i < devName.end() && isdigit(*i); i++) - ; - - return (i == devName.end()); -} - -nvlist_t * -DevfsEvent::ReadLabel(int devFd, bool &inUse, bool °raded) -{ - pool_state_t poolState; - char *poolName; - boolean_t b_inuse; - - inUse = false; - degraded = false; - poolName = NULL; - if (zpool_in_use(g_zfsHandle, devFd, &poolState, - &poolName, &b_inuse) == 0) { - nvlist_t *devLabel; - - inUse = b_inuse == B_TRUE; - if (poolName != NULL) - free(poolName); - - if (zpool_read_label(devFd, &devLabel) != 0 - || devLabel == NULL) - return (NULL); - - try { - Vdev vdev(devLabel); - degraded = vdev.State() != VDEV_STATE_HEALTHY; - return (devLabel); - } catch (ZfsdException &exp) { - string devName = fdevname(devFd); - string devPath = _PATH_DEV + devName; - string context("DevfsEvent::ReadLabel: " + devPath + ": "); - - exp.GetString().insert(0, context); - exp.Log(); - } - } - return (NULL); -} - -bool -DevfsEvent::OnlineByLabel(const string &devPath, const string& physPath, - nvlist_t *devConfig) -{ - try { - /* - * A device with ZFS label information has been - * inserted. If it matches a device for which we - * have a case, see if we can solve that case. - */ - syslog(LOG_INFO, "Interrogating VDEV label for %s\n", - devPath.c_str()); - Vdev vdev(devConfig); - CaseFile *caseFile(CaseFile::Find(vdev.PoolGUID(), - vdev.GUID())); - if (caseFile != NULL) - return (caseFile->ReEvaluate(devPath, physPath, &vdev)); - - } catch (ZfsdException &exp) { - string context("DevfsEvent::OnlineByLabel: " + devPath + ": "); - - exp.GetString().insert(0, context); - exp.Log(); - } - return (false); -} - -//- DevfsEvent Virtual Public Methods ------------------------------------------ -DevCtlEvent * -DevfsEvent::DeepCopy() const -{ - return (new DevfsEvent(*this)); -} - -bool -DevfsEvent::Process() const -{ - /* - * We are only concerned with newly discovered - * devices that can be ZFS vdevs. - */ - string devName(Value("cdev")); - if (Value("type") != "CREATE" - || Value("subsystem") != "CDEV" - || !IsDiskDev(devName)) - return (false); - - /* Log the event since it is of interest. */ - Log(LOG_INFO); - - string devPath(_PATH_DEV + devName); - int devFd(open(devPath.c_str(), O_RDONLY)); - if (devFd == -1) - return (false); - - /* Normalize the device name in case the DEVFS event is for a link. */ - devName = fdevname(devFd); - devPath = _PATH_DEV + devName; - - bool inUse; - bool degraded; - nvlist_t *devLabel(ReadLabel(devFd, inUse, degraded)); - - char physPath[MAXPATHLEN]; - physPath[0] = '\0'; - bool havePhysPath(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0); - - close(devFd); - - if (inUse && devLabel != NULL) { - OnlineByLabel(devPath, physPath, devLabel); - } else if (degraded) { - syslog(LOG_INFO, "%s is marked degraded. Ignoring " - "as a replace by physical path candidate.\n", - devName.c_str()); - } else if (havePhysPath && IsWholeDev(devName)) { - syslog(LOG_INFO, "Searching for CaseFile by Physical Path\n"); - CaseFile *caseFile(CaseFile::Find(physPath)); - if (caseFile != NULL) { - syslog(LOG_INFO, - "Found CaseFile(%s:%s:%s) - ReEvaluating\n", - caseFile->PoolGUIDString().c_str(), - caseFile->VdevGUIDString().c_str(), - zpool_state_to_name(caseFile->VdevState(), - VDEV_AUX_NONE)); - caseFile->ReEvaluate(devPath, physPath, /*vdev*/NULL); - } - } - if (devLabel != NULL) - nvlist_free(devLabel); - return (false); -} - -//- DevfsEvent Protected Methods ----------------------------------------------- -DevfsEvent::DevfsEvent(DevCtlEvent::Type type, NVPairMap &nvpairs, - const string &eventString) - : DevCtlEvent(type, nvpairs, eventString) -{ -} - -DevfsEvent::DevfsEvent(const DevfsEvent &src) - : DevCtlEvent(src) -{ -} - -/*--------------------------------- ZfsEvent ---------------------------------*/ -//- ZfsEvent Static Public Methods --------------------------------------------- -DevCtlEvent * -ZfsEvent::ZfsEventFactory(DevCtlEvent::Type type, NVPairMap &nvpairs, - const string &eventString) -{ - return (new ZfsEvent(type, nvpairs, eventString)); -} - -//- ZfsEvent Virtual Public Methods -------------------------------------------- -DevCtlEvent * -ZfsEvent::DeepCopy() const -{ - return (new ZfsEvent(*this)); -} - -bool -ZfsEvent::Process() const -{ - string logstr(""); - - if (!Contains("class") && !Contains("type")) { - syslog(LOG_ERR, - "ZfsEvent::Process: Missing class or type data."); - return (false); - } - - /* On config syncs, replay any queued events first. */ - if (Value("type").find("misc.fs.zfs.config_sync") == 0) { - ZfsDaemon::ReplayUnconsumedEvents(); - CaseFile::ReEvaluateByGuid(PoolGUID(), *this); - } - - Log(LOG_INFO); - - if (Value("type").find("misc.fs.zfs.") == 0) { - /* Configuration changes, resilver events, etc. */ - ProcessPoolEvent(); - return (false); - } - - if (!Contains("pool_guid") || !Contains("vdev_guid")) { - /* Only currently interested in Vdev related events. */ - return (false); - } - - CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID())); - if (caseFile != NULL) { - syslog(LOG_INFO, "Evaluating existing case file\n"); - caseFile->ReEvaluate(*this); - return (false); - } - - /* Skip events that can't be handled. */ - Guid poolGUID(PoolGUID()); - /* If there are no replicas for a pool, then it's not manageable. */ - if (Value("class").find("fs.zfs.vdev.no_replicas") == 0) { - stringstream msg; - msg << "No replicas available for pool " << poolGUID; - msg << ", ignoring"; - syslog(LOG_INFO, "%s", msg.str().c_str()); - return (false); - } - - /* - * Create a case file for this vdev, and have it - * evaluate the event. - */ - ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID); - if (zpl.empty()) { - stringstream msg; - int priority = LOG_INFO; - msg << "ZfsEvent::Process: Event for unknown pool "; - msg << poolGUID << " "; - msg << "queued"; - syslog(priority, "%s", msg.str().c_str()); - return (true); - } - - nvlist_t *vdevConfig = VdevIterator(zpl.front()).Find(VdevGUID()); - if (vdevConfig == NULL) { - stringstream msg; - int priority = LOG_INFO; - msg << "ZfsEvent::Process: Event for unknown vdev "; - msg << VdevGUID() << " "; - msg << "queued"; - syslog(priority, "%s", msg.str().c_str()); - return (true); - } - - Vdev vdev(zpl.front(), vdevConfig); - caseFile = &CaseFile::Create(vdev); - if ( caseFile->ReEvaluate(*this) == false) { - stringstream msg; - int priority = LOG_INFO; - msg << "ZfsEvent::Process: Unconsumed event for vdev("; - msg << zpool_get_name(zpl.front()) << ","; - msg << vdev.GUID() << ") "; - msg << "queued"; - syslog(priority, "%s", msg.str().c_str()); - return (true); - } - return (false); -} - -//- ZfsEvent Protected Methods ------------------------------------------------- -ZfsEvent::ZfsEvent(DevCtlEvent::Type type, NVPairMap &nvpairs, - const string &eventString) - : DevCtlEvent(type, nvpairs, eventString), - m_poolGUID(Guid(Value("pool_guid"))), - m_vdevGUID(Guid(Value("vdev_guid"))) -{ -} - -ZfsEvent::ZfsEvent(const ZfsEvent &src) - : DevCtlEvent(src), - m_poolGUID(src.m_poolGUID), - m_vdevGUID(src.m_vdevGUID) -{ -} - -void -ZfsEvent::ProcessPoolEvent() const -{ - bool degradedDevice(false); - - CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID())); - if (caseFile != NULL) { - if (caseFile->VdevState() != VDEV_STATE_UNKNOWN - && caseFile->VdevState() < VDEV_STATE_HEALTHY) - degradedDevice = true; - - caseFile->ReEvaluate(*this); - } - - if (Value("type") == "misc.fs.zfs.vdev_remove" - && degradedDevice == false) { - /* See if any other cases can make use of this device. */ - ZfsDaemon::RequestSystemRescan(); - } -} diff --git a/cddl/sbin/zfsd/dev_ctl_event.h b/cddl/sbin/zfsd/dev_ctl_event.h deleted file mode 100644 index 51f81dddbfed..000000000000 --- a/cddl/sbin/zfsd/dev_ctl_event.h +++ /dev/null @@ -1,525 +0,0 @@ -/*- - * Copyright (c) 2011 Spectra Logic Corporation - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Justin T. Gibbs (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file dev_ctl_event.h - * - * \brief Class hierarchy used to express events received via - * the devctl API. - */ - -#ifndef _DEV_CTL_EVENT_H_ -#define _DEV_CTL_EVENT_H_ - -#include -#include -#include - -#include -#include - -#include "vdev.h" - -/*============================ Namespace Control =============================*/ -using std::map; -using std::pair; -using std::string; - -/*============================= Class Definitions ============================*/ -/*------------------------------ ParseException ------------------------------*/ -/** - * Exception thrown when an event string is not converted to an actionable - * DevCtlEvent object. - */ -class ParseException -{ -public: - enum Type - { - /** Improperly formatted event string encounterd. */ - INVALID_FORMAT, - - /** No handlers for this event type. */ - DISCARDED_EVENT_TYPE, - - /** Unhandled event type. */ - UNKNOWN_EVENT_TYPE - }; - - /** - * Constructor - * - * \param type The type of this exception. - * \param parsedBuffer The parsing buffer active at the time of - * the exception. - * \param offset The location in the parse buffer where this - * exception occurred. - */ - ParseException(Type type, const string &parsedBuffer, - size_t offset = 0); - - /** - * Accessor - * - * \return The classification for this exception. - */ - Type GetType() const; - - /** - * Accessor - * - * \return The offset into the event string where this exception - * occurred. - */ - size_t GetOffset() const; - - /** - * Convert an exception into a human readable string. - * - * \param parsedBuffer The event buffer that caused the failure. - */ - string ToString() const; - - /** - * Log exception data to syslog. - * - * \param parsedBuffer The event buffer that caused the failure. - */ - void Log() const; - -private: - /** The type of this exception. */ - Type m_type; - - /** The parsing buffer that was active at the time of the exception. */ - const string m_parsedBuffer; - - /** - * The offset into the event string buffer from where this - * exception was triggered. - */ - size_t m_offset; -}; - -//- ParseException Inline Public Methods --------------------------------------- -inline -ParseException::ParseException(Type type, const string &parsedBuffer, - size_t offset) - : m_type(type), - m_parsedBuffer(parsedBuffer), - m_offset(offset) -{ -} - -//- ParseException Inline Const Public Methods --------------------------------- -inline ParseException::Type -ParseException::GetType() const -{ - return (m_type); -} - -inline size_t -ParseException::GetOffset() const -{ - return (m_offset); -} - -/*-------------------------------- NVPairMap ---------------------------------*/ -/** - * NVPairMap is a specialization of the standard map STL container. - */ -typedef map NVPairMap; - -/*-------------------------------- DevCtlEvent -------------------------------*/ -/** - * \brief Container for the name => value pairs that comprise the content of - * a device control event. - * - * All name => value data for events can be accessed via the Contains() - * and Value() methods. name => value pairs for data not explicitly - * received as a name => value pair are synthesized during parsing. For - * example, ATTACH and DETACH events have "device-name" and "parent" - * name => value pairs added. - */ -class DevCtlEvent -{ -public: - /** Event type */ - enum Type { - /** Generic event notification. */ - NOTIFY = '!', - - /** A driver was not found for this device. */ - NOMATCH = '?', - - /** A bus device instance has been added. */ - ATTACH = '+', - - /** A bus device instance has been removed. */ - DETACH = '-' - }; - - /** Prepare the DevCtlEvent class for processing of events. */ - static void Init(); - - /** - * Factory method for creating events. - * - * \param buffer String representing a single event received - * from devd. - * - * \note Init() must be invoked prior to the first call to - * CreateEvent(). - */ - static DevCtlEvent *CreateEvent(const string &buffer); - - /** - * Provide a user friendly string representation of an - * event type. - * - * \param type The type of event to map to a string. - * - * \return A user friendly string representing the input type. - */ - static const char *TypeToString(Type type); - - /** - * Determine the availability of a name => value pair by name. - * - * \param name The key name to search for in this event instance. - * - * \return true if the specified key is available in this - * event, otherwise false. - */ - bool Contains(const string &name) const; - - /** - * \param key The name of the key for which to retrieve its - * associated value. - * - * \return A const reference to the string representing the - * value associated with key. - * - * \note For key's with no registered value, the empty string - * is returned. - */ - const string &Value(const string &key) const; - - /** - * Get the type of this event instance. - * - * \return The type of this event instance. - */ - Type GetType() const; - - /** - * Get the orginal DevCtl event string for this event. - * - * \return The DevCtl event string. - */ - const string &GetEventString() const; - - /** - * Convert the event instance into a string suitable for - * printing to the console or emitting to syslog. - * - * \return A string of formatted event data. - */ - string ToString() const; - - /** - * Pretty-print this event instance to cout. - */ - void Print() const; - - /** - * Pretty-print this event instance to syslog. - * - * \param priority The logging priority/facility. - * See syslog(3). - */ - void Log(int priority) const; - - /** - * Create and return a fully independent clone - * of this event. - */ - virtual DevCtlEvent *DeepCopy() const = 0; - - /** Destructor */ - virtual ~DevCtlEvent(); - - /** - * Interpret and perform any actions necessary to - * consume the event. - * \return True if this event should be queued for later reevaluation - */ - virtual bool Process() const; - - /** - * Get the time that the event was created - */ - timeval GetTimestamp() const; - -protected: - /** Table entries used to map a type to a user friendly string. */ - struct EventTypeRecord - { - Type m_type; - const char *m_typeName; - }; - - /** - * Event creation handlers are matched by event type and a - * string representing the system emitting the event. - */ - typedef pair EventFactoryKey; - - /** - * Event factory methods construct a DevCtlEvent given - * the type of event and an NVPairMap populated from - * the event string received from devd. - */ - typedef DevCtlEvent* (EventFactory)(Type, NVPairMap &, const string &); - - /** Map type for Factory method lookups. */ - typedef map EventFactoryRegistry; - - /** Table record of factory methods to add to our registry. */ - struct EventFactoryRecord - { - Type m_type; - const char *m_subsystem; - EventFactory *m_method; - }; - - /** - * Constructor - * - * \param type The type of event to create. - */ - DevCtlEvent(Type type, NVPairMap &map, const string &eventString); - - /** Deep copy constructor. */ - DevCtlEvent(const DevCtlEvent &src); - - /** Always empty string returned when NVPairMap lookups fail. */ - static const string s_theEmptyString; - - /** Unsorted table of event types. */ - static EventTypeRecord s_typeTable[]; - - /** Unsorted table of factory methods to add to our registry. */ - static EventFactoryRecord s_factoryTable[]; - - /** Registry of event factory methods providing O(log(n)) lookup. */ - static EventFactoryRegistry s_factoryRegistry; - - /** The type of this event. */ - const Type m_type; - - /** - * Event attribute storage. - * - * \note Although stored by reference (since m_nvPairs can - * never be NULL), the NVPairMap referenced by this field - * is dynamically allocated and owned by this event object. - * m_nvPairs must be deleted at event desctruction. - */ - NVPairMap &m_nvPairs; - - /** - * The unaltered event string, as received from devd, used to - * create this event object. - */ - string m_eventString; - -private: - /** - * Ingest event data from the supplied string. - * - * \param[in] eventString The string of devd event data to parse. - * \param[out] nvpairs Returns the parsed data - */ - static void ParseEventString(Type type, const string &eventString, - NVPairMap &nvpairs); -}; - -inline DevCtlEvent::Type -DevCtlEvent::GetType() const -{ - return (m_type); -} - -inline const string & -DevCtlEvent::GetEventString() const -{ - return (m_eventString); -} - -/*------------------------------ DevCtlEventList -----------------------------*/ -/** - * DevCtlEventList is a specialization of the standard list STL container. - */ -typedef std::list DevCtlEventList; - -/*-------------------------------- DevfsEvent --------------------------------*/ -class DevfsEvent : public DevCtlEvent -{ -public: - /** Specialized DevCtlEvent object factory for Devfs events. */ - static EventFactory DevfsEventFactory; - - virtual DevCtlEvent *DeepCopy() const; - - /** - * Interpret and perform any actions necessary to - * consume the event. - * \return True if this event should be queued for later reevaluation - */ - virtual bool Process() const; - -protected: - /** - * Determine if the given device name references a potential - * ZFS leaf vdev. - * - * \param devName The device name to test. - */ - static bool IsDiskDev(const string &devName); - - /** - * Given the device name of a disk, determine if the device - * represents the whole device, not just a partition. - * - * \param devName Device name of disk device to test. - * - * \return True if the device name represents the whole device. - * Otherwise false. - */ - static bool IsWholeDev(const string &devName); - - /** - * \brief Read and return label information for a device. - * - * \param devFd The device from which to read ZFS label information. - * \param inUse The device is part of an active or potentially - * active configuration. - * \param degraded The device label indicates the vdev is not healthy. - * - * \return If label information is available, an nvlist describing - * the vdev configuraiton found on the device specified by - * devFd. Otherwise NULL. - */ - static nvlist_t *ReadLabel(int devFd, bool &inUse, bool °raded); - - /** - * Attempt to match the ZFS labeled device at devPath with an active - * CaseFile for a missing vdev. If a CaseFile is found, attempt - * to re-integrate the device with its pool. - * - * \param devPath The devfs path to the potential leaf vdev. - * \param physPath The physical path string reported by the device - * at devPath. - * \param devConfig The ZFS label information found on the device - * at devPath. - * - * \return true if the event that caused the online action can - * be considered consumed. - */ - static bool OnlineByLabel(const string &devPath, - const string& physPath, - nvlist_t *devConfig); - - /** DeepCopy Constructor. */ - DevfsEvent(const DevfsEvent &src); - - /** Constructor */ - DevfsEvent(Type, NVPairMap &, const string &); -}; - -/*--------------------------------- ZfsEvent ---------------------------------*/ -class ZfsEvent : public DevCtlEvent -{ -public: - /** Specialized DevCtlEvent object factory for ZFS events. */ - static EventFactory ZfsEventFactory; - - virtual DevCtlEvent *DeepCopy() const; - - /** - * Interpret and perform any actions necessary to - * consume the event. - * \return True if this event should be queued for later reevaluation - */ - virtual bool Process() const; - - const string &PoolName() const; - Guid PoolGUID() const; - Guid VdevGUID() const; - -protected: - /** Constructor */ - ZfsEvent(Type, NVPairMap &, const string &); - - /** Deep copy constructor. */ - ZfsEvent(const ZfsEvent &src); - - virtual void ProcessPoolEvent() const; - - Guid m_poolGUID; - Guid m_vdevGUID; -}; - -//- ZfsEvent Inline Public Methods -------------------------------------------- -inline const string& -ZfsEvent::PoolName() const -{ - /* The pool name is reported as the subsystem of ZFS events. */ - return (Value("subsystem")); -} - -inline Guid -ZfsEvent::PoolGUID() const -{ - return (m_poolGUID); -} - -inline Guid -ZfsEvent::VdevGUID() const -{ - return (m_vdevGUID); -} - -#endif /*_DEV_CTL_EVENT_H_ */ diff --git a/cddl/sbin/zfsd/guid.cc b/cddl/sbin/zfsd/guid.cc deleted file mode 100644 index 08c1ce6a1070..000000000000 --- a/cddl/sbin/zfsd/guid.cc +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * Copyright (c) 2012 Spectra Logic Corporation - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file guid.cc - * - * Implementation of the Guid class. - */ -#include - -#include -#include -#include - -#include -#include - -#include "guid.h" - -__FBSDID("$FreeBSD$"); -/*============================ Namespace Control =============================*/ -using std::string; - -/*=========================== Class Implementations ==========================*/ -/*----------------------------------- Guid -----------------------------------*/ -Guid::Guid(const string &guidString) -{ - if (guidString.empty()) { - m_GUID = INVALID_GUID; - } else { - /* - * strtoumax() returns zero on conversion failure - * which nicely matches our choice for INVALID_GUID. - */ - m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0); - } -} - -std::ostream& -operator<< (std::ostream& out, Guid g) -{ - if (g.IsValid()) - out << (uint64_t)g; - else - out << "None"; - return (out); -} diff --git a/cddl/sbin/zfsd/guid.h b/cddl/sbin/zfsd/guid.h deleted file mode 100644 index ecfd7e015a47..000000000000 --- a/cddl/sbin/zfsd/guid.h +++ /dev/null @@ -1,137 +0,0 @@ -/*- - * Copyright (c) 2012 Spectra Logic Corporation - * 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, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. - * - * Authors: Alan Somers (Spectra Logic Corporation) - * - * $FreeBSD$ - */ - -/** - * \file guid.h - * - * Definition of the Guid class. - */ -#ifndef _GUID_H_ -#define _GUID_H_ - -#include - -/** - * \brief Object that represents guids. - * - * It can generally be manipulated as a uint64_t, but with a special - * value INVALID_GUID that does not equal any valid guid. - * - * As of this writing, spa_generate_guid() in spa_misc.c explicitly - * refuses to return a guid of 0. So this class uses 0 as the value - * for INVALID_GUID. In the future, if 0 is allowed to be a valid - * guid, the implementation of this class must change. - */ -class Guid -{ -public: - /* Constructors */ - Guid(); - Guid(uint64_t guid); - Guid(const std::string &guid); - - /* Assignment */ - Guid& operator=(const Guid& rhs); - - /* Test the validity of this guid. */ - bool IsValid() const; - - /* Comparison to other Guid operators */ - bool operator==(const Guid& rhs) const; - bool operator!=(const Guid& rhs) const; - - /* Integer conversion operators */ - operator uint64_t() const; - operator bool() const; - - static const uint64_t INVALID_GUID = 0; -protected: - /* The integer value of the GUID. */ - uint64_t m_GUID; -}; - -//- Guid Inline Public Methods ------------------------------------------------ -inline -Guid::Guid() - : m_GUID(INVALID_GUID) -{ -} - -inline -Guid::Guid(uint64_t guid) - : m_GUID(guid) -{ -} - -inline Guid& -Guid::operator=(const Guid &rhs) -{ - m_GUID = rhs.m_GUID; - return (*this); -} - -inline bool -Guid::IsValid() const -{ - return (m_GUID != INVALID_GUID); -} - -inline bool -Guid::operator==(const Guid& rhs) const -{ - return (m_GUID == rhs.m_GUID); -} - -inline bool -Guid::operator!=(const Guid& rhs) const -{ - return (m_GUID != rhs.m_GUID); -} - -inline -Guid::operator uint64_t() const -{ - return (m_GUID); -} - -inline -Guid::operator bool() const -{ - return (m_GUID != INVALID_GUID); -} - -/** Convert the GUID into its string representation */ -std::ostream& operator<< (std::ostream& out, Guid g); - -#endif /* _GUID_H_ */ diff --git a/cddl/sbin/zfsd/vdev.cc b/cddl/sbin/zfsd/vdev.cc index cd7d5e7ae002..f05413b122b1 100644 --- a/cddl/sbin/zfsd/vdev.cc +++ b/cddl/sbin/zfsd/vdev.cc @@ -38,15 +38,30 @@ * Implementation of the Vdev class. */ #include +#include +#include + +#include +#include +#include #include +#include +#include +#include +#include +#include +#include + #include "vdev.h" +#include "vdev_iterator.h" #include "zfsd.h" #include "zfsd_exception.h" __FBSDID("$FreeBSD$"); /*============================ Namespace Control =============================*/ +using std::string; using std::stringstream; /*=========================== Class Implementations ==========================*/ diff --git a/cddl/sbin/zfsd/vdev.h b/cddl/sbin/zfsd/vdev.h index ddeb9771f6f7..9c49b1a769fa 100644 --- a/cddl/sbin/zfsd/vdev.h +++ b/cddl/sbin/zfsd/vdev.h @@ -36,18 +36,25 @@ * \file vdev.h * * Definition of the Vdev class. + * + * Header requirements: + * + * #include + * + * #include */ #ifndef _VDEV_H_ #define _VDEV_H_ -#include -#include - -#include -#include +/*=========================== Forward Declarations ===========================*/ +struct zpool_handle; +typedef struct zpool_handle zpool_handle_t; -#include "guid.h" +struct nvlist; +typedef struct nvlist nvlist_t; +/*============================= Class Definitions ============================*/ +/*----------------------------------- Vdev -----------------------------------*/ /** * \brief Wrapper class for a vdev's name/value configuration list * simplifying access to commonly used vdev attributes. @@ -96,30 +103,30 @@ public: */ Vdev(nvlist_t *vdevConfig); - virtual Guid GUID() const; - virtual Guid PoolGUID() const; - virtual vdev_state State() const; - std::string Path() const; - virtual std::string PhysicalPath() const; - std::string GUIDString() const; - nvlist_t *PoolConfig() const; - nvlist_t *Config() const; + virtual DevCtl::Guid GUID() const; + virtual DevCtl::Guid PoolGUID() const; + virtual vdev_state State() const; + std::string Path() const; + virtual std::string PhysicalPath() const; + std::string GUIDString() const; + nvlist_t *PoolConfig() const; + nvlist_t *Config() const; private: - Guid m_poolGUID; - Guid m_vdevGUID; - nvlist_t *m_poolConfig; - nvlist_t *m_config; + DevCtl::Guid m_poolGUID; + DevCtl::Guid m_vdevGUID; + nvlist_t *m_poolConfig; + nvlist_t *m_config; }; //- Vdev Inline Public Methods ------------------------------------------------ -inline Guid +inline DevCtl::Guid Vdev::PoolGUID() const { return (m_poolGUID); } -inline Guid +inline DevCtl::Guid Vdev::GUID() const { return (m_vdevGUID); diff --git a/cddl/sbin/zfsd/vdev_iterator.cc b/cddl/sbin/zfsd/vdev_iterator.cc index ce624fbfcca4..6fac3259d91d 100644 --- a/cddl/sbin/zfsd/vdev_iterator.cc +++ b/cddl/sbin/zfsd/vdev_iterator.cc @@ -35,17 +35,27 @@ * * Implementation of the VdevIterator class. */ +#include +#include + #include #include -#include #include +#include +#include + +#include +#include + #include "vdev.h" #include "vdev_iterator.h" -#include "zfsd.h" #include "zfsd_exception.h" +/*============================ Namespace Control =============================*/ +using DevCtl::Guid; + /*=========================== Class Implementations ==========================*/ /*------------------------------- VdevIterator -------------------------------*/ VdevIterator::VdevIterator(zpool_handle_t *pool) diff --git a/cddl/sbin/zfsd/vdev_iterator.h b/cddl/sbin/zfsd/vdev_iterator.h index bf6709731639..398d0aec8e9b 100644 --- a/cddl/sbin/zfsd/vdev_iterator.h +++ b/cddl/sbin/zfsd/vdev_iterator.h @@ -34,16 +34,21 @@ * \file vdev_iterator.h * * VdevIterator class definition. + * + * Header requirements: + * + * #include */ #ifndef _VDEV_ITERATOR_H_ #define _VDEV_ITERATOR_H_ -#include +/*=========================== Forward Declarations ===========================*/ +struct zpool_handle; +typedef struct zpool_handle zpool_handle_t; -#include -#include +struct nvlist; +typedef struct nvlist nvlist_t; -/*=========================== Forward Declarations ===========================*/ class Vdev; /*============================= Class Definitions ============================*/ @@ -97,7 +102,7 @@ public: * Upon return, the VdevIterator's cursor points to the vdev just * past the returned vdev or end() if no matching vdev is found. */ - nvlist_t *Find(Guid vdevGUID); + nvlist_t *Find(DevCtl::Guid vdevGUID); /** * \brief Perform the specified operation on each leaf member of diff --git a/cddl/sbin/zfsd/zfsd.cc b/cddl/sbin/zfsd/zfsd.cc index 01a5d71b8446..a6ee947403f7 100644 --- a/cddl/sbin/zfsd/zfsd.cc +++ b/cddl/sbin/zfsd/zfsd.cc @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Spectra Logic Corporation + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,242 +42,77 @@ */ #include -#include -#include #include -#include -#include -#include -#include - -#include -#include -#include +#include + #include -#include -#include -#include +#include #include -#include -#include +#include #include -#include #include -#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include #include "callout.h" +#include "zfsd_event.h" +#include "case_file.h" #include "vdev.h" +#include "vdev_iterator.h" #include "zfsd.h" #include "zfsd_exception.h" #include "zpool_list.h" __FBSDID("$FreeBSD$"); +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + /*============================ Namespace Control =============================*/ -using std::string; -using std::stringstream; -using std::cerr; -using std::cout; -using std::endl; +using DevCtl::Event; +using DevCtl::EventBuffer; +using DevCtl::EventFactory; +using DevCtl::EventList; +using DevCtl::Guid; +using DevCtl::NVPairMap; /*================================ Global Data ===============================*/ -const char g_devdSock[] = "/var/run/devd.pipe"; int g_debug = 0; libzfs_handle_t *g_zfsHandle; -/*-------------------------------- FDReader -------------------------------*/ -//- FDReader Public Methods ---------------------------------------------------- -size_t -FDReader::in_avail() const -{ - int bytes; - if (ioctl(m_fd, FIONREAD, &bytes)) { - syslog(LOG_ERR, "ioctl FIONREAD: %s", strerror(errno)); - return (0); - } - return (bytes); -} - - -/*-------------------------------- IstreamReader ---------------------------*/ -//- IstreamReader Public Methods ---------------------------------------------- -ssize_t -IstreamReader::read(char* buf, size_t count) -{ - m_stream->read(buf, count); - if (m_stream->fail()) - return (-1); - return (m_stream->gcount()); -} - - -/*-------------------------------- EventBuffer -------------------------------*/ -//- EventBuffer Static Data ---------------------------------------------------- -/** - * NOTIFY, NOMATCH, ATTACH, DETACH. See DevCtlEvent::Type. - */ -const char EventBuffer::s_eventStartTokens[] = "!?+-"; - -/** - * Events are terminated by a newline. - */ -const char EventBuffer::s_eventEndTokens[] = "\n"; - -/** - * Key=Value pairs are terminated by whitespace. - */ -const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; - -//- EventBuffer Public Methods ------------------------------------------------- -EventBuffer::EventBuffer(Reader& reader) - : m_reader(reader), - m_validLen(0), - m_parsedLen(0), - m_nextEventOffset(0), - m_synchronized(true) -{ -} - -bool -EventBuffer::ExtractEvent(string &eventString) +/*--------------------------------- ZfsDaemon --------------------------------*/ +//- ZfsDaemon Static Private Data ---------------------------------------------- +ZfsDaemon *ZfsDaemon::s_theZfsDaemon; +bool ZfsDaemon::s_logCaseFiles; +bool ZfsDaemon::s_terminateEventLoop; +char ZfsDaemon::s_pidFilePath[] = "/var/run/zfsd.pid"; +pidfh *ZfsDaemon::s_pidFH; +int ZfsDaemon::s_signalPipeFD[2]; +bool ZfsDaemon::s_systemRescanRequested(false); +EventFactory::Record ZfsDaemon::s_registryEntries[] = { - stringstream tsField; - timeval now; - - gettimeofday(&now, NULL); - tsField << " timestamp=" << now.tv_sec; - - while (UnParsed() > 0 || Fill()) { - - /* - * If the valid data in the buffer isn't enough to hold - * a full event, try reading more. - */ - if (NextEventMaxLen() < MIN_EVENT_SIZE) { - m_parsedLen += UnParsed(); - continue; - } - - char *nextEvent(m_buf + m_nextEventOffset); - bool truncated(true); - size_t eventLen(strcspn(nextEvent, s_eventEndTokens)); - - if (!m_synchronized) { - /* Discard data until an end token is read. */ - if (nextEvent[eventLen] != '\0') - m_synchronized = true; - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - continue; - } else if (nextEvent[eventLen] == '\0') { - - m_parsedLen += eventLen; - if (m_parsedLen < MAX_EVENT_SIZE) { - /* - * Ran out of buffer before hitting - * a full event. Fill() and try again. - */ - continue; - } - syslog(LOG_WARNING, "Overran event buffer\n\tm_nextEventOffset" - "=%zd\n\tm_parsedLen=%zd\n\tm_validLen=%zd", - m_nextEventOffset, m_parsedLen, m_validLen); - } else { - /* - * Include the normal terminator in the extracted - * event data. - */ - eventLen += 1; - truncated = false; - } - - m_nextEventOffset += eventLen; - m_parsedLen = m_nextEventOffset; - eventString.assign(nextEvent, eventLen); - - if (truncated) { - size_t fieldEnd; - - /* Break cleanly at the end of a key<=>value pair. */ - fieldEnd = eventString.find_last_of(s_keyPairSepTokens); - if (fieldEnd != string::npos) - eventString.erase(fieldEnd); - eventString += '\n'; - - m_synchronized = false; - syslog(LOG_WARNING, - "Truncated %zd characters from event.", - eventLen - fieldEnd); - } - - /* - * Add a timestamp as the final field of the event if it is - * not already present. - */ - if (eventString.find("timestamp=") == string::npos) { - size_t eventEnd(eventString.find_last_not_of('\n') + 1); - - eventString.insert(eventEnd, tsField.str()); - } - - return (true); - } - return (false); -} + { Event::NOTIFY, "DEVFS", &DevfsEvent::DevfsEventBuilder }, + { Event::NOTIFY, "ZFS", &ZfsEvent::ZfsEventBuilder } +}; -//- EventBuffer Private Methods ------------------------------------------------ -bool -EventBuffer::Fill() +//- ZfsDaemon Static Public Methods -------------------------------------------- +ZfsDaemon & +ZfsDaemon::Get() { - size_t avail; - ssize_t consumed(0); - - /* Compact the buffer. */ - if (m_nextEventOffset != 0) { - memmove(m_buf, m_buf + m_nextEventOffset, - m_validLen - m_nextEventOffset); - m_validLen -= m_nextEventOffset; - m_parsedLen -= m_nextEventOffset; - m_nextEventOffset = 0; - } - - /* Fill any empty space. */ - avail = m_reader.in_avail(); - if (avail) { - size_t want; - - want = std::min(avail, MAX_READ_SIZE - m_validLen); - consumed = m_reader.read(m_buf + m_validLen, want); - if (consumed == -1) { - if (errno == EINTR) - return (false); - else - err(1, "EventBuffer::Fill(): Read failed"); - } - } - - m_validLen += consumed; - /* Guarantee our buffer is always NUL terminated. */ - m_buf[m_validLen] = '\0'; - - return (consumed > 0); + return (*s_theZfsDaemon); } -/*--------------------------------- ZfsDaemon --------------------------------*/ -//- ZfsDaemon Static Private Data ---------------------------------------------- -bool ZfsDaemon::s_logCaseFiles; -bool ZfsDaemon::s_terminateEventLoop; -char ZfsDaemon::s_pidFilePath[] = "/var/run/zfsd.pid"; -pidfh *ZfsDaemon::s_pidFH; -FDReader* ZfsDaemon::s_reader; -int ZfsDaemon::s_devdSockFD = -1; -int ZfsDaemon::s_signalPipeFD[2]; -bool ZfsDaemon::s_systemRescanRequested(false); -bool ZfsDaemon::s_consumingEvents(false); -DevCtlEventList ZfsDaemon::s_unconsumedEvents; - -//- ZfsDaemon Static Public Methods -------------------------------------------- void ZfsDaemon::WakeEventLoop() { @@ -294,36 +129,40 @@ ZfsDaemon::RequestSystemRescan() void ZfsDaemon::Run() { - Init(); + ZfsDaemon daemon; while (s_terminateEventLoop == false) { try { - DisconnectFromDevd(); + daemon.DisconnectFromDevd(); - if (ConnectToDevd() == false) { + if (daemon.ConnectToDevd() == false) { sleep(30); continue; } - DetectMissedEvents(); + daemon.DetectMissedEvents(); - EventLoop(); + daemon.EventLoop(); } catch (const ZfsdException &exp) { exp.Log(); } } - DisconnectFromDevd(); - - Fini(); + daemon.DisconnectFromDevd(); } -//- ZfsDaemon Static Private Methods ------------------------------------------- -void -ZfsDaemon::Init() +//- ZfsDaemon Private Methods -------------------------------------------------- +ZfsDaemon::ZfsDaemon() + : Consumer(/*defBuilder*/NULL, s_registryEntries, + NUM_ELEMENTS(s_registryEntries)) { + if (s_theZfsDaemon != NULL) + errx(1, "Multiple ZfsDaemon instances created. Exiting"); + + s_theZfsDaemon = this; + if (pipe(s_signalPipeFD) != 0) errx(1, "Unable to allocate signal pipe. Exiting"); @@ -344,7 +183,6 @@ ZfsDaemon::Init() errx(1, "Unable to initialize ZFS library. Exiting"); Callout::Init(); - DevCtlEvent::Init(); InitializeSyslog(); OpenPIDFile(); @@ -354,195 +192,12 @@ ZfsDaemon::Init() UpdatePIDFile(); } -void -ZfsDaemon::Fini() +ZfsDaemon::~ZfsDaemon() { PurgeCaseFiles(); ClosePIDFile(); } -void -ZfsDaemon::InfoSignalHandler(int) -{ - s_logCaseFiles = true; - ZfsDaemon::WakeEventLoop(); -} - -void -ZfsDaemon::RescanSignalHandler(int) -{ - RequestSystemRescan(); -} - -void -ZfsDaemon::QuitSignalHandler(int) -{ - s_terminateEventLoop = true; - ZfsDaemon::WakeEventLoop(); -} - -void -ZfsDaemon::OpenPIDFile() -{ - pid_t otherPID; - - s_pidFH = pidfile_open(s_pidFilePath, 0600, &otherPID); - if (s_pidFH == NULL) { - if (errno == EEXIST) - errx(1, "already running as PID %d. Exiting", otherPID); - warn("cannot open PID file"); - } -} - -void -ZfsDaemon::UpdatePIDFile() -{ - if (s_pidFH != NULL) - pidfile_write(s_pidFH); -} - -void -ZfsDaemon::ClosePIDFile() -{ - if (s_pidFH != NULL) - pidfile_close(s_pidFH); -} - -void -ZfsDaemon::InitializeSyslog() -{ - openlog("zfsd", LOG_NDELAY, LOG_DAEMON); -} - -bool -ZfsDaemon::ConnectToDevd() -{ - struct sockaddr_un devdAddr; - int sLen; - int result; - - syslog(LOG_INFO, "Connecting to devd"); - - memset(&devdAddr, 0, sizeof(devdAddr)); - devdAddr.sun_family= AF_UNIX; - strlcpy(devdAddr.sun_path, g_devdSock, sizeof(devdAddr.sun_path)); - sLen = SUN_LEN(&devdAddr); - - s_devdSockFD = socket(AF_UNIX, SOCK_STREAM, 0); - if (s_devdSockFD == -1) - err(1, "Unable to create socket"); - result = connect(s_devdSockFD, - reinterpret_cast(&devdAddr), - sLen); - if (result == -1) { - syslog(LOG_INFO, "Unable to connect to devd"); - return (false); - } - - - /* Connect the stream to the file descriptor */ - s_reader = new FDReader(s_devdSockFD); - syslog(LOG_INFO, "Connection to devd successful"); - return (true); -} - -void -ZfsDaemon::DisconnectFromDevd() -{ - if (s_devdSockFD != -1) - syslog(LOG_INFO, "Disconnecting from devd."); - - delete s_reader; - s_reader = NULL; - close(s_devdSockFD); - s_devdSockFD = -1; -} - -void -ZfsDaemon::ReplayUnconsumedEvents() -{ - DevCtlEventList::iterator event(s_unconsumedEvents.begin()); - bool replayed_any = (event != s_unconsumedEvents.end()); - - s_consumingEvents = true; - if (replayed_any) - syslog(LOG_INFO, "Started replaying unconsumed events"); - while (event != s_unconsumedEvents.end()) { - /* - * Even if the event is unconsumed the second time around, drop - * it. By now we should've gotten a config_sync so any events - * that still can't be consumed are probably referring to vdevs - * or pools that no longer exist. - */ - (*event)->Process(); - delete *event; - s_unconsumedEvents.erase(event++); - } - if (replayed_any) - syslog(LOG_INFO, "Finished replaying unconsumed events"); - s_consumingEvents = false; -} - -bool -ZfsDaemon::SaveEvent(const DevCtlEvent &event) -{ - if (s_consumingEvents) - return (false); - s_unconsumedEvents.push_back(event.DeepCopy()); - return (true); -} - -/* Capture and process buffered events. */ -void -ZfsDaemon::ProcessEvents(EventBuffer &eventBuffer) -{ - string evString; - while (eventBuffer.ExtractEvent(evString)) { - DevCtlEvent *event(DevCtlEvent::CreateEvent(evString)); - if (event != NULL) { - if (event->Process()) - SaveEvent(*event); - delete event; - } - } -} - -void -ZfsDaemon::FlushEvents() -{ - char discardBuf[256]; - - while (s_reader->in_avail()) - s_reader->read(discardBuf, sizeof(discardBuf)); -} - -bool -ZfsDaemon::EventsPending() -{ - struct pollfd fds[1]; - int result; - - do { - fds->fd = s_devdSockFD; - fds->events = POLLIN; - fds->revents = 0; - result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0); - } while (result == -1 && errno == EINTR); - - if (result == -1) - err(1, "Polling for devd events failed"); - - if ((fds->revents & POLLERR) != 0) - throw ZfsdException("ZfsdDaemon:EventsPending(): " - "POLLERR detected on devd socket."); - - if ((fds->revents & POLLHUP) != 0) - throw ZfsdException("ZfsDaemon::EventsPending(): " - "POLLHUP detected on devd socket."); - - return ((fds->revents & POLLIN) != 0); -} - void ZfsDaemon::PurgeCaseFiles() { @@ -552,7 +207,6 @@ ZfsDaemon::PurgeCaseFiles() bool ZfsDaemon::VdevAddCaseFile(Vdev &vdev, void *cbArg) { - if (vdev.State() != VDEV_STATE_HEALTHY) CaseFile::Create(vdev); @@ -599,10 +253,11 @@ ZfsDaemon::RescanSystem() LIST_FOREACH(mp, &mesh.lg_class, lg_class) { LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { - DevCtlEvent *event; + Event *event; string evString(evStart + pp->lg_name + "\n"); - event = DevCtlEvent::CreateEvent(evString); + event = Event::CreateEvent(GetFactory(), + evString); if (event != NULL) if (event->Process()) SaveEvent(*event); @@ -640,25 +295,22 @@ ZfsDaemon::DetectMissedEvents() void ZfsDaemon::EventLoop() { - EventBuffer eventBuffer(*s_reader); - while (s_terminateEventLoop == false) { struct pollfd fds[2]; int result; if (s_logCaseFiles == true) { - DevCtlEventList::iterator - event(s_unconsumedEvents.begin()); + EventList::iterator event(m_unconsumedEvents.begin()); s_logCaseFiles = false; CaseFile::LogAll(); - while (event != s_unconsumedEvents.end()) + while (event != m_unconsumedEvents.end()) (*event++)->Log(LOG_INFO); } Callout::ExpireCallouts(); /* Wait for data. */ - fds[0].fd = s_devdSockFD; + fds[0].fd = m_devdSockFD; fds[0].events = POLLIN; fds[0].revents = 0; fds[1].fd = s_signalPipeFD[0]; @@ -675,7 +327,7 @@ ZfsDaemon::EventLoop() } if ((fds[0].revents & POLLIN) != 0) - ProcessEvents(eventBuffer); + ProcessEvents(); if ((fds[1].revents & POLLIN) != 0) { static char discardBuf[128]; @@ -707,3 +359,57 @@ ZfsDaemon::EventLoop() } } } +//- ZfsDaemon staic Private Methods -------------------------------------------- +void +ZfsDaemon::InfoSignalHandler(int) +{ + s_logCaseFiles = true; + ZfsDaemon::WakeEventLoop(); +} + +void +ZfsDaemon::RescanSignalHandler(int) +{ + RequestSystemRescan(); +} + +void +ZfsDaemon::QuitSignalHandler(int) +{ + s_terminateEventLoop = true; + ZfsDaemon::WakeEventLoop(); +} + +void +ZfsDaemon::OpenPIDFile() +{ + pid_t otherPID; + + s_pidFH = pidfile_open(s_pidFilePath, 0600, &otherPID); + if (s_pidFH == NULL) { + if (errno == EEXIST) + errx(1, "already running as PID %d. Exiting", otherPID); + warn("cannot open PID file"); + } +} + +void +ZfsDaemon::UpdatePIDFile() +{ + if (s_pidFH != NULL) + pidfile_write(s_pidFH); +} + +void +ZfsDaemon::ClosePIDFile() +{ + if (s_pidFH != NULL) + pidfile_close(s_pidFH); +} + +void +ZfsDaemon::InitializeSyslog() +{ + openlog("zfsd", LOG_NDELAY, LOG_DAEMON); +} + diff --git a/cddl/sbin/zfsd/zfsd.h b/cddl/sbin/zfsd/zfsd.h index 3e9e16b37ff9..94bbd83108e9 100644 --- a/cddl/sbin/zfsd/zfsd.h +++ b/cddl/sbin/zfsd/zfsd.h @@ -37,304 +37,57 @@ * * Class definitions and supporting data strutures for the ZFS fault * management daemon. + * + * Header requirements: + * + * #include + * + * #include + * + * #include + * #include + * #include + * + * #include + * #include + * #include + * #include + * #include + * + * #include "vdev_iterator.h" */ #ifndef _ZFSD_H_ #define _ZFSD_H_ -#include -#include -#include -#include -#include +/*=========================== Forward Declarations ===========================*/ +struct pidfh; + +struct zpool_handle; +typedef struct zpool_handle zpool_handle_t; -#include -#include +struct zfs_handle; +typedef struct libzfs_handle libzfs_handle_t; -#include "case_file.h" -#include "dev_ctl_event.h" -#include "vdev_iterator.h" +struct nvlist; +typedef struct nvlist nvlist_t; -/*============================ Namespace Control =============================*/ -using std::auto_ptr; -using std::map; -using std::pair; -using std::istream; -using std::string; +typedef int LeafIterFunc(zpool_handle_t *, nvlist_t *, void *); /*================================ Global Data ===============================*/ -extern const char g_devdSock[]; extern int g_debug; extern libzfs_handle_t *g_zfsHandle; -/*=========================== Forward Declarations ===========================*/ -struct EventFactoryRecord; -struct pidfh; - -typedef int LeafIterFunc(zpool_handle_t *, nvlist_t *, void *); - -/*================================== Macros ==================================*/ -#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) - /*============================= Class Definitions ============================*/ - -/*-------------------------------- Reader -------------------------------*/ -/** - * \brief A class that presents a common interface to both file descriptors - * and istreams. - * - * Standard C++ provides no way to create an iostream from a file descriptor or - * a FILE. The GNU, Apache, HPUX, and Solaris C++ libraries all provide - * non-standard ways to construct such a stream using similar semantics, but - * FreeBSD's C++ library does not. This class supports only the functionality - * needed by ZFSD; it does not implement the iostream API. - */ -class Reader -{ -public: - /** - * \brief Return the number of bytes immediately available for reading - */ - virtual size_t in_avail() const = 0; - - /** - * \brief Reads up to count bytes - * - * Whether this call blocks depends on the underlying input source. - * On error, -1 is returned, and errno will be set by the underlying - * source. - * - * \param buf Destination for the data - * \param count Maximum amount of data to read - * \returns Amount of data that was actually read - */ - virtual ssize_t read(char* buf, size_t count) = 0; - - virtual ~Reader() = 0; -}; - -inline Reader::~Reader() {} - - -/*-------------------------------- FDReader -------------------------------*/ -/** - * \brief Specialization of Reader that uses a file descriptor - */ -class FDReader : public Reader -{ -public: - /** - * \brief Constructor - * - * \param fd An open file descriptor. It will not be garbage - * collected by the destructor. - */ - FDReader(int fd); - - virtual size_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying file descriptor */ - int m_fd; -}; - -//- FDReader Inline Public Methods ----------------------------------------- -inline -FDReader::FDReader(int fd) - : m_fd(fd) -{ -} - -inline ssize_t -FDReader::read(char* buf, size_t count) -{ - return (::read(m_fd, buf, count)); -} - -/*-------------------------------- IstreamReader------------------------------*/ -/** - * \brief Specialization of Reader that uses a std::istream - */ -class IstreamReader : public Reader -{ -public: - /** - * Constructor - * - * \param stream Pointer to an open istream. It will not be - * garbage collected by the destructor. - */ - IstreamReader(istream* stream); - - virtual size_t in_avail() const; - - virtual ssize_t read(char* buf, size_t count); - -protected: - /** Copy of the underlying stream */ - istream *m_stream; -}; - -//- IstreamReader Inline Public Methods ---------------------------------------- -inline -IstreamReader::IstreamReader(istream* stream) - : m_stream(stream) -{ -} - -inline size_t -IstreamReader::in_avail() const -{ - return (m_stream->rdbuf()->in_avail()); -} - - -/*-------------------------------- EventBuffer -------------------------------*/ -/** - * \brief Class buffering event data from Devd or a similar source and - * splitting it into individual event strings. - * - * Users of this class initialize it with a Reader associated with the unix - * domain socket connection with devd or a compatible source. The lifetime of - * an EventBuffer instance should match that of the Reader passed to it. This - * is required as data from partially received events is retained in the - * EventBuffer in order to allow reconstruction of these events across multiple - * reads of the stream. - * - * Once the program determines that the Reader is ready for reading, the - * EventBuffer::ExtractEvent() should be called in a loop until the method - * returns false. - */ -class EventBuffer -{ -public: - /** - * Constructor - * - * \param reader The data source on which to buffer/parse event data. - */ - EventBuffer(Reader& reader); - - /** - * Pull a single event string out of the event buffer. - * - * \param eventString The extracted event data (if available). - * - * \return true if event data is available and eventString has - * been populated. Otherwise false. - */ - bool ExtractEvent(string &eventString); - -private: - enum { - /** - * Size of an empty event (start and end token with - * no data. The EventBuffer parsing needs at least - * this much data in the buffer for safe event extraction. - */ - MIN_EVENT_SIZE = 2, - - /* - * The maximum event size supported by ZFSD. - * Events larger than this size (minus 1) are - * truncated at the end of the last fully received - * key/value pair. - */ - MAX_EVENT_SIZE = 8192, - - /** - * The maximum amount of buffer data to read at - * a single time from the Devd file descriptor. - */ - MAX_READ_SIZE = MAX_EVENT_SIZE, - - /** - * The size of EventBuffer's buffer of Devd event data. - * This is one larger than the maximum supported event - * size, which alows us to always include a terminating - * NUL without overwriting any received data. - */ - EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 - }; - - /** The amount of data in m_buf we have yet to look at. */ - size_t UnParsed() const; - - /** The amount of data in m_buf available for the next event. */ - size_t NextEventMaxLen() const; - - /** Fill the event buffer with event data from Devd. */ - bool Fill(); - - /** Characters we treat as beginning an event string. */ - static const char s_eventStartTokens[]; - - /** Characters we treat as ending an event string. */ - static const char s_eventEndTokens[]; - - /** Characters found between successive "key=value" strings. */ - static const char s_keyPairSepTokens[]; - - /** Temporary space for event data during our parsing. Laid out like - * this: - * <---------------------------------------------------------> - * | | | | | - * m_buf---| | | | | - * m_nextEventOffset-- | | | - * m_parsedLen------------- | | - * m_validLen-------------------------- | - * EVENT_BUFSIZE------------------------------------------------------ - * - * Data before m_nextEventOffset has already been processed. - * - * Data between m_nextEvenOffset and m_parsedLen has been parsed, but - * not processed as a single event. - * - * Data between m_parsedLen and m_validLen has been read from the - * source, but not yet parsed. - * - * Between m_validLen and EVENT_BUFSIZE is empty space. - * - * */ - char m_buf[EVENT_BUFSIZE]; - - /** Reference to the reader linked to devd's domain socket. */ - Reader& m_reader; - - /** Offset within m_buf to the beginning of free space. */ - size_t m_validLen; - - /** Offset within m_buf to the beginning of data not yet parsed */ - size_t m_parsedLen; - - /** Offset within m_buf to the start token of the next event. */ - size_t m_nextEventOffset; - - /** The EventBuffer is aligned and tracking event records. */ - bool m_synchronized; -}; - -//- EventBuffer Inline Private Methods ----------------------------------------- -inline size_t -EventBuffer::UnParsed() const -{ - return (m_validLen - m_parsedLen); -} - -inline size_t -EventBuffer::NextEventMaxLen() const -{ - return (m_validLen - m_nextEventOffset); -} - /*--------------------------------- ZfsDaemon --------------------------------*/ /** * Static singleton orchestrating the operations of the ZFS daemon program. */ -class ZfsDaemon +class ZfsDaemon : public DevCtl::Consumer { public: + /** Return the ZfsDaemon singleton. */ + static ZfsDaemon &Get(); + /** * Used by signal handlers to ensure, in a race free way, that * the event loop will perform at least one more full loop @@ -349,68 +102,38 @@ public: */ static void RequestSystemRescan(); - /** - * Queue an event for replay after the next ZFS configuration - * sync event is received. This facility is used when an event - * is received for a pool or vdev that is not visible in the - * current ZFS configuration, but may "arrive" once the kernel - * commits the configuration change that emitted the event. - */ - static bool SaveEvent(const DevCtlEvent &event); - - /** - * Reprocess any events saved via the SaveEvent() facility. - */ - static void ReplayUnconsumedEvents(); - /** Daemonize and perform all functions of the ZFS daemon. */ static void Run(); private: - /** Initialize the daemon. */ - static void Init(); - - /** Perform any necessary cleanup at daemon shutdown. */ - static void Fini(); - - /** Process incoming devctl events from devd. */ - static void ProcessEvents(EventBuffer &eventBuffer); - - /** Discard all data pending in s_devdSockFD. */ - static void FlushEvents(); + ZfsDaemon(); + ~ZfsDaemon(); static VdevCallback_t VdevAddCaseFile; - /** - * Test for data pending in s_devdSockFD - * - * \return True if data is pending. Otherwise false. - */ - static bool EventsPending(); - /** Purge our cache of outstanding ZFS issues in the system. */ - static void PurgeCaseFiles(); + void PurgeCaseFiles(); /** Build a cache of outstanding ZFS issues in the system. */ - static void BuildCaseFiles(); + void BuildCaseFiles(); /** * Iterate over all known issues and attempt to solve them * given resources currently available in the system. */ - static void RescanSystem(); + void RescanSystem(); /** * Interrogate the system looking for previously unknown * faults that occurred either before ZFSD was started, * or during a period of lost communication with Devd. */ - static void DetectMissedEvents(); + void DetectMissedEvents(); /** * Wait for and process event source activity. */ - static void EventLoop(); + void EventLoop(); /** * Signal handler for which our response is to @@ -456,74 +179,51 @@ private: */ static void InitializeSyslog(); - /** - * Open a connection to devd's unix domain socket. - * - * \return True if the connection attempt is successsful. Otherwise - * false. - */ - static bool ConnectToDevd(); - - /** - * Close a connection (if any) to devd's unix domain socket. - */ - static void DisconnectFromDevd(); + static ZfsDaemon *s_theZfsDaemon; /** * Set to true when our program is signaled to * gracefully exit. */ - static bool s_logCaseFiles; + static bool s_logCaseFiles; /** * Set to true when our program is signaled to * gracefully exit. */ - static bool s_terminateEventLoop; + static bool s_terminateEventLoop; /** * The canonical path and file name of zfsd's PID file. */ - static char s_pidFilePath[]; + static char s_pidFilePath[]; /** * Control structure for PIDFILE(3) API. */ - static pidfh *s_pidFH; - - /** - * File descriptor representing the unix domain socket - * connection with devd. - */ - static int s_devdSockFD; - - /** - * Reader object used by the EventBuffer - */ - static FDReader* s_reader; + static pidfh *s_pidFH; /** * Pipe file descriptors used to close races with our * signal handlers. */ - static int s_signalPipeFD[2]; - - /** Queued events for replay. */ - static DevCtlEventList s_unconsumedEvents; + static int s_signalPipeFD[2]; /** * Flag controlling a rescan from ZFSD's event loop of all * GEOM providers in the system to find candidates for solving * cases. */ - static bool s_systemRescanRequested; + static bool s_systemRescanRequested; /** * Flag controlling whether events can be queued. This boolean * is set during event replay to ensure that events for pools or * devices no longer in the system are not retained forever. */ - static bool s_consumingEvents; + static bool s_consumingEvents; + + static DevCtl::EventFactory::Record s_registryEntries[]; }; #endif /* _ZFSD_H_ */ diff --git a/cddl/sbin/zfsd/zfsd_event.cc b/cddl/sbin/zfsd/zfsd_event.cc new file mode 100644 index 000000000000..81cf8eeb031e --- /dev/null +++ b/cddl/sbin/zfsd/zfsd_event.cc @@ -0,0 +1,369 @@ +/*- + * Copyright (c) 2011 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file zfsd_event.cc + */ +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "callout.h" +#include "zfsd_event.h" +#include "case_file.h" +#include "vdev.h" +#include "vdev_iterator.h" +#include "zfsd.h" +#include "zfsd_exception.h" +#include "zpool_list.h" + +__FBSDID("$FreeBSD$"); +/*============================ Namespace Control =============================*/ +using DevCtl::Event; +using DevCtl::Guid; +using DevCtl::NVPairMap; +using std::stringstream; + +/*=========================== Class Implementations ==========================*/ + +/*-------------------------------- DevfsEvent --------------------------------*/ + +//- DevfsEvent Static Public Methods ------------------------------------------- +Event * +DevfsEvent::DevfsEventBuilder(Event::Type type, + NVPairMap &nvPairs, + const string &eventString) +{ + return (new DevfsEvent(type, nvPairs, eventString)); +} + +//- DevfsEvent Static Protected Methods ---------------------------------------- +nvlist_t * +DevfsEvent::ReadLabel(int devFd, bool &inUse, bool °raded) +{ + pool_state_t poolState; + char *poolName; + boolean_t b_inuse; + + inUse = false; + degraded = false; + poolName = NULL; + if (zpool_in_use(g_zfsHandle, devFd, &poolState, + &poolName, &b_inuse) == 0) { + nvlist_t *devLabel; + + inUse = b_inuse == B_TRUE; + if (poolName != NULL) + free(poolName); + + if (zpool_read_label(devFd, &devLabel) != 0 + || devLabel == NULL) + return (NULL); + + try { + Vdev vdev(devLabel); + degraded = vdev.State() != VDEV_STATE_HEALTHY; + return (devLabel); + } catch (ZfsdException &exp) { + string devName = fdevname(devFd); + string devPath = _PATH_DEV + devName; + string context("DevfsEvent::ReadLabel: " + + devPath + ": "); + + exp.GetString().insert(0, context); + exp.Log(); + } + } + return (NULL); +} + +bool +DevfsEvent::OnlineByLabel(const string &devPath, const string& physPath, + nvlist_t *devConfig) +{ + try { + /* + * A device with ZFS label information has been + * inserted. If it matches a device for which we + * have a case, see if we can solve that case. + */ + syslog(LOG_INFO, "Interrogating VDEV label for %s\n", + devPath.c_str()); + Vdev vdev(devConfig); + CaseFile *caseFile(CaseFile::Find(vdev.PoolGUID(), + vdev.GUID())); + if (caseFile != NULL) + return (caseFile->ReEvaluate(devPath, physPath, &vdev)); + + } catch (ZfsdException &exp) { + string context("DevfsEvent::OnlineByLabel: " + devPath + ": "); + + exp.GetString().insert(0, context); + exp.Log(); + } + return (false); +} + +//- DevfsEvent Virtual Public Methods ------------------------------------------ +Event * +DevfsEvent::DeepCopy() const +{ + return (new DevfsEvent(*this)); +} + +bool +DevfsEvent::Process() const +{ + /* + * We are only concerned with newly discovered + * devices that can be ZFS vdevs. + */ + if (Value("type") != "CREATE" || !IsDiskDev()) + return (false); + + /* Log the event since it is of interest. */ + Log(LOG_INFO); + + string devPath; + if (!DevPath(devPath)) + return (false); + + int devFd(open(devPath.c_str(), O_RDONLY)); + if (devFd == -1) + return (false); + + bool inUse; + bool degraded; + nvlist_t *devLabel(ReadLabel(devFd, inUse, degraded)); + + string physPath; + bool havePhysPath(PhysicalPath(physPath)); + + string devName; + DevName(devName); + close(devFd); + + if (inUse && devLabel != NULL) { + OnlineByLabel(devPath, physPath, devLabel); + } else if (degraded) { + syslog(LOG_INFO, "%s is marked degraded. Ignoring " + "as a replace by physical path candidate.\n", + devName.c_str()); + } else if (havePhysPath && IsWholeDev()) { + syslog(LOG_INFO, "Searching for CaseFile by Physical Path\n"); + CaseFile *caseFile(CaseFile::Find(physPath)); + if (caseFile != NULL) { + syslog(LOG_INFO, + "Found CaseFile(%s:%s:%s) - ReEvaluating\n", + caseFile->PoolGUIDString().c_str(), + caseFile->VdevGUIDString().c_str(), + zpool_state_to_name(caseFile->VdevState(), + VDEV_AUX_NONE)); + caseFile->ReEvaluate(devPath, physPath, /*vdev*/NULL); + } + } + if (devLabel != NULL) + nvlist_free(devLabel); + return (false); +} + +//- DevfsEvent Protected Methods ----------------------------------------------- +DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : DevCtl::DevfsEvent(type, nvpairs, eventString) +{ +} + +DevfsEvent::DevfsEvent(const DevfsEvent &src) + : DevCtl::DevfsEvent::DevfsEvent(src) +{ +} + +/*--------------------------------- ZfsEvent ---------------------------------*/ +//- ZfsEvent Static Public Methods --------------------------------------------- +DevCtl::Event * +ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs, + const string &eventString) +{ + return (new ZfsEvent(type, nvpairs, eventString)); +} + +//- ZfsEvent Virtual Public Methods -------------------------------------------- +Event * +ZfsEvent::DeepCopy() const +{ + return (new ZfsEvent(*this)); +} + +bool +ZfsEvent::Process() const +{ + string logstr(""); + + if (!Contains("class") && !Contains("type")) { + syslog(LOG_ERR, + "ZfsEvent::Process: Missing class or type data."); + return (false); + } + + /* On config syncs, replay any queued events first. */ + if (Value("type").find("misc.fs.zfs.config_sync") == 0) { + /* + * Even if saved events are unconsumed the second time + * around, drop them. Any events that still can't be + * consumed are probably referring to vdevs or pools that + * no longer exist. + */ + ZfsDaemon::Get().ReplayUnconsumedEvents(/*discard*/true); + CaseFile::ReEvaluateByGuid(PoolGUID(), *this); + } + + Log(LOG_INFO); + + if (Value("type").find("misc.fs.zfs.") == 0) { + /* Configuration changes, resilver events, etc. */ + ProcessPoolEvent(); + return (false); + } + + if (!Contains("pool_guid") || !Contains("vdev_guid")) { + /* Only currently interested in Vdev related events. */ + return (false); + } + + CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID())); + if (caseFile != NULL) { + syslog(LOG_INFO, "Evaluating existing case file\n"); + caseFile->ReEvaluate(*this); + return (false); + } + + /* Skip events that can't be handled. */ + Guid poolGUID(PoolGUID()); + /* If there are no replicas for a pool, then it's not manageable. */ + if (Value("class").find("fs.zfs.vdev.no_replicas") == 0) { + stringstream msg; + msg << "No replicas available for pool " << poolGUID; + msg << ", ignoring"; + syslog(LOG_INFO, "%s", msg.str().c_str()); + return (false); + } + + /* + * Create a case file for this vdev, and have it + * evaluate the event. + */ + ZpoolList zpl(ZpoolList::ZpoolByGUID, &poolGUID); + if (zpl.empty()) { + stringstream msg; + int priority = LOG_INFO; + msg << "ZfsEvent::Process: Event for unknown pool "; + msg << poolGUID << " "; + msg << "queued"; + syslog(priority, "%s", msg.str().c_str()); + return (true); + } + + nvlist_t *vdevConfig = VdevIterator(zpl.front()).Find(VdevGUID()); + if (vdevConfig == NULL) { + stringstream msg; + int priority = LOG_INFO; + msg << "ZfsEvent::Process: Event for unknown vdev "; + msg << VdevGUID() << " "; + msg << "queued"; + syslog(priority, "%s", msg.str().c_str()); + return (true); + } + + Vdev vdev(zpl.front(), vdevConfig); + caseFile = &CaseFile::Create(vdev); + if ( caseFile->ReEvaluate(*this) == false) { + stringstream msg; + int priority = LOG_INFO; + msg << "ZfsEvent::Process: Unconsumed event for vdev("; + msg << zpool_get_name(zpl.front()) << ","; + msg << vdev.GUID() << ") "; + msg << "queued"; + syslog(priority, "%s", msg.str().c_str()); + return (true); + } + return (false); +} + +//- ZfsEvent Protected Methods ------------------------------------------------- +ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : DevCtl::ZfsEvent(type, nvpairs, eventString) +{ +} + +ZfsEvent::ZfsEvent(const ZfsEvent &src) + : DevCtl::ZfsEvent(src) +{ +} + +void +ZfsEvent::ProcessPoolEvent() const +{ + bool degradedDevice(false); + + CaseFile *caseFile(CaseFile::Find(PoolGUID(), VdevGUID())); + if (caseFile != NULL) { + if (caseFile->VdevState() != VDEV_STATE_UNKNOWN + && caseFile->VdevState() < VDEV_STATE_HEALTHY) + degradedDevice = true; + + caseFile->ReEvaluate(*this); + } + + if (Value("type") == "misc.fs.zfs.vdev_remove" + && degradedDevice == false) { + /* See if any other cases can make use of this device. */ + ZfsDaemon::RequestSystemRescan(); + } +} diff --git a/cddl/sbin/zfsd/zfsd_event.h b/cddl/sbin/zfsd/zfsd_event.h new file mode 100644 index 000000000000..dfd405a583fc --- /dev/null +++ b/cddl/sbin/zfsd/zfsd_event.h @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 2011 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file dev_ctl_event.h + * + * \brief Class hierarchy used to express events received via + * the devctl API. + * + * Header requirements: + * #include + * #include + * #include + * + * #include + * #include + */ + +#ifndef _ZFSD_EVENT_H_ +#define _ZFSD_EVENT_H_ + +/*============================ Namespace Control =============================*/ +using std::string; + +/*=========================== Forward Declarations ===========================*/ +struct zpool_handle; +typedef struct zpool_handle zpool_handle_t; + +struct nvlist; +typedef struct nvlist nvlist_t; + +/*============================= Class Definitions ============================*/ +/*-------------------------------- DevfsEvent --------------------------------*/ +class DevfsEvent : public DevCtl::DevfsEvent +{ +public: + /** Specialized DevCtlEvent object factory for Devfs events. */ + static BuildMethod DevfsEventBuilder; + + virtual DevCtl::Event *DeepCopy() const; + + /** + * Interpret and perform any actions necessary to + * consume the event. + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + +protected: + /** + * \brief Read and return label information for a device. + * + * \param devFd The device from which to read ZFS label information. + * \param inUse The device is part of an active or potentially + * active configuration. + * \param degraded The device label indicates the vdev is not healthy. + * + * \return If label information is available, an nvlist describing + * the vdev configuraiton found on the device specified by + * devFd. Otherwise NULL. + */ + static nvlist_t *ReadLabel(int devFd, bool &inUse, bool °raded); + + /** + * Attempt to match the ZFS labeled device at devPath with an active + * CaseFile for a missing vdev. If a CaseFile is found, attempt + * to re-integrate the device with its pool. + * + * \param devPath The devfs path to the potential leaf vdev. + * \param physPath The physical path string reported by the device + * at devPath. + * \param devConfig The ZFS label information found on the device + * at devPath. + * + * \return true if the event that caused the online action can + * be considered consumed. + */ + static bool OnlineByLabel(const string &devPath, + const string& physPath, + nvlist_t *devConfig); + + /** DeepCopy Constructor. */ + DevfsEvent(const DevfsEvent &src); + + /** Constructor */ + DevfsEvent(Type, DevCtl::NVPairMap &, const string &); +}; + +/*--------------------------------- ZfsEvent ---------------------------------*/ +class ZfsEvent : public DevCtl::ZfsEvent +{ +public: + /** Specialized DevCtlEvent object factory for ZFS events. */ + static BuildMethod ZfsEventBuilder; + + virtual DevCtl::Event *DeepCopy() const; + + /** + * Interpret and perform any actions necessary to + * consume the event. + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + +protected: + /** DeepCopy Constructor. */ + ZfsEvent(const ZfsEvent &src); + + /** Constructor */ + ZfsEvent(Type, DevCtl::NVPairMap &, const string &); + + virtual void ProcessPoolEvent() const; +}; + +#endif /*_ZFSD_EVENT_H_ */ diff --git a/cddl/sbin/zfsd/zfsd_exception.cc b/cddl/sbin/zfsd/zfsd_exception.cc index 243cafa30a9d..1aff8a3576b5 100644 --- a/cddl/sbin/zfsd/zfsd_exception.cc +++ b/cddl/sbin/zfsd/zfsd_exception.cc @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2011 Spectra Logic Corporation + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,15 +35,23 @@ * * Implementation of the ZfsdException class. */ -#include +#include +#include + #include -#include +#include +#include + +#include +#include + #include #include "vdev.h" #include "zfsd_exception.h" +__FBSDID("$FreeBSD$"); /*============================ Namespace Control =============================*/ using std::endl; using std::string; @@ -51,17 +59,9 @@ using std::stringstream; /*=========================== Class Implementations ==========================*/ /*------------------------------- ZfsdException ------------------------------*/ -void -ZfsdException::FormatLog(const char *fmt, va_list ap) -{ - char buf[256]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - m_log = buf; -} - ZfsdException::ZfsdException(const char *fmt, ...) - : m_poolConfig(NULL), + : DevCtl::Exception(), + m_poolConfig(NULL), m_vdevConfig(NULL) { va_list ap; @@ -72,7 +72,8 @@ ZfsdException::ZfsdException(const char *fmt, ...) } ZfsdException::ZfsdException(zpool_handle_t *pool, const char *fmt, ...) - : m_poolConfig(zpool_get_config(pool, NULL)), + : DevCtl::Exception(), + m_poolConfig(zpool_get_config(pool, NULL)), m_vdevConfig(NULL) { va_list ap; @@ -83,7 +84,8 @@ ZfsdException::ZfsdException(zpool_handle_t *pool, const char *fmt, ...) } ZfsdException::ZfsdException(nvlist_t *poolConfig, const char *fmt, ...) - : m_poolConfig(poolConfig), + : DevCtl::Exception(), + m_poolConfig(poolConfig), m_vdevConfig(NULL) { va_list ap; diff --git a/cddl/sbin/zfsd/zfsd_exception.h b/cddl/sbin/zfsd/zfsd_exception.h index e28ea2eb8245..412836f5e388 100644 --- a/cddl/sbin/zfsd/zfsd_exception.h +++ b/cddl/sbin/zfsd/zfsd_exception.h @@ -35,12 +35,15 @@ * * Definition of the ZfsdException class hierarchy. All exceptions * explicitly thrown by Zfsd are defined here. + * + * Header requirements: + * #include + * + * #include */ #ifndef _ZFSD_EXCEPTION_H_ #define _ZFSD_EXCEPTION_H_ -#include - /*=========================== Forward Declarations ===========================*/ struct zpool_handle; typedef struct zpool_handle zpool_handle_t; @@ -53,7 +56,7 @@ typedef struct nvlist nvlist_t; /** * \brief Class allowing unified reporting/logging of exceptional events. */ -class ZfsdException +class ZfsdException : public DevCtl::Exception { public: /** @@ -92,31 +95,13 @@ public: */ ZfsdException(nvlist_t *poolConfig, const char *, ...); - /** - * \brief Augment/Modify a ZfsdException's string data. - */ - std::string& GetString(); - /** * \brief Emit exception data to syslog(3). */ - void Log() const; + virtual void Log() const; private: - /** - * \brief Convert exception string data and arguments provided - * in ZfsdException constructors into a linear string. - */ - void FormatLog(const char *fmt, va_list ap); - nvlist_t *m_poolConfig; nvlist_t *m_vdevConfig; - std::string m_log; }; -inline std::string & -ZfsdException::GetString() -{ - return (m_log); -} - #endif /* _ZFSD_EXCEPTION_H_ */ diff --git a/cddl/sbin/zfsd/zfsd_main.cc b/cddl/sbin/zfsd/zfsd_main.cc index 0fdcc6a28d5c..62d154a29b92 100644 --- a/cddl/sbin/zfsd/zfsd_main.cc +++ b/cddl/sbin/zfsd/zfsd_main.cc @@ -37,12 +37,26 @@ * */ +#include + #include #include #include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "vdev_iterator.h" #include "zfsd.h" +__FBSDID("$FreeBSD$"); /*=============================== Program Main ===============================*/ static void diff --git a/cddl/sbin/zfsd/zpool_list.cc b/cddl/sbin/zfsd/zpool_list.cc index 0b9cd9819fc3..7529770a71b4 100644 --- a/cddl/sbin/zfsd/zpool_list.cc +++ b/cddl/sbin/zfsd/zpool_list.cc @@ -35,10 +35,31 @@ * * Implementation of the ZpoolList class. */ +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + #include "vdev.h" +#include "vdev_iterator.h" #include "zpool_list.h" #include "zfsd.h" +/*============================ Namespace Control =============================*/ +using DevCtl::Guid; + /*=========================== Class Implementations ==========================*/ /*--------------------------------- ZpoolList --------------------------------*/ bool diff --git a/cddl/sbin/zfsd/zpool_list.h b/cddl/sbin/zfsd/zpool_list.h index ec2948b5d48c..0a97c3b94ee4 100644 --- a/cddl/sbin/zfsd/zpool_list.h +++ b/cddl/sbin/zfsd/zpool_list.h @@ -35,20 +35,25 @@ * * ZpoolList class definition. ZpoolList is a standard container * allowing filtering and iteration of imported ZFS pool information. + * + * Header requirements: + * + * #include + * #include */ #ifndef _ZPOOL_LIST_H_ #define _ZPOOL_LIST_H_ -#include -#include - -#include -#include - /*============================ Namespace Control =============================*/ using std::string; /*=========================== Forward Declarations ===========================*/ +struct zpool_handle; +typedef struct zpool_handle zpool_handle_t; + +struct nvlist; +typedef struct nvlist nvlist_t; + class Vdev; /*============================= Class Definitions ============================*/ diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 76cdf9488d44..911b95fabfce 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -159,6 +159,8 @@ wi .. .. + devctl + .. edit readline .. diff --git a/lib/Makefile b/lib/Makefile index 9ac894505998..2d845cb3c914 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -69,6 +69,7 @@ SUBDIR= ${SUBDIR_ORDERED} \ libcalendar \ libcam \ libcompat \ + libdevctl \ libdevinfo \ libdevstat \ libdwarf \ diff --git a/lib/libdevctl/Makefile b/lib/libdevctl/Makefile new file mode 100644 index 000000000000..250538f1ae22 --- /dev/null +++ b/lib/libdevctl/Makefile @@ -0,0 +1,23 @@ +# $FreeBSD: stable/9/lib/libdevinfo/Makefile 201381 2010-01-02 09:58:07Z ed $ + +LIB= devctl +INCS= consumer.h \ + event.h \ + event_buffer.h \ + event_factory.h \ + exception.h \ + guid.h \ + reader.h +SRCS= consumer.cc \ + event.cc \ + event_buffer.cc \ + event_factory.cc \ + exception.cc \ + guid.cc \ + reader.cc + +INCSDIR= ${INCLUDEDIR}/devctl + +WARNS?= 3 + +.include diff --git a/lib/libdevctl/consumer.cc b/lib/libdevctl/consumer.cc new file mode 100644 index 000000000000..d2d5c0c6f713 --- /dev/null +++ b/lib/libdevctl/consumer.cc @@ -0,0 +1,246 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file consumer.cc + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_buffer.h" +#include "event_factory.h" +#include "exception.h" +#include "reader.h" + +#include "consumer.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +using std::string; +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*----------------------------- DevCtl::Consumer -----------------------------*/ +//- Consumer Static Private Data ----------------------------------------------- +const char Consumer::s_devdSockPath[] = "/var/run/devd.pipe"; + +//- Consumer Public Methods ---------------------------------------------------- +Consumer::Consumer(Event::BuildMethod *defBuilder, + EventFactory::Record *regEntries, + size_t numEntries) + : m_devdSockFD(-1), + m_reader(NULL), + m_eventBuffer(NULL), + m_eventFactory(defBuilder), + m_replayingEvents(false) +{ + m_eventFactory.UpdateRegistry(regEntries, numEntries); +} + +Consumer::~Consumer() +{ + DisconnectFromDevd(); + delete m_reader; + m_reader = NULL; +} + +bool +Consumer::ConnectToDevd() +{ + struct sockaddr_un devdAddr; + int sLen; + int result; + + syslog(LOG_INFO, "Connecting to devd"); + if (m_devdSockFD != -1) { + /* Already connected. */ + return (true); + } + + memset(&devdAddr, 0, sizeof(devdAddr)); + devdAddr.sun_family= AF_UNIX; + strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path)); + sLen = SUN_LEN(&devdAddr); + + m_devdSockFD = socket(AF_UNIX, SOCK_STREAM, 0); + if (m_devdSockFD == -1) + err(1, "Unable to create socket"); + result = connect(m_devdSockFD, + reinterpret_cast(&devdAddr), + sLen); + if (result == -1) { + syslog(LOG_INFO, "Unable to connect to devd"); + return (false); + } + + /* Connect the stream to the file descriptor */ + m_reader = new FDReader(m_devdSockFD); + m_eventBuffer = new EventBuffer(*m_reader); + syslog(LOG_INFO, "Connection to devd successful"); + return (true); +} + +void +Consumer::DisconnectFromDevd() +{ + if (m_devdSockFD != -1) + syslog(LOG_INFO, "Disconnecting from devd."); + + delete m_eventBuffer; + m_eventBuffer = NULL; + delete m_reader; + m_reader = NULL; + close(m_devdSockFD); + m_devdSockFD = -1; +} + +void +Consumer::ReplayUnconsumedEvents(bool discardUnconsumed) +{ + EventList::iterator event(m_unconsumedEvents.begin()); + bool replayed_any = (event != m_unconsumedEvents.end()); + + m_replayingEvents = true; + if (replayed_any) + syslog(LOG_INFO, "Started replaying unconsumed events"); + while (event != m_unconsumedEvents.end()) { + bool consumed((*event)->Process()); + if (consumed || discardUnconsumed) { + delete *event; + event = m_unconsumedEvents.erase(event); + } else { + event++; + } + } + if (replayed_any) + syslog(LOG_INFO, "Finished replaying unconsumed events"); + m_replayingEvents = false; +} + +bool +Consumer::SaveEvent(const Event &event) +{ + if (m_replayingEvents) + return (false); + m_unconsumedEvents.push_back(event.DeepCopy()); + return (true); +} + +Event * +Consumer::NextEvent(EventBuffer *eventBuffer) +{ + if (!Connected()) + return(NULL); + + if (eventBuffer == NULL) + eventBuffer = m_eventBuffer; + + Event *event(NULL); + try { + string evString; + + if (eventBuffer->ExtractEvent(evString)) + event = Event::CreateEvent(m_eventFactory, evString); + } catch (const Exception &exp) { + exp.Log(); + DisconnectFromDevd(); + } + return (event); +} + +/* Capture and process buffered events. */ +void +Consumer::ProcessEvents(EventBuffer *eventBuffer) +{ + Event *event; + while ((event = NextEvent(eventBuffer)) != NULL) { + if (event->Process()) + SaveEvent(*event); + delete event; + } +} + +void +Consumer::FlushEvents() +{ + char discardBuf[256]; + + while (m_reader->in_avail()) + m_reader->read(discardBuf, sizeof(discardBuf)); +} + +bool +Consumer::EventsPending() +{ + struct pollfd fds[1]; + int result; + + do { + fds->fd = m_devdSockFD; + fds->events = POLLIN; + fds->revents = 0; + result = poll(fds, NUM_ELEMENTS(fds), /*timeout*/0); + } while (result == -1 && errno == EINTR); + + if (result == -1) + err(1, "Polling for devd events failed"); + + if ((fds->revents & POLLERR) != 0) + throw Exception("ZfsdDaemon:EventsPending(): " + "POLLERR detected on devd socket."); + + if ((fds->revents & POLLHUP) != 0) + throw Exception("Consumer::EventsPending(): " + "POLLHUP detected on devd socket."); + + return ((fds->revents & POLLIN) != 0); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/consumer.h b/lib/libdevctl/consumer.h new file mode 100644 index 000000000000..f8242425a3ac --- /dev/null +++ b/lib/libdevctl/consumer.h @@ -0,0 +1,171 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_consumer.h + */ +#ifndef _DEVCTL_CONSUMER_H_ +#define _DEVCTL_CONSUMER_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class Event; +class EventBuffer; +class FDReader; + +/*============================ Class Declarations ============================*/ +/*----------------------------- DevCtl::Consumer -----------------------------*/ + +/** + */ +class Consumer +{ +public: + Consumer(Event::BuildMethod *defBuilder = NULL, + EventFactory::Record *regEntries = NULL, + size_t numEntries = 0); + virtual ~Consumer(); + + bool Connected() const; + + /** + * Return file descriptor useful for client's wishing to poll(2) + * for new events. + */ + int GetPollFd(); + + /** + * Queue an event for deferred processing or replay. + */ + bool SaveEvent(const Event &event); + + /** + * Reprocess any events saved via the SaveEvent() facility. + * + * \param discardUnconsumed If true, events that are not conumed + * during replay are discarded. + */ + void ReplayUnconsumedEvents(bool discardUnconsumed); + + /** Return an event, if available, from the provided EventBuffer. */ + Event *NextEvent(EventBuffer *eventBuffer = NULL); + + /** + * Extract events from the provided eventBuffer and invoke + * each event's Process method. + */ + void ProcessEvents(EventBuffer *eventBuffer = NULL); + + /** Discard all data pending in m_devdSockFD. */ + void FlushEvents(); + + /** + * Test for data pending in m_devdSockFD + * + * \return True if data is pending. Otherwise false. + */ + bool EventsPending(); + + /** + * Open a connection to devd's unix domain socket. + * + * \return True if the connection attempt is successsful. Otherwise + * false. + */ + bool ConnectToDevd(); + + /** + * Close a connection (if any) to devd's unix domain socket. + */ + void DisconnectFromDevd(); + + EventFactory GetFactory(); + +protected: + static const char s_devdSockPath[]; + + /** + * File descriptor representing the unix domain socket + * connection with devd. + */ + int m_devdSockFD; + + /** + * Reader tied to the devd socket. + */ + FDReader *m_reader; + + /** + * Default EventBuffer connected to m_reader. + */ + EventBuffer *m_eventBuffer; + + EventFactory m_eventFactory; + + /** Queued events for replay. */ + EventList m_unconsumedEvents; + + /** + * Flag controlling whether events can be queued. This boolean + * is set during event replay to ensure that previosuly deferred + * events are not requeued and thus retained forever. + */ + bool m_replayingEvents; +}; + +//- Consumer Const Public Inline Methods --------------------------------------- +inline bool +Consumer::Connected() const +{ + return (m_devdSockFD != -1); +} + +//- Consumer Public Inline Methods --------------------------------------------- +inline int +Consumer::GetPollFd() +{ + return (m_devdSockFD); +} + +inline EventFactory +Consumer::GetFactory() +{ + return (m_eventFactory); +} + +} // namespace DevCtl +#endif /* _DEVCTL_CONSUMER_H_ */ diff --git a/lib/libdevctl/event.cc b/lib/libdevctl/event.cc new file mode 100644 index 000000000000..20230944b9a8 --- /dev/null +++ b/lib/libdevctl/event.cc @@ -0,0 +1,513 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event.cc + * + * Implementation of the class hierarchy used to express events + * received via the devctl API. + */ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_factory.h" +#include "exception.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +using std::cout; +using std::endl; +using std::string; +using std::stringstream; + +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*----------------------------------- Event ----------------------------------*/ +//- Event Static Protected Data ------------------------------------------------ +const string Event::s_theEmptyString; + +Event::EventTypeRecord Event::s_typeTable[] = +{ + { Event::NOTIFY, "Notify" }, + { Event::NOMATCH, "No Driver Match" }, + { Event::ATTACH, "Attach" }, + { Event::DETACH, "Detach" } +}; + +//- Event Static Public Methods ------------------------------------------------ +Event * +Event::CreateEvent(const EventFactory &factory, const string &eventString) +{ + NVPairMap &nvpairs(*new NVPairMap); + Type type(static_cast(eventString[0])); + + try { + ParseEventString(type, eventString, nvpairs); + } catch (const ParseException &exp) { + if (exp.GetType() == ParseException::INVALID_FORMAT) + exp.Log(); + return (NULL); + } + + /* + * Allow entries in our table for events with no system specified. + * These entries should specify the string "none". + */ + NVPairMap::iterator system_item(nvpairs.find("system")); + if (system_item == nvpairs.end()) + nvpairs["system"] = "none"; + + return (factory.Build(type, nvpairs, eventString)); +} + +const char * +Event::TypeToString(Event::Type type) +{ + EventTypeRecord *rec(s_typeTable); + EventTypeRecord *lastRec(s_typeTable + NUM_ELEMENTS(s_typeTable) - 1); + + for (; rec <= lastRec; rec++) { + if (rec->m_type == type) + return (rec->m_typeName); + } + return ("Unknown"); +} + +//- Event Public Methods ------------------------------------------------------- +const string & +Event::Value(const string &varName) const +{ + NVPairMap::const_iterator item(m_nvPairs.find(varName)); + if (item == m_nvPairs.end()) + return (s_theEmptyString); + + return (item->second); +} + +bool +Event::Contains(const string &varName) const +{ + return (m_nvPairs.find(varName) != m_nvPairs.end()); +} + +string +Event::ToString() const +{ + stringstream result; + + NVPairMap::const_iterator devName(m_nvPairs.find("device-name")); + if (devName != m_nvPairs.end()) + result << devName->second << ": "; + + NVPairMap::const_iterator systemName(m_nvPairs.find("system")); + if (systemName != m_nvPairs.end() + && systemName->second != "none") + result << systemName->second << ": "; + + result << TypeToString(GetType()) << ' '; + + for (NVPairMap::const_iterator curVar = m_nvPairs.begin(); + curVar != m_nvPairs.end(); curVar++) { + if (curVar == devName || curVar == systemName) + continue; + + result << ' ' + << curVar->first << "=" << curVar->second; + } + result << endl; + + return (result.str()); +} + +void +Event::Print() const +{ + cout << ToString() << std::flush; +} + +void +Event::Log(int priority) const +{ + syslog(priority, "%s", ToString().c_str()); +} + +//- Event Virtual Public Methods ----------------------------------------------- +Event::~Event() +{ + delete &m_nvPairs; +} + +bool +Event::Process() const +{ + return (false); +} + +timeval +Event::GetTimestamp() const +{ + timeval tv_timestamp; + struct tm tm_timestamp; + + if (!Contains("timestamp")) { + throw Exception("Event contains no timestamp: %s", + m_eventString.c_str()); + } + strptime(Value(string("timestamp")).c_str(), "%s", &tm_timestamp); + tv_timestamp.tv_sec = mktime(&tm_timestamp); + tv_timestamp.tv_usec = 0; + return (tv_timestamp); +} + + +//- Event Protected Methods ---------------------------------------------------- +Event::Event(Type type, NVPairMap &map, const string &eventString) + : m_type(type), + m_nvPairs(map), + m_eventString(eventString) +{ +} + +Event::Event(const Event &src) + : m_type(src.m_type), + m_nvPairs(*new NVPairMap(src.m_nvPairs)), + m_eventString(src.m_eventString) +{ +} + +void +Event::ParseEventString(Event::Type type, + const string &eventString, + NVPairMap& nvpairs) +{ + size_t start; + size_t end; + + switch (type) { + case ATTACH: + case DETACH: + + /* + * \ + * at \ + * on + * + * Handle all data that doesn't conform to the + * "name=value" format, and let the generic parser + * below handle the rest. + * + * Type is a single char. Skip it. + */ + start = 1; + end = eventString.find_first_of(" \t\n", start); + if (end == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, start); + + nvpairs["device-name"] = eventString.substr(start, end - start); + + start = eventString.find(" on ", end); + if (end == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, start); + start += 4; + end = eventString.find_first_of(" \t\n", start); + nvpairs["parent"] = eventString.substr(start, end); + break; + case NOTIFY: + break; + case NOMATCH: + throw ParseException(ParseException::DISCARDED_EVENT_TYPE, + eventString); + default: + throw ParseException(ParseException::UNKNOWN_EVENT_TYPE, + eventString); + } + + /* Process common "key=value" format. */ + for (start = 1; start < eventString.length(); start = end + 1) { + + /* Find the '=' in the middle of the key/value pair. */ + end = eventString.find('=', start); + if (end == string::npos) + break; + + /* + * Find the start of the key by backing up until + * we hit whitespace or '!' (event type "notice"). + * Due to the devctl format, all key/value pair must + * start with one of these two characters. + */ + start = eventString.find_last_of("! \t\n", end); + if (start == string::npos) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, end); + start++; + string key(eventString.substr(start, end - start)); + + /* + * Walk forward from the '=' until either we exhaust + * the buffer or we hit whitespace. + */ + start = end + 1; + if (start >= eventString.length()) + throw ParseException(ParseException::INVALID_FORMAT, + eventString, end); + end = eventString.find_first_of(" \t\n", start); + if (end == string::npos) + end = eventString.length() - 1; + string value(eventString.substr(start, end - start)); + + nvpairs[key] = value; + } +} + +/*-------------------------------- DevfsEvent --------------------------------*/ +//- DevfsEvent Static Public Methods ------------------------------------------- +Event * +DevfsEvent::DevfsEventBuilder(Event::Type type, NVPairMap &nvPairs, + const string &eventString) +{ + return (new DevfsEvent(type, nvPairs, eventString)); +} + +//- DevfsEvent Static Protected Methods ---------------------------------------- +bool +DevfsEvent::IsDiskDev(const string &devName) +{ + static const char *diskDevNames[] = + { + "da", + "ada" + }; + + const char **diskName(diskDevNames); + const char **lastDiskName(diskDevNames + + NUM_ELEMENTS(diskDevNames) - 1); + size_t find_start = devName.rfind('/'); + if (find_start == string::npos) { + find_start = 0; + } else { + /* Just after the last '/'. */ + find_start++; + } + + for (; diskName <= lastDiskName; diskName++) { + + size_t loc(devName.find(*diskName, find_start)); + if (loc == find_start) { + size_t prefixLen(strlen(*diskName)); + + if (devName.length() - find_start >= prefixLen + && isdigit(devName[find_start + prefixLen])) + return (true); + } + } + + return (false); +} + +bool +DevfsEvent::IsWholeDev(const string &devName) +{ + string::const_iterator i(devName.begin()); + + size_t start = devName.rfind('/'); + if (start == string::npos) { + start = 0; + } else { + /* Just after the last '/'. */ + start++; + } + i += start; + + /* alpha prefix followed only by digits. */ + for (; i < devName.end() && !isdigit(*i); i++) + ; + + if (i == devName.end()) + return (false); + + for (; i < devName.end() && isdigit(*i); i++) + ; + + return (i == devName.end()); +} + +//- DevfsEvent Virtual Public Methods ------------------------------------------ +Event * +DevfsEvent::DeepCopy() const +{ + return (new DevfsEvent(*this)); +} + +bool +DevfsEvent::Process() const +{ + return (true); +} + +//- DevfsEvent Public Methods -------------------------------------------------- +bool +DevfsEvent::IsDiskDev() const +{ + string devName; + + return (DevName(devName) && IsDiskDev(devName)); +} + +bool +DevfsEvent::IsWholeDev() const +{ + string devName; + + return (DevName(devName) && IsDiskDev() && IsWholeDev(devName)); +} + +bool +DevfsEvent::DevName(std::string &name) const +{ + if (Value("subsystem") != "CDEV") + return (false); + + name = Value("cdev"); + return (!name.empty()); +} + +bool +DevfsEvent::DevPath(std::string &path) const +{ + string devName; + + if (!DevName(devName)) + return (false); + + string devPath(_PATH_DEV + devName); + int devFd(open(devPath.c_str(), O_RDONLY)); + if (devFd == -1) + return (false); + + /* Normalize the device name in case the DEVFS event is for a link. */ + devName = fdevname(devFd); + path = _PATH_DEV + devName; + + close(devFd); + + return (true); +} + +bool +DevfsEvent::PhysicalPath(std::string &path) const +{ + string devPath; + + if (!DevPath(devPath)) + return (false); + + int devFd(open(devPath.c_str(), O_RDONLY)); + if (devFd == -1) + return (false); + + char physPath[MAXPATHLEN]; + physPath[0] = '\0'; + bool result(ioctl(devFd, DIOCGPHYSPATH, physPath) == 0); + close(devFd); + if (result) + path = physPath; + return (result); +} + +//- DevfsEvent Protected Methods ----------------------------------------------- +DevfsEvent::DevfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : Event(type, nvpairs, eventString) +{ +} + +DevfsEvent::DevfsEvent(const DevfsEvent &src) + : Event(src) +{ +} + +/*--------------------------------- ZfsEvent ---------------------------------*/ +//- ZfsEvent Static Public Methods --------------------------------------------- +Event * +ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs, + const string &eventString) +{ + return (new ZfsEvent(type, nvpairs, eventString)); +} + +//- ZfsEvent Virtual Public Methods -------------------------------------------- +Event * +ZfsEvent::DeepCopy() const +{ + return (new ZfsEvent(*this)); +} + +//- ZfsEvent Protected Methods ------------------------------------------------- +ZfsEvent::ZfsEvent(Event::Type type, NVPairMap &nvpairs, + const string &eventString) + : Event(type, nvpairs, eventString), + m_poolGUID(Guid(Value("pool_guid"))), + m_vdevGUID(Guid(Value("vdev_guid"))) +{ +} + +ZfsEvent::ZfsEvent(const ZfsEvent &src) + : Event(src), + m_poolGUID(src.m_poolGUID), + m_vdevGUID(src.m_vdevGUID) +{ +} + +} // namespace DevCtl diff --git a/lib/libdevctl/event.h b/lib/libdevctl/event.h new file mode 100644 index 000000000000..e7b92300fe37 --- /dev/null +++ b/lib/libdevctl/event.h @@ -0,0 +1,366 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event.h + * + * \brief Class hierarchy used to express events received via + * the devctl API. + */ + +#ifndef _DEVCTL_EVENT_H_ +#define _DEVCTL_EVENT_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class EventFactory; + +/*============================= Class Definitions ============================*/ +/*-------------------------------- NVPairMap ---------------------------------*/ +/** + * NVPairMap is a specialization of the standard map STL container. + */ +typedef std::map NVPairMap; + +/*----------------------------------- Event ----------------------------------*/ +/** + * \brief Container for the name => value pairs that comprise the content of + * a device control event. + * + * All name => value data for events can be accessed via the Contains() + * and Value() methods. name => value pairs for data not explicitly + * received as a name => value pair are synthesized during parsing. For + * example, ATTACH and DETACH events have "device-name" and "parent" + * name => value pairs added. + */ +class Event +{ + friend class EventFactory; + +public: + /** Event type */ + enum Type { + /** Generic event notification. */ + NOTIFY = '!', + + /** A driver was not found for this device. */ + NOMATCH = '?', + + /** A bus device instance has been added. */ + ATTACH = '+', + + /** A bus device instance has been removed. */ + DETACH = '-' + }; + + /** + * Factory method type to construct an Event given + * the type of event and an NVPairMap populated from + * the event string received from devd. + */ + typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &); + + static Event *CreateEvent(const EventFactory &factory, + const std::string &eventString); + + /** + * Provide a user friendly string representation of an + * event type. + * + * \param type The type of event to map to a string. + * + * \return A user friendly string representing the input type. + */ + static const char *TypeToString(Type type); + + /** + * Determine the availability of a name => value pair by name. + * + * \param name The key name to search for in this event instance. + * + * \return true if the specified key is available in this + * event, otherwise false. + */ + bool Contains(const std::string &name) const; + + /** + * \param key The name of the key for which to retrieve its + * associated value. + * + * \return A const reference to the string representing the + * value associated with key. + * + * \note For key's with no registered value, the empty string + * is returned. + */ + const std::string &Value(const std::string &key) const; + + /** + * Get the type of this event instance. + * + * \return The type of this event instance. + */ + Type GetType() const; + + /** + * Get the orginal DevCtl event string for this event. + * + * \return The DevCtl event string. + */ + const std::string &GetEventString() const; + + /** + * Convert the event instance into a string suitable for + * printing to the console or emitting to syslog. + * + * \return A string of formatted event data. + */ + std::string ToString() const; + + /** + * Pretty-print this event instance to cout. + */ + void Print() const; + + /** + * Pretty-print this event instance to syslog. + * + * \param priority The logging priority/facility. + * See syslog(3). + */ + void Log(int priority) const; + + /** + * Create and return a fully independent clone + * of this event. + */ + virtual Event *DeepCopy() const = 0; + + /** Destructor */ + virtual ~Event(); + + /** + * Interpret and perform any actions necessary to + * consume the event. + * + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + + /** + * Get the time that the event was created + */ + timeval GetTimestamp() const; + + /** + * Access all parsed key => value pairs. + */ + const NVPairMap &GetMap() const; + +protected: + /** Table entries used to map a type to a user friendly string. */ + struct EventTypeRecord + { + Type m_type; + const char *m_typeName; + }; + + /** + * Constructor + * + * \param type The type of event to create. + */ + Event(Type type, NVPairMap &map, const std::string &eventString); + + /** Deep copy constructor. */ + Event(const Event &src); + + /** Always empty string returned when NVPairMap lookups fail. */ + static const std::string s_theEmptyString; + + /** Unsorted table of event types. */ + static EventTypeRecord s_typeTable[]; + + /** The type of this event. */ + const Type m_type; + + /** + * Event attribute storage. + * + * \note Although stored by reference (since m_nvPairs can + * never be NULL), the NVPairMap referenced by this field + * is dynamically allocated and owned by this event object. + * m_nvPairs must be deleted at event desctruction. + */ + NVPairMap &m_nvPairs; + + /** + * The unaltered event string, as received from devd, used to + * create this event object. + */ + std::string m_eventString; + +private: + /** + * Ingest event data from the supplied string. + * + * \param[in] eventString The string of devd event data to parse. + * \param[out] nvpairs Returns the parsed data + */ + static void ParseEventString(Type type, const std::string &eventString, + NVPairMap &nvpairs); +}; + +inline Event::Type +Event::GetType() const +{ + return (m_type); +} + +inline const std::string & +Event::GetEventString() const +{ + return (m_eventString); +} + +inline const NVPairMap & +Event::GetMap() const +{ + return (m_nvPairs); +} + +/*--------------------------------- EventList --------------------------------*/ +/** + * EventList is a specialization of the standard list STL container. + */ +typedef std::list EventList; + +/*-------------------------------- DevfsEvent --------------------------------*/ +class DevfsEvent : public Event +{ +public: + /** Specialized Event object factory for Devfs events. */ + static BuildMethod DevfsEventBuilder; + + virtual Event *DeepCopy() const; + + /** + * Interpret and perform any actions necessary to + * consume the event. + * \return True if this event should be queued for later reevaluation + */ + virtual bool Process() const; + + bool IsDiskDev() const; + bool IsWholeDev() const; + bool DevName(std::string &name) const; + bool DevPath(std::string &path) const; + bool PhysicalPath(std::string &path) const; + +protected: + /** + * Determine if the given device name references a potential + * disk device. + * + * \param devName The device name to test. + */ + static bool IsDiskDev(const std::string &devName); + + /** + * Given the device name of a disk, determine if the device + * represents the whole device, not just a partition. + * + * \param devName Device name of disk device to test. + * + * \return True if the device name represents the whole device. + * Otherwise false. + */ + static bool IsWholeDev(const std::string &devName); + + /** DeepCopy Constructor. */ + DevfsEvent(const DevfsEvent &src); + + /** Constructor */ + DevfsEvent(Type, NVPairMap &, const std::string &); +}; + +/*--------------------------------- ZfsEvent ---------------------------------*/ +class ZfsEvent : public Event +{ +public: + /** Specialized Event object factory for ZFS events. */ + static BuildMethod ZfsEventBuilder; + + virtual Event *DeepCopy() const; + + const std::string &PoolName() const; + Guid PoolGUID() const; + Guid VdevGUID() const; + +protected: + /** Constructor */ + ZfsEvent(Type, NVPairMap &, const std::string &); + + /** Deep copy constructor. */ + ZfsEvent(const ZfsEvent &src); + + Guid m_poolGUID; + Guid m_vdevGUID; +}; + +//- ZfsEvent Inline Public Methods -------------------------------------------- +inline const std::string& +ZfsEvent::PoolName() const +{ + /* The pool name is reported as the subsystem of ZFS events. */ + return (Value("subsystem")); +} + +inline Guid +ZfsEvent::PoolGUID() const +{ + return (m_poolGUID); +} + +inline Guid +ZfsEvent::VdevGUID() const +{ + return (m_vdevGUID); +} + +} // namespace DevCtl +#endif /*_DEVCTL_EVENT_H_ */ diff --git a/lib/libdevctl/event_buffer.cc b/lib/libdevctl/event_buffer.cc new file mode 100644 index 000000000000..5fe0ac64b924 --- /dev/null +++ b/lib/libdevctl/event_buffer.cc @@ -0,0 +1,216 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event_buffer.cc + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "event_buffer.h" +#include "exception.h" +#include "reader.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +using std::string; +using std::stringstream; +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*-------------------------------- EventBuffer -------------------------------*/ +//- EventBuffer Static Data ---------------------------------------------------- +/** + * NOTIFY, NOMATCH, ATTACH, DETACH. See DevCtlEvent::Type. + */ +const char EventBuffer::s_eventStartTokens[] = "!?+-"; + +/** + * Events are terminated by a newline. + */ +const char EventBuffer::s_eventEndTokens[] = "\n"; + +/** + * Key=Value pairs are terminated by whitespace. + */ +const char EventBuffer::s_keyPairSepTokens[] = " \t\n"; + +//- EventBuffer Public Methods ------------------------------------------------- +EventBuffer::EventBuffer(Reader& reader) + : m_reader(reader), + m_validLen(0), + m_parsedLen(0), + m_nextEventOffset(0), + m_synchronized(true) +{ +} + +bool +EventBuffer::ExtractEvent(string &eventString) +{ + stringstream tsField; + timeval now; + + gettimeofday(&now, NULL); + tsField << " timestamp=" << now.tv_sec; + + while (UnParsed() > 0 || Fill()) { + + /* + * If the valid data in the buffer isn't enough to hold + * a full event, try reading more. + */ + if (NextEventMaxLen() < MIN_EVENT_SIZE) { + m_parsedLen += UnParsed(); + continue; + } + + char *nextEvent(m_buf + m_nextEventOffset); + bool truncated(true); + size_t eventLen(strcspn(nextEvent, s_eventEndTokens)); + + if (!m_synchronized) { + /* Discard data until an end token is read. */ + if (nextEvent[eventLen] != '\0') + m_synchronized = true; + m_nextEventOffset += eventLen; + m_parsedLen = m_nextEventOffset; + continue; + } else if (nextEvent[eventLen] == '\0') { + + m_parsedLen += eventLen; + if (m_parsedLen < MAX_EVENT_SIZE) { + /* + * Ran out of buffer before hitting + * a full event. Fill() and try again. + */ + continue; + } + syslog(LOG_WARNING, "Overran event buffer\n\tm_nextEventOffset" + "=%zd\n\tm_parsedLen=%zd\n\tm_validLen=%zd", + m_nextEventOffset, m_parsedLen, m_validLen); + } else { + /* + * Include the normal terminator in the extracted + * event data. + */ + eventLen += 1; + truncated = false; + } + + m_nextEventOffset += eventLen; + m_parsedLen = m_nextEventOffset; + eventString.assign(nextEvent, eventLen); + + if (truncated) { + size_t fieldEnd; + + /* Break cleanly at the end of a key<=>value pair. */ + fieldEnd = eventString.find_last_of(s_keyPairSepTokens); + if (fieldEnd != string::npos) + eventString.erase(fieldEnd); + eventString += '\n'; + + m_synchronized = false; + syslog(LOG_WARNING, + "Truncated %zd characters from event.", + eventLen - fieldEnd); + } + + /* + * Add a timestamp as the final field of the event if it is + * not already present. + */ + if (eventString.find("timestamp=") == string::npos) { + size_t eventEnd(eventString.find_last_not_of('\n') + 1); + + eventString.insert(eventEnd, tsField.str()); + } + + return (true); + } + return (false); +} + +//- EventBuffer Private Methods ------------------------------------------------ +bool +EventBuffer::Fill() +{ + ssize_t avail; + ssize_t consumed(0); + + /* Compact the buffer. */ + if (m_nextEventOffset != 0) { + memmove(m_buf, m_buf + m_nextEventOffset, + m_validLen - m_nextEventOffset); + m_validLen -= m_nextEventOffset; + m_parsedLen -= m_nextEventOffset; + m_nextEventOffset = 0; + } + + /* Fill any empty space. */ + avail = m_reader.in_avail(); + if (avail > 0) { + size_t want; + + want = std::min((size_t)avail, MAX_READ_SIZE - m_validLen); + consumed = m_reader.read(m_buf + m_validLen, want); + if (consumed == -1) { + if (errno == EINTR) + return (false); + else + err(1, "EventBuffer::Fill(): Read failed"); + } + } else if (avail == -1) { + throw Exception("EventBuffer::Fill(): Reader disconnected"); + } + + m_validLen += consumed; + /* Guarantee our buffer is always NUL terminated. */ + m_buf[m_validLen] = '\0'; + + return (consumed > 0); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/event_buffer.h b/lib/libdevctl/event_buffer.h new file mode 100644 index 000000000000..4640a2d0128d --- /dev/null +++ b/lib/libdevctl/event_buffer.h @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event_buffer.h + */ +#ifndef _DEVCTL_EVENT_BUFFER_H_ +#define _DEVCTL_EVENT_BUFFER_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Forward Declarations ===========================*/ +class Reader; + +/*============================= Class Definitions ============================*/ +/*-------------------------------- EventBuffer -------------------------------*/ +/** + * \brief Class buffering event data from Devd or a similar source and + * splitting it into individual event strings. + * + * Users of this class initialize it with a Reader associated with the unix + * domain socket connection with devd or a compatible source. The lifetime of + * an EventBuffer instance should match that of the Reader passed to it. This + * is required as data from partially received events is retained in the + * EventBuffer in order to allow reconstruction of these events across multiple + * reads of the stream. + * + * Once the program determines that the Reader is ready for reading, the + * EventBuffer::ExtractEvent() should be called in a loop until the method + * returns false. + */ +class EventBuffer +{ +public: + /** + * Constructor + * + * \param reader The data source on which to buffer/parse event data. + */ + EventBuffer(Reader& reader); + + /** + * Pull a single event string out of the event buffer. + * + * \param eventString The extracted event data (if available). + * + * \return true if event data is available and eventString has + * been populated. Otherwise false. + */ + bool ExtractEvent(std::string &eventString); + +private: + enum { + /** + * Size of an empty event (start and end token with + * no data. The EventBuffer parsing needs at least + * this much data in the buffer for safe event extraction. + */ + MIN_EVENT_SIZE = 2, + + /* + * The maximum event size supported by ZFSD. + * Events larger than this size (minus 1) are + * truncated at the end of the last fully received + * key/value pair. + */ + MAX_EVENT_SIZE = 8192, + + /** + * The maximum amount of buffer data to read at + * a single time from the Devd file descriptor. + */ + MAX_READ_SIZE = MAX_EVENT_SIZE, + + /** + * The size of EventBuffer's buffer of Devd event data. + * This is one larger than the maximum supported event + * size, which alows us to always include a terminating + * NUL without overwriting any received data. + */ + EVENT_BUFSIZE = MAX_EVENT_SIZE + /*NUL*/1 + }; + + /** The amount of data in m_buf we have yet to look at. */ + size_t UnParsed() const; + + /** The amount of data in m_buf available for the next event. */ + size_t NextEventMaxLen() const; + + /** Fill the event buffer with event data from Devd. */ + bool Fill(); + + /** Characters we treat as beginning an event string. */ + static const char s_eventStartTokens[]; + + /** Characters we treat as ending an event string. */ + static const char s_eventEndTokens[]; + + /** Characters found between successive "key=value" strings. */ + static const char s_keyPairSepTokens[]; + + /** Temporary space for event data during our parsing. Laid out like + * this: + * <---------------------------------------------------------> + * | | | | | + * m_buf---| | | | | + * m_nextEventOffset-- | | | + * m_parsedLen------------- | | + * m_validLen-------------------------- | + * EVENT_BUFSIZE------------------------------------------------------ + * + * Data before m_nextEventOffset has already been processed. + * + * Data between m_nextEvenOffset and m_parsedLen has been parsed, but + * not processed as a single event. + * + * Data between m_parsedLen and m_validLen has been read from the + * source, but not yet parsed. + * + * Between m_validLen and EVENT_BUFSIZE is empty space. + * + * */ + char m_buf[EVENT_BUFSIZE]; + + /** Reference to the reader linked to devd's domain socket. */ + Reader& m_reader; + + /** Offset within m_buf to the beginning of free space. */ + size_t m_validLen; + + /** Offset within m_buf to the beginning of data not yet parsed */ + size_t m_parsedLen; + + /** Offset within m_buf to the start token of the next event. */ + size_t m_nextEventOffset; + + /** The EventBuffer is aligned and tracking event records. */ + bool m_synchronized; +}; + +//- EventBuffer Inline Private Methods ----------------------------------------- +inline size_t +EventBuffer::UnParsed() const +{ + return (m_validLen - m_parsedLen); +} + +inline size_t +EventBuffer::NextEventMaxLen() const +{ + return (m_validLen - m_nextEventOffset); +} + +} // namespace DevCtl +#endif /* _DEVCTL_EVENT_BUFFER_H_ */ diff --git a/lib/libdevctl/event_factory.cc b/lib/libdevctl/event_factory.cc new file mode 100644 index 000000000000..2e9da4eb6a8b --- /dev/null +++ b/lib/libdevctl/event_factory.cc @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file event_factory.cc + */ +#include + +#include +#include +#include + +#include "guid.h" +#include "event.h" +#include "event_factory.h" + +__FBSDID("$FreeBSD$"); + +/*================================== Macros ==================================*/ +#define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*------------------------------- EventFactory -------------------------------*/ +//- Event Public Methods ------------------------------------------------------- +EventFactory::EventFactory(Event::BuildMethod *defaultBuildMethod) + : m_defaultBuildMethod(defaultBuildMethod) +{ +} + +void +EventFactory::UpdateRegistry(Record regEntries[], size_t numEntries) +{ + EventFactory::Record *rec(regEntries); + EventFactory::Record *lastRec(rec + numEntries - 1); + + for (; rec <= lastRec; rec++) { + Key key(rec->m_type, rec->m_subsystem); + + if (rec->m_buildMethod == NULL) + m_registry.erase(key); + else + m_registry[key] = rec->m_buildMethod; + } +} + +Event * +EventFactory::Build(Event::Type type, NVPairMap &nvpairs, + const std::string eventString) const +{ + Key key(type, nvpairs["system"]); + Event::BuildMethod *buildMethod(m_defaultBuildMethod); + + Registry::const_iterator foundMethod(m_registry.find(key)); + if (foundMethod != m_registry.end()) + buildMethod = foundMethod->second; + + if (buildMethod == NULL) + return (NULL); + + return ((foundMethod->second)(type, nvpairs, eventString)); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/event_factory.h b/lib/libdevctl/event_factory.h new file mode 100644 index 000000000000..d7fdecb7786c --- /dev/null +++ b/lib/libdevctl/event_factory.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_event_factory.h + */ + +#ifndef _DEVCTL_EVENT_FACTORY_H_ +#define _DEVCTL_EVENT_FACTORY_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*------------------------------- EventFactory -------------------------------*/ +/** + * \brief Container for "event type" => "event object" creaction methods. + */ +class EventFactory +{ +public: + /** + * Event creation handlers are matched by event type and a + * string representing the system emitting the event. + */ + typedef std::pair Key; + + /** Map type for Factory method lookups. */ + typedef std::map Registry; + + /** Table record of factory methods to add to our registry. */ + struct Record + { + Event::Type m_type; + const char *m_subsystem; + Event::BuildMethod *m_buildMethod; + }; + + const Registry &GetRegistry() const; + Event *Build(Event::Type type, NVPairMap &nvpairs, + const std::string eventString) const; + + EventFactory(Event::BuildMethod *defaultBuildMethod = NULL); + + void UpdateRegistry(Record regEntries[], size_t numEntries); + + +protected: + /** Registry of event factory methods providing O(log(n)) lookup. */ + Registry m_registry; + + Event::BuildMethod *m_defaultBuildMethod; +}; + +inline const EventFactory::Registry & +EventFactory::GetRegistry() const +{ + return (m_registry); +} + +} // namespace DevCtl +#endif /*_DEVCTL_EVENT_FACTORY_H_ */ diff --git a/lib/libdevctl/exception.cc b/lib/libdevctl/exception.cc new file mode 100644 index 000000000000..4d242df29f42 --- /dev/null +++ b/lib/libdevctl/exception.cc @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file exception.cc + */ +#include + +#include + +#include +#include + +#include "exception.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +using std::string; +using std::stringstream; +using std::endl; +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*--------------------------------- Exception --------------------------------*/ +void +Exception::FormatLog(const char *fmt, va_list ap) +{ + char buf[256]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + m_log = buf; +} + +Exception::Exception(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + FormatLog(fmt, ap); + va_end(ap); +} + +Exception::Exception() +{ +} + +void +Exception::Log() const +{ + syslog(LOG_ERR, "%s", m_log.c_str()); +} + +/*------------------------------ ParseException ------------------------------*/ +//- ParseException Inline Public Methods --------------------------------------- +ParseException::ParseException(Type type, const std::string &parsedBuffer, + size_t offset) + : Exception(), + m_type(type), + m_parsedBuffer(parsedBuffer), + m_offset(offset) +{ + stringstream logstream; + + logstream << "Parsing "; + + switch (Type()) { + case INVALID_FORMAT: + logstream << "invalid format "; + break; + case DISCARDED_EVENT_TYPE: + logstream << "discarded event "; + break; + case UNKNOWN_EVENT_TYPE: + logstream << "unknown event "; + break; + default: + break; + } + logstream << "exception on buffer: \'"; + if (GetOffset() == 0) { + logstream << m_parsedBuffer << '\'' << endl; + } else { + string markedBuffer(m_parsedBuffer); + + markedBuffer.insert(GetOffset(), ""); + logstream << markedBuffer << '\'' << endl; + } + + GetString() = logstream.str(); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/exception.h b/lib/libdevctl/exception.h new file mode 100644 index 000000000000..8c4a4e7b2961 --- /dev/null +++ b/lib/libdevctl/exception.h @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + */ + +/** + * \file zfsd_exception.h + * + * Definition of the ZfsdException class hierarchy. All exceptions + * explicitly thrown by Zfsd are defined here. + */ +#ifndef _DEVCTL_EXCEPTION_H_ +#define _DEVCTL_EXCEPTION_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ + +/*--------------------------------- Exception --------------------------------*/ +/** + * \brief Class allowing unified reporting/logging of exceptional events. + */ +class Exception +{ +public: + /** + * \brief Exception constructor allowing arbitrary string + * data to be reported. + * + * \param fmt Printf-like string format specifier. + */ + Exception(const char *fmt, ...); + + /** + * \brief Augment/Modify a Exception's string data. + */ + std::string& GetString(); + + /** + * \brief Emit exception data to syslog(3). + */ + virtual void Log() const; + +protected: + Exception(); + + /** + * \brief Convert exception string format and arguments provided + * in event constructors into a linear string. + */ + void FormatLog(const char *fmt, va_list ap); + + std::string m_log; +}; + +inline std::string & +Exception::GetString() +{ + return (m_log); +} + +/*------------------------------ ParseException ------------------------------*/ +/** + * Exception thrown when an event string is not converted to an actionable + * Event object. + */ +class ParseException : public Exception +{ +public: + enum Type + { + /** Improperly formatted event string encounterd. */ + INVALID_FORMAT, + + /** No handlers for this event type. */ + DISCARDED_EVENT_TYPE, + + /** Unhandled event type. */ + UNKNOWN_EVENT_TYPE + }; + + /** + * Constructor + * + * \param type The type of this exception. + * \param parsedBuffer The parsing buffer active at the time of + * the exception. + * \param offset The location in the parse buffer where this + * exception occurred. + */ + ParseException(Type type, const std::string &parsedBuffer, + size_t offset = 0); + + /** + * Accessor + * + * \return The classification for this exception. + */ + Type GetType() const; + + /** + * Accessor + * + * \return The offset into the event string where this exception + * occurred. + */ + size_t GetOffset() const; + +private: + /** The type of this exception. */ + Type m_type; + + /** The parsing buffer that was active at the time of the exception. */ + const std::string m_parsedBuffer; + + /** + * The offset into the event string buffer from where this + * exception was triggered. + */ + size_t m_offset; +}; + +//- ParseException Inline Const Public Methods --------------------------------- +inline ParseException::Type +ParseException::GetType() const +{ + return (m_type); +} + +inline size_t +ParseException::GetOffset() const +{ + return (m_offset); +} + +} // namespace DevCtl +#endif /* _DEVCTL_EXCEPTION_H_ */ diff --git a/lib/libdevctl/guid.cc b/lib/libdevctl/guid.cc new file mode 100644 index 000000000000..031f3f61558a --- /dev/null +++ b/lib/libdevctl/guid.cc @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file guid.cc + * + * Implementation of the Guid class. + */ +#include + +#include +#include +#include + +#include +#include + +#include "guid.h" + +__FBSDID("$FreeBSD$"); +/*============================ Namespace Control =============================*/ +using std::string; +namespace DevCtl +{ + +/*=========================== Class Implementations ==========================*/ +/*----------------------------------- Guid -----------------------------------*/ +Guid::Guid(const string &guidString) +{ + if (guidString.empty()) { + m_GUID = INVALID_GUID; + } else { + /* + * strtoumax() returns zero on conversion failure + * which nicely matches our choice for INVALID_GUID. + */ + m_GUID = (uint64_t)strtoumax(guidString.c_str(), NULL, 0); + } +} + +std::ostream& +operator<< (std::ostream& out, Guid g) +{ + if (g.IsValid()) + out << (uint64_t)g; + else + out << "None"; + return (out); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/guid.h b/lib/libdevctl/guid.h new file mode 100644 index 000000000000..cecc5e1fff4b --- /dev/null +++ b/lib/libdevctl/guid.h @@ -0,0 +1,143 @@ +/*- + * Copyright (c) 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_guid.h + * + * Definition of the Guid class. + */ +#ifndef _DEVCTL_GUID_H_ +#define _DEVCTL_GUID_H_ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ +/*----------------------------------- Guid -----------------------------------*/ +/** + * \brief Object that represents guids. + * + * It can generally be manipulated as a uint64_t, but with a special + * value INVALID_GUID that does not equal any valid guid. + * + * As of this writing, this class is only used to to represent ZFS + * guids in events and spa_generate_guid() in spa_misc.c explicitly + * refuses to return a guid of 0. So this class uses 0 as the value + * for INVALID_GUID. In the future, if 0 is allowed to be a valid + * guid, the implementation of this class must change. + */ +class Guid +{ +public: + /* Constructors */ + Guid(); + Guid(uint64_t guid); + Guid(const std::string &guid); + + /* Assignment */ + Guid& operator=(const Guid& rhs); + + /* Test the validity of this guid. */ + bool IsValid() const; + + /* Comparison to other Guid operators */ + bool operator==(const Guid& rhs) const; + bool operator!=(const Guid& rhs) const; + + /* Integer conversion operators */ + operator uint64_t() const; + operator bool() const; + + static const uint64_t INVALID_GUID = 0; +protected: + /* The integer value of the GUID. */ + uint64_t m_GUID; +}; + +//- Guid Inline Public Methods ------------------------------------------------ +inline +Guid::Guid() + : m_GUID(INVALID_GUID) +{ +} + +inline +Guid::Guid(uint64_t guid) + : m_GUID(guid) +{ +} + +inline Guid& +Guid::operator=(const Guid &rhs) +{ + m_GUID = rhs.m_GUID; + return (*this); +} + +inline bool +Guid::IsValid() const +{ + return (m_GUID != INVALID_GUID); +} + +inline bool +Guid::operator==(const Guid& rhs) const +{ + return (m_GUID == rhs.m_GUID); +} + +inline bool +Guid::operator!=(const Guid& rhs) const +{ + return (m_GUID != rhs.m_GUID); +} + +inline +Guid::operator uint64_t() const +{ + return (m_GUID); +} + +inline +Guid::operator bool() const +{ + return (m_GUID != INVALID_GUID); +} + +/** Convert the GUID into its string representation */ +std::ostream& operator<< (std::ostream& out, Guid g); + +} // namespace DevCtl +#endif /* _DEVCTL_GUID_H_ */ diff --git a/lib/libdevctl/reader.cc b/lib/libdevctl/reader.cc new file mode 100644 index 000000000000..85286f7bb1af --- /dev/null +++ b/lib/libdevctl/reader.cc @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Alan Somers (Spectra Logic Corporation) + */ + +/** + * \file reader.cc + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#include "reader.h" + +__FBSDID("$FreeBSD$"); + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +//- FDReader Public Methods --------------------------------------------------- +FDReader::FDReader(int fd) + : m_fd(fd) +{ +} + +ssize_t +FDReader::read(char* buf, size_t count) +{ + return (::read(m_fd, buf, count)); +} + +ssize_t +FDReader::in_avail() const +{ + int bytes; + if (ioctl(m_fd, FIONREAD, &bytes)) { + syslog(LOG_ERR, "ioctl FIONREAD: %s", strerror(errno)); + return (-1); + } + return (bytes); +} + +//- IstreamReader Inline Public Methods ---------------------------------------- +IstreamReader::IstreamReader(std::istream* stream) + : m_stream(stream) +{ +} + +ssize_t +IstreamReader::read(char* buf, size_t count) +{ + m_stream->read(buf, count); + if (m_stream->fail()) + return (-1); + return (m_stream->gcount()); +} + +ssize_t +IstreamReader::in_avail() const +{ + return (m_stream->rdbuf()->in_avail()); +} + +} // namespace DevCtl diff --git a/lib/libdevctl/reader.h b/lib/libdevctl/reader.h new file mode 100644 index 000000000000..9eb8533f7cb3 --- /dev/null +++ b/lib/libdevctl/reader.h @@ -0,0 +1,136 @@ +/*- + * Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + * + * Authors: Justin T. Gibbs (Spectra Logic Corporation) + * + * $FreeBSD$ + */ + +/** + * \file devctl_reader.h + */ +#ifndef _DEVCTL_READER_H_ +#define _DEVCTL_READER_H_ + +/*=========================== Forward Declarations ===========================*/ + +/*============================ Namespace Control =============================*/ +namespace DevCtl +{ + +/*============================= Class Definitions ============================*/ + +/*-------------------------------- Reader -------------------------------*/ +/** + * \brief A class that presents a common interface to both file descriptors + * and istreams. + * + * Standard C++ provides no way to create an iostream from a file descriptor or + * a FILE. The GNU, Apache, HPUX, and Solaris C++ libraries all provide + * non-standard ways to construct such a stream using similar semantics, but + * FreeBSD's C++ library does not. This class supports only the functionality + * needed by ZFSD; it does not implement the iostream API. + */ +class Reader +{ +public: + /** + * \brief Return the number of bytes immediately available for reading + */ + virtual ssize_t in_avail() const = 0; + + /** + * \brief Reads up to count bytes + * + * Whether this call blocks depends on the underlying input source. + * On error, -1 is returned, and errno will be set by the underlying + * source. + * + * \param buf Destination for the data + * \param count Maximum amount of data to read + * \returns Amount of data that was actually read + */ + virtual ssize_t read(char* buf, size_t count) = 0; + + virtual ~Reader() = 0; +}; + +inline Reader::~Reader() {} + + +/*--------------------------------- FDReader ---------------------------------*/ +/** + * \brief Specialization of Reader that uses a file descriptor + */ +class FDReader : public Reader +{ +public: + /** + * \brief Constructor + * + * \param fd An open file descriptor. It will not be garbage + * collected by the destructor. + */ + FDReader(int fd); + + virtual ssize_t in_avail() const; + + virtual ssize_t read(char* buf, size_t count); + +protected: + /** Copy of the underlying file descriptor */ + int m_fd; +}; + +/*-------------------------------- IstreamReader------------------------------*/ +/** + * \brief Specialization of Reader that uses a std::istream + */ +class IstreamReader : public Reader +{ +public: + /** + * Constructor + * + * \param stream Pointer to an open istream. It will not be + * garbage collected by the destructor. + */ + IstreamReader(std::istream* stream); + + virtual ssize_t in_avail() const; + + virtual ssize_t read(char* buf, size_t count); + +protected: + /** Copy of the underlying stream */ + std::istream *m_stream; +}; + +} // namespace DevCtl +#endif /* _DEVCTL_READER_H_ */ diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk index 8ef6e7a9f139..b0fb1666442a 100644 --- a/share/mk/bsd.libnames.mk +++ b/share/mk/bsd.libnames.mk @@ -39,6 +39,7 @@ LIBCRYPT?= ${DESTDIR}${LIBDIR}/libcrypt.a LIBCRYPTO?= ${DESTDIR}${LIBDIR}/libcrypto.a LIBCTF?= ${DESTDIR}${LIBDIR}/libctf.a LIBCURSES?= ${DESTDIR}${LIBDIR}/libcurses.a +LIBDEVCLT?= ${DESTDIR}${LIBDIR}/libdevctl.a LIBDEVINFO?= ${DESTDIR}${LIBDIR}/libdevinfo.a LIBDEVSTAT?= ${DESTDIR}${LIBDIR}/libdevstat.a LIBDIALOG?= ${DESTDIR}${LIBDIR}/libdialog.a -- cgit v1.3 From 0ec3dc36e5bdcd84825f7ee5bb3df41b0dbdb471 Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Tue, 15 Oct 2013 00:09:22 +0000 Subject: etc/rc.d/zfsd Remove set_rcvar, in accordance with rev 230103. Submitted by: will Approved by: ken (mentor) Sponsored by: Spectra Logic Corporation --- etc/rc.d/zfsd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/zfsd b/etc/rc.d/zfsd index 3167a22505b2..3ea64f380cc6 100644 --- a/etc/rc.d/zfsd +++ b/etc/rc.d/zfsd @@ -10,7 +10,7 @@ . /etc/rc.subr name="zfsd" -rcvar=`set_rcvar` +rcvar="zfsd_enable" command="/sbin/${name}" load_rc_config $name -- cgit v1.3 From 6c96553e8a5ee6ec90f42db0e511879b69c8543a Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Fri, 23 May 2014 23:13:34 +0000 Subject: MFP4 zfsd-related changes Convert libdevctl to use devd's new SEQPACKET socket. lib/libdevctl/consumer.cc lib/libdevctl/event_buffer.cc lib/libdevctl/event_buffer.h lib/libdevctl/reader.cc lib/libdevctl/reader.h Read from the new /var/run/devd.seqpacket.pipe instead of /var/run/devd.pipe. Since it preserves record boundaries, we can eliminate all the repacketization code in EventBuffer::ExtractEvent as well as much supporting code from the Reader class. lib/libdevctl/consumer.cc Make the pipe nonblocking. Previously, we avoided blocking by using the FIONREAD ioctl, but this is simpler. cddl/sbin/zfsd/case_file.cc cddl/sbin/zfsd/tests/zfsd_unittest.cc cddl/sbin/zfsd/vdev.cc cddl/sbin/zfsd/zfsd.cc cddl/sbin/zfsd/zfsd.h cddl/sbin/zfsd/zfsd_event.cc Update zfsd according to the libdevctl changes. The only nontrivial change is to CaseFile::DeSerialize, which elimintes the use of IStreamReader. cddl/sbin/zfsd/case_file.cc For an unknown reason, sometimes the std::ios::failbit will get set on caseStream. Instead of checking for !eof(), check for good(). That method checks the eofbit, errorbit, and failbit. livdevctl cleanup (from gibbs) lib/libdevctl/event.cc: lib/libdevctl/event.h: Remove the event class's name from its Builder method. It's perfectly clear that DevfsEvent::Builder() is the DevfsEvent class's Builder function. cddl/sbin/zfsd/zfsd.cc: cddl/sbin/zfsd/zfsd_event.cc: cddl/sbin/zfsd/zfsd_event.h: Conform to new libdevct Builder naming convention. Fix autoreplace by physical path when a hotspare is present cddl/sbin/zfsd/case_file.cc Fix logic error in CaseFile::Replace regarding whether the replacement device is a spare or not. Reviewed by: gibbs Sponsored by: Spectra Logic --- cddl/sbin/zfsd/case_file.cc | 45 +++++++++++--------------- cddl/sbin/zfsd/tests/Makefile | 41 ++---------------------- cddl/sbin/zfsd/tests/zfsd_test.sh | 21 +++++++++++- cddl/sbin/zfsd/tests/zfsd_unittest.cc | 15 +++------ cddl/sbin/zfsd/vdev.cc | 1 - cddl/sbin/zfsd/zfsd.cc | 9 ++---- cddl/sbin/zfsd/zfsd.h | 1 - cddl/sbin/zfsd/zfsd_event.cc | 11 +++---- cddl/sbin/zfsd/zfsd_event.h | 4 +-- etc/mtree/BSD.tests.dist | 2 ++ lib/libdevctl/Makefile | 8 ++--- lib/libdevctl/consumer.cc | 60 ++++++++++++++++++++--------------- lib/libdevctl/consumer.h | 25 ++++++++++++--- lib/libdevctl/event.cc | 42 ++++++++++++++++++++---- lib/libdevctl/event.h | 16 ++++++++-- lib/libdevctl/event_factory.cc | 4 ++- lib/libdevctl/exception.cc | 2 ++ 17 files changed, 167 insertions(+), 140 deletions(-) (limited to 'etc') diff --git a/cddl/sbin/zfsd/case_file.cc b/cddl/sbin/zfsd/case_file.cc index dbba13ab9fc5..218c9d14979e 100644 --- a/cddl/sbin/zfsd/case_file.cc +++ b/cddl/sbin/zfsd/case_file.cc @@ -59,11 +59,9 @@ #include #include -#include #include #include #include -#include #include "callout.h" #include "vdev_iterator.h" @@ -89,7 +87,6 @@ using DevCtl::EventBuffer; using DevCtl::EventFactory; using DevCtl::EventList; using DevCtl::Guid; -using DevCtl::IstreamReader; using DevCtl::ParseException; /*-------------------------- File-scoped classes ----------------------------*/ @@ -840,26 +837,28 @@ CaseFile::Serialize() close(fd); } +/* + * XXX: This method assumes that events may not contain embedded newlines. If + * ever events can contain embedded newlines, then CaseFile must switch + * serialization formats + */ void CaseFile::DeSerialize(ifstream &caseStream) { - stringstream fakeDevdSocket(stringstream::in|stringstream::out); - IstreamReader caseReader(&fakeDevdSocket); - EventBuffer eventBuffer(caseReader); string evString; + const EventFactory &factory(ZfsDaemon::Get().GetFactory()); caseStream >> std::noskipws >> std::ws; - while (!caseStream.eof()) { + while (caseStream.good()) { /* * Outline: * read the beginning of a line and check it for * "tentative". If found, discard "tentative". - * Shove into fakeDevdSocket. - * call ExtractEvent + * Create a new event * continue */ EventList* destEvents; - string tentFlag("tentative "); + const string tentFlag("tentative "); string line; std::stringbuf lineBuf; @@ -867,20 +866,16 @@ CaseFile::DeSerialize(ifstream &caseStream) caseStream.ignore(); /*discard the newline character*/ line = lineBuf.str(); if (line.compare(0, tentFlag.size(), tentFlag) == 0) { + /* Discard "tentative" */ line.erase(0, tentFlag.size()); destEvents = &m_tentativeEvents; } else { destEvents = &m_events; } - fakeDevdSocket << line; - fakeDevdSocket << '\n'; - const EventFactory &factory(ZfsDaemon::Get().GetFactory()); - while (eventBuffer.ExtractEvent(evString)) { - Event *event(Event::CreateEvent(factory, evString)); - if (event != NULL) { - destEvents->push_back(event); - RegisterCallout(*event); - } + Event *event(Event::CreateEvent(factory, line)); + if (event != NULL) { + destEvents->push_back(event); + RegisterCallout(*event); } } } @@ -1032,7 +1027,7 @@ CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) { Vdev vd(zhp, CaseVdev(zhp)); Vdev replaced(BeingReplacedBy(zhp)); - if (!vd.IsSpare() && !replaced.DoesNotExist()) { + if (isspare && !vd.IsSpare() && !replaced.DoesNotExist()) { /* If we are already being replaced by a working spare, pass. */ if (replaced.IsResilvering() || replaced.State() == VDEV_STATE_HEALTHY) { @@ -1044,12 +1039,10 @@ CaseFile::Replace(const char* vdev_type, const char* path, bool isspare) { * If we have already been replaced by a spare, but that spare * is broken, we must spare the spare, not the original device. */ - if (isspare) { - oldstr = replaced.GUIDString(); - syslog(LOG_INFO, "CaseFile::Replace(%s->%s): sparing " - "broken spare %s instead", VdevGUIDString().c_str(), - path, oldstr.c_str()); - } + oldstr = replaced.GUIDString(); + syslog(LOG_INFO, "CaseFile::Replace(%s->%s): sparing " + "broken spare %s instead", VdevGUIDString().c_str(), + path, oldstr.c_str()); } /* diff --git a/cddl/sbin/zfsd/tests/Makefile b/cddl/sbin/zfsd/tests/Makefile index 3a1aa2baf5e3..4d8c0b565b83 100644 --- a/cddl/sbin/zfsd/tests/Makefile +++ b/cddl/sbin/zfsd/tests/Makefile @@ -7,8 +7,6 @@ SRCDIR=${.CURDIR}/../../../.. PROG_CXX= zfsd_unittest SRCS:= ${SRCS:Nzfsd_main.cc} SRCS+= libmocks.c zfsd_unittest.cc -CLEANFILES+= *.gcno *.gcda *.info -CLEANDIRS+= lcov-report # Use #include in test programs. INCFLAGS+= -I ${.CURDIR}/../.. @@ -26,9 +24,6 @@ LIBRARY_PATH= .endif ZFSD_UNITTEST= env LD_LIBRARY_PATH=${LIBRARY_PATH} ./zfsd_unittest -# Extra tools -LCOV= lcov - # Googletest options LOCALBASE?= /usr/local INCFLAGS+= -I ${LOCALBASE}/include -D_THREAD_SAFE -pthread @@ -42,42 +37,12 @@ LDADD+= ${LOCALBASE}/lib/libgmock.a ${LOCALBASE}/lib/libgmock_main.a # https://groups.google.com/forum/#!msg/googletestframework/h8ixEPCFm0o/amwfu4xGJb0J CFLAGS+= -DGTEST_HAS_PTHREAD -# GCOV options -CFLAGS+= -fprofile-arcs -ftest-coverage -LDADD+= -lgcov - -all: tests - # Install the tests TESTSBASE?= /usr/tests -TESTSDIR= ${TESTSBASE}/zfsd +TESTSDIR= ${TESTSBASE}/cddl/sbin/zfsd # TODO: Convert from an ATF SH test to a Kyua plain test # Long term TODO: Convert to a Kyua googletest test -TESTS_SH+= zfsd_test +ATF_TESTS_SH+= zfsd_test BINDIR= ${TESTSDIR} -# Install the gcov annotation files too -FILESDIR= ${TESTSDIR} -GCNOS= ${SRCS:C/.c+$/.gcno/} -${GCNOS}: ${SRCS:C/.c+$/.o/} -FILES= ${GCNOS} - - -# Run the tests and produce the coverage report -EXCLUDE_PATTERNS='/usr/include/*' '${LOCALBASE}/include/*' -EXCLUDE_PATTERNS+= '*/cddl/compat/opensolaris/include/*' -EXCLUDE_PATTERNS+= '*/tools/regression/zfsd/*' -.PHONY: tests -tests: zfsd_unittest - ${ZFSD_UNITTEST} --gmock_verbose=error - -.PHONY: lcov -lcov: zfsd_unittest - ${LCOV} -z -d . -f && \ - ${ZFSD_UNITTEST} --gmock_verbose=error - ${LCOV} -f -d . -c -o default.info && \ - ${LCOV} -r default.info $(EXCLUDE_PATTERNS) -o trimmed.info && \ - mkdir -p lcov-report && \ - genhtml -o lcov-report trimmed.info - -.include +.include diff --git a/cddl/sbin/zfsd/tests/zfsd_test.sh b/cddl/sbin/zfsd/tests/zfsd_test.sh index d549eebb2656..11690697339c 100644 --- a/cddl/sbin/zfsd/tests/zfsd_test.sh +++ b/cddl/sbin/zfsd/tests/zfsd_test.sh @@ -43,7 +43,26 @@ zfsd_unittest_head() zfsd_unittest_body() { - atf_check -s exit:0 -o ignore -e ignore $(atf_get_srcdir)/zfsd_unittest + TESTPROG=$(atf_get_srcdir)/zfsd_unittest + if atf_config_has coverage_dir; then + # If coverage_dir is defined, then we want to save the .gcda + # and .gcno files for future analysis. Put them in a directory + # tree that resembles /usr/src, but is anchored at + # coverage_dir. + export GCOV_PREFIX=`atf_config_get coverage_dir` + # Examine zfsd_unittest to calculate the GCOV_PREFIX_STRIP + # The outer echo command is needed to strip off whitespace + # printed by wc + OLDGCDADIR=`strings $TESTPROG | grep 'zfsd.gcda'` + export GCOV_PREFIX_STRIP=$( echo $( echo $OLDGCDADIR | \ + sed -e 's:/cddl/sbin/zfsd.*::' -e 's:/: :g' | \ + wc -w ) ) + NEWGCDADIR=$GCOV_PREFIX/`dirname $OLDGCDADIR | \ + sed -e 's:.*\(cddl/sbin/zfsd\):\1:'` + mkdir -p $NEWGCDADIR + cp $(atf_get_srcdir)/*.gcno $NEWGCDADIR + fi + atf_check -s exit:0 -o ignore -e ignore $TESTPROG } atf_init_test_cases() diff --git a/cddl/sbin/zfsd/tests/zfsd_unittest.cc b/cddl/sbin/zfsd/tests/zfsd_unittest.cc index ac425d171240..6c9a4f3094bd 100644 --- a/cddl/sbin/zfsd/tests/zfsd_unittest.cc +++ b/cddl/sbin/zfsd/tests/zfsd_unittest.cc @@ -47,11 +47,9 @@ #include #include -#include #include #include #include -#include #include #include @@ -365,17 +363,12 @@ TEST_F(VdevTest, AvailSpareState) { /* Test the Vdev::IsSpare method */ TEST_F(VdevTest, IsSpare) { - Vdev* vdev; - - vdev = new Vdev(m_poolConfig, m_vdevConfig); - EXPECT_EQ(false, vdev->IsSpare()); - delete vdev; - + Vdev notSpare(m_poolConfig, m_vdevConfig); + EXPECT_EQ(false, notSpare.IsSpare()); ASSERT_EQ(0, nvlist_add_uint64(m_vdevConfig, ZPOOL_CONFIG_IS_SPARE, 1)); - vdev = new Vdev(m_poolConfig, m_vdevConfig); - EXPECT_EQ(true, vdev->IsSpare()); - delete vdev; + Vdev isSpare(m_poolConfig, m_vdevConfig); + EXPECT_EQ(true, isSpare.IsSpare()); } /* diff --git a/cddl/sbin/zfsd/vdev.cc b/cddl/sbin/zfsd/vdev.cc index cbf668966c41..dbba3172d83a 100644 --- a/cddl/sbin/zfsd/vdev.cc +++ b/cddl/sbin/zfsd/vdev.cc @@ -50,7 +50,6 @@ #include #include -#include #include #include #include diff --git a/cddl/sbin/zfsd/zfsd.cc b/cddl/sbin/zfsd/zfsd.cc index b16ecfb46c8e..a4eda63b1ae8 100644 --- a/cddl/sbin/zfsd/zfsd.cc +++ b/cddl/sbin/zfsd/zfsd.cc @@ -59,11 +59,9 @@ #include #include -#include #include #include #include -#include #include "callout.h" #include "vdev_iterator.h" @@ -82,11 +80,8 @@ __FBSDID("$FreeBSD$"); /*============================ Namespace Control =============================*/ using DevCtl::Event; -using DevCtl::EventBuffer; using DevCtl::EventFactory; using DevCtl::EventList; -using DevCtl::Guid; -using DevCtl::NVPairMap; /*================================ Global Data ===============================*/ int g_debug = 0; @@ -103,8 +98,8 @@ int ZfsDaemon::s_signalPipeFD[2]; bool ZfsDaemon::s_systemRescanRequested(false); EventFactory::Record ZfsDaemon::s_registryEntries[] = { - { Event::NOTIFY, "DEVFS", &DevfsEvent::DevfsEventBuilder }, - { Event::NOTIFY, "ZFS", &ZfsEvent::ZfsEventBuilder } + { Event::NOTIFY, "DEVFS", &DevfsEvent::Builder }, + { Event::NOTIFY, "ZFS", &ZfsEvent::Builder } }; //- ZfsDaemon Static Public Methods -------------------------------------------- diff --git a/cddl/sbin/zfsd/zfsd.h b/cddl/sbin/zfsd/zfsd.h index 94bbd83108e9..c9135b3f7e73 100644 --- a/cddl/sbin/zfsd/zfsd.h +++ b/cddl/sbin/zfsd/zfsd.h @@ -52,7 +52,6 @@ * #include * #include * #include - * #include * * #include "vdev_iterator.h" */ diff --git a/cddl/sbin/zfsd/zfsd_event.cc b/cddl/sbin/zfsd/zfsd_event.cc index 5be4ee678cda..ad53383c69a8 100644 --- a/cddl/sbin/zfsd/zfsd_event.cc +++ b/cddl/sbin/zfsd/zfsd_event.cc @@ -51,7 +51,6 @@ #include #include #include -#include #include "callout.h" #include "vdev_iterator.h" @@ -75,9 +74,9 @@ using std::stringstream; //- DevfsEvent Static Public Methods ------------------------------------------- Event * -DevfsEvent::DevfsEventBuilder(Event::Type type, - NVPairMap &nvPairs, - const string &eventString) +DevfsEvent::Builder(Event::Type type, + NVPairMap &nvPairs, + const string &eventString) { return (new DevfsEvent(type, nvPairs, eventString)); } @@ -230,8 +229,8 @@ DevfsEvent::DevfsEvent(const DevfsEvent &src) /*--------------------------------- ZfsEvent ---------------------------------*/ //- ZfsEvent Static Public Methods --------------------------------------------- DevCtl::Event * -ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs, - const string &eventString) +ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs, + const string &eventString) { return (new ZfsEvent(type, nvpairs, eventString)); } diff --git a/cddl/sbin/zfsd/zfsd_event.h b/cddl/sbin/zfsd/zfsd_event.h index f2f7967ae7a8..d4d28ee6b465 100644 --- a/cddl/sbin/zfsd/zfsd_event.h +++ b/cddl/sbin/zfsd/zfsd_event.h @@ -66,7 +66,7 @@ class DevfsEvent : public DevCtl::DevfsEvent { public: /** Specialized DevCtlEvent object factory for Devfs events. */ - static BuildMethod DevfsEventBuilder; + static BuildMethod Builder; virtual DevCtl::Event *DeepCopy() const; @@ -122,7 +122,7 @@ class ZfsEvent : public DevCtl::ZfsEvent { public: /** Specialized DevCtlEvent object factory for ZFS events. */ - static BuildMethod ZfsEventBuilder; + static BuildMethod Builder; virtual DevCtl::Event *DeepCopy() const; diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 083054eb2748..ae41c5143102 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -54,6 +54,8 @@ lib .. sbin + zfsd + .. .. usr.bin .. diff --git a/lib/libdevctl/Makefile b/lib/libdevctl/Makefile index 250538f1ae22..9dace3327361 100644 --- a/lib/libdevctl/Makefile +++ b/lib/libdevctl/Makefile @@ -3,18 +3,14 @@ LIB= devctl INCS= consumer.h \ event.h \ - event_buffer.h \ event_factory.h \ exception.h \ - guid.h \ - reader.h + guid.h SRCS= consumer.cc \ event.cc \ - event_buffer.cc \ event_factory.cc \ exception.cc \ - guid.cc \ - reader.cc + guid.cc INCSDIR= ${INCLUDEDIR}/devctl diff --git a/lib/libdevctl/consumer.cc b/lib/libdevctl/consumer.cc index fe014b328525..d325206ea317 100644 --- a/lib/libdevctl/consumer.cc +++ b/lib/libdevctl/consumer.cc @@ -37,24 +37,24 @@ #include #include #include -#include #include #include #include +#include #include #include +#include +#include #include #include #include #include "guid.h" #include "event.h" -#include "event_buffer.h" #include "event_factory.h" #include "exception.h" -#include "reader.h" #include "consumer.h" @@ -71,15 +71,13 @@ namespace DevCtl /*============================= Class Definitions ============================*/ /*----------------------------- DevCtl::Consumer -----------------------------*/ //- Consumer Static Private Data ----------------------------------------------- -const char Consumer::s_devdSockPath[] = "/var/run/devd.pipe"; +const char Consumer::s_devdSockPath[] = "/var/run/devd.seqpacket.pipe"; //- Consumer Public Methods ---------------------------------------------------- Consumer::Consumer(Event::BuildMethod *defBuilder, EventFactory::Record *regEntries, size_t numEntries) : m_devdSockFD(-1), - m_reader(NULL), - m_eventBuffer(NULL), m_eventFactory(defBuilder), m_replayingEvents(false) { @@ -89,8 +87,6 @@ Consumer::Consumer(Event::BuildMethod *defBuilder, Consumer::~Consumer() { DisconnectFromDevd(); - delete m_reader; - m_reader = NULL; } bool @@ -112,9 +108,11 @@ Consumer::ConnectToDevd() strlcpy(devdAddr.sun_path, s_devdSockPath, sizeof(devdAddr.sun_path)); sLen = SUN_LEN(&devdAddr); - m_devdSockFD = socket(AF_UNIX, SOCK_STREAM, 0); + m_devdSockFD = socket(AF_UNIX, SOCK_SEQPACKET, 0); if (m_devdSockFD == -1) err(1, "Unable to create socket"); + if (fcntl(m_devdSockFD, F_SETFL, O_NONBLOCK) < 0) + err(1, "fcntl"); result = connect(m_devdSockFD, reinterpret_cast(&devdAddr), sLen); @@ -124,9 +122,6 @@ Consumer::ConnectToDevd() return (false); } - /* Connect the stream to the file descriptor */ - m_reader = new FDReader(m_devdSockFD); - m_eventBuffer = new EventBuffer(*m_reader); syslog(LOG_INFO, "Connection to devd successful"); return (true); } @@ -137,14 +132,26 @@ Consumer::DisconnectFromDevd() if (m_devdSockFD != -1) syslog(LOG_INFO, "Disconnecting from devd."); - delete m_eventBuffer; - m_eventBuffer = NULL; - delete m_reader; - m_reader = NULL; close(m_devdSockFD); m_devdSockFD = -1; } +std::string +Consumer::ReadEvent() +{ + char buf[MAX_EVENT_SIZE + 1]; + ssize_t len; + + len = ::recv(m_devdSockFD, buf, MAX_EVENT_SIZE, MSG_WAITALL); + if (len == -1) + return (std::string("")); + else { + /* NULL-terminate the result */ + buf[len] = '\0'; + return (std::string(buf)); + } +} + void Consumer::ReplayUnconsumedEvents(bool discardUnconsumed) { @@ -178,20 +185,20 @@ Consumer::SaveEvent(const Event &event) } Event * -Consumer::NextEvent(EventBuffer *eventBuffer) +Consumer::NextEvent() { if (!Connected()) return(NULL); - if (eventBuffer == NULL) - eventBuffer = m_eventBuffer; - Event *event(NULL); try { string evString; - if (eventBuffer->ExtractEvent(evString)) + evString = ReadEvent(); + if (! evString.empty()) { + Event::TimestampEventString(evString); event = Event::CreateEvent(m_eventFactory, evString); + } } catch (const Exception &exp) { exp.Log(); DisconnectFromDevd(); @@ -201,10 +208,10 @@ Consumer::NextEvent(EventBuffer *eventBuffer) /* Capture and process buffered events. */ void -Consumer::ProcessEvents(EventBuffer *eventBuffer) +Consumer::ProcessEvents() { Event *event; - while ((event = NextEvent(eventBuffer)) != NULL) { + while ((event = NextEvent()) != NULL) { if (event->Process()) SaveEvent(*event); delete event; @@ -214,10 +221,11 @@ Consumer::ProcessEvents(EventBuffer *eventBuffer) void Consumer::FlushEvents() { - char discardBuf[256]; + std::string s; - while (m_reader->in_avail() > 0) - m_reader->read(discardBuf, sizeof(discardBuf)); + do + s = ReadEvent(); + while (! s.empty()) ; } bool diff --git a/lib/libdevctl/consumer.h b/lib/libdevctl/consumer.h index f8242425a3ac..335bdaadf8ef 100644 --- a/lib/libdevctl/consumer.h +++ b/lib/libdevctl/consumer.h @@ -81,14 +81,13 @@ public: */ void ReplayUnconsumedEvents(bool discardUnconsumed); - /** Return an event, if available, from the provided EventBuffer. */ - Event *NextEvent(EventBuffer *eventBuffer = NULL); + /** Return an event, if one is available. */ + Event *NextEvent(); /** - * Extract events from the provided eventBuffer and invoke - * each event's Process method. + * Extract events and invoke each event's Process method. */ - void ProcessEvents(EventBuffer *eventBuffer = NULL); + void ProcessEvents(); /** Discard all data pending in m_devdSockFD. */ void FlushEvents(); @@ -116,6 +115,22 @@ public: EventFactory GetFactory(); protected: + /** + * \brief Reads the most recent record + * + * On error, "" is returned, and errno will be set by the OS + * + * \returns A string containing the record + */ + std::string ReadEvent(); + + enum { + /* + * The maximum event size supported by libdevctl. + */ + MAX_EVENT_SIZE = 8192, + }; + static const char s_devdSockPath[]; /** diff --git a/lib/libdevctl/event.cc b/lib/libdevctl/event.cc index 38a0c2c1e198..07f67210313f 100644 --- a/lib/libdevctl/event.cc +++ b/lib/libdevctl/event.cc @@ -40,12 +40,18 @@ #include #include #include +#include +#include +#include #include #include +#include #include #include +#include +#include #include #include #include @@ -86,8 +92,8 @@ Event::EventTypeRecord Event::s_typeTable[] = //- Event Static Public Methods ------------------------------------------------ Event * -Event::EventBuilder(Event::Type type, NVPairMap &nvPairs, - const string &eventString) +Event::Builder(Event::Type type, NVPairMap &nvPairs, + const string &eventString) { return (new Event(type, nvPairs, eventString)); } @@ -325,11 +331,35 @@ Event::ParseEventString(Event::Type type, } } +void +Event::TimestampEventString(std::string &eventString) +{ + if (eventString.size() > 0) { + /* + * Add a timestamp as the final field of the event if it is + * not already present. + */ + if (eventString.find("timestamp=") == string::npos) { + const size_t bufsize = 32; // Long enough for a 64-bit int + timeval now; + struct tm* time_s; + char timebuf[bufsize]; + + size_t eventEnd(eventString.find_last_not_of('\n') + 1); + if (gettimeofday(&now, NULL) != 0) + err(1, "gettimeofday"); + time_s = gmtime(&now.tv_sec); + strftime(timebuf, bufsize, " timestamp=%s", time_s); + eventString.insert(eventEnd, timebuf); + } + } +} + /*-------------------------------- DevfsEvent --------------------------------*/ //- DevfsEvent Static Public Methods ------------------------------------------- Event * -DevfsEvent::DevfsEventBuilder(Event::Type type, NVPairMap &nvPairs, - const string &eventString) +DevfsEvent::Builder(Event::Type type, NVPairMap &nvPairs, + const string &eventString) { return (new DevfsEvent(type, nvPairs, eventString)); } @@ -495,8 +525,8 @@ DevfsEvent::DevfsEvent(const DevfsEvent &src) /*--------------------------------- ZfsEvent ---------------------------------*/ //- ZfsEvent Static Public Methods --------------------------------------------- Event * -ZfsEvent::ZfsEventBuilder(Event::Type type, NVPairMap &nvpairs, - const string &eventString) +ZfsEvent::Builder(Event::Type type, NVPairMap &nvpairs, + const string &eventString) { return (new ZfsEvent(type, nvpairs, eventString)); } diff --git a/lib/libdevctl/event.h b/lib/libdevctl/event.h index 9f13f91db335..eac253cb5fc7 100644 --- a/lib/libdevctl/event.h +++ b/lib/libdevctl/event.h @@ -95,7 +95,7 @@ public: typedef Event* (BuildMethod)(Type, NVPairMap &, const std::string &); /** Generic Event object factory. */ - static BuildMethod EventBuilder; + static BuildMethod Builder; static Event *CreateEvent(const EventFactory &factory, const std::string &eventString); @@ -189,6 +189,16 @@ public: */ timeval GetTimestamp() const; + /** + * Add a timestamp to the event string, if one does not already exist + * TODO: make this an instance method that operates on the std::map + * instead of the string. We must fix zfsd's CaseFile serialization + * routines first, so that they don't need the raw event string. + * + * \param[in,out] eventString The devd event string to modify + */ + static void TimestampEventString(std::string &eventString); + /** * Access all parsed key => value pairs. */ @@ -277,7 +287,7 @@ class DevfsEvent : public Event { public: /** Specialized Event object factory for Devfs events. */ - static BuildMethod DevfsEventBuilder; + static BuildMethod Builder; virtual Event *DeepCopy() const; @@ -326,7 +336,7 @@ class ZfsEvent : public Event { public: /** Specialized Event object factory for ZFS events. */ - static BuildMethod ZfsEventBuilder; + static BuildMethod Builder; virtual Event *DeepCopy() const; diff --git a/lib/libdevctl/event_factory.cc b/lib/libdevctl/event_factory.cc index 364e0d096876..d705ec8e35d9 100644 --- a/lib/libdevctl/event_factory.cc +++ b/lib/libdevctl/event_factory.cc @@ -88,8 +88,10 @@ EventFactory::Build(Event::Type type, NVPairMap &nvpairs, if (foundMethod != m_registry.end()) buildMethod = foundMethod->second; - if (buildMethod == NULL) + if (buildMethod == NULL) { + delete &nvpairs; return (NULL); + } return (buildMethod(type, nvpairs, eventString)); } diff --git a/lib/libdevctl/exception.cc b/lib/libdevctl/exception.cc index 4d242df29f42..c20c2c5b6b3e 100644 --- a/lib/libdevctl/exception.cc +++ b/lib/libdevctl/exception.cc @@ -37,6 +37,8 @@ #include +#include +#include #include #include -- cgit v1.3 From 6ffcf5d515a276f16e4d84604a2ab70ffd887f55 Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Fri, 1 Aug 2014 19:32:20 +0000 Subject: Like with /usr/lib + /usr/lib/compat, add the optional /usr/lib32/compat to the ldconfig32 default path. /usr/lib32 is the 32 bit versions of *current* libraries, while old versions should be able to be in /usr/lib32/compat, like with /usr/lib/compat. The separation is meant to keep the compile time default search paths cleaner. --- etc/defaults/rc.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index aa19b3031e56..da0e419545e0 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -610,7 +610,8 @@ clear_tmp_X="YES" # Clear and recreate X11-related directories in /tmp ldconfig_insecure="NO" # Set to YES to disable ldconfig security checks ldconfig_paths="/usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg" # shared library search paths -ldconfig32_paths="/usr/lib32" # 32-bit compatibility shared library search paths +ldconfig32_paths="/usr/lib32 /usr/lib32/compat" + # 32-bit compatibility shared library search paths ldconfig_paths_aout="/usr/lib/compat/aout /usr/local/lib/aout" # a.out shared library search paths ldconfig_local_dirs="/usr/local/libdata/ldconfig" -- cgit v1.3 From dfed135e5cea0ade1886b98f3df4e68fca9e1fb0 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Mon, 4 Aug 2014 22:10:07 +0000 Subject: Integrate lib/libmp into the build/kyua - Remove the .t wrapper - Fix -Wreturn-type warnings with clang This change has been tested on amd64/i386 Phabric: D530 Reviewed by: jmmv Approved by: jmmv (co-mentor) MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 + lib/libmp/Makefile | 6 + lib/libmp/tests/Makefile | 10 ++ lib/libmp/tests/legacy_test.c | 211 ++++++++++++++++++++++++++++++++ tools/regression/lib/libmp/Makefile | 12 -- tools/regression/lib/libmp/test-libmp.c | 211 -------------------------------- tools/regression/lib/libmp/test-libmp.t | 10 -- 7 files changed, 229 insertions(+), 233 deletions(-) create mode 100644 lib/libmp/tests/Makefile create mode 100644 lib/libmp/tests/legacy_test.c delete mode 100644 tools/regression/lib/libmp/Makefile delete mode 100644 tools/regression/lib/libmp/test-libmp.c delete mode 100644 tools/regression/lib/libmp/test-libmp.t (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 4d6f18a287e5..1f61599eddd4 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -85,6 +85,8 @@ .. libcrypt .. + libmp + .. .. libexec atf diff --git a/lib/libmp/Makefile b/lib/libmp/Makefile index a9001a10c375..5d0e7a702c55 100644 --- a/lib/libmp/Makefile +++ b/lib/libmp/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= mp SHLIB_MAJOR= 7 DPADD= ${LIBCRYPTO} @@ -13,4 +15,8 @@ CFLAGS+= -I${.CURDIR}/../../crypto VERSION_DEF= ${.CURDIR}/../libc/Versions.def SYMBOL_MAPS= ${.CURDIR}/Symbol.map +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/lib/libmp/tests/Makefile b/lib/libmp/tests/Makefile new file mode 100644 index 000000000000..0f591eb3ea42 --- /dev/null +++ b/lib/libmp/tests/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libmp + +TAP_TESTS_C+= legacy_test + +DPADD+= ${LIBCRYPTO} ${LIBMP} +LDADD+= -lcrypto -lmp + +.include diff --git a/lib/libmp/tests/legacy_test.c b/lib/libmp/tests/legacy_test.c new file mode 100644 index 000000000000..6f3f7b60e8d0 --- /dev/null +++ b/lib/libmp/tests/legacy_test.c @@ -0,0 +1,211 @@ +/*- + * Copyright (c) 2006, Simon L. Nielsen + * 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +MINT *c0, *c1, *c2, *c3, *c5, *c6, *c8, *c10, *c14, *c15, *c25, \ + *c42,*c43, *c44, *c45, *t0, *t1; +static int tnr = 0; + +static void +testmcmp(const MINT *mp1, const MINT *mp2, const char *tname) +{ + + if (mp_mcmp(mp1, mp2) == 0) + printf("ok %d - %s\n", ++tnr, tname); + else + printf("not ok - %d %s\n", ++tnr, tname); +} + +static void +testsimpel(void) +{ + const char str42[] = "2a"; + MINT *t2; + char *s; + + mp_madd(c42, c1, t0); + testmcmp(c43, t0, "madd0"); + mp_madd(t0, c1, t0); + testmcmp(c44, t0, "madd1"); + mp_msub(t0, c1, t0); + testmcmp(c43, t0, "msub0"); + mp_msub(t0, c1, t0); + testmcmp(c42, t0, "msub1"); + mp_move(c42, t0); + testmcmp(c42, t0, "move0"); + + t2 = mp_xtom(str42); + testmcmp(c42, t2, "xtom"); + s = mp_mtox(t2); + if (strcmp(str42, s) == 0) + printf("ok %d - %s\n", ++tnr, "mtox0"); + else + printf("not ok %d - %s\n", ++tnr, "mtox0"); + mp_mfree(t2); +} + +static void +testgcd(void) +{ + + mp_gcd(c10, c15, t0); + testmcmp(t0, c5, "gcd0"); +} + +static void +testmsqrt(void) +{ + + mp_msqrt(c25, t0, t1); + testmcmp(t0, c5, "msqrt0"); + testmcmp(t1, c0, "msqrt1"); + mp_msqrt(c42, t0, t1); + testmcmp(t0, c6, "msqrt2"); + testmcmp(t1, c6, "msqrt3"); +} + +static void +testdiv(void) +{ + short ro; + MINT *t2; + + mp_mdiv(c42, c5, t0, t1); + testmcmp(t0, c8, "mdiv0"); + testmcmp(t1, c2, "mdiv1"); + + mp_mdiv(c10, c8, t0, t1); + testmcmp(t0, c1, "mdiv2"); + testmcmp(t1, c2, "mdiv3"); + + mp_sdiv(c42, 5, t0, &ro); + testmcmp(t0, c8, "sdiv0"); + t2 = mp_itom(ro); // Simpler to use common testmcmp() + testmcmp(t2, c2, "sdiv1"); + mp_mfree(t2); + + mp_sdiv(c10, 8, t0, &ro); + testmcmp(t0, c1, "sdiv2"); + t2 = mp_itom(ro); // Simpler to use common testmcmp() + testmcmp(t2, c2, "sdiv3"); + mp_mfree(t2); +} + +static void +testmult(void) +{ + + mp_mult(c5, c2, t0); + testmcmp(t0, c10, "mmult0"); + mp_mult(c3, c14, t0); + testmcmp(t0, c42, "mmult1"); +} + +static void +testpow(void) +{ + + mp_pow(c2, c3, c10, t0); + testmcmp(t0, c8, "pow0"); + mp_pow(c2, c3, c3, t0); + testmcmp(t0, c2, "pow1"); + mp_rpow(c2, 3, t0); + testmcmp(t0, c8, "rpow0"); +} + +/* + * This program performs some very basic tests of libmp(3). It is by + * no means expected to perform a complete test of the library for + * correctness, but is meant to test the API to make sure libmp (or + * libcrypto) updates don't totally break the library. + */ +int +main(int argc, char *argv[]) +{ + + printf("1..25\n"); + + /* + * Init "constants" variables - done in this somewhat + * cumbersome way to in theory be able to check for memory + * leaks. + */ + c0 = mp_itom(0); + c1 = mp_itom(1); + c2 = mp_itom(2); + c3 = mp_itom(3); + c5 = mp_itom(5); + c6 = mp_itom(6); + c8 = mp_itom(8); + c10 = mp_itom(10); + c14 = mp_itom(14); + c15 = mp_itom(15); + c25 = mp_itom(25); + c42 = mp_itom(42); + c43 = mp_itom(43); + c44 = mp_itom(44); + c45 = mp_itom(45); + + // Init temp variables + t0 = mp_itom(0); + t1 = mp_itom(0); + + // Run tests + testsimpel(); + testgcd(); + testdiv(); + testmult(); + testpow(); + testmsqrt(); + + // Cleanup + mp_mfree(c0); + mp_mfree(c1); + mp_mfree(c2); + mp_mfree(c3); + mp_mfree(c5); + mp_mfree(c6); + mp_mfree(c8); + mp_mfree(c10); + mp_mfree(c14); + mp_mfree(c15); + mp_mfree(c25); + mp_mfree(c42); + mp_mfree(c43); + mp_mfree(c44); + mp_mfree(c45); + mp_mfree(t0); + mp_mfree(t1); + + return (EX_OK); +} diff --git a/tools/regression/lib/libmp/Makefile b/tools/regression/lib/libmp/Makefile deleted file mode 100644 index a6f60b63bdbd..000000000000 --- a/tools/regression/lib/libmp/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $FreeBSD$ - -TESTS= test-libmp -CFLAGS+= -g -Wall -lcrypto -lmp - -.PHONY: tests -tests: ${TESTS} - for p in ${TESTS}; do ${.OBJDIR}/$$p; done - -.PHONY: clean -clean: - -rm -f ${TESTS} diff --git a/tools/regression/lib/libmp/test-libmp.c b/tools/regression/lib/libmp/test-libmp.c deleted file mode 100644 index d9d2c9f6b3e0..000000000000 --- a/tools/regression/lib/libmp/test-libmp.c +++ /dev/null @@ -1,211 +0,0 @@ -/*- - * Copyright (c) 2006, Simon L. Nielsen - * 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 AUTHOR 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 AUTHOR 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include - -MINT *c0, *c1, *c2, *c3, *c5, *c6, *c8, *c10, *c14, *c15, *c25, \ - *c42,*c43, *c44, *c45, *t0, *t1; -static int tnr = 0; - -static void -testmcmp(const MINT *mp1, const MINT *mp2, const char *tname) -{ - - if (mp_mcmp(mp1, mp2) == 0) - printf("ok %d - %s\n", ++tnr, tname); - else - printf("not ok - %d %s\n", ++tnr, tname); -} - -static int -testsimpel(void) -{ - const char str42[] = "2a"; - MINT *t2; - char *s; - - mp_madd(c42, c1, t0); - testmcmp(c43, t0, "madd0"); - mp_madd(t0, c1, t0); - testmcmp(c44, t0, "madd1"); - mp_msub(t0, c1, t0); - testmcmp(c43, t0, "msub0"); - mp_msub(t0, c1, t0); - testmcmp(c42, t0, "msub1"); - mp_move(c42, t0); - testmcmp(c42, t0, "move0"); - - t2 = mp_xtom(str42); - testmcmp(c42, t2, "xtom"); - s = mp_mtox(t2); - if (strcmp(str42, s) == 0) - printf("ok %d - %s\n", ++tnr, "mtox0"); - else - printf("not ok %d - %s\n", ++tnr, "mtox0"); - mp_mfree(t2); -} - -static int -testgcd(void) -{ - - mp_gcd(c10, c15, t0); - testmcmp(t0, c5, "gcd0"); -} - -static int -testmsqrt(void) -{ - - mp_msqrt(c25, t0, t1); - testmcmp(t0, c5, "msqrt0"); - testmcmp(t1, c0, "msqrt1"); - mp_msqrt(c42, t0, t1); - testmcmp(t0, c6, "msqrt2"); - testmcmp(t1, c6, "msqrt3"); -} - -static int -testdiv(void) -{ - short ro; - MINT *t2; - - mp_mdiv(c42, c5, t0, t1); - testmcmp(t0, c8, "mdiv0"); - testmcmp(t1, c2, "mdiv1"); - - mp_mdiv(c10, c8, t0, t1); - testmcmp(t0, c1, "mdiv2"); - testmcmp(t1, c2, "mdiv3"); - - mp_sdiv(c42, 5, t0, &ro); - testmcmp(t0, c8, "sdiv0"); - t2 = mp_itom(ro); // Simpler to use common testmcmp() - testmcmp(t2, c2, "sdiv1"); - mp_mfree(t2); - - mp_sdiv(c10, 8, t0, &ro); - testmcmp(t0, c1, "sdiv2"); - t2 = mp_itom(ro); // Simpler to use common testmcmp() - testmcmp(t2, c2, "sdiv3"); - mp_mfree(t2); -} - -static int -testmult(void) -{ - - mp_mult(c5, c2, t0); - testmcmp(t0, c10, "mmult0"); - mp_mult(c3, c14, t0); - testmcmp(t0, c42, "mmult1"); -} - -static int -testpow(void) -{ - - mp_pow(c2, c3, c10, t0); - testmcmp(t0, c8, "pow0"); - mp_pow(c2, c3, c3, t0); - testmcmp(t0, c2, "pow1"); - mp_rpow(c2, 3, t0); - testmcmp(t0, c8, "rpow0"); -} - -/* - * This program performs some very basic tests of libmp(3). It is by - * no means expected to perform a complete test of the library for - * correctness, but is meant to test the API to make sure libmp (or - * libcrypto) updates don't totally break the library. - */ -int -main(int argc, char *argv[]) -{ - - printf("1..25\n"); - - /* - * Init "constants" variables - done in this somewhat - * cumbersome way to in theory be able to check for memory - * leaks. - */ - c0 = mp_itom(0); - c1 = mp_itom(1); - c2 = mp_itom(2); - c3 = mp_itom(3); - c5 = mp_itom(5); - c6 = mp_itom(6); - c8 = mp_itom(8); - c10 = mp_itom(10); - c14 = mp_itom(14); - c15 = mp_itom(15); - c25 = mp_itom(25); - c42 = mp_itom(42); - c43 = mp_itom(43); - c44 = mp_itom(44); - c45 = mp_itom(45); - - // Init temp variables - t0 = mp_itom(0); - t1 = mp_itom(0); - - // Run tests - testsimpel(); - testgcd(); - testdiv(); - testmult(); - testpow(); - testmsqrt(); - - // Cleanup - mp_mfree(c0); - mp_mfree(c1); - mp_mfree(c2); - mp_mfree(c3); - mp_mfree(c5); - mp_mfree(c6); - mp_mfree(c8); - mp_mfree(c10); - mp_mfree(c14); - mp_mfree(c15); - mp_mfree(c25); - mp_mfree(c42); - mp_mfree(c43); - mp_mfree(c44); - mp_mfree(c45); - mp_mfree(t0); - mp_mfree(t1); - - return (EX_OK); -} diff --git a/tools/regression/lib/libmp/test-libmp.t b/tools/regression/lib/libmp/test-libmp.t deleted file mode 100644 index 8bdfd03be81b..000000000000 --- a/tools/regression/lib/libmp/test-libmp.t +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -# $FreeBSD$ - -cd `dirname $0` - -executable=`basename $0 .t` - -make $executable 2>&1 > /dev/null - -exec ./$executable -- cgit v1.3 From b236bcf1680ee4835fcbbdc6a9ffa625eb9269f6 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 5 Aug 2014 18:41:27 +0000 Subject: Integrate lib/libnv into the build/kyua Rename all of the TAP test applications from to _test to match the convention described in the TestSuite wiki page Phabric: D538 Approved by: jmmv (mentor) Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 + lib/libnv/Makefile | 6 + lib/libnv/tests/Makefile | 17 ++ lib/libnv/tests/nvlist_add_test.c | 196 ++++++++++++++++ lib/libnv/tests/nvlist_exists_test.c | 321 +++++++++++++++++++++++++ lib/libnv/tests/nvlist_free_test.c | 221 ++++++++++++++++++ lib/libnv/tests/nvlist_get_test.c | 182 +++++++++++++++ lib/libnv/tests/nvlist_move_test.c | 161 +++++++++++++ lib/libnv/tests/nvlist_send_recv_test.c | 325 ++++++++++++++++++++++++++ tools/regression/lib/libnv/Makefile | 35 --- tools/regression/lib/libnv/nvlist_add.c | 196 ---------------- tools/regression/lib/libnv/nvlist_exists.c | 321 ------------------------- tools/regression/lib/libnv/nvlist_free.c | 221 ------------------ tools/regression/lib/libnv/nvlist_get.c | 182 --------------- tools/regression/lib/libnv/nvlist_move.c | 161 ------------- tools/regression/lib/libnv/nvlist_send_recv.c | 325 -------------------------- 16 files changed, 1431 insertions(+), 1441 deletions(-) create mode 100644 lib/libnv/tests/Makefile create mode 100644 lib/libnv/tests/nvlist_add_test.c create mode 100644 lib/libnv/tests/nvlist_exists_test.c create mode 100644 lib/libnv/tests/nvlist_free_test.c create mode 100644 lib/libnv/tests/nvlist_get_test.c create mode 100644 lib/libnv/tests/nvlist_move_test.c create mode 100644 lib/libnv/tests/nvlist_send_recv_test.c delete mode 100644 tools/regression/lib/libnv/Makefile delete mode 100644 tools/regression/lib/libnv/nvlist_add.c delete mode 100644 tools/regression/lib/libnv/nvlist_exists.c delete mode 100644 tools/regression/lib/libnv/nvlist_free.c delete mode 100644 tools/regression/lib/libnv/nvlist_get.c delete mode 100644 tools/regression/lib/libnv/nvlist_move.c delete mode 100644 tools/regression/lib/libnv/nvlist_send_recv.c (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 1f61599eddd4..64bf426d0e02 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -87,6 +87,8 @@ .. libmp .. + libnv + .. .. libexec atf diff --git a/lib/libnv/Makefile b/lib/libnv/Makefile index 710c2950671c..cad1ea4eba63 100644 --- a/lib/libnv/Makefile +++ b/lib/libnv/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB= nv SHLIBDIR?= /lib SHLIB_MAJOR= 0 @@ -158,4 +160,8 @@ MLINKS+=nv.3 nvlist_existsv.3 \ WARNS?= 6 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/lib/libnv/tests/Makefile b/lib/libnv/tests/Makefile new file mode 100644 index 000000000000..df1054960cd2 --- /dev/null +++ b/lib/libnv/tests/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libnv + +TAP_TESTS_C+= nvlist_add_test +TAP_TESTS_C+= nvlist_exists_test +TAP_TESTS_C+= nvlist_free_test +TAP_TESTS_C+= nvlist_get_test +TAP_TESTS_C+= nvlist_move_test +TAP_TESTS_C+= nvlist_send_recv_test + +DPADD+= ${LIBNV} +LDADD+= -lnv + +WARNS?= 6 + +.include diff --git a/lib/libnv/tests/nvlist_add_test.c b/lib/libnv/tests/nvlist_add_test.c new file mode 100644 index 000000000000..06bcc639df94 --- /dev/null +++ b/lib/libnv/tests/nvlist_add_test.c @@ -0,0 +1,196 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +int +main(void) +{ + const nvlist_t *cnvl; + nvlist_t *nvl; + + printf("1..94\n"); + + nvl = nvlist_create(0); + + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + nvlist_add_null(nvl, "nvlist/null"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true")); + nvlist_add_bool(nvl, "nvlist/bool/true", true); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true")); + + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false")); + nvlist_add_bool(nvl, "nvlist/bool/false", false); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/0")); + nvlist_add_number(nvl, "nvlist/number/0", 0); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/0")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/1")); + nvlist_add_number(nvl, "nvlist/number/1", 1); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/1")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1")); + nvlist_add_number(nvl, "nvlist/number/-1", -1); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/-1")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); + nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); + nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); + nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); + nvlist_add_string(nvl, "nvlist/string/", ""); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/string/")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); + nvlist_add_string(nvl, "nvlist/string/x", "x"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/")); + nvlist_add_stringf(nvl, "nvlist/stringf/", "%s", ""); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/x")); + nvlist_add_stringf(nvl, "nvlist/stringf/x", "%s", "x"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); + nvlist_add_stringf(nvl, "nvlist/stringf/666Xabc", "%d%c%s", 666, 'X', "abc"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); + + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); + nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); + + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/0")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/1")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/-1")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); + CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); + CHECK(nvlist_exists_string(nvl, "nvlist/string/")); + CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); + CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/")); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x")); + CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + + cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); + CHECK(nvlist_exists_null(cnvl, "nvlist/null")); + CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/true")); + CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/false")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/0")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/1")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/-1")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/UINT64_MAX")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MIN")); + CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MAX")); + CHECK(nvlist_exists_string(cnvl, "nvlist/string/")); + CHECK(nvlist_exists_string(cnvl, "nvlist/string/x")); + CHECK(nvlist_exists_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/")); + CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/x")); + CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/666Xabc")); + CHECK(nvlist_exists_descriptor(cnvl, "nvlist/descriptor/STDERR_FILENO")); + CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x")); + CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libnv/tests/nvlist_exists_test.c b/lib/libnv/tests/nvlist_exists_test.c new file mode 100644 index 000000000000..cb595d7b7841 --- /dev/null +++ b/lib/libnv/tests/nvlist_exists_test.c @@ -0,0 +1,321 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +int +main(void) +{ + nvlist_t *nvl; + + printf("1..232\n"); + + nvl = nvlist_create(0); + + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/null")); + CHECK(!nvlist_exists_number(nvl, "nvlist/null")); + CHECK(!nvlist_exists_string(nvl, "nvlist/null")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/null")); + nvlist_add_null(nvl, "nvlist/null"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/null")); + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/null")); + CHECK(!nvlist_exists_number(nvl, "nvlist/null")); + CHECK(!nvlist_exists_string(nvl, "nvlist/null")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/null")); + + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_null(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_string(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/bool")); + nvlist_add_bool(nvl, "nvlist/bool", true); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_null(nvl, "nvlist/bool")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_string(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/bool")); + + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists_null(nvl, "nvlist/number")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/number")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/number")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/number")); + nvlist_add_number(nvl, "nvlist/number", 0); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists_null(nvl, "nvlist/number")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/number")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/number")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/number")); + + CHECK(!nvlist_exists(nvl, "nvlist/string")); + CHECK(!nvlist_exists_null(nvl, "nvlist/string")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/string")); + CHECK(!nvlist_exists_number(nvl, "nvlist/string")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/string")); + nvlist_add_string(nvl, "nvlist/string", "test"); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/string")); + CHECK(!nvlist_exists_null(nvl, "nvlist/string")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/string")); + CHECK(!nvlist_exists_number(nvl, "nvlist/string")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/string")); + + CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist")); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist")); + + CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor")); + nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor")); + + CHECK(!nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_number(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_string(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); + nvlist_add_binary(nvl, "nvlist/binary", "test", 4); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_number(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_string(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + CHECK(nvlist_exists(nvl, "nvlist/null")); + CHECK(nvlist_exists(nvl, "nvlist/bool")); + CHECK(nvlist_exists(nvl, "nvlist/number")); + CHECK(nvlist_exists(nvl, "nvlist/string")); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_null(nvl, "nvlist/null"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(nvlist_exists(nvl, "nvlist/bool")); + CHECK(nvlist_exists(nvl, "nvlist/number")); + CHECK(nvlist_exists(nvl, "nvlist/string")); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_bool(nvl, "nvlist/bool"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(nvlist_exists(nvl, "nvlist/number")); + CHECK(nvlist_exists(nvl, "nvlist/string")); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_number(nvl, "nvlist/number"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(nvlist_exists(nvl, "nvlist/string")); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_string(nvl, "nvlist/string"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists(nvl, "nvlist/string")); + CHECK(nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_nvlist(nvl, "nvlist/nvlist"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists(nvl, "nvlist/string")); + CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_descriptor(nvl, "nvlist/descriptor"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists(nvl, "nvlist/string")); + CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_binary(nvl, "nvlist/binary"); + CHECK(!nvlist_exists(nvl, "nvlist/null")); + CHECK(!nvlist_exists(nvl, "nvlist/bool")); + CHECK(!nvlist_exists(nvl, "nvlist/number")); + CHECK(!nvlist_exists(nvl, "nvlist/string")); + CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists(nvl, "nvlist/binary")); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); + + CHECK(nvlist_empty(nvl)); + + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libnv/tests/nvlist_free_test.c b/lib/libnv/tests/nvlist_free_test.c new file mode 100644 index 000000000000..4417a4464974 --- /dev/null +++ b/lib/libnv/tests/nvlist_free_test.c @@ -0,0 +1,221 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +int +main(void) +{ + nvlist_t *nvl; + + printf("1..114\n"); + + nvl = nvlist_create(0); + + nvlist_add_null(nvl, "nvlist/null"); + nvlist_add_bool(nvl, "nvlist/bool", true); + nvlist_add_number(nvl, "nvlist/number", 0); + nvlist_add_string(nvl, "nvlist/string", "test"); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); + nvlist_add_binary(nvl, "nvlist/binary", "test", 4); + + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_null(nvl, "nvlist/null"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_bool(nvl, "nvlist/bool"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_number(nvl, "nvlist/number"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_string(nvl, "nvlist/string"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_nvlist(nvl, "nvlist/nvlist"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_descriptor(nvl, "nvlist/descriptor"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free_binary(nvl, "nvlist/binary"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); + + CHECK(nvlist_empty(nvl)); + + nvlist_add_null(nvl, "nvlist/null"); + nvlist_add_bool(nvl, "nvlist/bool", true); + nvlist_add_number(nvl, "nvlist/number", 0); + nvlist_add_string(nvl, "nvlist/string", "test"); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); + nvlist_add_binary(nvl, "nvlist/binary", "test", 4); + + CHECK(nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/null"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/bool"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/number"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/string"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/nvlist"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/descriptor"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); + + nvlist_free(nvl, "nvlist/binary"); + CHECK(!nvlist_exists_null(nvl, "nvlist/null")); + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); + CHECK(!nvlist_exists_number(nvl, "nvlist/number")); + CHECK(!nvlist_exists_string(nvl, "nvlist/string")); + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); + + CHECK(nvlist_empty(nvl)); + + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libnv/tests/nvlist_get_test.c b/lib/libnv/tests/nvlist_get_test.c new file mode 100644 index 000000000000..b4468db88b11 --- /dev/null +++ b/lib/libnv/tests/nvlist_get_test.c @@ -0,0 +1,182 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) + +int +main(void) +{ + const nvlist_t *cnvl; + nvlist_t *nvl; + size_t size; + + printf("1..83\n"); + + nvl = nvlist_create(0); + + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true")); + nvlist_add_bool(nvl, "nvlist/bool/true", true); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true); + + CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false")); + nvlist_add_bool(nvl, "nvlist/bool/false", false); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/0")); + nvlist_add_number(nvl, "nvlist/number/0", 0); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/1")); + nvlist_add_number(nvl, "nvlist/number/1", 1); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1")); + nvlist_add_number(nvl, "nvlist/number/-1", -1); + CHECK(nvlist_error(nvl) == 0); + CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); + nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); + nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); + CHECK(nvlist_error(nvl) == 0); + CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN); + + CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); + nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); + CHECK(nvlist_error(nvl) == 0); + CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); + nvlist_add_string(nvl, "nvlist/string/", ""); + CHECK(nvlist_error(nvl) == 0); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); + nvlist_add_string(nvl, "nvlist/string/x", "x"); + CHECK(nvlist_error(nvl) == 0); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); + CHECK(nvlist_error(nvl) == 0); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); + + CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); + CHECK(nvlist_error(nvl) == 0); + CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"))); + + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); + nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); + CHECK(nvlist_error(nvl) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0); + CHECK(size == 1); + + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_error(nvl) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + CHECK(nvlist_error(nvl) == 0); + cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); + CHECK(nvlist_get_bool(cnvl, "nvlist/bool/true") == true); + CHECK(nvlist_get_bool(cnvl, "nvlist/bool/false") == false); + CHECK(nvlist_get_number(cnvl, "nvlist/number/0") == 0); + CHECK(nvlist_get_number(cnvl, "nvlist/number/1") == 1); + CHECK((int)nvlist_get_number(cnvl, "nvlist/number/-1") == -1); + CHECK(nvlist_get_number(cnvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); + CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MIN") == INT64_MIN); + CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MAX") == INT64_MAX); + CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/"), "") == 0); + CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/x"), "x") == 0); + CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); + /* TODO */ + CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", NULL), "x", 1) == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", &size), "x", 1) == 0); + CHECK(size == 1); + CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true); + CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false); + CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0); + CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1); + CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1); + CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); + CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN); + CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0); + CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); + CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"))); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0); + CHECK(size == 1); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libnv/tests/nvlist_move_test.c b/lib/libnv/tests/nvlist_move_test.c new file mode 100644 index 000000000000..760399da2631 --- /dev/null +++ b/lib/libnv/tests/nvlist_move_test.c @@ -0,0 +1,161 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +int +main(void) +{ + const nvlist_t *cnvl; + nvlist_t *nvl; + void *ptr; + size_t size; + int fd; + + printf("1..52\n"); + + nvl = nvlist_create(0); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); + ptr = strdup(""); + CHECK(ptr != NULL); + nvlist_move_string(nvl, "nvlist/string/", ptr); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/string/")); + CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/")); + + CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); + ptr = strdup("x"); + CHECK(ptr != NULL); + nvlist_move_string(nvl, "nvlist/string/x", ptr); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); + CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/x")); + + CHECK(!nvlist_exists_string(nvl, + "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + ptr = strdup("abcdefghijklmnopqrstuvwxyz"); + CHECK(ptr != NULL); + nvlist_move_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", + ptr); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_string(nvl, + "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + CHECK(ptr == + nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + + CHECK(!nvlist_exists_descriptor(nvl, + "nvlist/descriptor/STDERR_FILENO")); + fd = dup(STDERR_FILENO); + CHECK(fd >= 0); + nvlist_move_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", fd); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + CHECK(fd == + nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + + CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); + ptr = malloc(1); + CHECK(ptr != NULL); + memcpy(ptr, "x", 1); + nvlist_move_binary(nvl, "nvlist/binary/x", ptr, 1); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); + CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", NULL)); + CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", &size)); + CHECK(size == 1); + + CHECK(!nvlist_exists_binary(nvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + ptr = malloc(sizeof("abcdefghijklmnopqrstuvwxyz")); + CHECK(ptr != NULL); + memcpy(ptr, "abcdefghijklmnopqrstuvwxyz", + sizeof("abcdefghijklmnopqrstuvwxyz")); + nvlist_move_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", + ptr, sizeof("abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_binary(nvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + CHECK(ptr == nvlist_get_binary(nvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL)); + CHECK(ptr == nvlist_get_binary(nvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size)); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + ptr = nvlist_clone(nvl); + CHECK(ptr != NULL); + nvlist_move_nvlist(nvl, "nvlist/nvlist", ptr); + CHECK(nvlist_error(nvl) == 0); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + CHECK(ptr == nvlist_get_nvlist(nvl, "nvlist/nvlist")); + + CHECK(nvlist_exists_string(nvl, "nvlist/string/")); + CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); + CHECK(nvlist_exists_string(nvl, + "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); + CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); + CHECK(nvlist_exists_binary(nvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); + + cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); + CHECK(nvlist_exists_string(cnvl, "nvlist/string/")); + CHECK(nvlist_exists_string(cnvl, "nvlist/string/x")); + CHECK(nvlist_exists_string(cnvl, + "nvlist/string/abcdefghijklmnopqrstuvwxyz")); + CHECK(nvlist_exists_descriptor(cnvl, + "nvlist/descriptor/STDERR_FILENO")); + CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x")); + CHECK(nvlist_exists_binary(cnvl, + "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); + + nvlist_destroy(nvl); + + return (0); +} diff --git a/lib/libnv/tests/nvlist_send_recv_test.c b/lib/libnv/tests/nvlist_send_recv_test.c new file mode 100644 index 000000000000..c751bf782522 --- /dev/null +++ b/lib/libnv/tests/nvlist_send_recv_test.c @@ -0,0 +1,325 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Pawel Jakub Dawidek under sponsorship from + * the FreeBSD Foundation. + * + * 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 AUTHORS 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 AUTHORS 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. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static int ntest = 1; + +#define CHECK(expr) do { \ + if ((expr)) \ + printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ + else \ + printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ + ntest++; \ +} while (0) + +#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) + +static void +child(int sock) +{ + nvlist_t *nvl; + + nvl = nvlist_create(0); + + nvlist_add_bool(nvl, "nvlist/bool/true", true); + nvlist_add_bool(nvl, "nvlist/bool/false", false); + nvlist_add_number(nvl, "nvlist/number/0", 0); + nvlist_add_number(nvl, "nvlist/number/1", 1); + nvlist_add_number(nvl, "nvlist/number/-1", -1); + nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); + nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); + nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); + nvlist_add_string(nvl, "nvlist/string/", ""); + nvlist_add_string(nvl, "nvlist/string/x", "x"); + nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); + nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); + nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); + nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); + nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); + + nvlist_send(sock, nvl); + + nvlist_destroy(nvl); +} + +static void +parent(int sock) +{ + nvlist_t *nvl; + const nvlist_t *cnvl; + const char *name, *cname; + void *cookie, *ccookie; + int type, ctype; + size_t size; + + nvl = nvlist_recv(sock); + CHECK(nvlist_error(nvl) == 0); + if (nvlist_error(nvl) != 0) + err(1, "nvlist_recv() failed"); + + cookie = NULL; + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_BOOL); + CHECK(strcmp(name, "nvlist/bool/true") == 0); + CHECK(nvlist_get_bool(nvl, name) == true); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_BOOL); + CHECK(strcmp(name, "nvlist/bool/false") == 0); + CHECK(nvlist_get_bool(nvl, name) == false); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/0") == 0); + CHECK(nvlist_get_number(nvl, name) == 0); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/1") == 0); + CHECK(nvlist_get_number(nvl, name) == 1); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/-1") == 0); + CHECK((int)nvlist_get_number(nvl, name) == -1); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0); + CHECK(nvlist_get_number(nvl, name) == UINT64_MAX); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0); + CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NUMBER); + CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0); + CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_STRING); + CHECK(strcmp(name, "nvlist/string/") == 0); + CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_STRING); + CHECK(strcmp(name, "nvlist/string/x") == 0); + CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_STRING); + CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); + CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_DESCRIPTOR); + CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0); + CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name))); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_BINARY); + CHECK(strcmp(name, "nvlist/binary/x") == 0); + CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0); + CHECK(size == 1); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_BINARY); + CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); + CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name != NULL); + CHECK(type == NV_TYPE_NVLIST); + CHECK(strcmp(name, "nvlist/nvlist") == 0); + cnvl = nvlist_get_nvlist(nvl, name); + + ccookie = NULL; + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_BOOL); + CHECK(strcmp(cname, "nvlist/bool/true") == 0); + CHECK(nvlist_get_bool(cnvl, cname) == true); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_BOOL); + CHECK(strcmp(cname, "nvlist/bool/false") == 0); + CHECK(nvlist_get_bool(cnvl, cname) == false); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/0") == 0); + CHECK(nvlist_get_number(cnvl, cname) == 0); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/1") == 0); + CHECK(nvlist_get_number(cnvl, cname) == 1); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/-1") == 0); + CHECK((int)nvlist_get_number(cnvl, cname) == -1); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0); + CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0); + CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_NUMBER); + CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0); + CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_STRING); + CHECK(strcmp(cname, "nvlist/string/") == 0); + CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_STRING); + CHECK(strcmp(cname, "nvlist/string/x") == 0); + CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_STRING); + CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); + CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_DESCRIPTOR); + CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0); + CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname))); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_BINARY); + CHECK(strcmp(cname, "nvlist/binary/x") == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0); + CHECK(size == 1); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname != NULL); + CHECK(ctype == NV_TYPE_BINARY); + CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); + CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); + + cname = nvlist_next(cnvl, &ctype, &ccookie); + CHECK(cname == NULL); + + name = nvlist_next(nvl, &type, &cookie); + CHECK(name == NULL); +} + +int +main(void) +{ + int status, socks[2]; + pid_t pid; + + printf("1..126\n"); + fflush(stdout); + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) + err(1, "socketpair() failed"); + pid = fork(); + switch (pid) { + case -1: + /* Failure. */ + err(1, "unable to fork"); + case 0: + /* Child. */ + close(socks[0]); + child(socks[1]); + return (0); + default: + /* Parent. */ + close(socks[1]); + parent(socks[0]); + break; + } + + if (waitpid(pid, &status, 0) < 0) + err(1, "waitpid() failed"); + + return (0); +} diff --git a/tools/regression/lib/libnv/Makefile b/tools/regression/lib/libnv/Makefile deleted file mode 100644 index a64cb63fbe66..000000000000 --- a/tools/regression/lib/libnv/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -# $FreeBSD$ - -TESTS= nvlist_add -TESTS+= nvlist_exists -TESTS+= nvlist_free -TESTS+= nvlist_get -TESTS+= nvlist_move -TESTS+= nvlist_send_recv - -CFLAGS= -O2 -pipe -fstack-protector -CFLAGS+=-Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter -CFLAGS+=-Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wreturn-type -CFLAGS+=-Wcast-qual -Wwrite-strings -Wswitch -Wshadow -Wunused-parameter -CFLAGS+=-Wcast-align -Wchar-subscripts -Winline -Wnested-externs -Wredundant-decls -CFLAGS+=-Wold-style-definition -Wno-pointer-sign -Wextra - -LDFLAGS+=-lnv - -all: ${TESTS} ${TESTS:=.t} - -.for TEST in ${TESTS} - -${TEST}: ${TEST}.c - ${CC} ${CFLAGS} ${LDFLAGS} ${@}.c -o $@ - -${TEST}.t: ${TEST} - @printf "#!/bin/sh\n\n%s/%s\n" ${.CURDIR} ${@:.t=} > $@ - -.endfor - -test: all - @prove -r ${.CURDIR} - -clean: - rm -f ${TESTS} ${TESTS:=.t} diff --git a/tools/regression/lib/libnv/nvlist_add.c b/tools/regression/lib/libnv/nvlist_add.c deleted file mode 100644 index 06bcc639df94..000000000000 --- a/tools/regression/lib/libnv/nvlist_add.c +++ /dev/null @@ -1,196 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -int -main(void) -{ - const nvlist_t *cnvl; - nvlist_t *nvl; - - printf("1..94\n"); - - nvl = nvlist_create(0); - - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - nvlist_add_null(nvl, "nvlist/null"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true")); - nvlist_add_bool(nvl, "nvlist/bool/true", true); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true")); - - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false")); - nvlist_add_bool(nvl, "nvlist/bool/false", false); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/0")); - nvlist_add_number(nvl, "nvlist/number/0", 0); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/0")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/1")); - nvlist_add_number(nvl, "nvlist/number/1", 1); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/1")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1")); - nvlist_add_number(nvl, "nvlist/number/-1", -1); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/-1")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); - nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); - nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); - nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); - nvlist_add_string(nvl, "nvlist/string/", ""); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/string/")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); - nvlist_add_string(nvl, "nvlist/string/x", "x"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/")); - nvlist_add_stringf(nvl, "nvlist/stringf/", "%s", ""); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/x")); - nvlist_add_stringf(nvl, "nvlist/stringf/x", "%s", "x"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); - nvlist_add_stringf(nvl, "nvlist/stringf/666Xabc", "%d%c%s", 666, 'X', "abc"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); - - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); - nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); - - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool/true")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool/false")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/0")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/1")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/-1")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); - CHECK(nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); - CHECK(nvlist_exists_string(nvl, "nvlist/string/")); - CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); - CHECK(nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/")); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/x")); - CHECK(nvlist_exists_string(nvl, "nvlist/stringf/666Xabc")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - - cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); - CHECK(nvlist_exists_null(cnvl, "nvlist/null")); - CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/true")); - CHECK(nvlist_exists_bool(cnvl, "nvlist/bool/false")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/0")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/1")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/-1")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/UINT64_MAX")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MIN")); - CHECK(nvlist_exists_number(cnvl, "nvlist/number/INT64_MAX")); - CHECK(nvlist_exists_string(cnvl, "nvlist/string/")); - CHECK(nvlist_exists_string(cnvl, "nvlist/string/x")); - CHECK(nvlist_exists_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/")); - CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/x")); - CHECK(nvlist_exists_string(cnvl, "nvlist/stringf/666Xabc")); - CHECK(nvlist_exists_descriptor(cnvl, "nvlist/descriptor/STDERR_FILENO")); - CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x")); - CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - - nvlist_destroy(nvl); - - return (0); -} diff --git a/tools/regression/lib/libnv/nvlist_exists.c b/tools/regression/lib/libnv/nvlist_exists.c deleted file mode 100644 index cb595d7b7841..000000000000 --- a/tools/regression/lib/libnv/nvlist_exists.c +++ /dev/null @@ -1,321 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -int -main(void) -{ - nvlist_t *nvl; - - printf("1..232\n"); - - nvl = nvlist_create(0); - - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/null")); - CHECK(!nvlist_exists_number(nvl, "nvlist/null")); - CHECK(!nvlist_exists_string(nvl, "nvlist/null")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/null")); - nvlist_add_null(nvl, "nvlist/null"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/null")); - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/null")); - CHECK(!nvlist_exists_number(nvl, "nvlist/null")); - CHECK(!nvlist_exists_string(nvl, "nvlist/null")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/null")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/null")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/null")); - - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_null(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_string(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/bool")); - nvlist_add_bool(nvl, "nvlist/bool", true); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_null(nvl, "nvlist/bool")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_string(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/bool")); - - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists_null(nvl, "nvlist/number")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/number")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/number")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/number")); - nvlist_add_number(nvl, "nvlist/number", 0); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists_null(nvl, "nvlist/number")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/number")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/number")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/number")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/number")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/number")); - - CHECK(!nvlist_exists(nvl, "nvlist/string")); - CHECK(!nvlist_exists_null(nvl, "nvlist/string")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/string")); - CHECK(!nvlist_exists_number(nvl, "nvlist/string")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/string")); - nvlist_add_string(nvl, "nvlist/string", "test"); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/string")); - CHECK(!nvlist_exists_null(nvl, "nvlist/string")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/string")); - CHECK(!nvlist_exists_number(nvl, "nvlist/string")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/string")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/string")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/string")); - - CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist")); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_null(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_number(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_string(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/nvlist")); - - CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor")); - nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_null(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_number(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_string(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/descriptor")); - - CHECK(!nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_number(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_string(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); - nvlist_add_binary(nvl, "nvlist/binary", "test", 4); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_number(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_string(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/binary")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - CHECK(nvlist_exists(nvl, "nvlist/null")); - CHECK(nvlist_exists(nvl, "nvlist/bool")); - CHECK(nvlist_exists(nvl, "nvlist/number")); - CHECK(nvlist_exists(nvl, "nvlist/string")); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_null(nvl, "nvlist/null"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(nvlist_exists(nvl, "nvlist/bool")); - CHECK(nvlist_exists(nvl, "nvlist/number")); - CHECK(nvlist_exists(nvl, "nvlist/string")); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_bool(nvl, "nvlist/bool"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(nvlist_exists(nvl, "nvlist/number")); - CHECK(nvlist_exists(nvl, "nvlist/string")); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_number(nvl, "nvlist/number"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(nvlist_exists(nvl, "nvlist/string")); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_string(nvl, "nvlist/string"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists(nvl, "nvlist/string")); - CHECK(nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_nvlist(nvl, "nvlist/nvlist"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists(nvl, "nvlist/string")); - CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_descriptor(nvl, "nvlist/descriptor"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists(nvl, "nvlist/string")); - CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_binary(nvl, "nvlist/binary"); - CHECK(!nvlist_exists(nvl, "nvlist/null")); - CHECK(!nvlist_exists(nvl, "nvlist/bool")); - CHECK(!nvlist_exists(nvl, "nvlist/number")); - CHECK(!nvlist_exists(nvl, "nvlist/string")); - CHECK(!nvlist_exists(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists(nvl, "nvlist/binary")); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); - - CHECK(nvlist_empty(nvl)); - - nvlist_destroy(nvl); - - return (0); -} diff --git a/tools/regression/lib/libnv/nvlist_free.c b/tools/regression/lib/libnv/nvlist_free.c deleted file mode 100644 index 4417a4464974..000000000000 --- a/tools/regression/lib/libnv/nvlist_free.c +++ /dev/null @@ -1,221 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -int -main(void) -{ - nvlist_t *nvl; - - printf("1..114\n"); - - nvl = nvlist_create(0); - - nvlist_add_null(nvl, "nvlist/null"); - nvlist_add_bool(nvl, "nvlist/bool", true); - nvlist_add_number(nvl, "nvlist/number", 0); - nvlist_add_string(nvl, "nvlist/string", "test"); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); - nvlist_add_binary(nvl, "nvlist/binary", "test", 4); - - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_null(nvl, "nvlist/null"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_bool(nvl, "nvlist/bool"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_number(nvl, "nvlist/number"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_string(nvl, "nvlist/string"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_nvlist(nvl, "nvlist/nvlist"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_descriptor(nvl, "nvlist/descriptor"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free_binary(nvl, "nvlist/binary"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); - - CHECK(nvlist_empty(nvl)); - - nvlist_add_null(nvl, "nvlist/null"); - nvlist_add_bool(nvl, "nvlist/bool", true); - nvlist_add_number(nvl, "nvlist/number", 0); - nvlist_add_string(nvl, "nvlist/string", "test"); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - nvlist_add_descriptor(nvl, "nvlist/descriptor", STDERR_FILENO); - nvlist_add_binary(nvl, "nvlist/binary", "test", 4); - - CHECK(nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/null"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/bool"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/number"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/string"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/nvlist"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/descriptor"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary")); - - nvlist_free(nvl, "nvlist/binary"); - CHECK(!nvlist_exists_null(nvl, "nvlist/null")); - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool")); - CHECK(!nvlist_exists_number(nvl, "nvlist/number")); - CHECK(!nvlist_exists_string(nvl, "nvlist/string")); - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor")); - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary")); - - CHECK(nvlist_empty(nvl)); - - nvlist_destroy(nvl); - - return (0); -} diff --git a/tools/regression/lib/libnv/nvlist_get.c b/tools/regression/lib/libnv/nvlist_get.c deleted file mode 100644 index b4468db88b11..000000000000 --- a/tools/regression/lib/libnv/nvlist_get.c +++ /dev/null @@ -1,182 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) - -int -main(void) -{ - const nvlist_t *cnvl; - nvlist_t *nvl; - size_t size; - - printf("1..83\n"); - - nvl = nvlist_create(0); - - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/true")); - nvlist_add_bool(nvl, "nvlist/bool/true", true); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true); - - CHECK(!nvlist_exists_bool(nvl, "nvlist/bool/false")); - nvlist_add_bool(nvl, "nvlist/bool/false", false); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/0")); - nvlist_add_number(nvl, "nvlist/number/0", 0); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/1")); - nvlist_add_number(nvl, "nvlist/number/1", 1); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/-1")); - nvlist_add_number(nvl, "nvlist/number/-1", -1); - CHECK(nvlist_error(nvl) == 0); - CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/UINT64_MAX")); - nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MIN")); - nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); - CHECK(nvlist_error(nvl) == 0); - CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN); - - CHECK(!nvlist_exists_number(nvl, "nvlist/number/INT64_MAX")); - nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); - CHECK(nvlist_error(nvl) == 0); - CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); - nvlist_add_string(nvl, "nvlist/string/", ""); - CHECK(nvlist_error(nvl) == 0); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); - nvlist_add_string(nvl, "nvlist/string/x", "x"); - CHECK(nvlist_error(nvl) == 0); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); - CHECK(nvlist_error(nvl) == 0); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); - - CHECK(!nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); - CHECK(nvlist_error(nvl) == 0); - CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"))); - - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); - nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); - CHECK(nvlist_error(nvl) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0); - CHECK(size == 1); - - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_error(nvl) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - CHECK(nvlist_error(nvl) == 0); - cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); - CHECK(nvlist_get_bool(cnvl, "nvlist/bool/true") == true); - CHECK(nvlist_get_bool(cnvl, "nvlist/bool/false") == false); - CHECK(nvlist_get_number(cnvl, "nvlist/number/0") == 0); - CHECK(nvlist_get_number(cnvl, "nvlist/number/1") == 1); - CHECK((int)nvlist_get_number(cnvl, "nvlist/number/-1") == -1); - CHECK(nvlist_get_number(cnvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); - CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MIN") == INT64_MIN); - CHECK((int64_t)nvlist_get_number(cnvl, "nvlist/number/INT64_MAX") == INT64_MAX); - CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/"), "") == 0); - CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/x"), "x") == 0); - CHECK(strcmp(nvlist_get_string(cnvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); - /* TODO */ - CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", NULL), "x", 1) == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/x", &size), "x", 1) == 0); - CHECK(size == 1); - CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - CHECK(nvlist_get_bool(nvl, "nvlist/bool/true") == true); - CHECK(nvlist_get_bool(nvl, "nvlist/bool/false") == false); - CHECK(nvlist_get_number(nvl, "nvlist/number/0") == 0); - CHECK(nvlist_get_number(nvl, "nvlist/number/1") == 1); - CHECK((int)nvlist_get_number(nvl, "nvlist/number/-1") == -1); - CHECK(nvlist_get_number(nvl, "nvlist/number/UINT64_MAX") == UINT64_MAX); - CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MIN") == INT64_MIN); - CHECK((int64_t)nvlist_get_number(nvl, "nvlist/number/INT64_MAX") == INT64_MAX); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/"), "") == 0); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/x"), "x") == 0); - CHECK(strcmp(nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz"), "abcdefghijklmnopqrstuvwxyz") == 0); - CHECK(fd_is_valid(nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO"))); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", NULL), "x", 1) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/x", &size), "x", 1) == 0); - CHECK(size == 1); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - nvlist_destroy(nvl); - - return (0); -} diff --git a/tools/regression/lib/libnv/nvlist_move.c b/tools/regression/lib/libnv/nvlist_move.c deleted file mode 100644 index 760399da2631..000000000000 --- a/tools/regression/lib/libnv/nvlist_move.c +++ /dev/null @@ -1,161 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -int -main(void) -{ - const nvlist_t *cnvl; - nvlist_t *nvl; - void *ptr; - size_t size; - int fd; - - printf("1..52\n"); - - nvl = nvlist_create(0); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/")); - ptr = strdup(""); - CHECK(ptr != NULL); - nvlist_move_string(nvl, "nvlist/string/", ptr); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/string/")); - CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/")); - - CHECK(!nvlist_exists_string(nvl, "nvlist/string/x")); - ptr = strdup("x"); - CHECK(ptr != NULL); - nvlist_move_string(nvl, "nvlist/string/x", ptr); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); - CHECK(ptr == nvlist_get_string(nvl, "nvlist/string/x")); - - CHECK(!nvlist_exists_string(nvl, - "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - ptr = strdup("abcdefghijklmnopqrstuvwxyz"); - CHECK(ptr != NULL); - nvlist_move_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", - ptr); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_string(nvl, - "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - CHECK(ptr == - nvlist_get_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - - CHECK(!nvlist_exists_descriptor(nvl, - "nvlist/descriptor/STDERR_FILENO")); - fd = dup(STDERR_FILENO); - CHECK(fd >= 0); - nvlist_move_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", fd); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - CHECK(fd == - nvlist_get_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - - CHECK(!nvlist_exists_binary(nvl, "nvlist/binary/x")); - ptr = malloc(1); - CHECK(ptr != NULL); - memcpy(ptr, "x", 1); - nvlist_move_binary(nvl, "nvlist/binary/x", ptr, 1); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); - CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", NULL)); - CHECK(ptr == nvlist_get_binary(nvl, "nvlist/binary/x", &size)); - CHECK(size == 1); - - CHECK(!nvlist_exists_binary(nvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - ptr = malloc(sizeof("abcdefghijklmnopqrstuvwxyz")); - CHECK(ptr != NULL); - memcpy(ptr, "abcdefghijklmnopqrstuvwxyz", - sizeof("abcdefghijklmnopqrstuvwxyz")); - nvlist_move_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", - ptr, sizeof("abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_binary(nvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - CHECK(ptr == nvlist_get_binary(nvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz", NULL)); - CHECK(ptr == nvlist_get_binary(nvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz", &size)); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - CHECK(!nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - ptr = nvlist_clone(nvl); - CHECK(ptr != NULL); - nvlist_move_nvlist(nvl, "nvlist/nvlist", ptr); - CHECK(nvlist_error(nvl) == 0); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - CHECK(ptr == nvlist_get_nvlist(nvl, "nvlist/nvlist")); - - CHECK(nvlist_exists_string(nvl, "nvlist/string/")); - CHECK(nvlist_exists_string(nvl, "nvlist/string/x")); - CHECK(nvlist_exists_string(nvl, - "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO")); - CHECK(nvlist_exists_binary(nvl, "nvlist/binary/x")); - CHECK(nvlist_exists_binary(nvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_nvlist(nvl, "nvlist/nvlist")); - - cnvl = nvlist_get_nvlist(nvl, "nvlist/nvlist"); - CHECK(nvlist_exists_string(cnvl, "nvlist/string/")); - CHECK(nvlist_exists_string(cnvl, "nvlist/string/x")); - CHECK(nvlist_exists_string(cnvl, - "nvlist/string/abcdefghijklmnopqrstuvwxyz")); - CHECK(nvlist_exists_descriptor(cnvl, - "nvlist/descriptor/STDERR_FILENO")); - CHECK(nvlist_exists_binary(cnvl, "nvlist/binary/x")); - CHECK(nvlist_exists_binary(cnvl, - "nvlist/binary/abcdefghijklmnopqrstuvwxyz")); - - nvlist_destroy(nvl); - - return (0); -} diff --git a/tools/regression/lib/libnv/nvlist_send_recv.c b/tools/regression/lib/libnv/nvlist_send_recv.c deleted file mode 100644 index c751bf782522..000000000000 --- a/tools/regression/lib/libnv/nvlist_send_recv.c +++ /dev/null @@ -1,325 +0,0 @@ -/*- - * Copyright (c) 2013 The FreeBSD Foundation - * All rights reserved. - * - * This software was developed by Pawel Jakub Dawidek under sponsorship from - * the FreeBSD Foundation. - * - * 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 AUTHORS 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 AUTHORS 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. - * - * $FreeBSD$ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -static int ntest = 1; - -#define CHECK(expr) do { \ - if ((expr)) \ - printf("ok # %d %s:%u\n", ntest, __FILE__, __LINE__); \ - else \ - printf("not ok # %d %s:%u\n", ntest, __FILE__, __LINE__);\ - ntest++; \ -} while (0) - -#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) - -static void -child(int sock) -{ - nvlist_t *nvl; - - nvl = nvlist_create(0); - - nvlist_add_bool(nvl, "nvlist/bool/true", true); - nvlist_add_bool(nvl, "nvlist/bool/false", false); - nvlist_add_number(nvl, "nvlist/number/0", 0); - nvlist_add_number(nvl, "nvlist/number/1", 1); - nvlist_add_number(nvl, "nvlist/number/-1", -1); - nvlist_add_number(nvl, "nvlist/number/UINT64_MAX", UINT64_MAX); - nvlist_add_number(nvl, "nvlist/number/INT64_MIN", INT64_MIN); - nvlist_add_number(nvl, "nvlist/number/INT64_MAX", INT64_MAX); - nvlist_add_string(nvl, "nvlist/string/", ""); - nvlist_add_string(nvl, "nvlist/string/x", "x"); - nvlist_add_string(nvl, "nvlist/string/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz"); - nvlist_add_descriptor(nvl, "nvlist/descriptor/STDERR_FILENO", STDERR_FILENO); - nvlist_add_binary(nvl, "nvlist/binary/x", "x", 1); - nvlist_add_binary(nvl, "nvlist/binary/abcdefghijklmnopqrstuvwxyz", "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")); - nvlist_add_nvlist(nvl, "nvlist/nvlist", nvl); - - nvlist_send(sock, nvl); - - nvlist_destroy(nvl); -} - -static void -parent(int sock) -{ - nvlist_t *nvl; - const nvlist_t *cnvl; - const char *name, *cname; - void *cookie, *ccookie; - int type, ctype; - size_t size; - - nvl = nvlist_recv(sock); - CHECK(nvlist_error(nvl) == 0); - if (nvlist_error(nvl) != 0) - err(1, "nvlist_recv() failed"); - - cookie = NULL; - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_BOOL); - CHECK(strcmp(name, "nvlist/bool/true") == 0); - CHECK(nvlist_get_bool(nvl, name) == true); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_BOOL); - CHECK(strcmp(name, "nvlist/bool/false") == 0); - CHECK(nvlist_get_bool(nvl, name) == false); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/0") == 0); - CHECK(nvlist_get_number(nvl, name) == 0); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/1") == 0); - CHECK(nvlist_get_number(nvl, name) == 1); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/-1") == 0); - CHECK((int)nvlist_get_number(nvl, name) == -1); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/UINT64_MAX") == 0); - CHECK(nvlist_get_number(nvl, name) == UINT64_MAX); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/INT64_MIN") == 0); - CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MIN); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NUMBER); - CHECK(strcmp(name, "nvlist/number/INT64_MAX") == 0); - CHECK((int64_t)nvlist_get_number(nvl, name) == INT64_MAX); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_STRING); - CHECK(strcmp(name, "nvlist/string/") == 0); - CHECK(strcmp(nvlist_get_string(nvl, name), "") == 0); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_STRING); - CHECK(strcmp(name, "nvlist/string/x") == 0); - CHECK(strcmp(nvlist_get_string(nvl, name), "x") == 0); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_STRING); - CHECK(strcmp(name, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); - CHECK(strcmp(nvlist_get_string(nvl, name), "abcdefghijklmnopqrstuvwxyz") == 0); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_DESCRIPTOR); - CHECK(strcmp(name, "nvlist/descriptor/STDERR_FILENO") == 0); - CHECK(fd_is_valid(nvlist_get_descriptor(nvl, name))); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_BINARY); - CHECK(strcmp(name, "nvlist/binary/x") == 0); - CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "x", 1) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "x", 1) == 0); - CHECK(size == 1); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_BINARY); - CHECK(strcmp(name, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); - CHECK(memcmp(nvlist_get_binary(nvl, name, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(memcmp(nvlist_get_binary(nvl, name, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name != NULL); - CHECK(type == NV_TYPE_NVLIST); - CHECK(strcmp(name, "nvlist/nvlist") == 0); - cnvl = nvlist_get_nvlist(nvl, name); - - ccookie = NULL; - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_BOOL); - CHECK(strcmp(cname, "nvlist/bool/true") == 0); - CHECK(nvlist_get_bool(cnvl, cname) == true); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_BOOL); - CHECK(strcmp(cname, "nvlist/bool/false") == 0); - CHECK(nvlist_get_bool(cnvl, cname) == false); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/0") == 0); - CHECK(nvlist_get_number(cnvl, cname) == 0); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/1") == 0); - CHECK(nvlist_get_number(cnvl, cname) == 1); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/-1") == 0); - CHECK((int)nvlist_get_number(cnvl, cname) == -1); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/UINT64_MAX") == 0); - CHECK(nvlist_get_number(cnvl, cname) == UINT64_MAX); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/INT64_MIN") == 0); - CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MIN); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_NUMBER); - CHECK(strcmp(cname, "nvlist/number/INT64_MAX") == 0); - CHECK((int64_t)nvlist_get_number(cnvl, cname) == INT64_MAX); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_STRING); - CHECK(strcmp(cname, "nvlist/string/") == 0); - CHECK(strcmp(nvlist_get_string(cnvl, cname), "") == 0); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_STRING); - CHECK(strcmp(cname, "nvlist/string/x") == 0); - CHECK(strcmp(nvlist_get_string(cnvl, cname), "x") == 0); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_STRING); - CHECK(strcmp(cname, "nvlist/string/abcdefghijklmnopqrstuvwxyz") == 0); - CHECK(strcmp(nvlist_get_string(cnvl, cname), "abcdefghijklmnopqrstuvwxyz") == 0); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_DESCRIPTOR); - CHECK(strcmp(cname, "nvlist/descriptor/STDERR_FILENO") == 0); - CHECK(fd_is_valid(nvlist_get_descriptor(cnvl, cname))); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_BINARY); - CHECK(strcmp(cname, "nvlist/binary/x") == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "x", 1) == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "x", 1) == 0); - CHECK(size == 1); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname != NULL); - CHECK(ctype == NV_TYPE_BINARY); - CHECK(strcmp(cname, "nvlist/binary/abcdefghijklmnopqrstuvwxyz") == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, cname, NULL), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(memcmp(nvlist_get_binary(cnvl, cname, &size), "abcdefghijklmnopqrstuvwxyz", sizeof("abcdefghijklmnopqrstuvwxyz")) == 0); - CHECK(size == sizeof("abcdefghijklmnopqrstuvwxyz")); - - cname = nvlist_next(cnvl, &ctype, &ccookie); - CHECK(cname == NULL); - - name = nvlist_next(nvl, &type, &cookie); - CHECK(name == NULL); -} - -int -main(void) -{ - int status, socks[2]; - pid_t pid; - - printf("1..126\n"); - fflush(stdout); - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) - err(1, "socketpair() failed"); - pid = fork(); - switch (pid) { - case -1: - /* Failure. */ - err(1, "unable to fork"); - case 0: - /* Child. */ - close(socks[0]); - child(socks[1]); - return (0); - default: - /* Parent. */ - close(socks[1]); - parent(socks[0]); - break; - } - - if (waitpid(pid, &status, 0) < 0) - err(1, "waitpid() failed"); - - return (0); -} -- cgit v1.3 From 284f2cf8f746206c81cbc1f34d7fd2ba5d12af03 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Wed, 13 Aug 2014 05:15:28 +0000 Subject: Add missing BSD.tests.dist entry for lib/libutil to unbreak installworld with MK_TESTS == no Phabric: D555 X-MFC with: r269904 Approved by: jmmv (mentor, implicit) Pointyhat to: ngie --- etc/mtree/BSD.tests.dist | 2 ++ 1 file changed, 2 insertions(+) (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 64bf426d0e02..3c561bba4079 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -89,6 +89,8 @@ .. libnv .. + libutil + .. .. libexec atf -- cgit v1.3 From aecd25eea97814412cb95cab8984bfe89cdb20c2 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Fri, 15 Aug 2014 21:35:31 +0000 Subject: Make the USB and ZFS devd configuration files optional depending on the values of MK_USB/MK_ZFS Making zfs.conf optional resolves PR # 186971 PR: 186971 Phabric: D606 Approved by: jmmv (mentor) Sponsored by: EMC / Isilon Storage Division --- etc/devd/Makefile | 10 +++++++++- tools/build/mk/OptionalObsoleteFiles.inc | 8 +++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/devd/Makefile b/etc/devd/Makefile index c744398b84c2..94cafdc66288 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -FILES= uath.conf usb.conf zfs.conf +.include .if ${MACHINE} == "powerpc" FILES+= apple.conf @@ -10,6 +10,14 @@ FILES+= apple.conf FILES+= asus.conf .endif +.if ${MK_USB} != "no" +FILES+= uath.conf usb.conf +.endif + +.if ${MK_ZFS} != "no" +FILES+= zfs.conf +.endif + NO_OBJ= FILESDIR= /etc/devd FILESMODE= 644 diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index d3cf72f1d994..78878c2ea459 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -444,6 +444,7 @@ OLD_FILES+=usr/share/man/man1/dtrace.1.gz OLD_FILES+=boot/gptzfsboot OLD_FILES+=boot/zfsboot OLD_FILES+=boot/zfsloader +OLD_FILES+=etc/devd/zfs.conf OLD_FILES+=etc/periodic/daily/404.status-zfs OLD_FILES+=etc/periodic/daily/800.scrub-zfs OLD_LIBS+=lib/libzfs.so.2 @@ -4677,9 +4678,10 @@ OLD_FILES+=usr/sbin/unbound-control OLD_FILES+=usr/sbin/unbound-control-setup .endif -#.if ${MK_USB} == no -# to be filled in -#.endif +.if ${MK_USB} == no +OLD_FILES+=etc/devd/uauth.conf +OLD_FILES+=etc/devd/usb.conf +.endif .if ${MK_UTMPX} == no OLD_FILES+=etc/periodic/monthly/200.accounting -- cgit v1.3 From 3914ddf8a7b16925f50cc2e29e916aa2d56063fb Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sun, 17 Aug 2014 09:44:42 +0000 Subject: Bring in the new automounter, similar to what's provided in most other UNIX systems, eg. MacOS X and Solaris. It uses Sun-compatible map format, has proper kernel support, and LDAP integration. There are still a few outstanding problems; they will be fixed shortly. Reviewed by: allanjude@, emaste@, kib@, wblock@ (earlier versions) Phabric: D523 MFC after: 2 weeks Relnotes: yes Sponsored by: The FreeBSD Foundation --- etc/Makefile | 4 +- etc/auto_master | 5 + etc/autofs/Makefile | 9 + etc/autofs/include_ldap | 38 ++ etc/autofs/special_hosts | 17 + etc/autofs/special_null | 4 + etc/defaults/rc.conf | 1 + etc/mtree/BSD.root.dist | 2 + etc/rc.d/Makefile | 3 + etc/rc.d/automount | 31 ++ etc/rc.d/automountd | 19 + etc/rc.d/autounmountd | 18 + sbin/mount/mntopts.h | 6 +- sbin/mount/mount.c | 1 + share/man/man5/Makefile | 1 + share/man/man5/autofs.5 | 99 ++++ sys/conf/NOTES | 1 + sys/conf/files | 4 + sys/conf/options | 1 + sys/fs/autofs/autofs.c | 637 +++++++++++++++++++++++ sys/fs/autofs/autofs.h | 141 +++++ sys/fs/autofs/autofs_ioctl.h | 89 ++++ sys/fs/autofs/autofs_vfsops.c | 209 ++++++++ sys/fs/autofs/autofs_vnops.c | 646 +++++++++++++++++++++++ sys/kern/vfs_mount.c | 4 + sys/libkern/strndup.c | 51 ++ sys/modules/Makefile | 1 + sys/modules/autofs/Makefile | 11 + sys/sys/libkern.h | 1 + sys/sys/mount.h | 6 +- usr.sbin/Makefile | 1 + usr.sbin/autofs/Makefile | 33 ++ usr.sbin/autofs/auto_master.5 | 272 ++++++++++ usr.sbin/autofs/automount.8 | 107 ++++ usr.sbin/autofs/automount.c | 345 ++++++++++++ usr.sbin/autofs/automountd.8 | 103 ++++ usr.sbin/autofs/automountd.c | 498 ++++++++++++++++++ usr.sbin/autofs/autounmountd.8 | 88 ++++ usr.sbin/autofs/autounmountd.c | 351 +++++++++++++ usr.sbin/autofs/common.c | 1129 ++++++++++++++++++++++++++++++++++++++++ usr.sbin/autofs/common.h | 112 ++++ usr.sbin/autofs/defined.c | 270 ++++++++++ usr.sbin/autofs/log.c | 196 +++++++ usr.sbin/autofs/popen.c | 191 +++++++ usr.sbin/autofs/token.l | 57 ++ 45 files changed, 5808 insertions(+), 5 deletions(-) create mode 100644 etc/auto_master create mode 100644 etc/autofs/Makefile create mode 100644 etc/autofs/include_ldap create mode 100644 etc/autofs/special_hosts create mode 100644 etc/autofs/special_null create mode 100644 etc/rc.d/automount create mode 100644 etc/rc.d/automountd create mode 100644 etc/rc.d/autounmountd create mode 100644 share/man/man5/autofs.5 create mode 100644 sys/fs/autofs/autofs.c create mode 100644 sys/fs/autofs/autofs.h create mode 100644 sys/fs/autofs/autofs_ioctl.h create mode 100644 sys/fs/autofs/autofs_vfsops.c create mode 100644 sys/fs/autofs/autofs_vnops.c create mode 100644 sys/libkern/strndup.c create mode 100644 sys/modules/autofs/Makefile create mode 100644 usr.sbin/autofs/Makefile create mode 100644 usr.sbin/autofs/auto_master.5 create mode 100644 usr.sbin/autofs/automount.8 create mode 100644 usr.sbin/autofs/automount.c create mode 100644 usr.sbin/autofs/automountd.8 create mode 100644 usr.sbin/autofs/automountd.c create mode 100644 usr.sbin/autofs/autounmountd.8 create mode 100644 usr.sbin/autofs/autounmountd.c create mode 100644 usr.sbin/autofs/common.c create mode 100644 usr.sbin/autofs/common.h create mode 100644 usr.sbin/autofs/defined.c create mode 100644 usr.sbin/autofs/log.c create mode 100644 usr.sbin/autofs/popen.c create mode 100644 usr.sbin/autofs/token.l (limited to 'etc') diff --git a/etc/Makefile b/etc/Makefile index 3387e60d6f02..ff70cc12ad0b 100644 --- a/etc/Makefile +++ b/etc/Makefile @@ -11,7 +11,8 @@ SUBDIR= sendmail SUBDIR+=tests .endif -BIN1= crontab \ +BIN1= auto_master \ + crontab \ devd.conf \ devfs.conf \ ddb.conf \ @@ -225,6 +226,7 @@ distribution: echo "./etc/spwd.db type=file mode=0600 uname=root gname=wheel"; \ ) | ${METALOG.add} .endif + ${_+_}cd ${.CURDIR}/autofs; ${MAKE} install .if ${MK_BLUETOOTH} != "no" ${_+_}cd ${.CURDIR}/bluetooth; ${MAKE} install .endif diff --git a/etc/auto_master b/etc/auto_master new file mode 100644 index 000000000000..16d55e2b4cb3 --- /dev/null +++ b/etc/auto_master @@ -0,0 +1,5 @@ +# $FreeBSD$ +# +# Automounter master map, see auto_master(5) for details. +# +/net -hosts -nosuid diff --git a/etc/autofs/Makefile b/etc/autofs/Makefile new file mode 100644 index 000000000000..c9eda5073e42 --- /dev/null +++ b/etc/autofs/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +FILES= include_ldap special_hosts special_null + +NO_OBJ= +FILESDIR= /etc/autofs +FILESMODE= 755 + +.include diff --git a/etc/autofs/include_ldap b/etc/autofs/include_ldap new file mode 100644 index 000000000000..58970c06a449 --- /dev/null +++ b/etc/autofs/include_ldap @@ -0,0 +1,38 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# Modify this to suit your needs. The "$1" is the map name, eg. "auto_master". +# To debug, simply run this script with map name as the only parameter. It's +# supposed to output map contents ("key location" pairs) to standard output. +SEARCHBASE="ou=$1,dc=example,dc=com" +ENTRY_ATTRIBUTE="cn" +VALUE_ATTRIBUTE="automountInformation" + +/usr/local/bin/ldapsearch -LLL -x -o ldif-wrap=no -b "$SEARCHBASE" "$ENTRY_ATTRIBUTE" "$VALUE_ATTRIBUTE" | awk ' +$1 == "'$ENTRY_ATTRIBUTE':" { + key = $2 +} + +$1 == "'$VALUE_ATTRIBUTE':" && key { + printf "%s%s", key, OFS + key = "" + for (i=2; i 1 { printf "%s\t%s:%s ", $1, host, $1 } END { printf "\n" }' + diff --git a/etc/autofs/special_null b/etc/autofs/special_null new file mode 100644 index 000000000000..41c10001e676 --- /dev/null +++ b/etc/autofs/special_null @@ -0,0 +1,4 @@ +#!/usr/bin/true +# +# $FreeBSD$ +# diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index da0e419545e0..87d92168191a 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -306,6 +306,7 @@ amd_enable="NO" # Run amd service with $amd_flags (or NO). amd_program="/usr/sbin/amd" # path to amd, if you want a different one. amd_flags="-a /.amd_mnt -l syslog /host /etc/amd.map /net /etc/amd.map" amd_map_program="NO" # Can be set to "ypcat -k amd.master" +autofs_enable="NO" # Run automountd(8) nfs_client_enable="NO" # This host is an NFS client (or NO). nfs_access_cache="60" # Client cache timeout in seconds nfs_server_enable="NO" # This host is an NFS server (or NO). diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index 44620132499a..d494ef68420e 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -24,6 +24,8 @@ etc X11 .. + autofs + .. bluetooth .. casper diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 7302d2934c17..75f79b9b8210 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -20,6 +20,9 @@ FILES= DAEMON \ atm3 \ auditd \ auditdistd \ + automount \ + automountd \ + autounmountd \ bgfsck \ ${_bluetooth} \ bootparams \ diff --git a/etc/rc.d/automount b/etc/rc.d/automount new file mode 100644 index 000000000000..63bda42ceeb7 --- /dev/null +++ b/etc/rc.d/automount @@ -0,0 +1,31 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: automount +# REQUIRE: nfsclient +# KEYWORD: nojail shutdown + +. /etc/rc.subr + +name="automount" +rcvar="autofs_enable" +start_cmd="automount_start" +stop_cmd="automount_stop" +required_modules="autofs" + +automount_start() +{ + + /usr/sbin/automount +} + +automount_stop() +{ + + /sbin/umount -At autofs +} + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/automountd b/etc/rc.d/automountd new file mode 100644 index 000000000000..6d7466514077 --- /dev/null +++ b/etc/rc.d/automountd @@ -0,0 +1,19 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: automountd +# REQUIRE: automount +# KEYWORD: nojail + +. /etc/rc.subr + +name="automountd" +rcvar="autofs_enable" +pidfile="/var/run/${name}.pid" +command="/usr/sbin/${name}" +required_modules="autofs" + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/autounmountd b/etc/rc.d/autounmountd new file mode 100644 index 000000000000..c57f90da99e8 --- /dev/null +++ b/etc/rc.d/autounmountd @@ -0,0 +1,18 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: autounmountd +# REQUIRE: nfsclient +# KEYWORD: nojail + +. /etc/rc.subr + +name="autounmountd" +rcvar="autofs_enable" +pidfile="/var/run/${name}.pid" +command="/usr/sbin/${name}" + +load_rc_config $name +run_rc_command "$1" diff --git a/sbin/mount/mntopts.h b/sbin/mount/mntopts.h index 86a350fcab50..d273dde9f1d5 100644 --- a/sbin/mount/mntopts.h +++ b/sbin/mount/mntopts.h @@ -33,7 +33,7 @@ struct mntopt { const char *m_option; /* option name */ int m_inverse; /* if a negative option, e.g. "atime" */ - int m_flag; /* bit to set, e.g. MNT_RDONLY */ + long long m_flag; /* bit to set, e.g. MNT_RDONLY */ int m_altloc; /* 1 => set bit in altflags */ }; @@ -55,6 +55,7 @@ struct mntopt { #define MOPT_MULTILABEL { "multilabel", 0, MNT_MULTILABEL, 0 } #define MOPT_ACLS { "acls", 0, MNT_ACLS, 0 } #define MOPT_NFS4ACLS { "nfsv4acls", 0, MNT_NFS4ACLS, 0 } +#define MOPT_AUTOMOUNTED { "automounted",0, MNT_AUTOMOUNTED, 0 } /* Control flags. */ #define MOPT_FORCE { "force", 0, MNT_FORCE, 0 } @@ -89,7 +90,8 @@ struct mntopt { MOPT_NOCLUSTERW, \ MOPT_MULTILABEL, \ MOPT_ACLS, \ - MOPT_NFS4ACLS + MOPT_NFS4ACLS, \ + MOPT_AUTOMOUNTED void getmntopts(const char *, const struct mntopt *, int *, int *); void rmslashes(char *, char *); diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index 91c7d7c196eb..5ea45df11d1f 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -114,6 +114,7 @@ static struct opt { { MNT_ACLS, "acls" }, { MNT_NFS4ACLS, "nfsv4acls" }, { MNT_GJOURNAL, "gjournal" }, + { MNT_AUTOMOUNTED, "automounted" }, { 0, NULL } }; diff --git a/share/man/man5/Makefile b/share/man/man5/Makefile index 541f21176f07..e8483355926d 100644 --- a/share/man/man5/Makefile +++ b/share/man/man5/Makefile @@ -7,6 +7,7 @@ MAN= acct.5 \ ar.5 \ a.out.5 \ + autofs.5 \ bluetooth.device.conf.5 \ bluetooth.hosts.5 \ bluetooth.protocols.5 \ diff --git a/share/man/man5/autofs.5 b/share/man/man5/autofs.5 new file mode 100644 index 000000000000..a7a49b316f25 --- /dev/null +++ b/share/man/man5/autofs.5 @@ -0,0 +1,99 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 14, 2014 +.Dt AUTOFS 5 +.Os +.Sh NAME +.Nm autofs +.Nd "automounter filesystem" +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following line in the +kernel configuration file: +.Bd -ragged -offset indent +.Cd "options AUTOFS" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +autofs_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver is the kernel component of the automounter infrastructure. +Its job is to pass mount requests to the +.Xr automountd 8 +daemon, and pause the processes trying to access the automounted filesystem +until the mount is completed. +It is mounted by the +.Xr automount 8 . +.Sh OPTIONS +These options are available when +mounting +.Nm +file systems: +.Bl -tag -width indent +.It Cm master_options +Mount options for all filesystems specified in the map entry. +.It Cm master_prefix +Filesystem mountpoint prefix. +.El +.Sh EXAMPLES +To unmount all mounted +.Nm +filesystems: +.Pp +.Dl "umount -At autofs" +.Pp +To mount +.Nm +filesystems specified in +.Xr auto_master 5 : +.Pp +.Dl "automount" +.Sh SEE ALSO +.Xr auto_master 5 , +.Xr automount 8 , +.Xr automountd 8 , +.Xr autounmountd 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 10.2 . +.Sh AUTHORS +The +.Nm +was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 695942518946..50d76dc571eb 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1012,6 +1012,7 @@ options FFS #Fast filesystem options NFSCLIENT #Network File System client # The rest are optional: +options AUTOFS #Automounter filesystem options CD9660 #ISO 9660 filesystem options FDESCFS #File descriptor filesystem options FUSE #FUSE support module diff --git a/sys/conf/files b/sys/conf/files index d1f3cbf6fa8c..82b55af383b5 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2627,6 +2627,9 @@ dev/xen/timer/timer.c optional xen | xenhvm dev/xen/pvcpu/pvcpu.c optional xen | xenhvm dev/xl/if_xl.c optional xl pci dev/xl/xlphy.c optional xl pci +fs/autofs/autofs.c optional autofs +fs/autofs/autofs_vfsops.c optional autofs +fs/autofs/autofs_vnops.c optional autofs fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_dir.c standard @@ -3164,6 +3167,7 @@ libkern/strcmp.c standard libkern/strcpy.c standard libkern/strcspn.c standard libkern/strdup.c standard +libkern/strndup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard diff --git a/sys/conf/options b/sys/conf/options index 6ed7ce945e6c..eff8a120d729 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -221,6 +221,7 @@ INCLUDE_CONFIG_FILE opt_config.h # time, since the corresponding lkms cannot work if there are any static # dependencies. Unusability is enforced by hiding the defines for the # options in a never-included header. +AUTOFS opt_dontuse.h CD9660 opt_dontuse.h EXT2FS opt_dontuse.h FDESCFS opt_dontuse.h diff --git a/sys/fs/autofs/autofs.c b/sys/fs/autofs/autofs.c new file mode 100644 index 000000000000..9715eea174aa --- /dev/null +++ b/sys/fs/autofs/autofs.c @@ -0,0 +1,637 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ +/*- + * Copyright (c) 1989, 1991, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "autofs.h" +#include "autofs_ioctl.h" + +MALLOC_DEFINE(M_AUTOFS, "autofs", "Automounter filesystem"); + +uma_zone_t autofs_request_zone; +uma_zone_t autofs_node_zone; + +static int autofs_open(struct cdev *dev, int flags, int fmt, + struct thread *td); +static int autofs_close(struct cdev *dev, int flag, int fmt, + struct thread *td); +static int autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, + int mode, struct thread *td); + +static struct cdevsw autofs_cdevsw = { + .d_version = D_VERSION, + .d_open = autofs_open, + .d_close = autofs_close, + .d_ioctl = autofs_ioctl, + .d_name = "autofs", +}; + +/* + * List of signals that can interrupt an autofs trigger. Might be a good + * idea to keep it synchronised with list in sys/fs/nfs/nfs_commonkrpc.c. + */ +int autofs_sig_set[] = { + SIGINT, + SIGTERM, + SIGHUP, + SIGKILL, + SIGQUIT +}; + +struct autofs_softc *sc; + +SYSCTL_NODE(_vfs, OID_AUTO, autofs, CTLFLAG_RD, 0, "Automounter filesystem"); +int autofs_debug = 1; +TUNABLE_INT("vfs.autofs.debug", &autofs_debug); +SYSCTL_INT(_vfs_autofs, OID_AUTO, debug, CTLFLAG_RWTUN, + &autofs_debug, 1, "Enable debug messages"); +int autofs_mount_on_stat = 0; +TUNABLE_INT("vfs.autofs.mount_on_stat", &autofs_mount_on_stat); +SYSCTL_INT(_vfs_autofs, OID_AUTO, mount_on_stat, CTLFLAG_RWTUN, + &autofs_mount_on_stat, 0, "Trigger mount on stat(2) on mountpoint"); +int autofs_timeout = 30; +TUNABLE_INT("vfs.autofs.timeout", &autofs_timeout); +SYSCTL_INT(_vfs_autofs, OID_AUTO, timeout, CTLFLAG_RWTUN, + &autofs_timeout, 30, "Number of seconds to wait for automountd(8)"); +int autofs_cache = 600; +TUNABLE_INT("vfs.autofs.cache", &autofs_cache); +SYSCTL_INT(_vfs_autofs, OID_AUTO, cache, CTLFLAG_RWTUN, + &autofs_cache, 600, "Number of seconds to wait before reinvoking " + "automountd(8) for any given file or directory"); +int autofs_retry_attempts = 3; +TUNABLE_INT("vfs.autofs.retry_attempts", &autofs_retry_attempts); +SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_attempts, CTLFLAG_RWTUN, + &autofs_retry_attempts, 3, "Number of attempts before failing mount"); +int autofs_retry_delay = 1; +TUNABLE_INT("vfs.autofs.retry_delay", &autofs_retry_delay); +SYSCTL_INT(_vfs_autofs, OID_AUTO, retry_delay, CTLFLAG_RWTUN, + &autofs_retry_delay, 1, "Number of seconds before retrying"); +int autofs_interruptible = 1; +TUNABLE_INT("vfs.autofs.interruptible", &autofs_interruptible); +SYSCTL_INT(_vfs_autofs, OID_AUTO, interruptible, CTLFLAG_RWTUN, + &autofs_interruptible, 1, "Allow requests to be interrupted by signal"); + +int +autofs_init(struct vfsconf *vfsp) +{ + int error; + + sc = malloc(sizeof(*sc), M_AUTOFS, M_WAITOK | M_ZERO); + + autofs_request_zone = uma_zcreate("autofs_request", + sizeof(struct autofs_request), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); + autofs_node_zone = uma_zcreate("autofs_node", + sizeof(struct autofs_node), NULL, NULL, NULL, NULL, + UMA_ALIGN_PTR, 0); + + TAILQ_INIT(&sc->sc_requests); + cv_init(&sc->sc_cv, "autofscv"); + sx_init(&sc->sc_lock, "autofslk"); + + error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &autofs_cdevsw, + NULL, UID_ROOT, GID_WHEEL, 0600, "autofs"); + if (error != 0) { + AUTOFS_WARN("failed to create device node, error %d", error); + free(sc, M_AUTOFS); + return (error); + } + sc->sc_cdev->si_drv1 = sc; + + return (0); +} + +int +autofs_uninit(struct vfsconf *vfsp) +{ + + sx_xlock(&sc->sc_lock); + if (sc->sc_dev_opened) { + sx_xunlock(&sc->sc_lock); + return (EBUSY); + } + if (sc->sc_cdev != NULL) + destroy_dev(sc->sc_cdev); + + uma_zdestroy(autofs_request_zone); + uma_zdestroy(autofs_node_zone); + + sx_xunlock(&sc->sc_lock); + /* + * XXX: Race with open? + */ + free(sc, M_AUTOFS); + + return (0); +} + +bool +autofs_ignore_thread(const struct thread *td) +{ + struct proc *p; + + p = td->td_proc; + + if (sc->sc_dev_opened == false) + return (false); + + PROC_LOCK(p); + if (p->p_session->s_sid == sc->sc_dev_sid) { + PROC_UNLOCK(p); + return (true); + } + PROC_UNLOCK(p); + + return (false); +} + +static char * +autofs_path(struct autofs_node *anp) +{ + struct autofs_mount *amp; + char *path, *tmp; + + amp = anp->an_mount; + + path = strdup("", M_AUTOFS); + for (; anp->an_parent != NULL; anp = anp->an_parent) { + tmp = malloc(strlen(anp->an_name) + strlen(path) + 2, + M_AUTOFS, M_WAITOK); + strcpy(tmp, anp->an_name); + strcat(tmp, "/"); + strcat(tmp, path); + free(path, M_AUTOFS); + path = tmp; + } + + tmp = malloc(strlen(amp->am_mountpoint) + strlen(path) + 2, + M_AUTOFS, M_WAITOK); + strcpy(tmp, amp->am_mountpoint); + strcat(tmp, "/"); + strcat(tmp, path); + free(path, M_AUTOFS); + path = tmp; + + return (path); +} + +static void +autofs_callout(void *context) +{ + struct autofs_request *ar; + struct autofs_softc *sc; + + ar = context; + sc = ar->ar_mount->am_softc; + + sx_xlock(&sc->sc_lock); + AUTOFS_WARN("request %d for %s timed out after %d seconds", + ar->ar_id, ar->ar_path, autofs_timeout); + /* + * XXX: EIO perhaps? + */ + ar->ar_error = ETIMEDOUT; + ar->ar_done = true; + ar->ar_in_progress = false; + cv_broadcast(&sc->sc_cv); + sx_xunlock(&sc->sc_lock); +} + +bool +autofs_cached(struct autofs_node *anp, const char *component, int componentlen) +{ + int error; + struct autofs_mount *amp; + + amp = anp->an_mount; + + AUTOFS_ASSERT_UNLOCKED(amp); + + /* + * For top-level nodes we need to request automountd(8) + * assistance even if the node is marked as cached, + * but the requested subdirectory does not exist. This + * is necessary for wildcard indirect map keys to work. + */ + if (anp->an_parent == NULL && componentlen != 0) { + AUTOFS_LOCK(amp); + error = autofs_node_find(anp, component, componentlen, NULL); + AUTOFS_UNLOCK(amp); + if (error != 0) + return (false); + } + + return (anp->an_cached); +} + +static void +autofs_cache_callout(void *context) +{ + struct autofs_node *anp; + + anp = context; + anp->an_cached = false; +} + +/* + * The set/restore sigmask functions are used to (temporarily) overwrite + * the thread td_sigmask during triggering. + */ +static void +autofs_set_sigmask(sigset_t *oldset) +{ + sigset_t newset; + int i; + + SIGFILLSET(newset); + /* Remove the autofs set of signals from newset */ + PROC_LOCK(curproc); + mtx_lock(&curproc->p_sigacts->ps_mtx); + for (i = 0 ; i < sizeof(autofs_sig_set)/sizeof(int) ; i++) { + /* + * But make sure we leave the ones already masked + * by the process, i.e. remove the signal from the + * temporary signalmask only if it wasn't already + * in p_sigmask. + */ + if (!SIGISMEMBER(curthread->td_sigmask, autofs_sig_set[i]) && + !SIGISMEMBER(curproc->p_sigacts->ps_sigignore, + autofs_sig_set[i])) { + SIGDELSET(newset, autofs_sig_set[i]); + } + } + mtx_unlock(&curproc->p_sigacts->ps_mtx); + kern_sigprocmask(curthread, SIG_SETMASK, &newset, oldset, + SIGPROCMASK_PROC_LOCKED); + PROC_UNLOCK(curproc); +} + +static void +autofs_restore_sigmask(sigset_t *set) +{ + + kern_sigprocmask(curthread, SIG_SETMASK, set, NULL, 0); +} + +static int +autofs_trigger_one(struct autofs_node *anp, + const char *component, int componentlen) +{ + sigset_t oldset; + struct autofs_mount *amp; + struct autofs_softc *sc; + struct autofs_node *firstanp; + struct autofs_request *ar; + char *key, *path; + int error = 0, request_error, last; + + amp = VFSTOAUTOFS(anp->an_vnode->v_mount); + sc = amp->am_softc; + + sx_assert(&sc->sc_lock, SA_XLOCKED); + + if (anp->an_parent == NULL) { + key = strndup(component, componentlen, M_AUTOFS); + } else { + for (firstanp = anp; firstanp->an_parent->an_parent != NULL; + firstanp = firstanp->an_parent) + continue; + key = strdup(firstanp->an_name, M_AUTOFS); + } + + path = autofs_path(anp); + + TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) { + if (strcmp(ar->ar_path, path) != 0) + continue; + if (strcmp(ar->ar_key, key) != 0) + continue; + + KASSERT(strcmp(ar->ar_from, amp->am_from) == 0, + ("from changed; %s != %s", ar->ar_from, amp->am_from)); + KASSERT(strcmp(ar->ar_prefix, amp->am_prefix) == 0, + ("prefix changed; %s != %s", + ar->ar_prefix, amp->am_prefix)); + KASSERT(strcmp(ar->ar_options, amp->am_options) == 0, + ("options changed; %s != %s", + ar->ar_options, amp->am_options)); + + break; + } + + if (ar != NULL) { + refcount_acquire(&ar->ar_refcount); + } else { + ar = uma_zalloc(autofs_request_zone, M_WAITOK | M_ZERO); + ar->ar_mount = amp; + + ar->ar_id = atomic_fetchadd_int(&sc->sc_last_request_id, 1); + strlcpy(ar->ar_from, amp->am_from, sizeof(ar->ar_from)); + strlcpy(ar->ar_path, path, sizeof(ar->ar_path)); + strlcpy(ar->ar_prefix, amp->am_prefix, sizeof(ar->ar_prefix)); + strlcpy(ar->ar_key, key, sizeof(ar->ar_key)); + strlcpy(ar->ar_options, + amp->am_options, sizeof(ar->ar_options)); + + callout_init(&ar->ar_callout, 1); + callout_reset(&ar->ar_callout, + autofs_timeout * hz, autofs_callout, ar); + refcount_init(&ar->ar_refcount, 1); + TAILQ_INSERT_TAIL(&sc->sc_requests, ar, ar_next); + } + + cv_broadcast(&sc->sc_cv); + while (ar->ar_done == false) { + if (autofs_interruptible != 0) { + autofs_set_sigmask(&oldset); + error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); + autofs_restore_sigmask(&oldset); + if (error != 0) { + /* + * XXX: For some reson this returns -1 + * instead of EINTR, wtf?! + */ + error = EINTR; + AUTOFS_WARN("cv_wait_sig for %s failed " + "with error %d", ar->ar_path, error); + break; + } + } else { + cv_wait(&sc->sc_cv, &sc->sc_lock); + } + } + + request_error = ar->ar_error; + if (request_error != 0) { + AUTOFS_WARN("request for %s completed with error %d", + ar->ar_path, request_error); + } + + last = refcount_release(&ar->ar_refcount); + if (last) { + TAILQ_REMOVE(&sc->sc_requests, ar, ar_next); + /* + * XXX: Is it safe? + */ + sx_xunlock(&sc->sc_lock); + callout_drain(&ar->ar_callout); + sx_xlock(&sc->sc_lock); + uma_zfree(autofs_request_zone, ar); + } + + /* + * Note that we do not do negative caching on purpose. This + * way the user can retry access at any time, e.g. after fixing + * the failure reason, without waiting for cache timer to expire. + */ + if (error == 0 && request_error == 0 && autofs_cache > 0) { + anp->an_cached = true; + callout_reset(&anp->an_callout, autofs_cache * hz, + autofs_cache_callout, anp); + } + + free(key, M_AUTOFS); + free(path, M_AUTOFS); + + if (error != 0) + return (error); + return (request_error); +} + +/* + * Send request to automountd(8) and wait for completion. + */ +int +autofs_trigger(struct autofs_node *anp, + const char *component, int componentlen) +{ + int error; + + for (;;) { + error = autofs_trigger_one(anp, component, componentlen); + if (error == 0) { + anp->an_retries = 0; + return (0); + } + if (error == EINTR) { + AUTOFS_DEBUG("trigger interrupted by signal, " + "not retrying"); + anp->an_retries = 0; + return (error); + } + anp->an_retries++; + if (anp->an_retries >= autofs_retry_attempts) { + AUTOFS_DEBUG("trigger failed %d times; returning " + "error %d", anp->an_retries, error); + anp->an_retries = 0; + return (error); + + } + AUTOFS_DEBUG("trigger failed with error %d; will retry in " + "%d seconds, %d attempts left", error, autofs_retry_delay, + autofs_retry_attempts - anp->an_retries); + sx_xunlock(&sc->sc_lock); + pause("autofs_retry", autofs_retry_delay * hz); + sx_xlock(&sc->sc_lock); + } +} + +static int +autofs_ioctl_request(struct autofs_softc *sc, struct autofs_daemon_request *adr) +{ + struct autofs_request *ar; + int error; + + sx_xlock(&sc->sc_lock); + for (;;) { + TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) { + if (ar->ar_done) + continue; + if (ar->ar_in_progress) + continue; + + break; + } + + if (ar != NULL) + break; + + error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); + if (error != 0) { + /* + * XXX: For some reson this returns -1 instead + * of EINTR, wtf?! + */ + error = EINTR; + sx_xunlock(&sc->sc_lock); + AUTOFS_DEBUG("failed with error %d", error); + return (error); + } + } + + ar->ar_in_progress = true; + sx_xunlock(&sc->sc_lock); + + adr->adr_id = ar->ar_id; + strlcpy(adr->adr_from, ar->ar_from, sizeof(adr->adr_from)); + strlcpy(adr->adr_path, ar->ar_path, sizeof(adr->adr_path)); + strlcpy(adr->adr_prefix, ar->ar_prefix, sizeof(adr->adr_prefix)); + strlcpy(adr->adr_key, ar->ar_key, sizeof(adr->adr_key)); + strlcpy(adr->adr_options, ar->ar_options, sizeof(adr->adr_options)); + + PROC_LOCK(curproc); + sc->sc_dev_sid = curproc->p_session->s_sid; + PROC_UNLOCK(curproc); + + return (0); +} + +static int +autofs_ioctl_done(struct autofs_softc *sc, struct autofs_daemon_done *add) +{ + struct autofs_request *ar; + + sx_xlock(&sc->sc_lock); + TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) { + if (ar->ar_id == add->add_id) + break; + } + + if (ar == NULL) { + sx_xunlock(&sc->sc_lock); + AUTOFS_DEBUG("id %d not found", add->add_id); + return (ESRCH); + } + + ar->ar_error = add->add_error; + ar->ar_done = true; + ar->ar_in_progress = false; + cv_broadcast(&sc->sc_cv); + + sx_xunlock(&sc->sc_lock); + + return (0); +} + +static int +autofs_open(struct cdev *dev, int flags, int fmt, struct thread *td) +{ + + sx_xlock(&sc->sc_lock); + if (sc->sc_dev_opened) { + sx_xunlock(&sc->sc_lock); + return (EBUSY); + } + + sc->sc_dev_opened = true; + sx_xunlock(&sc->sc_lock); + + return (0); +} + +static int +autofs_close(struct cdev *dev, int flag, int fmt, struct thread *td) +{ + + sx_xlock(&sc->sc_lock); + KASSERT(sc->sc_dev_opened, ("not opened?")); + sc->sc_dev_opened = false; + sx_xunlock(&sc->sc_lock); + + return (0); +} + +static int +autofs_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, + struct thread *td) +{ + + KASSERT(sc->sc_dev_opened, ("not opened?")); + + switch (cmd) { + case AUTOFSREQUEST: + return (autofs_ioctl_request(sc, + (struct autofs_daemon_request *)arg)); + case AUTOFSDONE: + return (autofs_ioctl_done(sc, + (struct autofs_daemon_done *)arg)); + default: + AUTOFS_DEBUG("invalid cmd %lx", cmd); + return (EINVAL); + } +} diff --git a/sys/fs/autofs/autofs.h b/sys/fs/autofs/autofs.h new file mode 100644 index 000000000000..ec1ca664f162 --- /dev/null +++ b/sys/fs/autofs/autofs.h @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef AUTOFS_H +#define AUTOFS_H + +#include +__FBSDID("$FreeBSD$"); + +#define VFSTOAUTOFS(mp) ((struct autofs_mount *)((mp)->mnt_data)) + +MALLOC_DECLARE(M_AUTOFS); + +extern uma_zone_t autofs_request_zone; +extern uma_zone_t autofs_node_zone; + +extern int autofs_debug; +extern int autofs_mount_on_stat; + +#define AUTOFS_DEBUG(X, ...) \ + if (autofs_debug > 1) { \ + printf("%s: " X "\n", __func__, ## __VA_ARGS__);\ + } while (0) + +#define AUTOFS_WARN(X, ...) \ + if (autofs_debug > 0) { \ + printf("WARNING: %s: " X "\n", \ + __func__, ## __VA_ARGS__); \ + } while (0) + +#define AUTOFS_LOCK(X) sx_xlock(&X->am_lock) +#define AUTOFS_UNLOCK(X) sx_xunlock(&X->am_lock) +#define AUTOFS_ASSERT_LOCKED(X) sx_assert(&X->am_lock, SA_XLOCKED) +#define AUTOFS_ASSERT_UNLOCKED(X) sx_assert(&X->am_lock, SA_UNLOCKED) + +struct autofs_node { + TAILQ_ENTRY(autofs_node) an_next; + char *an_name; + int an_fileno; + struct autofs_node *an_parent; + TAILQ_HEAD(, autofs_node) an_children; + struct autofs_mount *an_mount; + struct vnode *an_vnode; + struct sx an_vnode_lock; + bool an_cached; + struct callout an_callout; + int an_retries; + struct timespec an_ctime; +}; + +struct autofs_mount { + TAILQ_ENTRY(autofs_mount) am_next; + struct autofs_softc *am_softc; + struct autofs_node *am_root; + struct mount *am_mp; + struct sx am_lock; + char am_from[MAXPATHLEN]; + char am_mountpoint[MAXPATHLEN]; + char am_options[MAXPATHLEN]; + char am_prefix[MAXPATHLEN]; + int am_last_fileno; +}; + +struct autofs_request { + TAILQ_ENTRY(autofs_request) ar_next; + struct autofs_mount *ar_mount; + int ar_id; + bool ar_done; + int ar_error; + bool ar_in_progress; + char ar_from[MAXPATHLEN]; + char ar_path[MAXPATHLEN]; + char ar_prefix[MAXPATHLEN]; + char ar_key[MAXPATHLEN]; + char ar_options[MAXPATHLEN]; + struct callout ar_callout; + volatile u_int ar_refcount; +}; + +struct autofs_softc { + device_t sc_dev; + struct cdev *sc_cdev; + struct cv sc_cv; + struct sx sc_lock; + TAILQ_HEAD(, autofs_request) sc_requests; + bool sc_dev_opened; + pid_t sc_dev_sid; + int sc_last_request_id; +}; + +/* + * Limits and constants + */ +#define AUTOFS_NAMELEN 24 +#define AUTOFS_FSNAMELEN 16 /* equal to MFSNAMELEN */ +#define AUTOFS_DELEN (8 + AUTOFS_NAMELEN) + +int autofs_init(struct vfsconf *vfsp); +int autofs_uninit(struct vfsconf *vfsp); +int autofs_trigger(struct autofs_node *anp, const char *component, + int componentlen); +bool autofs_cached(struct autofs_node *anp, const char *component, + int componentlen); +bool autofs_ignore_thread(const struct thread *td); +int autofs_node_new(struct autofs_node *parent, struct autofs_mount *amp, + const char *name, int namelen, struct autofs_node **anpp); +int autofs_node_find(struct autofs_node *parent, + const char *name, int namelen, struct autofs_node **anpp); +void autofs_node_delete(struct autofs_node *anp); +int autofs_node_vn(struct autofs_node *anp, struct mount *mp, + struct vnode **vpp); + +#endif /* !AUTOFS_H */ diff --git a/sys/fs/autofs/autofs_ioctl.h b/sys/fs/autofs/autofs_ioctl.h new file mode 100644 index 000000000000..8d03ef7480a2 --- /dev/null +++ b/sys/fs/autofs/autofs_ioctl.h @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef AUTOFS_IOCTL_H +#define AUTOFS_IOCTL_H + +#define AUTOFS_PATH "/dev/autofs" + +struct autofs_daemon_request { + /* + * Request identifier. + */ + int adr_id; + + /* + * The "from" field, containing map name. For example, + * when accessing '/net/192.168.1.3/tank/vm/', that would + * be '-hosts'. + */ + char adr_from[MAXPATHLEN]; + + /* + * Full path to the node being looked up; for requests that result + * in actual mount it is the full mount path. + */ + char adr_path[MAXPATHLEN]; + + /* + * Prefix, which is basically the mountpoint from auto_master(5). + * In example above that would be "/net"; for direct maps it is "/". + */ + char adr_prefix[MAXPATHLEN]; + + /* + * Map key, also used as command argument for dynamic maps; in example + * above that would be '192.168.1.3'. + */ + char adr_key[MAXPATHLEN]; + + /* + * Mount options from auto_master(5). + */ + char adr_options[MAXPATHLEN]; +}; + +struct autofs_daemon_done { + /* + * Identifier, copied from adr_id. + */ + int add_id; + + /* + * Error number, possibly returned to userland. + */ + int add_error; +}; + +#define AUTOFSREQUEST _IOR('I', 0x01, struct autofs_daemon_request) +#define AUTOFSDONE _IOW('I', 0x02, struct autofs_daemon_done) + +#endif /* !AUTOFS_IOCTL_H */ diff --git a/sys/fs/autofs/autofs_vfsops.c b/sys/fs/autofs/autofs_vfsops.c new file mode 100644 index 000000000000..0c1f36b06300 --- /dev/null +++ b/sys/fs/autofs/autofs_vfsops.c @@ -0,0 +1,209 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "autofs.h" + +static const char *autofs_opts[] = { + "from", "master_options", "master_prefix", NULL +}; + +extern struct autofs_softc *sc; + +static int +autofs_mount(struct mount *mp) +{ + struct autofs_mount *amp; + char *from, *fspath, *options, *prefix; + int error; + + if (vfs_filteropt(mp->mnt_optnew, autofs_opts)) + return (EINVAL); + + if (mp->mnt_flag & MNT_UPDATE) + return (0); + + if (vfs_getopt(mp->mnt_optnew, "from", (void **)&from, NULL)) + return (EINVAL); + + if (vfs_getopt(mp->mnt_optnew, "fspath", (void **)&fspath, NULL)) + return (EINVAL); + + if (vfs_getopt(mp->mnt_optnew, "master_options", (void **)&options, NULL)) + return (EINVAL); + + if (vfs_getopt(mp->mnt_optnew, "master_prefix", (void **)&prefix, NULL)) + return (EINVAL); + + amp = malloc(sizeof(*amp), M_AUTOFS, M_WAITOK | M_ZERO); + mp->mnt_data = amp; + amp->am_mp = mp; + amp->am_softc = sc; + strlcpy(amp->am_from, from, sizeof(amp->am_from)); + strlcpy(amp->am_mountpoint, fspath, sizeof(amp->am_mountpoint)); + strlcpy(amp->am_options, options, sizeof(amp->am_options)); + strlcpy(amp->am_prefix, prefix, sizeof(amp->am_prefix)); + sx_init(&->am_lock, "autofslk"); + amp->am_last_fileno = 1; + + vfs_getnewfsid(mp); + + AUTOFS_LOCK(amp); + error = autofs_node_new(NULL, amp, ".", -1, &->am_root); + if (error != 0) { + AUTOFS_UNLOCK(amp); + free(amp, M_AUTOFS); + return (error); + } + AUTOFS_UNLOCK(amp); + + vfs_mountedfrom(mp, from); + + return (0); +} + +static int +autofs_unmount(struct mount *mp, int mntflags) +{ + struct autofs_mount *amp; + struct autofs_node *anp; + struct autofs_request *ar; + int error, flags; + bool found; + + amp = VFSTOAUTOFS(mp); + + flags = 0; + if (mntflags & MNT_FORCE) + flags |= FORCECLOSE; + error = vflush(mp, 0, flags, curthread); + if (error != 0) { + AUTOFS_WARN("vflush failed with error %d", error); + return (error); + } + + /* + * All vnodes are gone, and new one will not appear - so, + * no new triggerings. We can iterate over outstanding + * autofs_requests and terminate them. + */ + for (;;) { + found = false; + sx_xlock(&sc->sc_lock); + TAILQ_FOREACH(ar, &sc->sc_requests, ar_next) { + if (ar->ar_mount != amp) + continue; + ar->ar_error = ENXIO; + ar->ar_done = true; + ar->ar_in_progress = false; + found = true; + } + sx_xunlock(&sc->sc_lock); + if (found == false) + break; + + cv_broadcast(&sc->sc_cv); + pause("autofs_umount", 1); + } + + AUTOFS_LOCK(amp); + + /* + * Not terribly efficient, but at least not recursive. + */ + while (!TAILQ_EMPTY(&->am_root->an_children)) { + anp = TAILQ_FIRST(&->am_root->an_children); + while (!TAILQ_EMPTY(&anp->an_children)) + anp = TAILQ_FIRST(&anp->an_children); + autofs_node_delete(anp); + } + autofs_node_delete(amp->am_root); + + mp->mnt_data = NULL; + AUTOFS_UNLOCK(amp); + + sx_destroy(&->am_lock); + + free(amp, M_AUTOFS); + + return (0); +} + +static int +autofs_root(struct mount *mp, int flags, struct vnode **vpp) +{ + struct autofs_mount *amp; + int error; + + amp = VFSTOAUTOFS(mp); + + error = autofs_node_vn(amp->am_root, mp, vpp); + + return (error); +} + +static int +autofs_statfs(struct mount *mp, struct statfs *sbp) +{ + + sbp->f_bsize = 512; + sbp->f_iosize = 0; + sbp->f_blocks = 0; + sbp->f_bfree = 0; + sbp->f_bavail = 0; + sbp->f_files = 0; + sbp->f_ffree = 0; + + return (0); +} + +static struct vfsops autofs_vfsops = { + .vfs_fhtovp = NULL, /* XXX */ + .vfs_mount = autofs_mount, + .vfs_unmount = autofs_unmount, + .vfs_root = autofs_root, + .vfs_statfs = autofs_statfs, + .vfs_init = autofs_init, + .vfs_uninit = autofs_uninit, +}; + +VFS_SET(autofs_vfsops, autofs, VFCF_SYNTHETIC | VFCF_NETWORK); +MODULE_VERSION(autofs, 1); diff --git a/sys/fs/autofs/autofs_vnops.c b/sys/fs/autofs/autofs_vnops.c new file mode 100644 index 000000000000..7623145e63c5 --- /dev/null +++ b/sys/fs/autofs/autofs_vnops.c @@ -0,0 +1,646 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "autofs.h" + +static int autofs_trigger_vn(struct vnode *vp, const char *path, + int pathlen, struct vnode **newvp); + +static int +autofs_access(struct vop_access_args *ap) +{ + + /* + * Nothing to do here; the only kind of access control + * needed is in autofs_mkdir(). + */ + + return (0); +} + +static int +autofs_getattr(struct vop_getattr_args *ap) +{ + struct vnode *vp, *newvp; + struct autofs_node *anp; + struct mount *mp; + struct vattr *vap; + int error; + + vp = ap->a_vp; + anp = vp->v_data; + mp = vp->v_mount; + vap = ap->a_vap; + + KASSERT(ap->a_vp->v_type == VDIR, ("!VDIR")); + + /* + * The reason we must do this is that some tree-walking software, + * namely fts(3), assumes that stat(".") results will not change + * between chdir("subdir") and chdir(".."), and fails with ENOENT + * otherwise. + */ + if (autofs_mount_on_stat && autofs_cached(anp, NULL, 0) == false && + autofs_ignore_thread(curthread) == false) { + error = autofs_trigger_vn(vp, "", 0, &newvp); + if (error != 0) + return (error); + + if (newvp != NULL) { + error = VOP_GETATTR(newvp, ap->a_vap, + ap->a_cred); + vput(newvp); + return (error); + } + } + + vap->va_type = VDIR; + vap->va_mode = 0755; + vap->va_nlink = 3; /* XXX */ + vap->va_uid = 0; + vap->va_gid = 0; + vap->va_rdev = NODEV; + vap->va_fsid = mp->mnt_stat.f_fsid.val[0]; + vap->va_fileid = anp->an_fileno; + vap->va_size = 512; /* XXX */ + vap->va_blocksize = 512; + vap->va_mtime = anp->an_ctime; + vap->va_atime = anp->an_ctime; + vap->va_ctime = anp->an_ctime; + vap->va_birthtime = anp->an_ctime; + vap->va_gen = 0; + vap->va_flags = 0; + vap->va_rdev = 0; + vap->va_bytes = 512; /* XXX */ + vap->va_filerev = 0; + vap->va_spare = 0; + + return (0); +} + +/* + * Unlock the vnode, request automountd(8) action, and then lock it back. + * If anything got mounted on top of the vnode, return the new filesystem's + * root vnode in 'newvp', locked. + */ +static int +autofs_trigger_vn(struct vnode *vp, const char *path, int pathlen, + struct vnode **newvp) +{ + struct autofs_node *anp; + struct autofs_mount *amp; + struct autofs_softc *sc; + int error, lock_flags; + + anp = vp->v_data; + amp = VFSTOAUTOFS(vp->v_mount); + sc = amp->am_softc; + + /* + * Release the vnode lock, so that other operations, in partcular + * mounting a filesystem on top of it, can proceed. Increase use + * count, to prevent the vnode from being deallocated and to prevent + * filesystem from being unmounted. + */ + lock_flags = VOP_ISLOCKED(vp); + vref(vp); + VOP_UNLOCK(vp, 0); + + sx_xlock(&sc->sc_lock); + + /* + * XXX: Workaround for mounting the same thing multiple times; revisit. + */ + if (vp->v_mountedhere != NULL) { + error = 0; + goto mounted; + } + + error = autofs_trigger(anp, path, pathlen); +mounted: + sx_xunlock(&sc->sc_lock); + vn_lock(vp, lock_flags | LK_RETRY); + vunref(vp); + if ((vp->v_iflag & VI_DOOMED) != 0) { + AUTOFS_DEBUG("VI_DOOMED"); + return (ENOENT); + } + + if (error != 0) + return (error); + + if (vp->v_mountedhere == NULL) { + *newvp = NULL; + return (0); + } else { + /* + * If the operation that succeeded was mount, then mark + * the node as non-cached. Otherwise, if someone unmounts + * the filesystem before the cache times out, we will fail + * to trigger. + */ + anp->an_cached = false; + } + + error = VFS_ROOT(vp->v_mountedhere, lock_flags, newvp); + if (error != 0) { + AUTOFS_WARN("VFS_ROOT() failed with error %d", error); + return (error); + } + + return (0); +} + +static int +autofs_lookup(struct vop_lookup_args *ap) +{ + struct vnode *dvp, *newvp, **vpp; + struct mount *mp; + struct autofs_mount *amp; + struct autofs_node *anp, *child; + struct componentname *cnp; + int error, lock_flags; + + dvp = ap->a_dvp; + vpp = ap->a_vpp; + mp = dvp->v_mount; + amp = VFSTOAUTOFS(mp); + anp = dvp->v_data; + cnp = ap->a_cnp; + + if (cnp->cn_flags & ISDOTDOT) { + KASSERT(anp->an_parent != NULL, ("NULL parent")); + /* + * Note that in this case, dvp is the child vnode, and we are + * looking up the parent vnode - exactly reverse from normal + * operation. To preserve lock order, we unlock the child + * (dvp), obtain the lock on parent (*vpp) in autofs_node_vn(), + * then relock the child. We use vhold()/vdrop() to prevent + * dvp from being freed in the meantime. + */ + lock_flags = VOP_ISLOCKED(dvp); + vhold(dvp); + VOP_UNLOCK(dvp, 0); + error = autofs_node_vn(anp->an_parent, mp, vpp); + if (error != 0) { + AUTOFS_WARN("autofs_node_vn() failed with error %d", + error); + } + vn_lock(dvp, lock_flags | LK_RETRY); + vdrop(dvp); + + return (error); + } + + if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { + vref(dvp); + *vpp = dvp; + + return (0); + } + + if (autofs_cached(anp, cnp->cn_nameptr, cnp->cn_namelen) == false && + autofs_ignore_thread(cnp->cn_thread) == false) { + error = autofs_trigger_vn(dvp, + cnp->cn_nameptr, cnp->cn_namelen, &newvp); + if (error != 0) + return (error); + + if (newvp != NULL) { + error = VOP_LOOKUP(newvp, ap->a_vpp, ap->a_cnp); + + /* + * Instead of figuring out whether our vnode should + * be locked or not given the error and cnp flags, + * just "copy" the lock status from vnode returned + * by mounted filesystem's VOP_LOOKUP(). Get rid + * of that new vnode afterwards. + */ + lock_flags = VOP_ISLOCKED(newvp); + if (lock_flags == 0) { + VOP_UNLOCK(dvp, 0); + vrele(newvp); + } else { + vput(newvp); + } + return (error); + } + } + + if (cnp->cn_nameiop == RENAME) + return (EOPNOTSUPP); + + AUTOFS_LOCK(amp); + error = autofs_node_find(anp, cnp->cn_nameptr, cnp->cn_namelen, &child); + if (error != 0) { + if ((cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == CREATE) { + AUTOFS_UNLOCK(amp); + return (EJUSTRETURN); + } + + AUTOFS_UNLOCK(amp); + return (ENOENT); + } + + /* + * XXX: Dropping the node here is ok, because we never remove nodes. + */ + AUTOFS_UNLOCK(amp); + + error = autofs_node_vn(child, mp, vpp); + if (error != 0) { + if ((cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == CREATE) + return (EJUSTRETURN); + + return (error); + } + + return (0); +} + +static int +autofs_mkdir(struct vop_mkdir_args *ap) +{ + struct vnode *vp; + struct autofs_node *anp; + struct autofs_mount *amp; + struct autofs_node *child; + int error; + + vp = ap->a_dvp; + anp = vp->v_data; + amp = VFSTOAUTOFS(vp->v_mount); + + /* + * Do not allow mkdir() if the calling thread is not + * automountd(8) descendant. + */ + if (autofs_ignore_thread(curthread) == false) + return (EPERM); + + AUTOFS_LOCK(amp); + error = autofs_node_new(anp, amp, ap->a_cnp->cn_nameptr, + ap->a_cnp->cn_namelen, &child); + if (error != 0) { + AUTOFS_UNLOCK(amp); + return (error); + } + AUTOFS_UNLOCK(amp); + + error = autofs_node_vn(child, vp->v_mount, ap->a_vpp); + + return (error); +} + +static int +autofs_readdir_one(struct uio *uio, const char *name, int fileno) +{ + struct dirent dirent; + int error, i; + + memset(&dirent, 0, sizeof(dirent)); + dirent.d_type = DT_DIR; + dirent.d_reclen = AUTOFS_DELEN; + dirent.d_fileno = fileno; + /* PFS_DELEN was picked to fit PFS_NAMLEN */ + for (i = 0; i < AUTOFS_NAMELEN - 1 && name[i] != '\0'; ++i) + dirent.d_name[i] = name[i]; + dirent.d_name[i] = 0; + dirent.d_namlen = i; + + error = uiomove(&dirent, AUTOFS_DELEN, uio); + return (error); +} + +static int +autofs_readdir(struct vop_readdir_args *ap) +{ + struct vnode *vp, *newvp; + struct autofs_mount *amp; + struct autofs_node *anp, *child; + struct uio *uio; + off_t offset; + int error, i, resid; + + vp = ap->a_vp; + amp = VFSTOAUTOFS(vp->v_mount); + anp = vp->v_data; + uio = ap->a_uio; + + KASSERT(vp->v_type == VDIR, ("!VDIR")); + + if (autofs_cached(anp, NULL, 0) == false && + autofs_ignore_thread(curthread) == false) { + error = autofs_trigger_vn(vp, "", 0, &newvp); + if (error != 0) + return (error); + + if (newvp != NULL) { + error = VOP_READDIR(newvp, ap->a_uio, ap->a_cred, + ap->a_eofflag, ap->a_ncookies, ap->a_cookies); + vput(newvp); + return (error); + } + } + + /* only allow reading entire entries */ + offset = uio->uio_offset; + resid = uio->uio_resid; + if (offset < 0 || offset % AUTOFS_DELEN != 0 || + (resid && resid < AUTOFS_DELEN)) + return (EINVAL); + if (resid == 0) + return (0); + + if (ap->a_eofflag != NULL) + *ap->a_eofflag = TRUE; + + if (offset == 0 && resid >= AUTOFS_DELEN) { + error = autofs_readdir_one(uio, ".", anp->an_fileno); + if (error != 0) + return (error); + offset += AUTOFS_DELEN; + resid -= AUTOFS_DELEN; + } + + if (offset == AUTOFS_DELEN && resid >= AUTOFS_DELEN) { + if (anp->an_parent == NULL) { + /* + * XXX: Right? + */ + error = autofs_readdir_one(uio, "..", anp->an_fileno); + } else { + error = autofs_readdir_one(uio, "..", + anp->an_parent->an_fileno); + } + if (error != 0) + return (error); + offset += AUTOFS_DELEN; + resid -= AUTOFS_DELEN; + } + + i = 2; /* Account for "." and "..". */ + AUTOFS_LOCK(amp); + TAILQ_FOREACH(child, &anp->an_children, an_next) { + if (resid < AUTOFS_DELEN) { + if (ap->a_eofflag != NULL) + *ap->a_eofflag = 0; + break; + } + + /* + * Skip entries returned by previous call to getdents(). + */ + i++; + if (i * AUTOFS_DELEN <= offset) + continue; + + error = autofs_readdir_one(uio, child->an_name, + child->an_fileno); + if (error != 0) { + AUTOFS_UNLOCK(amp); + return (error); + } + offset += AUTOFS_DELEN; + resid -= AUTOFS_DELEN; + } + + AUTOFS_UNLOCK(amp); + return (0); +} + +static int +autofs_reclaim(struct vop_reclaim_args *ap) +{ + struct vnode *vp = ap->a_vp; + struct autofs_node *anp = vp->v_data; + + vp = ap->a_vp; + anp = vp->v_data; + + /* + * We do not free autofs_node here; instead we are + * destroying them in autofs_node_delete(). + */ + sx_xlock(&anp->an_vnode_lock); + anp->an_vnode = NULL; + vp->v_data = NULL; + sx_xunlock(&anp->an_vnode_lock); + + return (0); +} + +struct vop_vector autofs_vnodeops = { + .vop_default = &default_vnodeops, + + .vop_access = autofs_access, + .vop_lookup = autofs_lookup, + .vop_create = VOP_EOPNOTSUPP, + .vop_getattr = autofs_getattr, + .vop_link = VOP_EOPNOTSUPP, + .vop_mkdir = autofs_mkdir, + .vop_mknod = VOP_EOPNOTSUPP, + .vop_read = VOP_EOPNOTSUPP, + .vop_readdir = autofs_readdir, + .vop_remove = VOP_EOPNOTSUPP, + .vop_rename = VOP_EOPNOTSUPP, + .vop_rmdir = VOP_EOPNOTSUPP, + .vop_setattr = VOP_EOPNOTSUPP, + .vop_symlink = VOP_EOPNOTSUPP, + .vop_write = VOP_EOPNOTSUPP, + .vop_reclaim = autofs_reclaim, +}; + +int +autofs_node_new(struct autofs_node *parent, struct autofs_mount *amp, + const char *name, int namelen, struct autofs_node **anpp) +{ + struct autofs_node *anp; + + if (parent != NULL) + AUTOFS_ASSERT_LOCKED(parent->an_mount); + + anp = uma_zalloc(autofs_node_zone, M_WAITOK | M_ZERO); + if (namelen >= 0) + anp->an_name = strndup(name, namelen, M_AUTOFS); + else + anp->an_name = strdup(name, M_AUTOFS); + anp->an_fileno = atomic_fetchadd_int(&->am_last_fileno, 1); + callout_init(&anp->an_callout, 1); + /* + * The reason for SX_NOWITNESS here is that witness(4) + * cannot tell vnodes apart, so the following perfectly + * valid lock order... + * + * vnode lock A -> autofsvlk B -> vnode lock B + * + * ... gets reported as a LOR. + */ + sx_init_flags(&anp->an_vnode_lock, "autofsvlk", SX_NOWITNESS); + getnanotime(&anp->an_ctime); + anp->an_parent = parent; + anp->an_mount = amp; + if (parent != NULL) + TAILQ_INSERT_TAIL(&parent->an_children, anp, an_next); + TAILQ_INIT(&anp->an_children); + + *anpp = anp; + return (0); +} + +int +autofs_node_find(struct autofs_node *parent, const char *name, + int namelen, struct autofs_node **anpp) +{ + struct autofs_node *anp; + + AUTOFS_ASSERT_LOCKED(parent->an_mount); + + TAILQ_FOREACH(anp, &parent->an_children, an_next) { + if (namelen >= 0) { + if (strncmp(anp->an_name, name, namelen) != 0) + continue; + } else { + if (strcmp(anp->an_name, name) != 0) + continue; + } + + if (anpp != NULL) + *anpp = anp; + return (0); + } + + return (ENOENT); +} + +void +autofs_node_delete(struct autofs_node *anp) +{ + struct autofs_node *parent; + + AUTOFS_ASSERT_LOCKED(anp->an_mount); + KASSERT(TAILQ_EMPTY(&anp->an_children), ("have children")); + + callout_drain(&anp->an_callout); + + parent = anp->an_parent; + if (parent != NULL) + TAILQ_REMOVE(&parent->an_children, anp, an_next); + sx_destroy(&anp->an_vnode_lock); + free(anp->an_name, M_AUTOFS); + uma_zfree(autofs_node_zone, anp); +} + +int +autofs_node_vn(struct autofs_node *anp, struct mount *mp, struct vnode **vpp) +{ + struct vnode *vp; + int error; + + AUTOFS_ASSERT_UNLOCKED(anp->an_mount); + + sx_xlock(&anp->an_vnode_lock); + + vp = anp->an_vnode; + if (vp != NULL) { + error = vget(vp, LK_EXCLUSIVE | LK_RETRY, curthread); + if (error != 0) { + AUTOFS_WARN("vget failed with error %d", error); + sx_xunlock(&anp->an_vnode_lock); + return (error); + } + if (vp->v_iflag & VI_DOOMED) { + /* + * We got forcibly unmounted. + */ + AUTOFS_DEBUG("doomed vnode"); + sx_xunlock(&anp->an_vnode_lock); + vput(vp); + + return (ENOENT); + } + + *vpp = vp; + sx_xunlock(&anp->an_vnode_lock); + return (0); + } + + error = getnewvnode("autofs", mp, &autofs_vnodeops, &vp); + if (error != 0) { + sx_xunlock(&anp->an_vnode_lock); + return (error); + } + + error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (error != 0) { + sx_xunlock(&anp->an_vnode_lock); + vdrop(vp); + return (error); + } + + vp->v_type = VDIR; + if (anp->an_parent == NULL) + vp->v_vflag |= VV_ROOT; + vp->v_data = anp; + + error = insmntque(vp, mp); + if (error != 0) { + AUTOFS_WARN("insmntque() failed with error %d", error); + sx_xunlock(&anp->an_vnode_lock); + return (error); + } + + KASSERT(anp->an_vnode == NULL, ("lost race")); + anp->an_vnode = vp; + + sx_xunlock(&anp->an_vnode_lock); + + *vpp = vp; + return (0); +} diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 674e52674879..c407699d2ca7 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -649,6 +649,10 @@ vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions) fsflags |= MNT_SYNCHRONOUS; else if (strcmp(opt->name, "union") == 0) fsflags |= MNT_UNION; + else if (strcmp(opt->name, "automounted") == 0) { + fsflags |= MNT_AUTOMOUNTED; + vfs_freeopt(optlist, opt); + } } /* diff --git a/sys/libkern/strndup.c b/sys/libkern/strndup.c new file mode 100644 index 000000000000..43983d5ba062 --- /dev/null +++ b/sys/libkern/strndup.c @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2003 Networks Associates Technology, Inc. + * All rights reserved. + * + * This software was developed for the FreeBSD Project by Network + * Associates Laboratories, the Security Research Division of Network + * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 + * ("CBOSS"), as part of the DARPA CHATS research program. + * + * 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 AUTHOR 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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +char * +strndup(const char *string, size_t maxlen, struct malloc_type *type) +{ + size_t len; + char *copy; + + len = strnlen(string, maxlen) + 1; + copy = malloc(len, type, M_WAITOK); + bcopy(string, copy, len); + copy[len - 1] = '\0'; + return (copy); +} diff --git a/sys/modules/Makefile b/sys/modules/Makefile index d22e95229cde..a66a4b119ea9 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -48,6 +48,7 @@ SUBDIR= \ ata \ ath \ ath_pci \ + autofs \ ${_auxio} \ ${_bce} \ bfe \ diff --git a/sys/modules/autofs/Makefile b/sys/modules/autofs/Makefile new file mode 100644 index 000000000000..5aaa8927267b --- /dev/null +++ b/sys/modules/autofs/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../fs/autofs + +KMOD= autofs +SRCS= vnode_if.h \ + autofs.c \ + autofs_vnops.c \ + autofs_vfsops.c + +.include diff --git a/sys/sys/libkern.h b/sys/sys/libkern.h index 3665b3a59946..5f850fb2da85 100644 --- a/sys/sys/libkern.h +++ b/sys/sys/libkern.h @@ -117,6 +117,7 @@ int strcmp(const char *, const char *); char *strcpy(char * __restrict, const char * __restrict); size_t strcspn(const char * __restrict, const char * __restrict) __pure; char *strdup(const char *__restrict, struct malloc_type *); +char *strndup(const char *__restrict, size_t, struct malloc_type *); size_t strlcat(char *, const char *, size_t); size_t strlcpy(char *, const char *, size_t); size_t strlen(const char *); diff --git a/sys/sys/mount.h b/sys/sys/mount.h index ca3bc436a3d2..d18659990338 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -260,6 +260,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *); #define MNT_NOCLUSTERR 0x0000000040000000ULL /* disable cluster read */ #define MNT_NOCLUSTERW 0x0000000080000000ULL /* disable cluster write */ #define MNT_SUJ 0x0000000100000000ULL /* using journaled soft updates */ +#define MNT_AUTOMOUNTED 0x0000000200000000ULL /* mounted by automountd(8) */ /* * NFS export related mount flags. @@ -296,7 +297,7 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *); MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \ MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \ MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \ - MNT_NFS4ACLS) + MNT_NFS4ACLS | MNT_AUTOMOUNTED) /* Mask of flags that can be updated. */ #define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \ @@ -304,7 +305,8 @@ void __mnt_vnode_markerfree_active(struct vnode **mvp, struct mount *); MNT_NOATIME | \ MNT_NOSYMFOLLOW | MNT_IGNORE | \ MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | \ - MNT_ACLS | MNT_USER | MNT_NFS4ACLS) + MNT_ACLS | MNT_USER | MNT_NFS4ACLS | \ + MNT_AUTOMOUNTED) /* * External filesystem command modifier flags. diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index fa0c9951440d..f4c51d2e7a60 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -5,6 +5,7 @@ SUBDIR= adduser \ arp \ + autofs \ binmiscctl \ bootparamd \ bsdconfig \ diff --git a/usr.sbin/autofs/Makefile b/usr.sbin/autofs/Makefile new file mode 100644 index 000000000000..fab6865a8906 --- /dev/null +++ b/usr.sbin/autofs/Makefile @@ -0,0 +1,33 @@ +# $FreeBSD$ + +PROG= automountd +SRCS= automount.c +SRCS+= automountd.c +SRCS+= autounmountd.c +SRCS+= common.c +SRCS+= defined.c +SRCS+= getmntopts.c +SRCS+= log.c +SRCS+= popen.c +SRCS+= token.l + +CFLAGS+=-I${.CURDIR} +CFLAGS+=-I${.CURDIR}/../../sys/fs/autofs + +MAN= automount.8 automountd.8 autounmountd.8 auto_master.5 + +DPADD= ${LIBUTIL} +LDADD= -lutil + +# Needed for getmntopts.c +MOUNT= ${.CURDIR}/../../sbin/mount +CFLAGS+=-I${MOUNT} + +WARNS= 6 + +LINKS= ${BINDIR}/automountd ${BINDIR}/automount +LINKS+= ${BINDIR}/automountd ${BINDIR}/autounmountd + +.PATH: ${MOUNT} + +.include diff --git a/usr.sbin/autofs/auto_master.5 b/usr.sbin/autofs/auto_master.5 new file mode 100644 index 000000000000..f923f4f76827 --- /dev/null +++ b/usr.sbin/autofs/auto_master.5 @@ -0,0 +1,272 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd July 31, 2014 +.Dt AUTO_MASTER 5 +.Os +.Sh NAME +.Nm auto_master +.Nd auto_master and map file format +.Sh DESCRIPTION +The +.Nm +configuration file is used by the +.Xr automount 8 +command. +Map files are read by the +.Xr automountd 8 +daemon. +.Sh AUTO_MASTER SYNTAX +The +.Nm +file consists of lines with two or three entries separated by whitespace +and terminated by newline character: +.Bd -literal -offset indent +.Pa mountpoint Pa map_name Op Ar -options +.Ed +.Pp +.Pa mountpoint +is either a fully specified path, or +.Li /- . +When +.Pa mountpoint +is a full path, +.Pa map_name +must reference an indirect map. +Otherwise, +.Pa map_name +must reference a direct map. +See +.Sx "MAP SYNTAX" below. +.Pp +.Pa map_name +specifies map to use. +If +.Pa map_name +begins with +.Li - , +it specifies a special map. +See +.Sx "MAP SYNTAX" +below. +If +.Pa map_name +is not a fully specified path +.Pq it does not start with Li / , +.Xr automountd 8 +will search for that name in +.Li /etc . +Otherwise it will use the path as given. +If the file indicated by +.Pa map_name +is executable, +.Xr automountd 8 +will assume it is an executable map. +See +.Sx "MAP SYNTAX" +below. +Otherwise, the file is opened and the contents parsed. +.Pp +.Pa -options +is an optional field that starts with +.Li - +and can contain generic filesystem mount options. +.Pp +The following example specifies that the /etc/auto_example indirect map +will be mounted on /example. +.Bd -literal -offset indent +/example auto_example +.Ed +.Sh MAP SYNTAX +Map files consist of lines with a number of entries separated by whitespace +and terminated by newline character: +.Bd -literal -offset indent +.Pa key Oo Ar -options Oc Oo Ar mountpoint Oo -options Oc Oc Ar location Op ... +.Ed +.Pp +In most cases, it can be simplified to: +.Bd -literal -offset indent +.Pa key Oo Ar -options Oc Ar location +.Ed +.Pp +.Pa key +is the path component used by +.Xr automountd 8 +to find the right map entry to use. +It is also used to form the final mountpoint. +.Pp +The +.Ar options +field, if present, must begin with +.Li - . +When mounting the filesystem, options supplied to +.Nm +and options specified in the map entry are concatenated together. +The special option +.Li fstype +is used to specify filesystem type. +It is not passed to the mount program as an option. +Instead, it is passed as argument to +.Cm "mount -t". +.Pp +The optional +.Pa mountpoint +field is used to specify multiple mount points +for a single key. +.Pp +The +.Ar location +field specifies the filesystem to be mounted. +To pass location that begins with +.Li / , +prefix it with colon. +For example, +.Li :/dev/cd0 . +.Pp +This example, when used with the +.Nm +example above, specifies that the NFS share +.Li 192.168.1.1:/share/example/x +will be mounted on +.Pa /example/x/ +when any process attempts to access that mountpoint, with +.Li intr +and +.Li nfsv4 +mount options: +.Bd -literal -offset indent +.Li x -intr,nfsv4 192.168.1.1:/share/example/x +.Ed +.Pp +Automatically mount the CD drive on access: +.Bd -literal -offset indent +.Li cd -intr,fstype=cd9660 :/dev/cd0 +.Ed +.Sh SPECIAL MAPS +Special maps have names beginning with +.Li - . +Supported special maps are: +.Pp +.Bl -tag -width "-hosts" -compact +.It Li -hosts +This map queries the remote NFS server and maps exported volumes. +It is traditionally mounted on +.Pa /net . +It enables access to files on a remote NFS server by accessing +.Pa /net/nfs-server-ip/share-name/ +directory, without the need for any further configuration. +.It Li -null +This map prevents the +.Xr automountd 8 +from mounting anything on the mountpoint. +.El +.Sh EXECUTABLE MAPS +If the map file specified in +.Nm +has execute bit set, the +.Xr automountd 8 +will execute it and parse the standard output instead of parsing +the file contents. +.Sh INDIRECT VERSUS DIRECT MAPS +Indirect maps are referred to in +.Nm +by entries with a fully qualified path as a mount point, and must contain only +relative paths as keys. +Direct maps are referred to in +.Nm +by entries with +.Li /- +as the mountpoint, and must contain only fully qualified paths as keys. +For indirect maps, the final mount point is determined by concatenating the +.Nm +mountpoint with the map entry key and optional map entry mountpoint. +For direct maps, the final mount point is determined by concatenating +the map entry key with the optional map entry mountpoint. +.Pp +The example above could be rewritten using direct map, by placing this in +.Nm : +.Bd -literal -offset indent +.Li /- auto_example +.Ed +.Pp +and this in +.Li /etc/auto_example +map file: +.Bd -literal -offset indent +.Li /example/x -intr,nfsv4 192.168.1.1:/share/example/x +.Li /example/cd -intr,fstype=cd9660 :/dev/cd0 +.Ed +.Sh DIRECTORY SERVICES +Both +.Nm +and maps may contain entries consisting of a plus sign and map name: +.Bd -literal -offset indent +.Li +auto_master +.Ed +.Pp +Those entries cause +.Xr automountd 8 +daemon to retrieve the named map from directory services (like LDAP) +and include it where the entry was. +.Pp +If the file containing the map referenced in +.Nm +is not found, the map will be retrieved from directory services instead. +.Pp +To retrieve entries from directory services, +.Xr automountd 8 +daemon runs +.Pa /etc/autofs/include , +which is usually a shell script, with map name as the only command line +parameter. +The script should output entries formatted according to +.Nm +or automounter map syntax to standard output. +An example script to use LDAP is included in +.Pa /etc/autofs/include_ldap . +It can be symlinked to +.Pa /etc/autofs/include . +.Sh FILES +.Bl -tag -width ".Pa /etc/auto_master" -compact +.It Pa /etc/auto_master +The default location of the +.Pa auto_master +file. +.El +.Sh SEE ALSO +.Xr autofs 5 , +.Xr automount 8 , +.Xr automountd 8 , +.Xr autounmountd 8 +.Sh AUTHORS +The +.Nm +configuration file functionality was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/usr.sbin/autofs/automount.8 b/usr.sbin/autofs/automount.8 new file mode 100644 index 000000000000..2988c68069db --- /dev/null +++ b/usr.sbin/autofs/automount.8 @@ -0,0 +1,107 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd April 20, 2014 +.Dt AUTOMOUNT 8 +.Os +.Sh NAME +.Nm automount +.Nd update autofs mounts +.Sh SYNOPSIS +.Nm +.Op Fl D Ar name=value +.Op Fl L +.Op Fl f +.Op Fl o Ar options +.Op Fl v +.Op Fl u +.Sh DESCRIPTION +When called without options, the +.Nm +command parses the +.Xr auto_master 5 +configuration file and any direct maps that it references, and mounts +or unmounts +.Xr autofs 4 +filesystems to match. +These options are available: +.Bl -tag -width ".Fl v" +.It Fl D +Define a variable. +It is only useful with +.Fl L . +.It Fl L +Do not mount or unmount anything. +Instead parse +.Xr auto_master 5 +and any direct maps, then print them to standard output. +When specified more than once, all the maps, including indirect ones, +will be parsed and shown. +This is useful when debugging configuration problems. +.It Fl f +Force unmount, to be used with +.Fl u . +.It Fl o +Specify mount options to be used along with the ones specified in the maps. +It is only useful with +.Fl L . +.It Fl u +Try to unmount filesystems mounted by +.Xr automountd 8 . +.Xr autofs 5 +mounts are not unmounted. +To unmount all +.Xr autofs +mounts, use +.Cm "umount -At autofs". +.It Fl v +Increase verbosity. +.El +.Sh EXIT STATUS +.Ex -std +.Sh EXAMPLES +Unmount all filesystems mounted by +.Xr automountd 8 : +.Dl Nm Fl u +.Sh SEE ALSO +.Xr auto_master 5 , +.Xr autofs 5 , +.Xr automountd 8 , +.Xr autounmountd 8 +.Sh HISTORY +The +.Nm +command appeared in +.Fx 10.1 . +.Sh AUTHORS +The +.Nm +was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/usr.sbin/autofs/automount.c b/usr.sbin/autofs/automount.c new file mode 100644 index 000000000000..ef784a69ae61 --- /dev/null +++ b/usr.sbin/autofs/automount.c @@ -0,0 +1,345 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" +#include "mntopts.h" + +static int +unmount_by_statfs(const struct statfs *sb, bool force) +{ + char *fsid_str; + int error, ret, flags; + + ret = asprintf(&fsid_str, "FSID:%d:%d", + sb->f_fsid.val[0], sb->f_fsid.val[1]); + if (ret < 0) + log_err(1, "asprintf"); + + log_debugx("unmounting %s using %s", sb->f_mntonname, fsid_str); + + flags = MNT_BYFSID; + if (force) + flags |= MNT_FORCE; + error = unmount(fsid_str, flags); + free(fsid_str); + if (error != 0) + log_warn("cannot unmount %s", sb->f_mntonname); + + return (error); +} + +static const struct statfs * +find_statfs(const struct statfs *mntbuf, int nitems, const char *mountpoint) +{ + int i; + + for (i = 0; i < nitems; i++) { + if (strcmp(mntbuf[i].f_mntonname, mountpoint) == 0) + return (mntbuf + i); + } + + return (NULL); +} + +static void +mount_autofs(const char *from, const char *fspath, const char *options, + const char *prefix) +{ + struct iovec *iov = NULL; + char errmsg[255]; + int error, iovlen = 0; + + create_directory(fspath); + + log_debugx("mounting %s on %s, prefix \"%s\", options \"%s\"", + from, fspath, prefix, options); + memset(errmsg, 0, sizeof(errmsg)); + + build_iovec(&iov, &iovlen, "fstype", + __DECONST(void *, "autofs"), (size_t)-1); + build_iovec(&iov, &iovlen, "fspath", + __DECONST(void *, fspath), (size_t)-1); + build_iovec(&iov, &iovlen, "from", + __DECONST(void *, from), (size_t)-1); + build_iovec(&iov, &iovlen, "errmsg", + errmsg, sizeof(errmsg)); + + /* + * Append the options and mountpoint defined in auto_master(5); + * this way automountd(8) does not need to parse it. + */ + build_iovec(&iov, &iovlen, "master_options", + __DECONST(void *, options), (size_t)-1); + build_iovec(&iov, &iovlen, "master_prefix", + __DECONST(void *, prefix), (size_t)-1); + + error = nmount(iov, iovlen, 0); + if (error != 0) { + if (*errmsg != '\0') { + log_err(1, "cannot mount %s on %s: %s", + from, fspath, errmsg); + } else { + log_err(1, "cannot mount %s on %s", from, fspath); + } + } +} + +static void +mount_if_not_already(const struct node *n, const char *map, + const struct statfs *mntbuf, int nitems) +{ + const struct statfs *sb; + char *mountpoint; + char *from; + int ret; + + ret = asprintf(&from, "map %s", map); + if (ret < 0) + log_err(1, "asprintf"); + + mountpoint = node_path(n); + sb = find_statfs(mntbuf, nitems, mountpoint); + if (sb != NULL) { + if (strcmp(sb->f_fstypename, "autofs") != 0) { + log_debugx("unknown filesystem mounted " + "on %s; mounting", mountpoint); + /* + * XXX: Compare options and 'from', + * and update the mount if necessary. + */ + } else { + log_debugx("autofs already mounted " + "on %s", mountpoint); + free(from); + free(mountpoint); + return; + } + } else { + log_debugx("nothing mounted on %s; mounting", + mountpoint); + } + + mount_autofs(from, mountpoint, n->n_options, n->n_key); + free(from); + free(mountpoint); +} + +static void +mount_unmount(struct node *root) +{ + struct statfs *mntbuf; + struct node *n, *n2, *n3; + int i, nitems; + + nitems = getmntinfo(&mntbuf, MNT_WAIT); + if (nitems <= 0) + log_err(1, "getmntinfo"); + + log_debugx("unmounting stale autofs mounts"); + + for (i = 0; i < nitems; i++) { + if (strcmp(mntbuf[i].f_fstypename, "autofs") != 0) { + log_debugx("skipping %s, filesystem type is not autofs", + mntbuf[i].f_mntonname); + continue; + } + + n = node_find(root, mntbuf[i].f_mntonname); + if (n != NULL) { + log_debugx("leaving autofs mounted on %s", + mntbuf[i].f_mntonname); + continue; + } + + log_debugx("autofs mounted on %s not found " + "in new configuration; unmounting", mntbuf[i].f_mntonname); + unmount_by_statfs(&(mntbuf[i]), false); + } + + log_debugx("mounting new autofs mounts"); + + TAILQ_FOREACH(n, &root->n_children, n_next) { + if (!node_is_direct_map(n)) { + mount_if_not_already(n, n->n_map, mntbuf, nitems); + continue; + } + + TAILQ_FOREACH(n2, &n->n_children, n_next) { + TAILQ_FOREACH(n3, &n2->n_children, n_next) { + mount_if_not_already(n3, n->n_map, + mntbuf, nitems); + } + } + } +} + +static void +unmount_automounted(bool force) +{ + struct statfs *mntbuf; + int i, nitems; + + nitems = getmntinfo(&mntbuf, MNT_WAIT); + if (nitems <= 0) + log_err(1, "getmntinfo"); + + log_debugx("unmounting automounted filesystems"); + + for (i = 0; i < nitems; i++) { + if (strcmp(mntbuf[i].f_fstypename, "autofs") == 0) { + log_debugx("skipping %s, filesystem type is autofs", + mntbuf[i].f_mntonname); + continue; + } + + if ((mntbuf[i].f_flags & MNT_AUTOMOUNTED) == 0) { + log_debugx("skipping %s, not automounted", + mntbuf[i].f_mntonname); + continue; + } + + unmount_by_statfs(&(mntbuf[i]), force); + } +} + +static void +usage_automount(void) +{ + + fprintf(stderr, "usage: automount [-D name=value][-o opts][-Lfuv]\n"); + exit(1); +} + +int +main_automount(int argc, char **argv) +{ + struct node *root; + int ch, debug = 0, show_maps = 0; + char *options = NULL; + bool do_unmount = false, force_unmount = false; + + /* + * Note that in automount(8), the only purpose of variable + * handling is to aid in debugging maps (automount -L). + */ + defined_init(); + + while ((ch = getopt(argc, argv, "D:Lfo:uv")) != -1) { + switch (ch) { + case 'D': + defined_parse_and_add(optarg); + break; + case 'L': + show_maps++; + break; + case 'f': + force_unmount = true; + break; + case 'o': + if (options == NULL) { + options = checked_strdup(optarg); + } else { + options = + separated_concat(options, optarg, ','); + } + break; + case 'u': + do_unmount = true; + break; + case 'v': + debug++; + break; + case '?': + default: + usage_automount(); + } + } + argc -= optind; + if (argc != 0) + usage_automount(); + + if (force_unmount && !do_unmount) + usage_automount(); + + log_init(debug); + + if (do_unmount) { + unmount_automounted(force_unmount); + return (0); + } + + root = node_new_root(); + parse_master(root, AUTO_MASTER_PATH); + + if (show_maps) { + if (options != NULL) { + root->n_options = separated_concat(options, + root->n_options, ','); + } + if (show_maps > 1) { + node_expand_indirect_maps(root); + node_expand_ampersand(root, NULL); + } + node_expand_defined(root); + node_print(root); + return (0); + } + + mount_unmount(root); + + return (0); +} diff --git a/usr.sbin/autofs/automountd.8 b/usr.sbin/autofs/automountd.8 new file mode 100644 index 000000000000..31fc8f20c700 --- /dev/null +++ b/usr.sbin/autofs/automountd.8 @@ -0,0 +1,103 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd April 20, 2014 +.Dt AUTOMOUNTD 8 +.Os +.Sh NAME +.Nm automountd +.Nd daemon handling autofs mount requests +.Sh SYNOPSIS +.Nm +.Op Fl D Ar name=value +.Op Fl i +.Op Fl m Ar maxproc +.Op Fl o Ar options +.Op Fl d +.Op Fl v +.Sh DESCRIPTION +The +.Nm +daemon is responsible for handling +.Xr autofs 5 +mount requests, parsing maps, +and mounting filesystems they specify. +On startup, +.Nm +forks into background and waits for kernel requests. +When a request is received, +.Nm +forks a child process. +The child process parses the appropriate map and mounts filesystems accordingly. +Then it signals the kernel to release blocked processes that were waiting +for the mount. +.Bl -tag -width ".Fl v" +.It Fl D +Define a variable. +.It Fl i +For indirect mounts, only create subdirectories if there are no wildcard +entries. +Without +.Fl i , +.Nm +creates all the subdirectories it can. +Users may not realize that the wildcard map entry makes it possible to access +directories that have not yet been created. +.It Fl m Ar maxproc +Limit the number of forked +.Nm +processes, and thus the number of mount requests being handled in parallel. +The default is 30. +.It Fl d +Debug mode: increase verbosity and do not daemonize. +.It Fl o Ar options +Specify mount options. +Options specified here ill be overridden by options entered in maps or +.Xr auto_master 5 . +.It Fl v +Increase verbosity. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr auto_master 5 , +.Xr autofs 5 , +.Xr automount 8 , +.Xr autounmountd 8 +.Sh HISTORY +The +.Nm +daemon appeared in +.Fx 10.1 . +.Sh AUTHORS +The +.Nm +was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/usr.sbin/autofs/automountd.c b/usr.sbin/autofs/automountd.c new file mode 100644 index 000000000000..0c743a3b2226 --- /dev/null +++ b/usr.sbin/autofs/automountd.c @@ -0,0 +1,498 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "autofs_ioctl.h" + +#include "common.h" + +#define AUTOMOUNTD_PIDFILE "/var/run/automountd.pid" + +static int nchildren = 0; +static int autofs_fd; +static int request_id; + +static void +done(int request_error) +{ + struct autofs_daemon_done add; + int error; + + memset(&add, 0, sizeof(add)); + add.add_id = request_id; + add.add_error = request_error; + + log_debugx("completing request %d with error %d", + request_id, request_error); + + error = ioctl(autofs_fd, AUTOFSDONE, &add); + if (error != 0) { + /* + * Do this instead of log_err() to avoid calling + * done() again with error, from atexit handler. + */ + log_warn("AUTOFSDONE"); + } + quick_exit(1); +} + +/* + * Remove "fstype=whatever" from optionsp and return the "whatever" part. + */ +static char * +pick_option(const char *option, char **optionsp) +{ + char *tofree, *pair, *newoptions; + char *picked = NULL; + bool first = true; + + tofree = *optionsp; + + newoptions = calloc(strlen(*optionsp) + 1, 1); + if (newoptions == NULL) + log_err(1, "calloc"); + + while ((pair = strsep(optionsp, ",")) != NULL) { + /* + * XXX: strncasecmp(3) perhaps? + */ + if (strncmp(pair, option, strlen(option)) == 0) { + picked = checked_strdup(pair + strlen(option)); + } else { + if (first == false) + strcat(newoptions, ","); + else + first = false; + strcat(newoptions, pair); + } + } + + free(tofree); + *optionsp = newoptions; + + return (picked); +} + +static void +create_subtree(const struct node *node, bool incomplete) +{ + const struct node *child; + char *path; + bool wildcard_found = false; + + /* + * Skip wildcard nodes. + */ + if (strcmp(node->n_key, "*") == 0) + return; + + path = node_path(node); + log_debugx("creating subtree at %s", path); + create_directory(path); + + if (incomplete) { + TAILQ_FOREACH(child, &node->n_children, n_next) { + if (strcmp(child->n_key, "*") == 0) { + wildcard_found = true; + break; + } + } + + if (wildcard_found) { + log_debugx("node %s contains wildcard entry; " + "not creating its subdirectories due to -d flag", + path); + free(path); + return; + } + } + + free(path); + + TAILQ_FOREACH(child, &node->n_children, n_next) + create_subtree(child, incomplete); +} + +static void +exit_callback(void) +{ + + done(EIO); +} + +static void +handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, + bool incomplete_hierarchy) +{ + const char *map; + struct node *root, *parent, *node; + FILE *f; + char *options, *fstype, *retrycnt, *tmp; + int error; + + log_debugx("got request %d: from %s, path %s, prefix \"%s\", " + "key \"%s\", options \"%s\"", adr->adr_id, adr->adr_from, + adr->adr_path, adr->adr_prefix, adr->adr_key, adr->adr_options); + + /* + * Try to notify the kernel about any problems. + */ + request_id = adr->adr_id; + atexit(exit_callback); + + if (strncmp(adr->adr_from, "map ", 4) != 0) { + log_errx(1, "invalid mountfrom \"%s\"; failing request", + adr->adr_from); + } + + map = adr->adr_from + 4; /* 4 for strlen("map "); */ + root = node_new_root(); + if (adr->adr_prefix[0] == '\0' || strcmp(adr->adr_prefix, "/") == 0) { + parent = root; + } else { + parent = node_new_map(root, checked_strdup(adr->adr_prefix), + checked_strdup(adr->adr_options), checked_strdup(map), + checked_strdup("[kernel request]"), lineno); + } + parse_map(parent, map, adr->adr_key[0] != '\0' ? adr->adr_key : NULL); + if (adr->adr_key[0] != '\0') + node_expand_wildcard(root, adr->adr_key); + node = node_find(root, adr->adr_path); + if (node == NULL) { + log_errx(1, "map %s does not contain key for \"%s\"; " + "failing mount", map, adr->adr_path); + } + + if (node->n_location == NULL) { + log_debugx("found node defined at %s:%d; not a mountpoint", + node->n_config_file, node->n_config_line); + + /* + * Not a mountpoint; create directories in the autofs mount + * and complete the request. + */ + create_subtree(node, incomplete_hierarchy); + + if (incomplete_hierarchy && adr->adr_key[0] != '\0') { + /* + * We still need to create the single subdirectory + * user is trying to access. + */ + tmp = separated_concat(adr->adr_path, + adr->adr_key, '/'); + node = node_find(root, tmp); + if (node != NULL) + create_subtree(node, false); + } + done(0); + + log_debugx("nothing to mount; exiting"); + + /* + * Exit without calling exit_callback(). + */ + quick_exit(0); + } + + log_debugx("found node defined at %s:%d; it is a mountpoint", + node->n_config_file, node->n_config_line); + + node_expand_ampersand(node, + adr->adr_key[0] != '\0' ? adr->adr_key : NULL); + error = node_expand_defined(node); + if (error != 0) { + log_errx(1, "variable expansion failed for %s; " + "failing mount", adr->adr_path); + } + + options = node_options(node); + + /* + * Prepend options passed via automountd(8) command line. + */ + if (cmdline_options != NULL) + options = separated_concat(cmdline_options, options, ','); + + /* + * Append "automounted". + */ + options = separated_concat(options, "automounted", ','); + + /* + * Figure out fstype. + */ + fstype = pick_option("fstype=", &options); + if (fstype == NULL) { + log_debugx("fstype not specified in options; " + "defaulting to \"nfs\""); + fstype = checked_strdup("nfs"); + } + + if (strcmp(fstype, "nfs") == 0) { + /* + * The mount_nfs(8) command defaults to retry undefinitely. + * We do not want that behaviour, because it leaves mount_nfs(8) + * instances and automountd(8) children hanging forever. + * Disable retries unless the option was passed explicitly. + */ + retrycnt = pick_option("retrycnt=", &options); + if (retrycnt == NULL) { + log_debugx("retrycnt not specified in options; " + "defaulting to 1"); + options = separated_concat(options, + separated_concat("retrycnt", "1", '='), ','); + } else { + options = separated_concat(options, + separated_concat("retrycnt", retrycnt, '='), ','); + } + } + + f = auto_popen("mount", "-t", fstype, "-o", options, + node->n_location, adr->adr_path, NULL); + assert(f != NULL); + error = auto_pclose(f); + if (error != 0) + log_errx(1, "mount failed"); + + done(0); + log_debugx("mount done; exiting"); + + /* + * Exit without calling exit_callback(). + */ + quick_exit(0); +} + +static int +wait_for_children(bool block) +{ + pid_t pid; + int status; + int num = 0; + + for (;;) { + /* + * If "block" is true, wait for at least one process. + */ + if (block && num == 0) + pid = wait4(-1, &status, 0, NULL); + else + pid = wait4(-1, &status, WNOHANG, NULL); + if (pid <= 0) + break; + if (WIFSIGNALED(status)) { + log_warnx("child process %d terminated with signal %d", + pid, WTERMSIG(status)); + } else if (WEXITSTATUS(status) != 0) { + log_warnx("child process %d terminated with exit status %d", + pid, WEXITSTATUS(status)); + } else { + log_debugx("child process %d terminated gracefully", pid); + } + num++; + } + + return (num); +} + +static void +usage_automountd(void) +{ + + fprintf(stderr, "usage: automountd [-D name=value][-m maxproc]" + "[-o opts][-Tidv]\n"); + exit(1); +} + +int +main_automountd(int argc, char **argv) +{ + struct pidfh *pidfh; + pid_t pid, otherpid; + const char *pidfile_path = AUTOMOUNTD_PIDFILE; + char *options = NULL; + struct autofs_daemon_request request; + int ch, debug = 0, error, maxproc = 30, retval, saved_errno; + bool dont_daemonize = false, incomplete_hierarchy = false; + + defined_init(); + + while ((ch = getopt(argc, argv, "D:Tdim:o:v")) != -1) { + switch (ch) { + case 'D': + defined_parse_and_add(optarg); + break; + case 'T': + /* + * For compatibility with other implementations, + * such as OS X. + */ + debug++; + break; + case 'd': + dont_daemonize = true; + debug++; + break; + case 'i': + incomplete_hierarchy = true; + break; + case 'm': + maxproc = atoi(optarg); + break; + case 'o': + if (options == NULL) { + options = checked_strdup(optarg); + } else { + options = + separated_concat(options, optarg, ','); + } + break; + case 'v': + debug++; + break; + case '?': + default: + usage_automountd(); + } + } + argc -= optind; + if (argc != 0) + usage_automountd(); + + log_init(debug); + + pidfh = pidfile_open(pidfile_path, 0600, &otherpid); + if (pidfh == NULL) { + if (errno == EEXIST) { + log_errx(1, "daemon already running, pid: %jd.", + (intmax_t)otherpid); + } + log_err(1, "cannot open or create pidfile \"%s\"", + pidfile_path); + } + + autofs_fd = open(AUTOFS_PATH, O_RDWR | O_CLOEXEC); + if (autofs_fd < 0 && errno == ENOENT) { + saved_errno = errno; + retval = kldload("autofs"); + if (retval != -1) + autofs_fd = open(AUTOFS_PATH, O_RDWR | O_CLOEXEC); + else + errno = saved_errno; + } + if (autofs_fd < 0) + log_err(1, "failed to open %s", AUTOFS_PATH); + + if (dont_daemonize == false) { + if (daemon(0, 0) == -1) { + log_warn("cannot daemonize"); + pidfile_remove(pidfh); + exit(1); + } + } else { + lesser_daemon(); + } + + pidfile_write(pidfh); + + for (;;) { + log_debugx("waiting for request from the kernel"); + + memset(&request, 0, sizeof(request)); + error = ioctl(autofs_fd, AUTOFSREQUEST, &request); + if (error != 0) { + if (errno == EINTR) { + nchildren -= wait_for_children(false); + assert(nchildren >= 0); + continue; + } + + log_err(1, "AUTOFSREQUEST"); + } + + if (dont_daemonize) { + log_debugx("not forking due to -d flag; " + "will exit after servicing a single request"); + } else { + nchildren -= wait_for_children(false); + assert(nchildren >= 0); + + while (maxproc > 0 && nchildren >= maxproc) { + log_debugx("maxproc limit of %d child processes hit; " + "waiting for child process to exit", maxproc); + nchildren -= wait_for_children(true); + assert(nchildren >= 0); + } + log_debugx("got request; forking child process #%d", + nchildren); + nchildren++; + + pid = fork(); + if (pid < 0) + log_err(1, "fork"); + if (pid > 0) + continue; + } + + pidfile_close(pidfh); + handle_request(&request, options, incomplete_hierarchy); + } + + pidfile_close(pidfh); + + return (0); +} + diff --git a/usr.sbin/autofs/autounmountd.8 b/usr.sbin/autofs/autounmountd.8 new file mode 100644 index 000000000000..1b5d9a8e3810 --- /dev/null +++ b/usr.sbin/autofs/autounmountd.8 @@ -0,0 +1,88 @@ +.\" Copyright (c) 2014 The FreeBSD Foundation +.\" All rights reserved. +.\" +.\" This software was developed by Edward Tomasz Napierala under sponsorship +.\" from the FreeBSD Foundation. +.\" +.\" 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 AUTHORS 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 AUTHORS 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. +.\" +.\" $FreeBSD$ +.\" +.Dd April 20, 2014 +.Dt AUTOUNMOUNTD 8 +.Os +.Sh NAME +.Nm autounmountd +.Nd daemon unmounting automounted filesystems +.Sh SYNOPSIS +.Nm +.Op Fl d +.Op Fl r time +.Op Fl t time +.Op Fl v +.Sh DESCRIPTION +The +.Nm +daemon is responsible for unmounting filesystems mounted by +.Xr automountd 8 . +On startup, +.Nm +retrieves a list of filesystems that have the +.Li automounted +mount option set. +The list is updated every time a filesystem is mounted or unmounted. +After a specified time passes, +.Nm +attempts to unmount a filesystem, retrying after some time if necessary. +.Pp +These options are available: +.Bl -tag -width ".Fl v" +.It Fl d +Debug mode: increase verbosity and do not daemonize. +.It Fl r +Number of seconds to wait before trying to unmount an expired filesystem +after a previous attempt failed, possibly due to filesystem being busy. +The default value is 600, or ten minutes. +.It Fl t +Number of seconds to wait before trying to unmount a filesystem. +The default value is 600, or ten minutes. +.It Fl v +Increase verbosity. +.El +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr auto_master 5 , +.Xr autofs 5 , +.Xr automount 8 , +.Xr automountd 8 +.Sh HISTORY +The +.Nm +daemon appeared in +.Fx 10.1 . +.Sh AUTHORS +The +.Nm +was developed by +.An Edward Tomasz Napierala Aq Mt trasz@FreeBSD.org +under sponsorship from the FreeBSD Foundation. diff --git a/usr.sbin/autofs/autounmountd.c b/usr.sbin/autofs/autounmountd.c new file mode 100644 index 000000000000..4ec24f7f4246 --- /dev/null +++ b/usr.sbin/autofs/autounmountd.c @@ -0,0 +1,351 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +#define AUTOUNMOUNTD_PIDFILE "/var/run/autounmountd.pid" + +struct automounted_fs { + TAILQ_ENTRY(automounted_fs) af_next; + time_t af_mount_time; + bool af_mark; + fsid_t af_fsid; + char af_mountpoint[MNAMELEN]; +}; + +static TAILQ_HEAD(, automounted_fs) automounted; + +static struct automounted_fs * +automounted_find(fsid_t fsid) +{ + struct automounted_fs *af; + + TAILQ_FOREACH(af, &automounted, af_next) { + if (af->af_fsid.val[0] == fsid.val[0] && + af->af_fsid.val[1] == fsid.val[1]) + return (af); + } + + return (NULL); +} + +static struct automounted_fs * +automounted_add(fsid_t fsid, const char *mountpoint) +{ + struct automounted_fs *af; + + af = calloc(sizeof(*af), 1); + if (af == NULL) + log_err(1, "calloc"); + af->af_mount_time = time(NULL); + af->af_fsid = fsid; + strlcpy(af->af_mountpoint, mountpoint, sizeof(af->af_mountpoint)); + + TAILQ_INSERT_TAIL(&automounted, af, af_next); + + return (af); +} + +static void +automounted_remove(struct automounted_fs *af) +{ + + TAILQ_REMOVE(&automounted, af, af_next); + free(af); +} + +static void +refresh_automounted(void) +{ + struct automounted_fs *af, *tmpaf; + struct statfs *mntbuf; + int i, nitems; + + nitems = getmntinfo(&mntbuf, MNT_WAIT); + if (nitems <= 0) + log_err(1, "getmntinfo"); + + log_debugx("refreshing list of automounted filesystems"); + + TAILQ_FOREACH(af, &automounted, af_next) + af->af_mark = false; + + for (i = 0; i < nitems; i++) { + if (strcmp(mntbuf[i].f_fstypename, "autofs") == 0) { + log_debugx("skipping %s, filesystem type is autofs", + mntbuf[i].f_mntonname); + continue; + } + + if ((mntbuf[i].f_flags & MNT_AUTOMOUNTED) == 0) { + log_debugx("skipping %s, not automounted", + mntbuf[i].f_mntonname); + continue; + } + + af = automounted_find(mntbuf[i].f_fsid); + if (af == NULL) { + log_debugx("new automounted filesystem found on %s " + "(FSID:%d:%d)", mntbuf[i].f_mntonname, + mntbuf[i].f_fsid.val[0], mntbuf[i].f_fsid.val[1]); + af = automounted_add(mntbuf[i].f_fsid, + mntbuf[i].f_mntonname); + } else { + log_debugx("already known automounted filesystem " + "found on %s (FSID:%d:%d)", mntbuf[i].f_mntonname, + mntbuf[i].f_fsid.val[0], mntbuf[i].f_fsid.val[1]); + } + af->af_mark = true; + } + + TAILQ_FOREACH_SAFE(af, &automounted, af_next, tmpaf) { + if (af->af_mark) + continue; + log_debugx("lost filesystem mounted on %s (FSID:%d:%d)", + af->af_mountpoint, af->af_fsid.val[0], af->af_fsid.val[1]); + automounted_remove(af); + } +} + +static int +unmount_by_fsid(const fsid_t fsid, const char *mountpoint) +{ + char *fsid_str; + int error, ret; + + ret = asprintf(&fsid_str, "FSID:%d:%d", fsid.val[0], fsid.val[1]); + if (ret < 0) + log_err(1, "asprintf"); + + error = unmount(fsid_str, MNT_BYFSID); + if (error != 0) { + if (errno == EBUSY) { + log_debugx("cannot unmount %s (%s): %s", + mountpoint, fsid_str, strerror(errno)); + } else { + log_warn("cannot unmount %s (%s)", + mountpoint, fsid_str); + } + } + + free(fsid_str); + + return (error); +} + +static double +expire_automounted(double expiration_time) +{ + struct automounted_fs *af, *tmpaf; + time_t now; + double mounted_for, mounted_max = 0; + int error; + bool unmounted = false; + + now = time(NULL); + + log_debugx("expiring automounted filesystems"); + + TAILQ_FOREACH_SAFE(af, &automounted, af_next, tmpaf) { + mounted_for = difftime(now, af->af_mount_time); + + if (mounted_for < expiration_time) { + log_debugx("skipping %s (FSID:%d:%d), mounted " + "for %.0f seconds", af->af_mountpoint, + af->af_fsid.val[0], af->af_fsid.val[1], + mounted_for); + + if (mounted_for > mounted_max) + mounted_max = mounted_for; + + continue; + } + + log_debugx("filesystem mounted on %s (FSID:%d:%d), " + "was mounted for %.0f seconds; unmounting", + af->af_mountpoint, af->af_fsid.val[0], af->af_fsid.val[1], + mounted_for); + error = unmount_by_fsid(af->af_fsid, af->af_mountpoint); + if (error != 0) { + if (mounted_for > mounted_max) + mounted_max = mounted_for; + } else { + unmounted = true; + } + } + + if (unmounted) { + /* + * Successful unmount of a filesystem could unbusy its parent + * filesystem that can now be unmounted. + */ + log_debugx("filesystem got unmounted; go around"); + return (expire_automounted(expiration_time)); + } + + return (mounted_max); +} + +static void +usage_autounmountd(void) +{ + + fprintf(stderr, "usage: autounmountd [-r time][-t time][-dv]\n"); + exit(1); +} + +static void +do_wait(int kq, double sleep_time) +{ + struct timespec timeout; + struct kevent unused; + int error; + + assert(sleep_time > 0); + timeout.tv_sec = sleep_time; + timeout.tv_nsec = 0; + + log_debugx("waiting for filesystem event for %.0f seconds", sleep_time); + error = kevent(kq, NULL, 0, &unused, 1, &timeout); + if (error < 0) + log_err(1, "kevent"); + + if (error == 0) + log_debugx("timeout reached"); + else + log_debugx("got filesystem event"); +} + +int +main_autounmountd(int argc, char **argv) +{ + struct kevent event; + struct pidfh *pidfh; + pid_t otherpid; + const char *pidfile_path = AUTOUNMOUNTD_PIDFILE; + int ch, debug = 0, error, kq; + double expiration_time = 600, retry_time = 600, mounted_max, sleep_time; + bool dont_daemonize = false; + + while ((ch = getopt(argc, argv, "dr:t:v")) != -1) { + switch (ch) { + case 'd': + dont_daemonize = true; + debug++; + break; + case 'r': + retry_time = atoi(optarg); + break; + case 't': + expiration_time = atoi(optarg); + break; + case 'v': + debug++; + break; + case '?': + default: + usage_autounmountd(); + } + } + argc -= optind; + if (argc != 0) + usage_autounmountd(); + + if (retry_time <= 0) + log_errx(1, "retry time must be greater than zero"); + if (expiration_time <= 0) + log_errx(1, "expiration time must be greater than zero"); + + log_init(debug); + + pidfh = pidfile_open(pidfile_path, 0600, &otherpid); + if (pidfh == NULL) { + if (errno == EEXIST) { + log_errx(1, "daemon already running, pid: %jd.", + (intmax_t)otherpid); + } + log_err(1, "cannot open or create pidfile \"%s\"", + pidfile_path); + } + + if (dont_daemonize == false) { + if (daemon(0, 0) == -1) { + log_warn("cannot daemonize"); + pidfile_remove(pidfh); + exit(1); + } + } + + pidfile_write(pidfh); + + TAILQ_INIT(&automounted); + + kq = kqueue(); + if (kq < 0) + log_err(1, "kqueue"); + + EV_SET(&event, 0, EVFILT_FS, EV_ADD | EV_CLEAR, 0, 0, NULL); + error = kevent(kq, &event, 1, NULL, 0, NULL); + if (error < 0) + log_err(1, "kevent"); + + for (;;) { + refresh_automounted(); + mounted_max = expire_automounted(expiration_time); + if (mounted_max < expiration_time) { + sleep_time = difftime(expiration_time, mounted_max); + log_debugx("some filesystems expire in %.0f seconds", + sleep_time); + } else { + sleep_time = retry_time; + log_debugx("some expired filesystems remain mounted, " + "will retry in %.0f seconds", sleep_time); + } + + do_wait(kq, sleep_time); + } + + return (0); +} diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c new file mode 100644 index 000000000000..0847c3b264fc --- /dev/null +++ b/usr.sbin/autofs/common.c @@ -0,0 +1,1129 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "autofs_ioctl.h" + +#include "common.h" + +extern FILE *yyin; +extern char *yytext; +extern int yylex(void); + +static void parse_master_yyin(struct node *root, const char *master); +static void parse_map_yyin(struct node *parent, const char *map, + const char *executable_key); + +char * +checked_strdup(const char *s) +{ + char *c; + + assert(s != NULL); + + c = strdup(s); + if (c == NULL) + log_err(1, "strdup"); + return (c); +} + +/* + * Take two pointers to strings, concatenate the contents with "/" in the + * middle, make the first pointer point to the result, the second pointer + * to NULL, and free the old strings. + * + * Concatenate pathnames, basically. + */ +static void +concat(char **p1, char **p2) +{ + int ret; + char *path; + + assert(p1 != NULL); + assert(p2 != NULL); + + if (*p1 == NULL) + *p1 = checked_strdup(""); + + if (*p2 == NULL) + *p2 = checked_strdup(""); + + ret = asprintf(&path, "%s/%s", *p1, *p2); + if (ret < 0) + log_err(1, "asprintf"); + + /* + * XXX + */ + //free(*p1); + //free(*p2); + + *p1 = path; + *p2 = NULL; +} + +/* + * Concatenate two strings, inserting separator between them, unless not needed. + * + * This function is very convenient to use when you do not care about freeing + * memory - which is okay here, because we are a short running process. + */ +char * +separated_concat(const char *s1, const char *s2, char separator) +{ + char *result; + int ret; + + assert(s1 != NULL); + assert(s2 != NULL); + + if (s1[0] == '\0' || s2[0] == '\0' || + s1[strlen(s1) - 1] == separator || s2[0] == separator) { + ret = asprintf(&result, "%s%s", s1, s2); + } else { + ret = asprintf(&result, "%s%c%s", s1, separator, s2); + } + if (ret < 0) + log_err(1, "asprintf"); + + //log_debugx("separated_concat: got %s and %s, returning %s", s1, s2, result); + + return (result); +} + +void +create_directory(const char *path) +{ + char *component, *copy, *tofree, *partial; + int error; + + assert(path[0] == '/'); + + /* + * +1 to skip the leading slash. + */ + copy = tofree = checked_strdup(path + 1); + + partial = NULL; + for (;;) { + component = strsep(©, "/"); + if (component == NULL) + break; + concat(&partial, &component); + //log_debugx("checking \"%s\" for existence", partial); + error = access(partial, F_OK); + if (error == 0) + continue; + if (errno != ENOENT) + log_err(1, "cannot access %s", partial); + log_debugx("directory %s does not exist, creating", + partial); + error = mkdir(partial, 0755); + if (error != 0) + log_err(1, "cannot create %s", partial); + } + + free(tofree); +} + +struct node * +node_new_root(void) +{ + struct node *n; + + n = calloc(1, sizeof(*n)); + if (n == NULL) + log_err(1, "calloc"); + // XXX + n->n_key = checked_strdup("/"); + n->n_options = checked_strdup(""); + + TAILQ_INIT(&n->n_children); + + return (n); +} + +struct node * +node_new(struct node *parent, char *key, char *options, char *location, + const char *config_file, int config_line) +{ + struct node *n; + + n = calloc(1, sizeof(*n)); + if (n == NULL) + log_err(1, "calloc"); + + TAILQ_INIT(&n->n_children); + assert(key != NULL); + n->n_key = key; + if (options != NULL) + n->n_options = options; + else + n->n_options = strdup(""); + n->n_location = location; + assert(config_file != NULL); + n->n_config_file = config_file; + assert(config_line >= 0); + n->n_config_line = config_line; + + assert(parent != NULL); + n->n_parent = parent; + TAILQ_INSERT_TAIL(&parent->n_children, n, n_next); + + return (n); +} + +struct node * +node_new_map(struct node *parent, char *key, char *options, char *map, + const char *config_file, int config_line) +{ + struct node *n; + + n = calloc(1, sizeof(*n)); + if (n == NULL) + log_err(1, "calloc"); + + TAILQ_INIT(&n->n_children); + assert(key != NULL); + n->n_key = key; + if (options != NULL) + n->n_options = options; + else + n->n_options = strdup(""); + n->n_map = map; + assert(config_file != NULL); + n->n_config_file = config_file; + assert(config_line >= 0); + n->n_config_line = config_line; + + assert(parent != NULL); + n->n_parent = parent; + TAILQ_INSERT_TAIL(&parent->n_children, n, n_next); + + return (n); +} + +static struct node * +node_duplicate(const struct node *o, struct node *parent) +{ + const struct node *child; + struct node *n; + + if (parent == NULL) + parent = o->n_parent; + + n = node_new(parent, o->n_key, o->n_options, o->n_location, + o->n_config_file, o->n_config_line); + + TAILQ_FOREACH(child, &o->n_children, n_next) + node_duplicate(child, n); + + return (n); +} + +static void +node_delete(struct node *n) +{ + struct node *child, *tmp; + + assert (n != NULL); + + TAILQ_FOREACH_SAFE(child, &n->n_children, n_next, tmp) + node_delete(child); + + if (n->n_parent != NULL) + TAILQ_REMOVE(&n->n_parent->n_children, n, n_next); + + free(n); +} + +/* + * Move (reparent) node 'n' to make it sibling of 'previous', placed + * just after it. + */ +static void +node_move_after(struct node *n, struct node *previous) +{ + + TAILQ_REMOVE(&n->n_parent->n_children, n, n_next); + n->n_parent = previous->n_parent; + TAILQ_INSERT_AFTER(&previous->n_parent->n_children, previous, n, n_next); +} + +static void +node_expand_includes(struct node *root, bool is_master) +{ + struct node *n, *n2, *tmp, *tmp2, *tmproot; + int error; + + TAILQ_FOREACH_SAFE(n, &root->n_children, n_next, tmp) { + if (n->n_key[0] != '+') + continue; + + error = access(AUTO_INCLUDE_PATH, F_OK); + if (error != 0) { + log_errx(1, "directory services not configured; " + "%s does not exist", AUTO_INCLUDE_PATH); + } + + /* + * "+1" to skip leading "+". + */ + yyin = auto_popen(AUTO_INCLUDE_PATH, n->n_key + 1, NULL); + assert(yyin != NULL); + + tmproot = node_new_root(); + if (is_master) + parse_master_yyin(tmproot, n->n_key); + else + parse_map_yyin(tmproot, n->n_key, NULL); + + error = auto_pclose(yyin); + yyin = NULL; + if (error != 0) { + log_errx(1, "failed to handle include \"%s\"", + n->n_key); + } + + /* + * Entries to be included are now in tmproot. We need to merge + * them with the rest, preserving their place and ordering. + */ + TAILQ_FOREACH_REVERSE_SAFE(n2, + &tmproot->n_children, nodehead, n_next, tmp2) { + node_move_after(n2, n); + } + + node_delete(n); + node_delete(tmproot); + } +} + +static char * +expand_ampersand(char *string, const char *key) +{ + char c, *expanded; + int i, ret, before_len = 0; + bool backslashed = false; + + assert(key[0] != '\0'); + + expanded = checked_strdup(string); + + for (i = 0; string[i] != '\0'; i++) { + c = string[i]; + if (c == '\\' && backslashed == false) { + backslashed = true; + continue; + } + if (backslashed) { + backslashed = false; + continue; + } + backslashed = false; + if (c != '&') + continue; + + /* + * The 'before_len' variable contains the number + * of characters before the '&'. + */ + before_len = i; + //assert(i + 1 < (int)strlen(string)); + + ret = asprintf(&expanded, "%.*s%s%s", + before_len, string, key, string + before_len + 1); + if (ret < 0) + log_err(1, "asprintf"); + + //log_debugx("\"%s\" expanded with key \"%s\" to \"%s\"", + // string, key, expanded); + + /* + * Figure out where to start searching for next variable. + */ + string = expanded; + i = before_len + strlen(key); + backslashed = false; + //assert(i < (int)strlen(string)); + } + + return (expanded); +} + +/* + * Expand "&" in n_location. If the key is NULL, try to use + * key from map entries themselves. Keep in mind that maps + * consist of tho levels of node structures, the key is one + * level up. + * + * Variant with NULL key is for "automount -LL". + */ +void +node_expand_ampersand(struct node *n, const char *key) +{ + struct node *child; + + if (n->n_location != NULL) { + if (key == NULL) { + if (n->n_parent != NULL && + strcmp(n->n_parent->n_key, "*") != 0) { + n->n_location = expand_ampersand(n->n_location, + n->n_parent->n_key); + } + } else { + n->n_location = expand_ampersand(n->n_location, key); + } + } + + TAILQ_FOREACH(child, &n->n_children, n_next) + node_expand_ampersand(child, key); +} + +/* + * Expand "*" in n_key. + */ +void +node_expand_wildcard(struct node *n, const char *key) +{ + struct node *child, *expanded; + + assert(key != NULL); + + if (strcmp(n->n_key, "*") == 0) { + expanded = node_duplicate(n, NULL); + expanded->n_key = checked_strdup(key); + node_move_after(expanded, n); + } + + TAILQ_FOREACH(child, &n->n_children, n_next) + node_expand_wildcard(child, key); +} + +int +node_expand_defined(struct node *n) +{ + struct node *child; + int error, cumulated_error = 0; + + if (n->n_location != NULL) { + n->n_location = defined_expand(n->n_location); + if (n->n_location == NULL) { + log_warnx("failed to expand location for %s", + node_path(n)); + return (EINVAL); + } + } + + TAILQ_FOREACH(child, &n->n_children, n_next) { + error = node_expand_defined(child); + if (error != 0 && cumulated_error == 0) + cumulated_error = error; + } + + return (cumulated_error); +} + +bool +node_is_direct_map(const struct node *n) +{ + + for (;;) { + assert(n->n_parent != NULL); + if (n->n_parent->n_parent == NULL) + break; + n = n->n_parent; + } + + assert(n->n_key != NULL); + if (strcmp(n->n_key, "/-") != 0) + return (false); + + return (true); +} + +static void +node_expand_maps(struct node *n, bool indirect) +{ + struct node *child, *tmp; + + TAILQ_FOREACH_SAFE(child, &n->n_children, n_next, tmp) { + if (node_is_direct_map(child)) { + if (indirect) + continue; + } else { + if (indirect == false) + continue; + } + + /* + * This is the first-level map node; the one that contains + * the key and subnodes with mountpoints and actual map names. + */ + if (child->n_map == NULL) + continue; + + if (indirect) { + log_debugx("map \"%s\" is an indirect map, parsing", + child->n_map); + } else { + log_debugx("map \"%s\" is a direct map, parsing", + child->n_map); + } + parse_map(child, child->n_map, NULL); + } +} + +static void +node_expand_direct_maps(struct node *n) +{ + + node_expand_maps(n, false); +} + +void +node_expand_indirect_maps(struct node *n) +{ + + node_expand_maps(n, true); +} + +static char * +node_path_x(const struct node *n, char *x) +{ + char *path; + size_t len; + + if (n->n_parent == NULL) + return (x); + + /* + * Return "/-" for direct maps only if we were asked for path + * to the "/-" node itself, not to any of its subnodes. + */ + if (n->n_parent->n_parent == NULL && + strcmp(n->n_key, "/-") == 0 && + x[0] != '\0') { + return (x); + } + + path = separated_concat(n->n_key, x, '/'); + free(x); + + /* + * Strip trailing slash. + */ + len = strlen(path); + assert(len > 0); + if (path[len - 1] == '/') + path[len - 1] = '\0'; + + return (node_path_x(n->n_parent, path)); +} + +/* + * Return full path for node, consisting of concatenated + * paths of node itself and all its parents, up to the root. + */ +char * +node_path(const struct node *n) +{ + + return (node_path_x(n, checked_strdup(""))); +} + +static char * +node_options_x(const struct node *n, char *x) +{ + char *options; + + options = separated_concat(x, n->n_options, ','); + if (n->n_parent == NULL) + return (options); + + return (node_options_x(n->n_parent, options)); +} + +/* + * Return options for node, consisting of concatenated + * options from the node itself and all its parents, + * up to the root. + */ +char * +node_options(const struct node *n) +{ + + return (node_options_x(n, checked_strdup(""))); +} + +static void +node_print_indent(const struct node *n, int indent) +{ + const struct node *child, *first_child; + char *path, *options; + + path = node_path(n); + options = node_options(n); + + /* + * Do not show both parent and child node if they have the same + * mountpoint; only show the child node. This means the typical, + * "key location", map entries are shown in a single line; + * the "key mountpoint1 location2 mountpoint2 location2" entries + * take multiple lines. + */ + first_child = TAILQ_FIRST(&n->n_children); + if (first_child == NULL || TAILQ_NEXT(first_child, n_next) != NULL || + strcmp(path, node_path(first_child)) != 0) { + assert(n->n_location == NULL || n->n_map == NULL); + printf("%*.s%-*s %s%-*s %-*s # %s map %s at %s:%d\n", + indent, "", + 25 - indent, + path, + options[0] != '\0' ? "-" : " ", + 20, + options[0] != '\0' ? options : "", + 20, + n->n_location != NULL ? n->n_location : n->n_map != NULL ? n->n_map : "", + node_is_direct_map(n) ? "direct" : "indirect", + indent == 0 ? "referenced" : "defined", + n->n_config_file, n->n_config_line); + } + + free(path); + free(options); + + TAILQ_FOREACH(child, &n->n_children, n_next) + node_print_indent(child, indent + 2); +} + +void +node_print(const struct node *n) +{ + const struct node *child; + + TAILQ_FOREACH(child, &n->n_children, n_next) + node_print_indent(child, 0); +} + +struct node * +node_find(struct node *node, const char *path) +{ + struct node *child, *found; + char *tmp; + + //log_debugx("looking up %s in %s", path, node->n_key); + + tmp = node_path(node); + if (strncmp(tmp, path, strlen(tmp)) != 0) { + free(tmp); + return (NULL); + } + free(tmp); + + TAILQ_FOREACH(child, &node->n_children, n_next) { + found = node_find(child, path); + if (found != NULL) + return (found); + } + + return (node); +} + +/* + * Canonical form of a map entry looks like this: + * + * key [-options] [ [/mountpoint] [-options2] location ... ] + * + * Entries for executable maps are slightly different, as they + * lack the 'key' field and are always single-line; the key field + * for those maps is taken from 'executable_key' argument. + * + * We parse it in such a way that a map always has two levels - first + * for key, and the second, for the mountpoint. + */ +static void +parse_map_yyin(struct node *parent, const char *map, const char *executable_key) +{ + char *key = NULL, *options = NULL, *mountpoint = NULL, + *options2 = NULL, *location = NULL; + int ret; + struct node *node; + + lineno = 1; + + if (executable_key != NULL) + key = checked_strdup(executable_key); + + for (;;) { + ret = yylex(); + if (ret == 0 || ret == NEWLINE) { + if (key != NULL || options != NULL) { + log_errx(1, "truncated entry at %s, line %d", + map, lineno); + } + if (ret == 0 || executable_key != NULL) { + /* + * End of file. + */ + break; + } else { + key = options = NULL; + continue; + } + } + if (key == NULL) { + key = checked_strdup(yytext); + if (key[0] == '+') { + node_new(parent, key, NULL, NULL, map, lineno); + key = options = NULL; + continue; + } + continue; + } else if (yytext[0] == '-') { + if (options != NULL) { + log_errx(1, "duplicated options at %s, line %d", + map, lineno); + } + /* + * +1 to skip leading "-". + */ + options = checked_strdup(yytext + 1); + continue; + } + + /* + * We cannot properly handle a situation where the map key + * is "/". Ignore such entries. + * + * XXX: According to Piete Brooks, Linux automounter uses + * "/" as a wildcard character in LDAP maps. Perhaps + * we should work around this braindamage by substituting + * "*" for "/"? + */ + if (strcmp(key, "/") == 0) { + log_warnx("nonsensical map key \"/\" at %s, line %d; " + "ignoring map entry ", map, lineno); + + /* + * Skip the rest of the entry. + */ + do { + ret = yylex(); + } while (ret != 0 && ret != NEWLINE); + + key = options = NULL; + continue; + } + + //log_debugx("adding map node, %s", key); + node = node_new(parent, key, options, NULL, map, lineno); + key = options = NULL; + + for (;;) { + if (yytext[0] == '/') { + if (mountpoint != NULL) { + log_errx(1, "duplicated mountpoint " + "in %s, line %d", map, lineno); + } + if (options2 != NULL || location != NULL) { + log_errx(1, "mountpoint out of order " + "in %s, line %d", map, lineno); + } + mountpoint = checked_strdup(yytext); + goto again; + } + + if (yytext[0] == '-') { + if (options2 != NULL) { + log_errx(1, "duplicated options " + "in %s, line %d", map, lineno); + } + if (location != NULL) { + log_errx(1, "options out of order " + "in %s, line %d", map, lineno); + } + options2 = checked_strdup(yytext + 1); + goto again; + } + + if (location != NULL) { + log_errx(1, "too many arguments " + "in %s, line %d", map, lineno); + } + + /* + * If location field starts with colon, e.g. ":/dev/cd0", + * then strip it. + */ + if (yytext[0] == ':') { + location = checked_strdup(yytext + 1); + if (location[0] == '\0') { + log_errx(1, "empty location in %s, " + "line %d", map, lineno); + } + } else { + location = checked_strdup(yytext); + } + + if (mountpoint == NULL) + mountpoint = checked_strdup("/"); + if (options2 == NULL) + options2 = checked_strdup(""); + +#if 0 + log_debugx("adding map node, %s %s %s", + mountpoint, options2, location); +#endif + node_new(node, mountpoint, options2, location, + map, lineno); + mountpoint = options2 = location = NULL; +again: + ret = yylex(); + if (ret == 0 || ret == NEWLINE) { + if (mountpoint != NULL || options2 != NULL || + location != NULL) { + log_errx(1, "truncated entry " + "in %s, line %d", map, lineno); + } + break; + } + } + } +} + +static bool +file_is_executable(const char *path) +{ + struct stat sb; + int error; + + error = stat(path, &sb); + if (error != 0) + log_err(1, "cannot stat %s", path); + if ((sb.st_mode & S_IXUSR) || (sb.st_mode & S_IXGRP) || + (sb.st_mode & S_IXOTH)) + return (true); + return (false); +} + +/* + * Parse a special map, e.g. "-hosts". + */ +static void +parse_special_map(struct node *parent, const char *map, const char *key) +{ + char *path; + int error, ret; + + assert(map[0] == '-'); + + if (key == NULL) { + log_debugx("skipping map %s due to forced -nobrowse", map); + return; + } + + /* + * +1 to skip leading "-" in map name. + */ + ret = asprintf(&path, "%s/special_%s", AUTO_SPECIAL_PREFIX, map + 1); + if (ret < 0) + log_err(1, "asprintf"); + + yyin = auto_popen(path, key, NULL); + assert(yyin != NULL); + + parse_map_yyin(parent, map, key); + + error = auto_pclose(yyin); + yyin = NULL; + if (error != 0) + log_errx(1, "failed to handle special map \"%s\"", map); + + node_expand_includes(parent, false); + node_expand_direct_maps(parent); + + free(path); +} + +/* + * Retrieve and parse map from directory services, e.g. LDAP. + * Note that it is different from executable maps, in that + * the include script outputs the whole map to standard output + * (as opposed to executable maps that only output a single + * entry, without the key), and it takes the map name as an + * argument, instead of key. + */ +static void +parse_included_map(struct node *parent, const char *map) +{ + int error; + + assert(map[0] != '-'); + assert(map[0] != '/'); + + error = access(AUTO_INCLUDE_PATH, F_OK); + if (error != 0) { + log_errx(1, "directory services not configured;" + " %s does not exist", AUTO_INCLUDE_PATH); + } + + yyin = auto_popen(AUTO_INCLUDE_PATH, map, NULL); + assert(yyin != NULL); + + parse_map_yyin(parent, map, NULL); + + error = auto_pclose(yyin); + yyin = NULL; + if (error != 0) + log_errx(1, "failed to handle remote map \"%s\"", map); + + node_expand_includes(parent, false); + node_expand_direct_maps(parent); +} + +void +parse_map(struct node *parent, const char *map, const char *key) +{ + char *path = NULL; + int error, ret; + bool executable; + + assert(map != NULL); + assert(map[0] != '\0'); + + log_debugx("parsing map \"%s\"", map); + + if (map[0] == '-') + return (parse_special_map(parent, map, key)); + + if (map[0] == '/') { + path = checked_strdup(map); + } else { + ret = asprintf(&path, "%s/%s", AUTO_MAP_PREFIX, map); + if (ret < 0) + log_err(1, "asprintf"); + log_debugx("map \"%s\" maps to \"%s\"", map, path); + + /* + * See if the file exists. If not, try to obtain the map + * from directory services. + */ + error = access(path, F_OK); + if (error != 0) { + log_debugx("map file \"%s\" does not exist; falling " + "back to directory services", path); + return (parse_included_map(parent, map)); + } + } + + executable = file_is_executable(path); + + if (executable) { + log_debugx("map \"%s\" is executable", map); + + if (key != NULL) { + yyin = auto_popen(path, key, NULL); + } else { + yyin = auto_popen(path, NULL); + } + assert(yyin != NULL); + } else { + yyin = fopen(path, "r"); + if (yyin == NULL) + log_err(1, "unable to open \"%s\"", path); + } + + free(path); + path = NULL; + + parse_map_yyin(parent, map, executable ? key : NULL); + + if (executable) { + error = auto_pclose(yyin); + yyin = NULL; + if (error != 0) { + log_errx(1, "failed to handle executable map \"%s\"", + map); + } + } else { + fclose(yyin); + } + yyin = NULL; + + log_debugx("done parsing map \"%s\"", map); + + node_expand_includes(parent, false); + node_expand_direct_maps(parent); +} + +static void +parse_master_yyin(struct node *root, const char *master) +{ + char *mountpoint = NULL, *map = NULL, *options = NULL; + int ret; + + /* + * XXX: 1 gives incorrect values; wtf? + */ + lineno = 0; + + for (;;) { + ret = yylex(); + if (ret == 0 || ret == NEWLINE) { + if (mountpoint != NULL) { + //log_debugx("adding map for %s", mountpoint); + node_new_map(root, mountpoint, options, map, + master, lineno); + } + if (ret == 0) { + break; + } else { + mountpoint = map = options = NULL; + continue; + } + } + if (mountpoint == NULL) { + mountpoint = checked_strdup(yytext); + } else if (map == NULL) { + map = checked_strdup(yytext); + } else if (options == NULL) { + /* + * +1 to skip leading "-". + */ + options = checked_strdup(yytext + 1); + } else { + log_errx(1, "too many arguments at %s, line %d", + master, lineno); + } + } +} + +void +parse_master(struct node *root, const char *master) +{ + + log_debugx("parsing auto_master file at \"%s\"", master); + + yyin = fopen(master, "r"); + if (yyin == NULL) + err(1, "unable to open %s", master); + + parse_master_yyin(root, master); + + fclose(yyin); + yyin = NULL; + + log_debugx("done parsing \"%s\"", master); + + node_expand_includes(root, true); + node_expand_direct_maps(root); +} + +/* + * Two things daemon(3) does, that we actually also want to do + * when running in foreground, is closing the stdin and chdiring + * to "/". This is what we do here. + */ +void +lesser_daemon(void) +{ + int error, fd; + + error = chdir("/"); + if (error != 0) + log_warn("chdir"); + + fd = open(_PATH_DEVNULL, O_RDWR, 0); + if (fd < 0) { + log_warn("cannot open %s", _PATH_DEVNULL); + return; + } + + error = dup2(fd, STDIN_FILENO); + if (error != 0) + log_warn("dup2"); + + error = close(fd); + if (error != 0) { + /* Bloody hell. */ + log_warn("close"); + } +} + +int +main(int argc, char **argv) +{ + char *cmdname; + + if (argv[0] == NULL) + log_errx(1, "NULL command name"); + + cmdname = basename(argv[0]); + + if (strcmp(cmdname, "automount") == 0) + return (main_automount(argc, argv)); + else if (strcmp(cmdname, "automountd") == 0) + return (main_automountd(argc, argv)); + else if (strcmp(cmdname, "autounmountd") == 0) + return (main_autounmountd(argc, argv)); + else + log_errx(1, "binary name should be either \"automount\", " + "\"automountd\", or \"autounmountd\""); +} diff --git a/usr.sbin/autofs/common.h b/usr.sbin/autofs/common.h new file mode 100644 index 000000000000..bc0b6f6c6116 --- /dev/null +++ b/usr.sbin/autofs/common.h @@ -0,0 +1,112 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef AUTOMOUNTD_H +#define AUTOMOUNTD_H + +#include +#include + +#define AUTO_MASTER_PATH "/etc/auto_master" +#define AUTO_MAP_PREFIX "/etc" +#define AUTO_SPECIAL_PREFIX "/etc/autofs" +#define AUTO_INCLUDE_PATH AUTO_SPECIAL_PREFIX "/include" + +struct node { + TAILQ_ENTRY(node) n_next; + TAILQ_HEAD(nodehead, node) n_children; + struct node *n_parent; + char *n_key; + char *n_options; + char *n_location; + char *n_map; + const char *n_config_file; + int n_config_line; +}; + +struct defined_value { + TAILQ_ENTRY(defined_value) d_next; + char *d_name; + char *d_value; +}; + +void log_init(int level); +void log_set_peer_name(const char *name); +void log_set_peer_addr(const char *addr); +void log_err(int, const char *, ...) + __dead2 __printf0like(2, 3); +void log_errx(int, const char *, ...) + __dead2 __printf0like(2, 3); +void log_warn(const char *, ...) __printf0like(1, 2); +void log_warnx(const char *, ...) __printflike(1, 2); +void log_debugx(const char *, ...) __printf0like(1, 2); + +char *checked_strdup(const char *); +char *separated_concat(const char *s1, const char *s2, char separator); +void create_directory(const char *path); + +struct node *node_new_root(void); +struct node *node_new(struct node *parent, char *key, char *options, + char *location, const char *config_file, int config_line); +struct node *node_new_map(struct node *parent, char *key, char *options, + char *map, const char *config_file, int config_line); +struct node *node_find(struct node *root, const char *mountpoint); +bool node_is_direct_map(const struct node *n); +char *node_path(const struct node *n); +char *node_options(const struct node *n); +void node_expand_ampersand(struct node *root, const char *key); +void node_expand_wildcard(struct node *root, const char *key); +int node_expand_defined(struct node *root); +void node_expand_indirect_maps(struct node *n); +void node_print(const struct node *n); +void parse_master(struct node *root, const char *path); +void parse_map(struct node *parent, const char *map, const char *args); +char *defined_expand(const char *string); +void defined_init(void); +void defined_parse_and_add(char *def); +void lesser_daemon(void); + +int main_automount(int argc, char **argv); +int main_automountd(int argc, char **argv); +int main_autounmountd(int argc, char **argv); + +FILE *auto_popen(const char *argv0, ...); +int auto_pclose(FILE *iop); + +/* + * lex(1) stuff. + */ +extern int lineno; + +#define STR 1 +#define NEWLINE 2 + +#endif /* !AUTOMOUNTD_H */ diff --git a/usr.sbin/autofs/defined.c b/usr.sbin/autofs/defined.c new file mode 100644 index 000000000000..7f1fb4b5d311 --- /dev/null +++ b/usr.sbin/autofs/defined.c @@ -0,0 +1,270 @@ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + * All the "defined" stuff is for handling variables, + * such as ${OSNAME}, in maps. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "common.h" + +static TAILQ_HEAD(, defined_value) defined_values; + +static const char * +defined_find(const char *name) +{ + struct defined_value *d; + + TAILQ_FOREACH(d, &defined_values, d_next) { + if (strcmp(d->d_name, name) == 0) + return (d->d_value); + } + + return (NULL); +} + +char * +defined_expand(const char *string) +{ + const char *value; + char c, *expanded, *name; + int i, ret, before_len = 0, name_off = 0, name_len = 0, after_off = 0; + bool backslashed = false, bracketed = false; + + expanded = checked_strdup(string); + + for (i = 0; string[i] != '\0'; i++) { + c = string[i]; + if (c == '\\' && backslashed == false) { + backslashed = true; + continue; + } + if (backslashed) { + backslashed = false; + continue; + } + backslashed = false; + if (c != '$') + continue; + + /* + * The 'before_len' variable contains the number + * of characters before the '$'. + */ + before_len = i; + assert(i + 1 < (int)strlen(string)); + if (string[i + 1] == '{') + bracketed = true; + + if (string[i + 1] == '\0') { + log_warnx("truncated variable"); + return (NULL); + } + + /* + * Skip '$'. + */ + i++; + + if (bracketed) { + if (string[i + 1] == '\0') { + log_warnx("truncated variable"); + return (NULL); + } + + /* + * Skip '{'. + */ + i++; + } + + /* + * The 'name_off' variable contains the number + * of characters before the variable name, + * including the "$" or "${". + */ + name_off = i; + + for (; string[i] != '\0'; i++) { + c = string[i]; + /* + * XXX: Decide on the set of characters that can be + * used in a variable name. + */ + if (isalnum(c) || c == '_') + continue; + + /* + * End of variable name. + */ + if (bracketed) { + if (c != '}') + continue; + + /* + * The 'after_off' variable contains the number + * of characters before the rest of the string, + * i.e. after the variable name. + */ + after_off = i + 1; + assert(i > 1); + assert(i - 1 > name_off); + name_len = i - name_off; + break; + } + + after_off = i; + assert(i > 1); + assert(i > name_off); + name_len = i - name_off; + break; + } + + name = strndup(string + name_off, name_len); + if (name == NULL) + log_err(1, "strndup"); + value = defined_find(name); + if (value == NULL) { + log_warnx("undefined variable ${%s}", name); + return (NULL); + } + + /* + * Concatenate it back. + */ + ret = asprintf(&expanded, "%.*s%s%s", + before_len, string, value, string + after_off); + if (ret < 0) + log_err(1, "asprintf"); + + //log_debugx("\"%s\" expanded to \"%s\"", string, expanded); + free(name); + + /* + * Figure out where to start searching for next variable. + */ + string = expanded; + i = before_len + strlen(value); + backslashed = bracketed = false; + before_len = name_off = name_len = after_off = 0; + assert(i <= (int)strlen(string)); + } + + if (before_len != 0 || name_off != 0 || name_len != 0 || after_off != 0) { + log_warnx("truncated variable"); + return (NULL); + } + + return (expanded); +} + +static void +defined_add(const char *name, const char *value) +{ + struct defined_value *d; + const char *found; + + found = defined_find(name); + if (found != NULL) + log_errx(1, "variable %s already defined", name); + + log_debugx("defining variable %s=%s", name, value); + + d = calloc(sizeof(*d), 1); + if (d == NULL) + log_err(1, "calloc"); + d->d_name = checked_strdup(name); + d->d_value = checked_strdup(value); + + TAILQ_INSERT_TAIL(&defined_values, d, d_next); +} + +void +defined_parse_and_add(char *def) +{ + char *name, *value; + + value = def; + name = strsep(&value, "="); + + if (value == NULL || value[0] == '\0') + log_errx(1, "missing variable value"); + if (name == NULL || name[0] == '\0') + log_errx(1, "missing variable name"); + + defined_add(name, value); +} + +void +defined_init(void) +{ + struct utsname name; + int error; + + TAILQ_INIT(&defined_values); + + error = uname(&name); + if (error != 0) + log_err(1, "uname"); + + defined_add("ARCH", name.machine); + defined_add("CPU", name.machine); + defined_add("HOST", name.nodename); + defined_add("OSNAME", name.sysname); + defined_add("OSREL", name.release); + defined_add("OSVERS", name.version); +} diff --git a/usr.sbin/autofs/log.c b/usr.sbin/autofs/log.c new file mode 100644 index 000000000000..a30ebaa846c4 --- /dev/null +++ b/usr.sbin/autofs/log.c @@ -0,0 +1,196 @@ +/*- + * Copyright (c) 2012 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +static int log_level = 0; +static char *peer_name = NULL; +static char *peer_addr = NULL; + +#define MSGBUF_LEN 1024 + +void +log_init(int level) +{ + + log_level = level; + openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON); +} + +void +log_set_peer_name(const char *name) +{ + + /* + * XXX: Turn it into assertion? + */ + if (peer_name != NULL) + log_errx(1, "%s called twice", __func__); + if (peer_addr == NULL) + log_errx(1, "%s called before log_set_peer_addr", __func__); + + peer_name = checked_strdup(name); +} + +void +log_set_peer_addr(const char *addr) +{ + + /* + * XXX: Turn it into assertion? + */ + if (peer_addr != NULL) + log_errx(1, "%s called twice", __func__); + + peer_addr = checked_strdup(addr); +} + +static void +log_common(int priority, int log_errno, const char *fmt, va_list ap) +{ + static char msgbuf[MSGBUF_LEN]; + static char msgbuf_strvised[MSGBUF_LEN * 4 + 1]; + int ret; + + ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); + if (ret < 0) { + fprintf(stderr, "%s: snprintf failed", getprogname()); + syslog(LOG_CRIT, "snprintf failed"); + exit(1); + } + + ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL); + if (ret < 0) { + fprintf(stderr, "%s: strnvis failed", getprogname()); + syslog(LOG_CRIT, "strnvis failed"); + exit(1); + } + + if (log_errno == -1) { + if (peer_name != NULL) { + fprintf(stderr, "%s: %s (%s): %s\n", getprogname(), + peer_addr, peer_name, msgbuf_strvised); + syslog(priority, "%s (%s): %s", + peer_addr, peer_name, msgbuf_strvised); + } else if (peer_addr != NULL) { + fprintf(stderr, "%s: %s: %s\n", getprogname(), + peer_addr, msgbuf_strvised); + syslog(priority, "%s: %s", + peer_addr, msgbuf_strvised); + } else { + fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised); + syslog(priority, "%s", msgbuf_strvised); + } + + } else { + if (peer_name != NULL) { + fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(), + peer_addr, peer_name, msgbuf_strvised, strerror(errno)); + syslog(priority, "%s (%s): %s: %s", + peer_addr, peer_name, msgbuf_strvised, strerror(errno)); + } else if (peer_addr != NULL) { + fprintf(stderr, "%s: %s: %s: %s\n", getprogname(), + peer_addr, msgbuf_strvised, strerror(errno)); + syslog(priority, "%s: %s: %s", + peer_addr, msgbuf_strvised, strerror(errno)); + } else { + fprintf(stderr, "%s: %s: %s\n", getprogname(), + msgbuf_strvised, strerror(errno)); + syslog(priority, "%s: %s", + msgbuf_strvised, strerror(errno)); + } + } +} + +void +log_err(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_common(LOG_CRIT, errno, fmt, ap); + va_end(ap); + + exit(eval); +} + +void +log_errx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_common(LOG_CRIT, -1, fmt, ap); + va_end(ap); + + exit(eval); +} + +void +log_warn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_common(LOG_WARNING, errno, fmt, ap); + va_end(ap); +} + +void +log_warnx(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + log_common(LOG_WARNING, -1, fmt, ap); + va_end(ap); +} + +void +log_debugx(const char *fmt, ...) +{ + va_list ap; + + if (log_level == 0) + return; + + va_start(ap, fmt); + log_common(LOG_DEBUG, -1, fmt, ap); + va_end(ap); +} diff --git a/usr.sbin/autofs/popen.c b/usr.sbin/autofs/popen.c new file mode 100644 index 000000000000..420fe2064bd1 --- /dev/null +++ b/usr.sbin/autofs/popen.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * Portions of this software were developed by Edward Tomasz Napierala + * under sponsorship from the FreeBSD Foundation. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +extern char **environ; + +struct pid { + SLIST_ENTRY(pid) next; + FILE *outfp; + pid_t pid; + char *command; +}; +static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist); + +#define ARGV_LEN 42 + +/* + * Replacement for popen(3), without stdin (which we do not use), but with + * stderr, proper logging, and improved command line arguments passing. + * Error handling is built in - if it returns, then it succeeded. + */ +FILE * +auto_popen(const char *argv0, ...) +{ + va_list ap; + struct pid *cur, *p; + pid_t pid; + int error, i, nullfd, outfds[2]; + char *arg, *argv[ARGV_LEN], *command; + + nullfd = open(_PATH_DEVNULL, O_RDWR, 0); + if (nullfd < 0) + log_err(1, "cannot open %s", _PATH_DEVNULL); + + error = pipe(outfds); + if (error != 0) + log_err(1, "pipe"); + + cur = malloc(sizeof(struct pid)); + if (cur == NULL) + log_err(1, "malloc"); + + argv[0] = checked_strdup(argv0); + command = argv[0]; + + va_start(ap, argv0); + for (i = 1;; i++) { + if (i >= ARGV_LEN) + log_errx(1, "too many arguments to auto_popen"); + arg = va_arg(ap, char *); + argv[i] = arg; + if (arg == NULL) + break; + + command = separated_concat(command, arg, ' '); + } + va_end(ap); + + cur->command = checked_strdup(command); + + switch (pid = fork()) { + case -1: /* Error. */ + log_err(1, "fork"); + /* NOTREACHED */ + case 0: /* Child. */ + dup2(nullfd, STDIN_FILENO); + dup2(outfds[1], STDOUT_FILENO); + + close(nullfd); + close(outfds[0]); + close(outfds[1]); + + SLIST_FOREACH(p, &pidlist, next) + close(fileno(p->outfp)); + execvp(argv[0], argv); + log_err(1, "failed to execute %s", argv[0]); + /* NOTREACHED */ + } + + log_debugx("executing \"%s\" as pid %d", command, pid); + + /* Parent; assume fdopen cannot fail. */ + cur->outfp = fdopen(outfds[0], "r"); + close(nullfd); + close(outfds[1]); + + /* Link into list of file descriptors. */ + cur->pid = pid; + SLIST_INSERT_HEAD(&pidlist, cur, next); + + return (cur->outfp); +} + +int +auto_pclose(FILE *iop) +{ + struct pid *cur, *last = NULL; + int status; + pid_t pid; + + /* + * Find the appropriate file pointer and remove it from the list. + */ + SLIST_FOREACH(cur, &pidlist, next) { + if (cur->outfp == iop) + break; + last = cur; + } + if (cur == NULL) { + return (-1); + } + if (last == NULL) + SLIST_REMOVE_HEAD(&pidlist, next); + else + SLIST_REMOVE_AFTER(last, next); + + fclose(cur->outfp); + + do { + pid = wait4(cur->pid, &status, 0, NULL); + } while (pid == -1 && errno == EINTR); + + if (WIFSIGNALED(status)) { + log_warnx("\"%s\", pid %d, terminated with signal %d", + cur->command, pid, WTERMSIG(status)); + return (status); + } + + if (WEXITSTATUS(status) != 0) { + log_warnx("\"%s\", pid %d, terminated with exit status %d", + cur->command, pid, WEXITSTATUS(status)); + return (status); + } + + log_debugx("\"%s\", pid %d, terminated gracefully", cur->command, pid); + + free(cur->command); + free(cur); + + return (pid == -1 ? -1 : status); +} diff --git a/usr.sbin/autofs/token.l b/usr.sbin/autofs/token.l new file mode 100644 index 000000000000..8224042114d8 --- /dev/null +++ b/usr.sbin/autofs/token.l @@ -0,0 +1,57 @@ +%{ +/*- + * Copyright (c) 2014 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Edward Tomasz Napierala under sponsorship + * from the FreeBSD Foundation. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +#include +#include + +#include "common.h" + +int lineno; + +#define YY_DECL int yylex(void) +extern int yylex(void); + +%} + +%option noinput +%option nounput +%option noyywrap + +%% +[a-zA-Z0-9\.\+-_/\:\[\]$&{}]+ { return STR; } +#.*\n { lineno++; return NEWLINE; }; +\\\n { lineno++; }; +\n { lineno++; return NEWLINE; } +[ \t]+ /* ignore whitespace */; +. { return STR; } +%% -- cgit v1.3 From fe248ffb7f054a5164e58660948e07bddf04f750 Mon Sep 17 00:00:00 2001 From: Dag-Erling Smørgrav Date: Sat, 23 Aug 2014 10:49:02 +0000 Subject: Setting rc_debug explicitly in /etc/defaults/rc.conf defeats its purpose. MFC after: 3 days --- etc/defaults/rc.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 87d92168191a..3c77d8dbb2eb 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -21,7 +21,7 @@ ### Important initial Boot-time options #################### ############################################################## -rc_debug="NO" # Set to YES to enable debugging output from rc.d +#rc_debug="NO" # Set to YES to enable debugging output from rc.d rc_info="NO" # Enables display of informational messages at boot. rc_startmsgs="YES" # Show "Starting foo:" messages at boot rcshutdown_timeout="90" # Seconds to wait before terminating rc.shutdown -- cgit v1.3 From 5407523fe59b73f0f4f371bb270f590c736575a9 Mon Sep 17 00:00:00 2001 From: Dag-Erling Smørgrav Date: Sat, 23 Aug 2014 10:51:37 +0000 Subject: Add support for /etc/rc.conf.d/ subdirectories. This is particularly useful for services such as "network" (netif) where each interface can now have its own separate configuration file. Add /etc/rc.conf.d to the mtree file so it is always present. MFC after: 3 days --- etc/mtree/BSD.root.dist | 2 ++ etc/rc.subr | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index d494ef68420e..7b8d9e7f8060 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -62,6 +62,8 @@ .. ppp .. + rc.conf.d + .. rc.d .. security diff --git a/etc/rc.subr b/etc/rc.subr index b6172dbf4d8a..f02ae14a6c0d 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -1290,8 +1290,16 @@ load_rc_config() _rc_conf_loaded=true fi if [ -f /etc/rc.conf.d/"$_name" ]; then - debug "Sourcing /etc/rc.conf.d/${_name}" + debug "Sourcing /etc/rc.conf.d/$_name" . /etc/rc.conf.d/"$_name" + elif [ -d /etc/rc.conf.d/"$_name" ] ; then + local _rc + for _rc in /etc/rc.conf.d/"$_name"/* ; do + if [ -f "$_rc" ] ; then + debug "Sourcing $_rc" + . "$_rc" + fi + done fi # Set defaults if defined. -- cgit v1.3 From f7ae83075ac308e01817a2ed7f11c32b27e31144 Mon Sep 17 00:00:00 2001 From: Edward Tomasz Napierala Date: Sat, 23 Aug 2014 12:00:45 +0000 Subject: Add "nobrowse" option. Previously automountd(8) always behaved as if it was set, now it's conditional. PR: 192862 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation --- etc/auto_master | 2 +- usr.sbin/autofs/auto_master.5 | 6 +++++- usr.sbin/autofs/automountd.c | 33 ++++++++++++++++++++++++++++++--- usr.sbin/autofs/common.c | 41 +++++++++++++++++++++++++++++++++++------ 4 files changed, 71 insertions(+), 11 deletions(-) (limited to 'etc') diff --git a/etc/auto_master b/etc/auto_master index 16d55e2b4cb3..3b3e5dad70b2 100644 --- a/etc/auto_master +++ b/etc/auto_master @@ -2,4 +2,4 @@ # # Automounter master map, see auto_master(5) for details. # -/net -hosts -nosuid +/net -hosts -nobrowse,nosuid diff --git a/usr.sbin/autofs/auto_master.5 b/usr.sbin/autofs/auto_master.5 index f923f4f76827..69d6afeac9d1 100644 --- a/usr.sbin/autofs/auto_master.5 +++ b/usr.sbin/autofs/auto_master.5 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 31, 2014 +.Dd August 23, 2014 .Dt AUTO_MASTER 5 .Os .Sh NAME @@ -134,6 +134,10 @@ is used to specify filesystem type. It is not passed to the mount program as an option. Instead, it is passed as argument to .Cm "mount -t". +The special option +.Li nobrowse +is used to disable creation of top-level directories for special +and executable maps. .Pp The optional .Pa mountpoint diff --git a/usr.sbin/autofs/automountd.c b/usr.sbin/autofs/automountd.c index 9eaf049d8639..b5111035fb6c 100644 --- a/usr.sbin/autofs/automountd.c +++ b/usr.sbin/autofs/automountd.c @@ -182,7 +182,7 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, const char *map; struct node *root, *parent, *node; FILE *f; - char *options, *fstype, *retrycnt, *tmp; + char *options, *fstype, *nobrowse, *retrycnt, *tmp; int error; log_debugx("got request %d: from %s, path %s, prefix \"%s\", " @@ -222,6 +222,28 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, log_debugx("found node defined at %s:%d; not a mountpoint", node->n_config_file, node->n_config_line); + options = node_options(node); + + /* + * Prepend options passed via automountd(8) command line. + */ + if (cmdline_options != NULL) { + options = + separated_concat(cmdline_options, options, ','); + } + + nobrowse = pick_option("nobrowse", &options); + if (nobrowse != NULL && adr->adr_key[0] == '\0') { + log_debugx("skipping map %s due to \"nobrowse\" " + "option; exiting", map); + done(0); + + /* + * Exit without calling exit_callback(). + */ + quick_exit(0); + } + /* * Not a mountpoint; create directories in the autofs mount * and complete the request. @@ -239,9 +261,9 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, if (node != NULL) create_subtree(node, false); } - done(0); log_debugx("nothing to mount; exiting"); + done(0); /* * Exit without calling exit_callback(). @@ -273,6 +295,11 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, */ options = separated_concat(options, "automounted", ','); + /* + * Remove "nobrowse", mount(8) doesn't understand it. + */ + pick_option("nobrowse", &options); + /* * Figure out fstype. */ @@ -309,8 +336,8 @@ handle_request(const struct autofs_daemon_request *adr, char *cmdline_options, if (error != 0) log_errx(1, "mount failed"); - done(0); log_debugx("mount done; exiting"); + done(0); /* * Exit without calling exit_callback(). diff --git a/usr.sbin/autofs/common.c b/usr.sbin/autofs/common.c index 205d15213774..9695db59b8ab 100644 --- a/usr.sbin/autofs/common.c +++ b/usr.sbin/autofs/common.c @@ -856,6 +856,36 @@ again: } } +/* + * Parse output of a special map called without argument. This is just + * a list of keys. + */ +static void +parse_map_keys_yyin(struct node *parent, const char *map) +{ + char *key = NULL; + int ret; + + lineno = 1; + + for (;;) { + ret = yylex(); + + if (ret == NEWLINE) + continue; + + if (ret == 0) { + /* + * End of file. + */ + break; + } + + key = checked_strdup(yytext); + node_new(parent, key, NULL, NULL, map, lineno); + } +} + static bool file_is_executable(const char *path) { @@ -882,11 +912,6 @@ parse_special_map(struct node *parent, const char *map, const char *key) assert(map[0] == '-'); - if (key == NULL) { - log_debugx("skipping map %s due to forced -nobrowse", map); - return; - } - /* * +1 to skip leading "-" in map name. */ @@ -897,7 +922,11 @@ parse_special_map(struct node *parent, const char *map, const char *key) yyin = auto_popen(path, key, NULL); assert(yyin != NULL); - parse_map_yyin(parent, map, key); + if (key == NULL) { + parse_map_keys_yyin(parent, map); + } else { + parse_map_yyin(parent, map, key); + } error = auto_pclose(yyin); yyin = NULL; -- cgit v1.3 From 651045d6de2189ba1f8e459ff4849b8ee8fcee0f Mon Sep 17 00:00:00 2001 From: Stefan Eßer Date: Tue, 26 Aug 2014 08:13:30 +0000 Subject: Add references to vt(4) and the configuration files in /usr7share/vt where appropriate (i.e. where syscons was already mentioned and vt supports the feature). Comments in defaults/rc.conf are updated to match the contents of the modified man-page rc.conf(5). Reviewed by: pluknet, emaste MFC after: 3 days --- etc/defaults/rc.conf | 8 ++++---- share/man/man4/atkbd.4 | 5 ++++- share/man/man4/kbdmux.4 | 3 ++- share/man/man4/splash.4 | 3 +++ share/man/man4/ukbd.4 | 5 ++++- share/man/man4/vkbd.4 | 3 ++- share/man/man4/vt.4 | 7 +++++-- share/man/man5/rc.conf.5 | 26 +++++++++++++++++++++----- share/man/man7/hier.7 | 20 ++++++++++++++++++++ share/man/man8/nanobsd.8 | 2 ++ 10 files changed, 67 insertions(+), 15 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 3c77d8dbb2eb..b5db884aab85 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -516,15 +516,15 @@ ip6addrctl_policy="AUTO" # A pre-defined address selection policy ############################################################## keyboard="" # keyboard device to use (default /dev/kbd0). -keymap="NO" # keymap in /usr/share/syscons/keymaps/* (or NO). +keymap="NO" # keymap in /usr/share/{syscons,vt}/keymaps/* (or NO). keyrate="NO" # keyboard rate to: slow, normal, fast (or NO). keybell="NO" # See kbdcontrol(1) for options. Use "off" to disable. keychange="NO" # function keys default values (or NO). cursor="NO" # cursor type {normal|blink|destructive} (or NO). scrnmap="NO" # screen map in /usr/share/syscons/scrnmaps/* (or NO). -font8x16="NO" # font 8x16 from /usr/share/syscons/fonts/* (or NO). -font8x14="NO" # font 8x14 from /usr/share/syscons/fonts/* (or NO). -font8x8="NO" # font 8x8 from /usr/share/syscons/fonts/* (or NO). +font8x16="NO" # font 8x16 from /usr/share/{syscons,vt}/fonts/* (or NO). +font8x14="NO" # font 8x14 from /usr/share/{syscons,vt}/fonts/* (or NO). +font8x8="NO" # font 8x8 from /usr/share/{syscons,vt}/fonts/* (or NO). blanktime="300" # blank time (in seconds) or "NO" to turn it off. saver="NO" # screen saver: Uses /boot/kernel/${saver}_saver.ko moused_nondefault_enable="YES" # Treat non-default mice as enabled unless diff --git a/share/man/man4/atkbd.4 b/share/man/man4/atkbd.4 index 202963a3035d..7ce99e70e467 100644 --- a/share/man/man4/atkbd.4 +++ b/share/man/man4/atkbd.4 @@ -51,7 +51,9 @@ driver, provides access to the AT 84 keyboard or the AT enhanced keyboard which is connected to the AT keyboard controller. .Pp This driver is required for the console driver -.Xr syscons 4 . +.Xr syscons 4 +or +.Xr vt 4 . .Pp There can be only one .Nm @@ -211,6 +213,7 @@ In both cases, you also need to have following lines in .Xr atkbdc 4 , .Xr psm 4 , .Xr syscons 4 , +.Xr vt 4 , .Xr kbdmap 5 , .Xr loader 8 .Sh HISTORY diff --git a/share/man/man4/kbdmux.4 b/share/man/man4/kbdmux.4 index a909ba9e8809..0815f054c8f5 100644 --- a/share/man/man4/kbdmux.4 +++ b/share/man/man4/kbdmux.4 @@ -34,7 +34,8 @@ utility. .Xr kbdcontrol 1 , .Xr atkbd 4 , .Xr syscons 4 , -.Xr ukbd 4 +.Xr ukbd 4 , +.Xr vt 4 .Sh HISTORY The .Nm diff --git a/share/man/man4/splash.4 b/share/man/man4/splash.4 index 6cbccf3d966f..46710c2ff225 100644 --- a/share/man/man4/splash.4 +++ b/share/man/man4/splash.4 @@ -245,6 +245,7 @@ bitmap_name="/boot/splash.bin" .Xr vidcontrol 1 , .Xr syscons 4 , .Xr vga 4 , +.Xr vt 4 , .Xr loader.conf 5 , .Xr rc.conf 5 , .Xr kldload 8 , @@ -285,6 +286,8 @@ code. .Sh CAVEATS Both the splash screen and the screen saver work with .Xr syscons 4 + or +.Xr vt 4 only. .Sh BUGS If you load a screen saver while another screen saver has already diff --git a/share/man/man4/ukbd.4 b/share/man/man4/ukbd.4 index 3a3125d74ed5..1fade2ad5755 100644 --- a/share/man/man4/ukbd.4 +++ b/share/man/man4/ukbd.4 @@ -127,7 +127,9 @@ Make the keyboards available through a character device in The above lines will put the French ISO keymap in the ukbd driver. You can specify any keymap in .Pa /usr/share/syscons/keymaps -with this option. +or +.Pa /usr/share/vt/keymaps +(depending on the console driver being used) with this option. .Pp .D1 Cd "options KBD_DISABLE_KEYMAP_LOADING" .Pp @@ -151,6 +153,7 @@ driver to the kernel. .Xr syscons 4 , .Xr uhci 4 , .Xr usb 4 , +.Xr vt 4 , .Xr config 8 .Sh AUTHORS .An -nosplit diff --git a/share/man/man4/vkbd.4 b/share/man/man4/vkbd.4 index 78110a6107bc..c70d22620b5c 100644 --- a/share/man/man4/vkbd.4 +++ b/share/man/man4/vkbd.4 @@ -129,7 +129,8 @@ All queued scan codes are thrown away. .Xr kbdcontrol 1 , .Xr atkbdc 4 , .Xr psm 4 , -.Xr syscons 4 +.Xr syscons 4 , +.Xr vt 4 .Sh HISTORY The .Nm diff --git a/share/man/man4/vt.4 b/share/man/man4/vt.4 index 013974a41c08..889c75c0afa9 100644 --- a/share/man/man4/vt.4 +++ b/share/man/man4/vt.4 @@ -211,13 +211,17 @@ Power down. Default is 15, all enabled. .El .Sh FILES -.Bl -tag -width /usr/share/syscons/keymaps/* -compact +.Bl -tag -width /usr/share/vt/keymaps/* -compact .It Pa /dev/console .It Pa /dev/consolectl .It Pa /dev/ttyv* virtual terminals .It Pa /etc/ttys terminal initialization information +.It Pa /usr/share/vt/fonts/*.fnt +console fonts +.It Pa /usr/share/vt/keymaps/*.kbd +keyboard layouts .El .Sh EXAMPLES This example changes the default color of normal text to green on a @@ -243,7 +247,6 @@ on a black background, or black on a bright red background when reversed. .Xr splash 4 , .Xr syscons 4 , .Xr ukbd 4 , -.Xr vga 4 , .Xr kbdmap 5 , .Xr rc.conf 5 , .Xr ttys 5 , diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index c87de447bce5..2c6aa0a1464d 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -3111,8 +3111,13 @@ set to this device. If set to .Dq Li NO , no keymap is installed, otherwise the value is used to install -the keymap file in -.Pa /usr/share/syscons/keymaps/ Ns Ao Ar value Ac Ns Pa .kbd . +the keymap file found in +.Pa /usr/share/syscons/keymaps/ Ns Ao Ar value Ac Ns Pa .kbd +(if using +.Xr syscons 4 ) or +.Pa /usr/share/vt/keymaps/ Ns Ao Ar value Ac Ns Pa .kbd +(if using +.Xr vt 4 ) . .It Va keyrate .Pq Vt str The keyboard repeat speed. @@ -3147,6 +3152,9 @@ If set to no screen map is installed, otherwise the value is used to install the screen map file in .Pa /usr/share/syscons/scrnmaps/ Ns Aq Ar value . +This parameter is ignored when using +.Xr vt 4 +as the console driver. .It Va font8x16 .Pq Vt str If set to @@ -3154,7 +3162,9 @@ If set to the default 8x16 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value -is used. +or +.Pa /usr/share/vt/fonts/ Ns Aq Ar value +is used (depending on the console driver being used). .It Va font8x14 .Pq Vt str If set to @@ -3162,7 +3172,9 @@ If set to the default 8x14 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value -is used. +or +.Pa /usr/share/vt/fonts/ Ns Aq Ar value +is used (depending on the console driver being used). .It Va font8x8 .Pq Vt str If set to @@ -3170,7 +3182,9 @@ If set to the default 8x8 font value is used for screen size requests, otherwise the value in .Pa /usr/share/syscons/fonts/ Ns Aq Ar value -is used. +or +.Pa /usr/share/vt/fonts/ Ns Aq Ar value +is used (depending on the console driver being used). .It Va blanktime .Pq Vt int If set to @@ -3377,6 +3391,8 @@ For example, .Dq Fl h Li 200 will set the .Xr syscons 4 +or +.Xr vt 4 scrollback (history) buffer to 200 lines. .It Va cron_enable .Pq Vt bool diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index 782517cefc94..ae1a2a1078d2 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -633,6 +633,26 @@ timezone configuration information; see .Xr tzfile 5 .El +.It Pa vt/ +files used by vt; +see +.Xr vt 4 +.Bl -tag -width ".Pa scrnmaps/" -compact +.It Pa fonts/ +console fonts; +see +.Xr vidcontrol 1 +and +.Xr vidfont 1 +.It Pa keymaps/ +console keyboard maps; +see +.Xr kbdcontrol 1 +and +.Xr kbdmap 1 +.\" .It Pa scrnmaps/ +.\" console screen maps +.El .It Pa src/ .Bx , third-party, and/or local source files diff --git a/share/man/man8/nanobsd.8 b/share/man/man8/nanobsd.8 index ef23aa81d9a7..3668112cce0a 100644 --- a/share/man/man8/nanobsd.8 +++ b/share/man/man8/nanobsd.8 @@ -277,6 +277,8 @@ Disables .Xr getty 8 on the virtual .Xr syscons 4 +or +.Xr vt 4 terminals .Pq Pa /dev/ttyv* and enables the use of the first serial port as the system -- cgit v1.3 From 0dba3159e1f4fabf6d29c43a8e2fefa7dd123e72 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Tue, 26 Aug 2014 22:33:34 +0000 Subject: Allow to configure services from ${LOCALBASE}/etc/rc.conf.d Reviewed by: bdrewery MFC after: 1 week Relnotes: yes --- etc/rc.subr | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'etc') diff --git a/etc/rc.subr b/etc/rc.subr index f02ae14a6c0d..59fe68be281f 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -1301,6 +1301,10 @@ load_rc_config() fi done fi + if [ -f ${LOCALBASE:-/usr/local}/etc/rc.conf.d/"$_name" ]; then + debug "Sourcing ${LOCALBASE:-/usr/local}/etc/rc.conf.d/${_name}" + . ${LOCALBASE:-/usr/local}/etc/rc.conf.d/"$_name" + fi # Set defaults if defined. for _var in $rcvar; do -- cgit v1.3 From 4ccf710a3b8965c93460984143bb7377a4665ca3 Mon Sep 17 00:00:00 2001 From: Gavin Atkinson Date: Tue, 26 Aug 2014 22:39:24 +0000 Subject: Fix xref, pam(8) -> pam(3) PR: 193045 Submitted by: rsimmons0 gmail com MFC after: 3 days --- etc/pam.d/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/pam.d/README b/etc/pam.d/README index 7b8f9582124e..2824c054fe85 100644 --- a/etc/pam.d/README +++ b/etc/pam.d/README @@ -8,7 +8,7 @@ particular service, the /etc/pam.d/other is used instead. If that file does not exist, /etc/pam.conf is searched for entries matching the specified service or, failing that, the "other" service. -See the pam(8) manual page for an explanation of the workings of the +See the pam(3) manual page for an explanation of the workings of the PAM library and descriptions of the various files and modules. Below is a summary of the format for the pam.conf and /etc/pam.d/* files. -- cgit v1.3 From 8eac80769b8e3817cea84c2d73e311114c03d938 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Wed, 27 Aug 2014 09:19:22 +0000 Subject: - Use $local_startup to load rc.conf.d/* scripts. - Document support of rc.conf.d//* introduced in r270392. Discussed with: bapt --- etc/rc.subr | 33 ++++++++++++++++----------------- share/man/man5/rc.conf.5 | 23 ++++++++++++++++++++--- 2 files changed, 36 insertions(+), 20 deletions(-) (limited to 'etc') diff --git a/etc/rc.subr b/etc/rc.subr index 59fe68be281f..ff4e898597ca 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -1270,7 +1270,7 @@ run_rc_script() # load_rc_config() { - local _name _rcvar_val _var _defval _v _msg _new + local _name _rcvar_val _var _defval _v _msg _new _d _name=$1 if [ -z "$_name" ]; then err 3 'USAGE: load_rc_config name' @@ -1289,22 +1289,21 @@ load_rc_config() fi _rc_conf_loaded=true fi - if [ -f /etc/rc.conf.d/"$_name" ]; then - debug "Sourcing /etc/rc.conf.d/$_name" - . /etc/rc.conf.d/"$_name" - elif [ -d /etc/rc.conf.d/"$_name" ] ; then - local _rc - for _rc in /etc/rc.conf.d/"$_name"/* ; do - if [ -f "$_rc" ] ; then - debug "Sourcing $_rc" - . "$_rc" - fi - done - fi - if [ -f ${LOCALBASE:-/usr/local}/etc/rc.conf.d/"$_name" ]; then - debug "Sourcing ${LOCALBASE:-/usr/local}/etc/rc.conf.d/${_name}" - . ${LOCALBASE:-/usr/local}/etc/rc.conf.d/"$_name" - fi + + for _d in /etc ${local_startup%*/rc.d}; do + if [ -f ${_d}/rc.conf.d/"$_name" ]; then + debug "Sourcing ${_d}/rc.conf.d/$_name" + . ${_d}/rc.conf.d/"$_name" + elif [ -d ${_d}/rc.conf.d/"$_name" ] ; then + local _rc + for _rc in ${_d}/rc.conf.d/"$_name"/* ; do + if [ -f "$_rc" ] ; then + debug "Sourcing $_rc" + . "$_rc" + fi + done + fi + done # Set defaults if defined. for _var in $rcvar; do diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index ea80394254ae..669e773bac64 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -63,20 +63,37 @@ The file is used to override settings in .Pa /etc/rc.conf for historical reasons. +.Pp In addition to .Pa /etc/rc.conf.local you can also place smaller configuration files for each .Xr rc 8 script in the .Pa /etc/rc.conf.d -directory or in the -.Pa ${LOCALBASE}/etc/rc.conf.d -directory, which will be included by the +directory or +.Ao Ar dir Ac Ns Pa /rc.conf.d +directories specified in +.Va local_startup , +which will be included by the .Va load_rc_config function. For jail configurations you could use the file .Pa /etc/rc.conf.d/jail to store jail specific configuration options. +If +.Va local_startup +contains +.Pa /usr/local/etc/rc.d +and +.Pa /opt/conf , +.Pa /usr/local/rc.conf.d/jail +and +.Pa /opt/conf/rc.conf.d/jail +will be loaded. +If +.Ao Ar dir Ac Ns Pa /rc.conf.d/ Ns Ao Ar name Ac +is a directory, +all of files in the directory will be loaded. Also see the .Va rc_conf_files variable below. -- cgit v1.3 From 5316d2b10f22296d0a4e77925d75d5f92033d6e1 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 29 Aug 2014 06:23:00 +0000 Subject: Fix rc.d/gssd script to define the default values in a standard way. --- etc/defaults/rc.conf | 1 + etc/rc.d/gssd | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index b5db884aab85..7c7d899470f6 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -282,6 +282,7 @@ kfd_enable="NO" # Run kfd (or NO) kfd_program="/usr/libexec/kfd" # path to kerberos 5 kfd daemon gssd_enable="NO" # Run the gssd daemon (or NO). +gssd_program="/usr/sbin/gssd" # Path to gssd. gssd_flags="" # Flags for gssd. rwhod_enable="NO" # Run the rwho daemon (or NO). diff --git a/etc/rc.d/gssd b/etc/rc.d/gssd index 3788307e2981..e981478acdd7 100755 --- a/etc/rc.d/gssd +++ b/etc/rc.d/gssd @@ -9,10 +9,8 @@ . /etc/rc.subr -name="gssd" +name=gssd +rcvar=gssd_enable load_rc_config $name -rcvar="gssd_enable" -command="${gssd:-/usr/sbin/${name}}" -eval ${name}_flags=\"${gssd_flags}\" run_rc_command "$1" -- cgit v1.3 From 7b3e8bee90fcf002ea50353d84d9309669f01b38 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 29 Aug 2014 06:31:18 +0000 Subject: - Add a warning message when an IPv6 address is specified with no prefixlen. - Use a parameter argument in jls(8) instead of doing grep. --- etc/rc.d/jail | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/jail b/etc/rc.d/jail index d8a88e438b7c..1049fcb23f2d 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -321,6 +321,8 @@ jail_extract_address() elif [ "${_type}" = "inet6" ]; then # In case _maske is not set for IPv6, use /128. _mask=${_mask:-/128} + warn "$_type $_addr: an IPv6 address should always be " \ + "specified with a prefix length. /128 is used." fi } @@ -420,7 +422,7 @@ jail_status() jail_start() { - local _j _jid _jn _jl + local _j _jid _jl if [ $# = 0 ]; then return @@ -433,12 +435,10 @@ jail_start() command_args="-f $jail_conf -c" _tmp=`mktemp -t jail` || exit 3 if $command $rc_flags $command_args >> $_tmp 2>&1; then - $jail_jls -nq | while read IN; do - _jn=$(echo $IN | tr " " "\n" | grep ^name=) - _jid=$(echo $IN | tr " " "\n" | grep ^jid=) - echo -n " ${_jn#name=}" - echo "${_jid#jid=}" \ - > /var/run/jail_${_jn#name=}.id + $jail_jls jid name | while read IN; do + set -- $IN + echo -n " $2" + echo $1 > /var/run/jail_$2.id done else tail -1 $_tmp @@ -468,9 +468,8 @@ jail_start() sleep 1 for _j in $_jl; do echo -n " ${_hostname:-${_j}}" - if _jid=$($jail_jls -n -j $_j | tr " " "\n" | \ - grep ^jid=); then - echo "${_jid#jid=}" > /var/run/jail_${_j}.id + if _jid=$($jail_jls -j $_j jid); then + echo "$_jid" > /var/run/jail_${_j}.id else rm -f /var/run/jail_${_j}.id echo " cannot start jail " \ @@ -492,9 +491,8 @@ jail_start() if $command $rc_flags $command_args \ >> $_tmp 2>&1 /var/run/jail_${_j}.id + _jid=$($jail_jls -j $_j jid) + echo $_jid > /var/run/jail_${_j}.id else rm -f /var/run/jail_${_j}.id echo " cannot start jail " \ @@ -509,7 +507,7 @@ jail_start() jail_stop() { - local _j _jn + local _j if [ $# = 0 ]; then return @@ -520,16 +518,14 @@ jail_stop() command=$jail_program rc_flags=$jail_flags command_args="-f $jail_conf -r" - $jail_jls -nq | while read IN; do - _jn=$(echo $IN | tr " " "\n" | grep ^name=) - echo -n " ${_jn#name=}" + $jail_jls name | while read _j; do + echo -n " $_j" _tmp=`mktemp -t jail` || exit 3 - $command $rc_flags $command_args ${_jn#name=} \ - >> $_tmp 2>&1 - if $jail_jls -j ${_jn#name=} > /dev/null 2>&1; then + $command $rc_flags $command_args $_j >> $_tmp 2>&1 + if $jail_jls -j $_j > /dev/null 2>&1; then tail -1 $_tmp else - rm -f /var/run/jail_${_jn#name=}.id + rm -f /var/run/jail_${_j}.id fi rm -f $_tmp done -- cgit v1.3 From 137ae2c4f0f7c18e457b74236cd0c0364a0858fc Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 29 Aug 2014 07:51:47 +0000 Subject: Restructure rc.d scripts for kerberos5 daemons: - Rename $kerberos5_server_enable with $kdc_enable and rename rc.d/kerberos with rc.d/kdc. - Rename $kadmin5_server_enable with $kadmind_enable. - Rename ${kerberos5,kpasswdd}_server with ${kdc,kpasswdd}_program. - Fix rc.d/{kadmind,kerberos,kpasswdd,kfd} scripts not to change variables after load_rc_config(). - Add rc.d/ipropd_master and rc.d/ipropd_slave scripts. These are for iprop-master(8) and iprop-slave(8). Keytab used for iprop service is defined in ipropd_{master,slave}_keytab (/etc/krb5.keytab by default). - Add dependency on rc.d/kdc to SERVERS. rc.d/kdc must be invoked as early as possible before scripts divided by rc.d/SERVERS. Note that changes to rc.d/{kdc,kpasswdd,kadmind} are backward-compatible with the old configuration variables: ${kerberos5,kpasswdd,kadmin5}_server{,_enable,_flags}. --- etc/defaults/rc.conf | 27 ++++++++++++++++++++------- etc/rc.d/Makefile | 4 +++- etc/rc.d/SERVERS | 2 +- etc/rc.d/ipropd_master | 40 ++++++++++++++++++++++++++++++++++++++++ etc/rc.d/ipropd_slave | 32 ++++++++++++++++++++++++++++++++ etc/rc.d/kadmind | 28 ++++++++++++++++++---------- etc/rc.d/kdc | 27 +++++++++++++++++++++++++++ etc/rc.d/kerberos | 17 ----------------- etc/rc.d/kfd | 12 +++++++++--- etc/rc.d/kpasswdd | 26 +++++++++++++++++--------- 10 files changed, 167 insertions(+), 48 deletions(-) create mode 100755 etc/rc.d/ipropd_master create mode 100755 etc/rc.d/ipropd_slave create mode 100755 etc/rc.d/kdc delete mode 100755 etc/rc.d/kerberos (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 7c7d899470f6..190bb9c074bd 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -271,15 +271,28 @@ local_unbound_enable="NO" # local caching resolver # # kerberos. Do not run the admin daemons on slave servers # -kerberos5_server_enable="NO" # Run a kerberos 5 master server (or NO). -kerberos5_server="/usr/libexec/kdc" # path to kerberos 5 KDC -kerberos5_server_flags="--detach" # Additional flags to the kerberos 5 server -kadmind5_server_enable="NO" # Run kadmind (or NO) -kadmind5_server="/usr/libexec/kadmind" # path to kerberos 5 admin daemon -kpasswdd_server_enable="NO" # Run kpasswdd (or NO) -kpasswdd_server="/usr/libexec/kpasswdd" # path to kerberos 5 passwd daemon +kdc_enable="NO" # Run a kerberos 5 KDC (or NO). +kdc_program="/usr/libexec/kdc" # path to kerberos 5 KDC +kdc_flags="" # Additional flags to the kerberos 5 KDC +kadmind_enable="NO" # Run kadmind (or NO) +kadmind_program="/usr/libexec/kadmind" # path to kadmind +kpasswdd_enable="NO" # Run kpasswdd (or NO) +kpasswdd_program="/usr/libexec/kpasswdd" # path to kpasswdd kfd_enable="NO" # Run kfd (or NO) kfd_program="/usr/libexec/kfd" # path to kerberos 5 kfd daemon +kfd_flags="" +ipropd_master_enable="NO" # Run Heimdal incremental propagation daemon + # (master daemon). +ipropd_master_program="/usr/libexec/ipropd-master" +ipropd_master_flags="" # Flags to ipropd-master. +ipropd_master_keytab="/etc/krb5.keytab" # keytab for ipropd-master. +ipropd_master_slaves="" # slave node names used for /var/heimdal/slaves. +ipropd_slave_enable="NO" # Run Heimdal incremental propagation daemon + # (slave daemon). +ipropd_slave_program="/usr/libexec/ipropd-slave" +ipropd_slave_flags="" # Flags to ipropd-slave. +ipropd_slave_keytab="/etc/krb5.keytab" # keytab for ipropd-slave. +ipropd_slave_masters="" # master node names. gssd_enable="NO" # Run the gssd daemon (or NO). gssd_program="/usr/sbin/gssd" # Path to gssd. diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 75f79b9b8210..64e83ac8ca50 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -65,12 +65,14 @@ FILES= DAEMON \ ipfw \ ipmon \ ipnat \ + ipropd_master \ + ipropd_slave \ ipsec \ iscsictl \ iscsid \ jail \ kadmind \ - kerberos \ + kdc \ keyserv \ kfd \ kld \ diff --git a/etc/rc.d/SERVERS b/etc/rc.d/SERVERS index 1cf019a056dd..7cd156a6237b 100755 --- a/etc/rc.d/SERVERS +++ b/etc/rc.d/SERVERS @@ -4,7 +4,7 @@ # # PROVIDE: SERVERS -# REQUIRE: mountcritremote abi ldconfig savecore watchdogd +# REQUIRE: mountcritremote abi ldconfig savecore watchdogd kdc # This is a dummy dependency, for early-start servers relying on # some basic configuration. diff --git a/etc/rc.d/ipropd_master b/etc/rc.d/ipropd_master new file mode 100755 index 000000000000..0611dea794d8 --- /dev/null +++ b/etc/rc.d/ipropd_master @@ -0,0 +1,40 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: ipropd_master +# REQUIRE: kdc +# KEYWORD: shutdown + +. /etc/rc.subr + +name=ipropd_master +rcvar=${name}_enable +required_files="$ipropd_master_keytab" +start_precmd=${name}_start_precmd +start_postcmd=${name}_start_postcmd + +ipropd_master_start_precmd() +{ + + if [ -z "$ipropd_master_slaves" ]; then + warn "\$ipropd_master_slaves is empty." + return 1 + fi + for _slave in $ipropd_master_slaves; do + echo $_slave + done > /var/heimdal/slaves || return 1 + command_args="$command_args \ + --keytab=\"$ipropd_master_keytab\" \ + --detach \ + " +} +ipropd_master_start_postcmd() +{ + + echo "${name}: slave nodes: $ipropd_master_slaves" +} + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/ipropd_slave b/etc/rc.d/ipropd_slave new file mode 100755 index 000000000000..803281e0e9fe --- /dev/null +++ b/etc/rc.d/ipropd_slave @@ -0,0 +1,32 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: ipropd_slave +# REQUIRE: kdc +# KEYWORD: shutdown + +. /etc/rc.subr + +name=ipropd_slave +rcvar=${name}_enable +required_files="$ipropd_slave_keytab" +start_precmd=${name}_start_precmd + +ipropd_slave_start_precmd() +{ + + if [ -z "$ipropd_slave_masters" ]; then + warn "\$ipropd_slave_masters is empty." + return 1 + fi + command_args=" \ + $command_args \ + --keytab=\"$ipropd_slave_keytab\" \ + --detach \ + $ipropd_slave_masters" +} + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/kadmind b/etc/rc.d/kadmind index 1e07938ffcd6..d4acd7cda558 100755 --- a/etc/rc.d/kadmind +++ b/etc/rc.d/kadmind @@ -3,18 +3,26 @@ # $FreeBSD$ # -# PROVIDE: kadmin -# REQUIRE: kerberos -# BEFORE: DAEMON +# PROVIDE: kadmind +# REQUIRE: kdc +# KEYWORD: shutdown . /etc/rc.subr -name="kadmind5" -load_rc_config $name -rcvar="kadmind5_server_enable" -unset start_cmd -command="${kadmind5_server}" -command_args="&" -required_vars="kerberos5_server_enable" +name=kadmind +rcvar=${name}_enable +required_vars=kdc_enable +start_precmd=${name}_start_precmd + +set_rcvar_obsolete kadmind5_server_enable kadmind_enable +set_rcvar_obsolete kadmind5_server kadmind_program +set_rcvar_obsolete kerberos5_server_enable kdc_enable + +kadmind_start_precmd() +{ + command_args="$command_args &" +} + +load_rc_config $name run_rc_command "$1" diff --git a/etc/rc.d/kdc b/etc/rc.d/kdc new file mode 100755 index 000000000000..aef96df34a15 --- /dev/null +++ b/etc/rc.d/kdc @@ -0,0 +1,27 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: kdc +# REQUIRE: NETWORKING +# KEYWORD: shutdown + +. /etc/rc.subr + +name=kdc +rcvar=${name}_enable +start_precmd=${name}_start_precmd + +set_rcvar_obsolete kerberos5_server_enable kdc_enable +set_rcvar_obsolete kerberos5_server kdc_program +set_rcvar_obsolete kerberos5_server_flags kdc_flags + +kdc_start_precmd() +{ + + command_args="$command_args --detach" +} + +load_rc_config $name +run_rc_command "$1" diff --git a/etc/rc.d/kerberos b/etc/rc.d/kerberos deleted file mode 100755 index 3eeb32af3ff5..000000000000 --- a/etc/rc.d/kerberos +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: kerberos -# REQUIRE: NETWORKING - -. /etc/rc.subr - -name="kerberos5" -rcvar="kerberos5_server_enable" - -load_rc_config $name -command="${kerberos5_server}" -kerberos5_flags="${kerberos5_server_flags}" -run_rc_command "$1" diff --git a/etc/rc.d/kfd b/etc/rc.d/kfd index d393f95025d1..b6d936591200 100755 --- a/etc/rc.d/kfd +++ b/etc/rc.d/kfd @@ -10,8 +10,14 @@ . /etc/rc.subr name=kfd -rcvar=kfd_enable -load_rc_config $name -command_args="-i &" +rcvar=${name}_enable +start_precmd=${name}_start_precmd + +kfd_start_precmd() +{ + command_args="$command_args -i &" +} + +load_rc_config $name run_rc_command "$1" diff --git a/etc/rc.d/kpasswdd b/etc/rc.d/kpasswdd index d7f40ac4ad7d..cf72d80fa713 100755 --- a/etc/rc.d/kpasswdd +++ b/etc/rc.d/kpasswdd @@ -4,17 +4,25 @@ # # PROVIDE: kpasswdd -# REQUIRE: kadmin -# BEFORE: DAEMON +# REQUIRE: kdc +# KEYWORD: shutdown . /etc/rc.subr -name="kpasswdd" -load_rc_config $name -rcvar="kpasswdd_server_enable" -unset start_cmd -command="${kpasswdd_server}" -command_args="&" -required_vars="kadmind5_server_enable" +name=kpasswdd +rcvar=${name}_enable +required_vars=kdc_enable +start_precmd=${name}_start_precmd + +set_rcvar_obsolete kpasswdd_server_enable kpasswdd_enable +set_rcvar_obsolete kpasswdd_server kpasswdd_program +set_rcvar_obsolete kerberos5_server_enable kdc_enable + +kpasswdd_start_precmd() +{ + command_args="$command_args &" +} + +load_rc_config $name run_rc_command "$1" -- cgit v1.3 From 69322f44edcf37c83891ef95f77acfe19a35e03e Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 29 Aug 2014 08:02:35 +0000 Subject: Return false status only when adding a route is failed. It could erroneously return false due to an afexists() check loop in routing_start(). --- etc/rc.d/routing | 50 ++++++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/routing b/etc/rc.d/routing index c37c706efdb9..9cb07e576980 100755 --- a/etc/rc.d/routing +++ b/etc/rc.d/routing @@ -23,32 +23,33 @@ ROUTE_CMD="/sbin/route" routing_start() { - local _cmd _af _if _a + local _cmd _af _if _a _ret _cmd=$1 _af=$2 _if=$3 + _ret=0 case $_if in ""|[Aa][Ll][Ll]|[Aa][Nn][Yy]) _if="" ;; esac case $_af in - inet|inet6|atm) - if afexists $_af; then - setroutes $_cmd $_af $_if - else - err 1 "Unsupported address family: $_af." - fi - ;; ""|[Aa][Ll][Ll]|[Aa][Nn][Yy]) for _a in inet inet6 atm; do - afexists $_a && setroutes $_cmd $_a $_if + afexists $_a || continue + setroutes $_cmd $_a $_if || _ret=1 done - ;; + ;; *) - err 1 "Unsupported address family: $_af." - ;; + if afexists $_af; then + setroutes $_cmd $_af $_if || _ret=1 + else + err 1 "Unsupported address family: $_af." + fi + ;; esac + + return $_ret } routing_stop() @@ -62,17 +63,6 @@ routing_stop() esac case $_af in - inet|inet6|atm) - if afexists $_af; then - eval static_${_af} delete $_if - # When $_if is specified, do not flush routes. - if ! [ -n "$_if" ]; then - eval routing_stop_${_af} - fi - else - err 1 "Unsupported address family: $_af." - fi - ;; ""|[Aa][Ll][Ll]|[Aa][Nn][Yy]) for _a in inet inet6 atm; do afexists $_a || continue @@ -82,10 +72,18 @@ routing_stop() eval routing_stop_${_a} fi done - ;; + ;; *) - err 1 "Unsupported address family: $_af." - ;; + if afexists $_af; then + eval static_${_af} delete $_if + # When $_if is specified, do not flush routes. + if ! [ -n "$_if" ]; then + eval routing_stop_${_af} + fi + else + err 1 "Unsupported address family: $_af." + fi + ;; esac } -- cgit v1.3 From cec7c03d34f3854825e82416cb1934176ab0ff02 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sat, 30 Aug 2014 07:08:10 +0000 Subject: Use ipv6_prefer when at least one ifconfig_IF_ipv6 is configured. Discussed on: -net@ --- etc/rc.d/ip6addrctl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'etc') diff --git a/etc/rc.d/ip6addrctl b/etc/rc.d/ip6addrctl index a7aa90c91473..8b7486feef01 100755 --- a/etc/rc.d/ip6addrctl +++ b/etc/rc.d/ip6addrctl @@ -75,6 +75,8 @@ ip6addrctl_start() else if checkyesno ipv6_activate_all_interfaces; then ip6addrctl_prefer_ipv6 + elif [ -n "$(list_vars ifconfig_\*_ipv6)" ]; then + ip6addrctl_prefer_ipv6 else ip6addrctl_prefer_ipv4 fi -- cgit v1.3 From c1b0ea2c83c719b467d1deba63181df1d9e238c2 Mon Sep 17 00:00:00 2001 From: Stefan Eßer Date: Mon, 1 Sep 2014 16:51:57 +0000 Subject: Add vt(4) support to the console initialisation script, specifically: - Identify the console driver used and print syscons or vt as appropriate. - If vt is used and a keymap could not be loaded, then try to replace the keymap name configured in rc.conf based on a replacement list in this script. Warn about the fact, that a syscons keyname is configured and report the replacement used under vt. - If no replacement keymap is found, no keymap is loaded and a warning is displayed, which points at the conversion script and allows the conversion of keymaps not part of the official distribution. This patch has been sent to the -hackers list for review, but no comment has been received, yet. It is tested to work under syscons and vt on my system (on vt with either the syscons or vt keymap file name in rc.conf). MFC after: 3 days --- etc/rc.d/syscons | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/syscons b/etc/rc.d/syscons index f611e3b9ffd8..0dc41ad5f0b8 100755 --- a/etc/rc.d/syscons +++ b/etc/rc.d/syscons @@ -45,16 +45,122 @@ stop_cmd=":" kbddev=/dev/ttyv0 viddev=/dev/ttyv0 -_sc_config="syscons" +_sc_config= +_sc_console= _sc_initdone= +_sc_keymap_msg= sc_init() { if [ -z "${_sc_initdone}" ]; then + if [ -z "${_sc_console}" ]; then + if [ x`sysctl -n kern.vty` = x"vt" ]; then + _sc_console="vt" + else + _sc_console="syscons" + fi + _sc_config="${_sc_console}" + fi echo -n "Configuring ${_sc_config}:" _sc_initdone=yes fi } +# syscons to vt migration helper +lookup_keymap_for_vt() +{ + keymap=`basename $1 .kbd` + case $keymap in +hy.armscii-8) echo am;; +be.iso.acc) echo be.acc;; +be.iso) echo be;; +bg.bds.ctrlcaps) echo bg.bds;; +bg.phonetic.ctrlcaps) echo bg.phonetic;; +br275.iso.acc) echo br;; +br275.*) echo br.noacc;; +by.*) echo by;; +fr_CA.iso.acc) echo ca-fr;; +swissgerman.macbook.acc) echo ch.macbook.acc;; +swissgerman.iso.acc) echo ch.acc;; +swissgerman.*) echo ch;; +swissfrench.iso.acc) echo ch-fr.acc;; +swissfrench.*) echo ch-fr;; +ce.iso2) echo centraleuropean.qwerty;; +colemak.iso15.acc) echo colemak.acc;; +cs.*|cz.*) echo cz;; +german.iso.acc) echo de.acc;; +german.*) echo de;; +danish.iso.acc) echo dk.acc;; +danish.iso.macbook) echo dk.macbook;; +danish.*) echo dk;; +estonian.*) echo ee;; +spanish.dvorak) echo es.dvorak;; +spanish.iso*.acc) echo es.acc;; +spanish.iso) echo es;; +finnish.*) echo fi;; +fr.macbook.acc) echo fr.macbook;; +fr.iso.acc) echo fr.acc;; +fr.iso) echo fr;; +el.iso07) echo gr;; +gr.us101.acc) echo gr.101.acc;; +hr.iso) echo hr;; +hu.iso2.101keys) echo hu.101;; +hu.iso2.102keys) echo hu.102;; +iw.iso8) echo il;; +icelandic.iso.acc) echo is.acc;; +icelandic.iso) echo is;; +it.iso) echo it;; +jp.106x) echo jp.capsctrl;; +jp.106) echo jp;; +#?? jp.pc98.iso) echo jp.pc98;; +kk.pt154.io) echo kz.io;; +kk.pt154.kst) echo kz.kst;; +latinamerican.iso.acc) echo latinamerican.acc;; +lt.iso4) echo lt;; +norwegian.iso) echo no;; +norwegian.dvorak) echo no.dvorak;; +dutch.iso.acc) echo nl;; +eee_nordic) echo nordic.asus-eee;; +pl_PL.dvorak) echo pl.dvorak;; +pl_PL.ISO8859-2) echo pl;; +pt.iso.acc) echo pt.acc;; +pt.iso) echo pt;; +ru.koi8-r.shift) echo ru.shift;; +ru.koi8-r.win) echo ru.win;; +ru.*) echo ru;; +swedish.*) echo se;; +si.iso) echo si;; +sk.iso2) echo sk;; +tr.iso9.q) echo tr;; +ua.koi8-u.shift.alt) echo ua.shift.alt;; +ua.*) echo ua;; +uk.*-ctrl) echo uk.capsctrl;; +uk.dvorak) echo uk.dvorak;; +uk.*) echo uk;; +us.iso.acc) echo us.acc;; +us.pc-ctrl) echo us.ctrl;; +us.iso) echo us;; + esac +} + +kbdcontrol_load_keymap() +{ + errmsg=`kbdcontrol < ${kbddev} -l ${keymap} 2>&1` + if [ -n "${errmsg}" -a "${_sc_console}" = "vt" ]; then + _sc_keymap_msg="${errmsg}" + keymap_vt=`lookup_keymap_for_vt ${keymap}` + if [ -n "${keymap_vt}" ]; then + errmsg=`kbdcontrol < ${kbddev} -l ${keymap_vt} 2>&1` + if [ -z "${errmsg}" ]; then + _sc_keymap_msg="New keymap: In /etc/rc.conf replace 'keymap=${keymap}' by 'keymap=${keymap_vt}'" + fi + else + _sc_keymap_msg="No replacement found for keymap '${keymap}'. +You may try to convert your keymap file using 'convert-keymap.pl', which is +part of the system sources and located in /usr/src/tools/tools/vt/keymaps/" + fi + fi +} + # helper syscons_configure_keyboard() { @@ -65,7 +171,7 @@ syscons_configure_keyboard() ;; *) sc_init - echo -n ' keymap'; kbdcontrol < ${kbddev} -l ${keymap} + echo -n ' keymap'; kbdcontrol_load_keymap ;; esac @@ -139,10 +245,9 @@ syscons_setkeyboard() # if [ -n "${_sc_initdone}" ]; then echo '.' - _sc_config="syscons" + _sc_config="${_sc_console}" _sc_initdone= fi - } syscons_precmd() @@ -256,6 +361,12 @@ syscons_start() fi [ -n "${_sc_initdone}" ] && echo '.' + if [ -n "${_sc_keymap_msg}" ]; then + echo + echo "WARNING:" + echo "${_sc_keymap_msg}." + echo + fi } load_rc_config $name -- cgit v1.3 From 7dbf7f266cfc7e66053fb8d01604b58806ee2527 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Wed, 3 Sep 2014 21:59:07 +0000 Subject: Create a /boot/dtb directory to house DTB blobs. The flattened device tree support includes a device tree source compiler dtc(8) which converts .dts files into .dtb files. /boot/loader will load dtb files from this directory by default, allowing for fewer differences between images for different SoCs. Compiled dts files will wind up here eventually as an alternative to embedding them into the kernel. Document this in hier(7), as well as add missing entries for /boot/firmware and /boot/zfs, though the latter two should only be considered place holders if someone wants to make them better. --- etc/mtree/BSD.root.dist | 2 ++ share/man/man7/hier.7 | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/mtree/BSD.root.dist b/etc/mtree/BSD.root.dist index 7b8d9e7f8060..af2f6a9add09 100644 --- a/etc/mtree/BSD.root.dist +++ b/etc/mtree/BSD.root.dist @@ -10,6 +10,8 @@ boot defaults .. + dtb + .. firmware .. kernel diff --git a/share/man/man7/hier.7 b/share/man/man7/hier.7 index ae1a2a1078d2..9cba8961d168 100644 --- a/share/man/man7/hier.7 +++ b/share/man/man7/hier.7 @@ -48,13 +48,25 @@ programs and configuration files used during operating system bootstrap .It Pa defaults/ default bootstrapping configuration files; see .Xr loader.conf 5 +.It Pa dtb/ +Compiled flattened device tree (FDT) files; see +.Xr fdt 4 +and +.Xr dtc 1 +.It Pa firmware/ +Loadable modules containing binary firmware for hardware that needs +firmware downloaded to it to function .It Pa kernel/ pure kernel executable (the operating system loaded into memory -at boot time). +at boot time) .It Pa modules/ third-party loadable kernel modules; see .Xr kldstat 8 +.It Pa zfs/ +Contains +.Xr zfs 8 +zpool cache files. .El .It Pa /cdrom/ default mount point for CD-ROM drives -- cgit v1.3 From f4d5538f79d9d77703376c0ab44436c718bf041c Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Thu, 4 Sep 2014 02:06:33 +0000 Subject: Fix typo: s/_maske/_mask/ MFC after: 3 days Sponsored by: The FreeBSD Foundation --- etc/rc.d/jail | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/jail b/etc/rc.d/jail index 1049fcb23f2d..75f3775cfacf 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -319,7 +319,7 @@ jail_extract_address() _mask=${_mask:-/32} elif [ "${_type}" = "inet6" ]; then - # In case _maske is not set for IPv6, use /128. + # In case _mask is not set for IPv6, use /128. _mask=${_mask:-/128} warn "$_type $_addr: an IPv6 address should always be " \ "specified with a prefix length. /128 is used." -- cgit v1.3 From fcb3a37075b9fb3335085b68c18e6a3ba2379a25 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 4 Sep 2014 22:00:52 +0000 Subject: Fix a bug which prevented mount.fstab parameter from being converted when jail_JID_devfs_enable=NO. Spotted by: peter --- etc/rc.d/jail | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/jail b/etc/rc.d/jail index 75f3775cfacf..cf1c6e2fae9d 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -207,6 +207,10 @@ parse_options() extract_var $_j consolelog exec.consolelog - \ /var/log/jail_${_j}_console.log + if [ -r $_fstab ]; then + echo " mount.fstab = \"$_fstab\";" + fi + eval : \${jail_${_j}_devfs_enable:=${jail_devfs_enable:-NO}} if checkyesno jail_${_j}_devfs_enable; then echo " mount.devfs;" @@ -222,11 +226,7 @@ parse_options() ;; *) warn "devfs_ruleset must be an integer." ;; esac - if [ -r $_fstab ]; then - echo " mount.fstab = \"$_fstab\";" - fi fi - eval : \${jail_${_j}_fdescfs_enable:=${jail_fdescfs_enable:-NO}} if checkyesno jail_${_j}_fdescfs_enable; then echo " mount.fdescfs;" -- cgit v1.3 From 78389e87b294fd3c15c1dd45c550b72fabc65450 Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Mon, 8 Sep 2014 05:14:58 +0000 Subject: Temporarily remove the warning added r270781 - it prints the warning regardless of whether the usage is correct or not and this generates a LOT of noise, even when you have specified a mask. --- etc/rc.d/jail | 2 -- 1 file changed, 2 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/jail b/etc/rc.d/jail index cf1c6e2fae9d..0b886fd56b59 100755 --- a/etc/rc.d/jail +++ b/etc/rc.d/jail @@ -321,8 +321,6 @@ jail_extract_address() elif [ "${_type}" = "inet6" ]; then # In case _mask is not set for IPv6, use /128. _mask=${_mask:-/128} - warn "$_type $_addr: an IPv6 address should always be " \ - "specified with a prefix length. /128 is used." fi } -- cgit v1.3 From e1d9a028f688a453d054565928a99a442dca963f Mon Sep 17 00:00:00 2001 From: Dag-Erling Smørgrav Date: Mon, 8 Sep 2014 09:33:43 +0000 Subject: Use the correct idiom for default values, and ensure that the script works correctly if the user overrides them. PR: 193255 Submitted by: hrs@ MFC after: 3 days --- etc/defaults/rc.conf | 7 +++++++ etc/rc.d/local_unbound | 20 ++++++-------------- 2 files changed, 13 insertions(+), 14 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 190bb9c074bd..766116e22de2 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -267,6 +267,13 @@ hastd_program="/sbin/hastd" # path to hastd, if you want a different one. hastd_flags="" # Optional flags to hastd. ctld_enable="NO" # CAM Target Layer / iSCSI target daemon. local_unbound_enable="NO" # local caching resolver +local_unbound_program="/usr/sbin/unbound" +local_unbound_workdir=/var/unbound +local_unbound_config="${local_unbound_workdir}/unbound.conf" +local_unbound_flags="-c${local_unbound_config}" +local_unbound_forwardconf="${local_unbound_workdir}/forward.conf}" +local_unbound_anchor="${local_unbound_workdir}/root.key" +local_unbound_forwarders="" # # kerberos. Do not run the admin daemons on slave servers diff --git a/etc/rc.d/local_unbound b/etc/rc.d/local_unbound index ed69c193d886..9a7e19122255 100755 --- a/etc/rc.d/local_unbound +++ b/etc/rc.d/local_unbound @@ -13,7 +13,6 @@ name="local_unbound" desc="local caching forwarding resolver" rcvar="local_unbound_enable" -command="/usr/sbin/unbound" extra_commands="anchor configtest reload setup" start_precmd="local_unbound_prestart" reload_precmd="local_unbound_configtest" @@ -22,18 +21,9 @@ configtest_cmd="local_unbound_configtest" setup_cmd="local_unbound_setup" pidfile="/var/run/${name}.pid" -: ${local_unbound_workdir:=/var/unbound} -: ${local_unbound_config:=${local_unbound_workdir}/unbound.conf} -: ${local_unbound_flags:=-c${local_unbound_config}} -: ${local_unbound_forwardconf:=${local_unbound_workdir}/forward.conf} -: ${local_unbound_anchor:=${local_unbound_workdir}/root.key} -: ${local_unbound_forwarders:=} - -load_rc_config $name - do_as_unbound() { - echo "$@" | su -m unbound + echo "$@" | /usr/bin/su -m unbound } # @@ -41,7 +31,8 @@ do_as_unbound() # local_unbound_anchor() { - do_as_unbound /usr/sbin/unbound-anchor -a ${local_unbound_anchor} + do_as_unbound ${local_unbound_program%/*}/unbound-anchor \ + -a ${local_unbound_anchor} # we can't trust the exit code - check if the file exists [ -f ${local_unbound_anchor} ] } @@ -51,7 +42,8 @@ local_unbound_anchor() # local_unbound_configtest() { - do_as_unbound /usr/sbin/unbound-checkconf ${local_unbound_config} + do_as_unbound ${local_unbound_program%/*}/unbound-checkconf \ + ${local_unbound_config} } # @@ -61,7 +53,7 @@ local_unbound_configtest() local_unbound_setup() { echo "Performing initial setup." - /usr/sbin/local-unbound-setup -n \ + ${local_unbound_program%/*}/local-unbound-setup -n \ -u unbound \ -w ${local_unbound_workdir} \ -c ${local_unbound_config} \ -- cgit v1.3 From 29be5943e8ea5a64d15747c24cb0730b1a9d8105 Mon Sep 17 00:00:00 2001 From: Dag-Erling Smørgrav Date: Mon, 8 Sep 2014 12:26:52 +0000 Subject: Revert r271257 after several issues were pointed out. An updated patch will be committed at a later date. --- etc/defaults/rc.conf | 7 ------- etc/rc.d/local_unbound | 20 ++++++++++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 766116e22de2..190bb9c074bd 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -267,13 +267,6 @@ hastd_program="/sbin/hastd" # path to hastd, if you want a different one. hastd_flags="" # Optional flags to hastd. ctld_enable="NO" # CAM Target Layer / iSCSI target daemon. local_unbound_enable="NO" # local caching resolver -local_unbound_program="/usr/sbin/unbound" -local_unbound_workdir=/var/unbound -local_unbound_config="${local_unbound_workdir}/unbound.conf" -local_unbound_flags="-c${local_unbound_config}" -local_unbound_forwardconf="${local_unbound_workdir}/forward.conf}" -local_unbound_anchor="${local_unbound_workdir}/root.key" -local_unbound_forwarders="" # # kerberos. Do not run the admin daemons on slave servers diff --git a/etc/rc.d/local_unbound b/etc/rc.d/local_unbound index 9a7e19122255..ed69c193d886 100755 --- a/etc/rc.d/local_unbound +++ b/etc/rc.d/local_unbound @@ -13,6 +13,7 @@ name="local_unbound" desc="local caching forwarding resolver" rcvar="local_unbound_enable" +command="/usr/sbin/unbound" extra_commands="anchor configtest reload setup" start_precmd="local_unbound_prestart" reload_precmd="local_unbound_configtest" @@ -21,9 +22,18 @@ configtest_cmd="local_unbound_configtest" setup_cmd="local_unbound_setup" pidfile="/var/run/${name}.pid" +: ${local_unbound_workdir:=/var/unbound} +: ${local_unbound_config:=${local_unbound_workdir}/unbound.conf} +: ${local_unbound_flags:=-c${local_unbound_config}} +: ${local_unbound_forwardconf:=${local_unbound_workdir}/forward.conf} +: ${local_unbound_anchor:=${local_unbound_workdir}/root.key} +: ${local_unbound_forwarders:=} + +load_rc_config $name + do_as_unbound() { - echo "$@" | /usr/bin/su -m unbound + echo "$@" | su -m unbound } # @@ -31,8 +41,7 @@ do_as_unbound() # local_unbound_anchor() { - do_as_unbound ${local_unbound_program%/*}/unbound-anchor \ - -a ${local_unbound_anchor} + do_as_unbound /usr/sbin/unbound-anchor -a ${local_unbound_anchor} # we can't trust the exit code - check if the file exists [ -f ${local_unbound_anchor} ] } @@ -42,8 +51,7 @@ local_unbound_anchor() # local_unbound_configtest() { - do_as_unbound ${local_unbound_program%/*}/unbound-checkconf \ - ${local_unbound_config} + do_as_unbound /usr/sbin/unbound-checkconf ${local_unbound_config} } # @@ -53,7 +61,7 @@ local_unbound_configtest() local_unbound_setup() { echo "Performing initial setup." - ${local_unbound_program%/*}/local-unbound-setup -n \ + /usr/sbin/local-unbound-setup -n \ -u unbound \ -w ${local_unbound_workdir} \ -c ${local_unbound_config} \ -- cgit v1.3 From 07509279d3920118d263ca9d0ab6a07d35cf4218 Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Tue, 9 Sep 2014 17:03:58 +0000 Subject: Don't cross mount boundaries when cleaning tmp files. Mounting something in /tmp such as a build jail with nullfs mounts for some directories can result in very surprising results the next day. MFC after: 2 weeks Relnotes: yes --- etc/periodic/daily/110.clean-tmps | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'etc') diff --git a/etc/periodic/daily/110.clean-tmps b/etc/periodic/daily/110.clean-tmps index eef3bc6545b5..67bcec6f00d3 100755 --- a/etc/periodic/daily/110.clean-tmps +++ b/etc/periodic/daily/110.clean-tmps @@ -45,8 +45,8 @@ case "$daily_clean_tmps_enable" in rc=$(for dir in $daily_clean_tmps_dirs do [ ."${dir#/}" != ."$dir" -a -d $dir ] && cd $dir && { - find -d . -type f $args -delete $print - find -d . ! -name . -type d $dargs -delete $print + find -x -d . -type f $args -delete $print + find -x -d . ! -name . -type d $dargs -delete $print } | sed "s,^\\., $dir," done | tee /dev/stderr | wc -l) [ -z "$print" ] && rc=0 -- cgit v1.3 From 15c7266a7f1d7814dca873273e5791c48bf5b755 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 11 Sep 2014 12:30:29 +0000 Subject: - Add $netif_ipexpand_max to specify the upper limit for the number of addresses generated by an address range specification. The default value is 2048. This can be increased by setting $netif_ipexpand_max in rc.conf. - Fix warning messages when an address range spec exceeds the upper limit. PR: 186841 --- etc/defaults/rc.conf | 1 + etc/network.subr | 12 +++++------- share/man/man5/rc.conf.5 | 13 +++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 190bb9c074bd..7a39a276cb89 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -110,6 +110,7 @@ synchronous_dhclient="NO" # Start dhclient directly on configured # interfaces during startup. defaultroute_delay="30" # Time to wait for a default route on a DHCP interface. defaultroute_carrier_delay="5" # Time to wait for carrier while waiting for a default route. +netif_ipexpand_max="2048" # Maximum number of IP addrs in a range spec. wpa_supplicant_program="/usr/sbin/wpa_supplicant" wpa_supplicant_flags="-s" # Extra flags to pass to wpa_supplicant wpa_supplicant_conf_file="/etc/wpa_supplicant.conf" diff --git a/etc/network.subr b/etc/network.subr index f67622d51efd..520c9e86a7e5 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -25,9 +25,7 @@ # $FreeBSD$ # IFCONFIG_CMD="/sbin/ifconfig" - -# Maximum number of addresses expanded from a address range specification. -_IPEXPANDMAX=31 +: ${netif_ipexpand_max:=2048} # # Subroutines commonly used from network startup scripts. @@ -886,8 +884,8 @@ ifalias_expand_addr_inet() _ipcount=$_iplow while [ "$_ipcount" -le "$_iphigh" ]; do _retstr="${_retstr} ${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail}${_plen:+/}${_plen}" - if [ $_ipcount -gt $(($_iplow + $_IPEXPANDMAX)) ]; then - warn "Range specification is too large (${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_iphigh}${_iptail:+.}${_iptail}). ${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail} was processed." + if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ]; then + warn "Range specification is too large (${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_iphigh}${_iptail:+.}${_iptail}). ${_iphead}${_iphead:+.}${_iplow}${_iptail:+.}${_iptail}-${_iphead}${_iphead:+.}${_ipcount}${_iptail:+.}${_iptail} was processed. Increase \$netif_ipexpand_max in rc.conf." break else _ipcount=$(($_ipcount + 1)) @@ -976,9 +974,9 @@ ifalias_expand_addr_inet6() $_ipleft $_ipcount $_ipright \ ${_plen:+/}$_plen` _retstr="$_retstr $_r" - if [ $_ipcount -gt $(($_iplow + $_IPEXPANDMAX)) ] + if [ $_ipcount -gt $(($_iplow + $netif_ipexpand_max)) ] then - warn "Range specification is too large $(printf '(%s:%04x%s-%s:%04x%s)' $_ipleft $_iplow $_ipright $_ipleft $_iphigh $_ipright). $(printf '%s:%04x%s-%s:%04x%s' $_ipleft $_iplow $_ipright $_ipleft $_ipcount $_ipright) was processed." + warn "Range specification is too large $(printf '(%s:%x%s-%s:%x%s)' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_iphigh" "$_ipright"). $(printf '%s:%x%s-%s:%x%s' "$_ipleft" "$_iplow" "$_ipright" "$_ipleft" "$_ipcount" "$_ipright") was processed. Increase \$netif_ipexpand_max in rc.conf." break else _ipcount=$(($_ipcount + 1)) diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 669e773bac64..47d9ef8e5520 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -1199,6 +1199,19 @@ or .Li inet6 2001:db8:1-f::1/64 . This notation allows address and prefix length part only, not the other address modifiers. +Note that the maximum number of the generated addresses from a range +specification is limited to an integer value specified in +.Va netif_ipexpand_max +in +.Xr rc.conf 5 +because a small typo can unexpectedly generate a large number of addresses. +The default value is +.Li 2048 . +It can be increased by adding the following line into +.Xr rc.conf 5 : +.Bd -literal +netif_ipexpand_max="4096" +.Ed .Pp In the case of .Li 192.0.2.5-23/24 , -- cgit v1.3 From a4767875cb9cf8c3add2c12c6f385ba1125e8afa Mon Sep 17 00:00:00 2001 From: Warren Block Date: Thu, 11 Sep 2014 18:24:16 +0000 Subject: Update motd, clarifying the information and adding pointers to other resources. MFC after: 3 days --- etc/motd | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) (limited to 'etc') diff --git a/etc/motd b/etc/motd index 50ce29d4b344..e616d517e0a5 100644 --- a/etc/motd +++ b/etc/motd @@ -1,25 +1,21 @@ FreeBSD ?.?.? (UNKNOWN) -Welcome to FreeBSD! +Welcome to FreeBSD! Handy technical support resources: -Before seeking technical support, please use the following resources: +Security advisories and errata: https://www.FreeBSD.org/releases/ +Handbook: https://www.FreeBSD.org/handbook/ +FAQ: https://www.FreeBSD.org/faq/ +Mailing list: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/ +Forums: https://forums.FreeBSD.org/ -o Security advisories and updated errata information for all releases are - at http://www.FreeBSD.org/releases/ - always consult the ERRATA section - for your release first as it's updated frequently. +Documents installed with the system are in the /usr/local/share/doc/freebsd/ +directory, or can be installed later with: pkg install en-freebsd-doc +For other languages, replace "en" with a language code like de or fr. -o The Handbook and FAQ documents are at http://www.FreeBSD.org/ and, - along with the mailing lists, can be searched by going to - http://www.FreeBSD.org/search/. If the doc package has been installed - (or fetched via pkg install lang-freebsd-doc, where lang is the - 2-letter language code, e.g. en), they are also available formatted - in /usr/local/share/doc/freebsd. +Show the version of FreeBSD installed: uname -a +Please include that output and any error messages when posting questions. -If you still have a question or problem, please take the output of -`uname -a', along with any relevant error messages, and email it -as a question to the questions@FreeBSD.org mailing list. If you are -unfamiliar with FreeBSD's directory layout, please refer to the hier(7) -manual page. If you are not familiar with manual pages, type `man man'. +Introduction to manual pages: man man +FreeBSD directory layout: man hier Edit /etc/motd to change this login announcement. - -- cgit v1.3 From e72055b7feba695a760d45f01f0f8268b1cb4a74 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Sat, 13 Sep 2014 02:15:31 +0000 Subject: Import HyperV Key-Value Pair (KVP) driver and daemon code by Microsoft, many thanks for their continued support of FreeBSD. While I'm there, also implement a new build knob, WITHOUT_HYPERV to disable building and installing of the HyperV utilities when necessary. The HyperV utilities are only built for i386 and amd64 targets. This is a stable/10 candidate for inclusion with 10.1-RELEASE. Submitted by: Wei Hu MFC after: 1 week --- contrib/hyperv/tools/hv_kvp_daemon.8 | 68 ++ contrib/hyperv/tools/hv_kvp_daemon.c | 1518 +++++++++++++++++++++++++ contrib/hyperv/tools/scripts/hv_get_dhcp_info | 24 + contrib/hyperv/tools/scripts/hv_get_dns_info | 12 + contrib/hyperv/tools/scripts/hv_set_ifconfig | 73 ++ etc/mtree/BSD.usr.dist | 2 + etc/mtree/BSD.var.dist | 2 + etc/rc.d/Makefile | 5 + etc/rc.d/hv_kvpd | 15 + libexec/Makefile | 5 + libexec/hyperv/Makefile | 10 + share/mk/src.opts.mk | 7 + sys/conf/files.amd64 | 1 + sys/conf/files.i386 | 1 + sys/dev/hyperv/include/hyperv.h | 29 + sys/dev/hyperv/utilities/hv_kvp.c | 1001 ++++++++++++++++ sys/dev/hyperv/utilities/hv_kvp.h | 143 +-- sys/dev/hyperv/utilities/hv_util.c | 47 +- sys/dev/hyperv/utilities/unicode.h | 201 ++++ sys/modules/hyperv/utilities/Makefile | 2 +- tools/build/mk/OptionalObsoleteFiles.inc | 8 + tools/build/options/WITHOUT_HYPERV | 2 + tools/build/options/WITH_HYPERV | 2 + usr.sbin/Makefile.amd64 | 3 + usr.sbin/Makefile.i386 | 3 + usr.sbin/hyperv/Makefile | 7 + usr.sbin/hyperv/Makefile.inc | 3 + usr.sbin/hyperv/tools/Makefile | 13 + 28 files changed, 3104 insertions(+), 103 deletions(-) create mode 100644 contrib/hyperv/tools/hv_kvp_daemon.8 create mode 100644 contrib/hyperv/tools/hv_kvp_daemon.c create mode 100644 contrib/hyperv/tools/scripts/hv_get_dhcp_info create mode 100644 contrib/hyperv/tools/scripts/hv_get_dns_info create mode 100644 contrib/hyperv/tools/scripts/hv_set_ifconfig create mode 100644 etc/rc.d/hv_kvpd create mode 100644 libexec/hyperv/Makefile create mode 100644 sys/dev/hyperv/utilities/hv_kvp.c create mode 100644 sys/dev/hyperv/utilities/unicode.h create mode 100644 tools/build/options/WITHOUT_HYPERV create mode 100644 tools/build/options/WITH_HYPERV create mode 100644 usr.sbin/hyperv/Makefile create mode 100644 usr.sbin/hyperv/Makefile.inc create mode 100644 usr.sbin/hyperv/tools/Makefile (limited to 'etc') diff --git a/contrib/hyperv/tools/hv_kvp_daemon.8 b/contrib/hyperv/tools/hv_kvp_daemon.8 new file mode 100644 index 000000000000..af574edef3a0 --- /dev/null +++ b/contrib/hyperv/tools/hv_kvp_daemon.8 @@ -0,0 +1,68 @@ +.\" Copyright (c) 2014 Microsoft Corp. +.\" 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 AUTHOR 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 AUTHOR 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 September 10, 2013 +.Dt HYPER-V 4 +.Os +.Sh NAME +.Nm hv_kvp_daemon +.Nd Hyper-V Key Value Pair Daemon +.Sh SYNOPSIS +The \fBhv_kvp_daemon\fP daemon provides the ability to store, retrieve, modify and delete +Key Value pairs for FreeBSD guest partitions running on Hyper-V. +.Sh DESCRIPTION +Hyper-V allows administrators to store custom metadata in the form +of Key Value pairs inside the FreeBSD guest partition. Administrators can +use Windows Powershell scripts to add, read, modify and delete such +Key Value pairs. + +The \fBhv_kvp_daemon\fP accepts Key Value pair management requests from the +\fBhv_utils\fP driver and performs the actual metadata management on the file-system. + +The same daemon and driver combination is also used to set and get +IP addresses from a FreeBSD guest. + +The set functionality is particularly +useful when the FreeBSD guest is assigned a static IP address and is failed +over from one Hyper-V host to another. After failover, Hyper-V uses the set IP +functionality to automatically +update the FreeBSD guest's IP address to its original static value. + +On the other hand, the get IP functionality is used to update the guest IP +address in the Hyper-V management console window. +.Sh SEE ALSO +.Xr hv_vmbus 4 , +.Xr hv_utils 4 , +.Xr hv_netvsc 4 , +.Xr hv_storvsc 4 , +.Xr hv_ata_pci_disengage 4 +.Sh HISTORY +Support for Hyper-V in the form of ports was first released in September 2013. +The daemon was developed through a joint effort between Citrix Inc., +Microsoft Corp. and Network Appliance Inc.. +.Sh AUTHORS +.An -nosplit +.Fx +support for \fBhv_kvp_daemon\fP was first added by +.An Microsoft BSD Integration Services Team Aq bsdic@microsoft.com . diff --git a/contrib/hyperv/tools/hv_kvp_daemon.c b/contrib/hyperv/tools/hv_kvp_daemon.c new file mode 100644 index 000000000000..890ca5b551e1 --- /dev/null +++ b/contrib/hyperv/tools/hv_kvp_daemon.c @@ -0,0 +1,1518 @@ +/*- + * Copyright (c) 2014 Microsoft Corp. + * 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 unmodified, 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 AUTHOR ``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 AUTHOR 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hv_kvp.h" + +typedef uint8_t __u8; +typedef uint16_t __u16; +typedef uint32_t __u32; +typedef uint64_t __u64; + +/* + * ENUM Data + */ + +enum key_index { + FullyQualifiedDomainName = 0, + IntegrationServicesVersion, /*This key is serviced in the kernel*/ + NetworkAddressIPv4, + NetworkAddressIPv6, + OSBuildNumber, + OSName, + OSMajorVersion, + OSMinorVersion, + OSVersion, + ProcessorArchitecture +}; + + +enum { + IPADDR = 0, + NETMASK, + GATEWAY, + DNS +}; + + +/* Global Variables */ + +/* + * The structure for operation handlers. + */ +struct kvp_op_hdlr { + int kvp_op_key; + void (*kvp_op_init)(void); + int (*kvp_op_exec)(struct hv_kvp_msg *kvp_op_msg, void *data); +}; + +static struct kvp_op_hdlr kvp_op_hdlrs[HV_KVP_OP_COUNT]; + +/* OS information */ + +static const char *os_name = ""; +static const char *os_major = ""; +static const char *os_minor = ""; +static const char *processor_arch; +static const char *os_build; +static const char *lic_version = "BSD Pre-Release version"; +static struct utsname uts_buf; + +/* Global flags */ +static int is_daemon = 1; +static int is_debugging = 0; + +#define KVP_LOG(priority, format, args...) do { \ + if (is_debugging == 1) { \ + if (is_daemon == 1) \ + syslog(priority, format, ## args); \ + else \ + printf(format, ## args); \ + } else { \ + if (priority < LOG_DEBUG) { \ + if (is_daemon == 1) \ + syslog(priority, format, ## args); \ + else \ + printf(format, ## args); \ + } \ + } \ + } while(0) + +/* + * For KVP pool file + */ + +#define MAX_FILE_NAME 100 +#define ENTRIES_PER_BLOCK 50 + +struct kvp_record { + char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; + char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; +}; + +struct kvp_pool { + int pool_fd; + int num_blocks; + struct kvp_record *records; + int num_records; + char fname[MAX_FILE_NAME]; +}; + +static struct kvp_pool kvp_pools[HV_KVP_POOL_COUNT]; + + +static void +kvp_acquire_lock(int pool) +{ + struct flock fl = { 0, 0, 0, F_WRLCK, SEEK_SET, 0 }; + + fl.l_pid = getpid(); + + if (fcntl(kvp_pools[pool].pool_fd, F_SETLKW, &fl) == -1) { + KVP_LOG(LOG_ERR, "Failed to acquire the lock pool: %d", pool); + exit(EXIT_FAILURE); + } +} + + +static void +kvp_release_lock(int pool) +{ + struct flock fl = { 0, 0, 0, F_UNLCK, SEEK_SET, 0 }; + + fl.l_pid = getpid(); + + if (fcntl(kvp_pools[pool].pool_fd, F_SETLK, &fl) == -1) { + perror("fcntl"); + KVP_LOG(LOG_ERR, "Failed to release the lock pool: %d\n", pool); + exit(EXIT_FAILURE); + } +} + + +/* + * Write in-memory copy of KVP to pool files + */ +static void +kvp_update_file(int pool) +{ + FILE *filep; + size_t bytes_written; + + kvp_acquire_lock(pool); + + filep = fopen(kvp_pools[pool].fname, "w"); + if (!filep) { + kvp_release_lock(pool); + KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool); + exit(EXIT_FAILURE); + } + + bytes_written = fwrite(kvp_pools[pool].records, + sizeof(struct kvp_record), + kvp_pools[pool].num_records, filep); + + if (ferror(filep) || fclose(filep)) { + kvp_release_lock(pool); + KVP_LOG(LOG_ERR, "Failed to write file, pool: %d\n", pool); + exit(EXIT_FAILURE); + } + + kvp_release_lock(pool); +} + + +/* + * Read KVPs from pool files and store in memory + */ +static void +kvp_update_mem_state(int pool) +{ + FILE *filep; + size_t records_read = 0; + struct kvp_record *record = kvp_pools[pool].records; + struct kvp_record *readp; + int num_blocks = kvp_pools[pool].num_blocks; + int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; + + kvp_acquire_lock(pool); + + filep = fopen(kvp_pools[pool].fname, "r"); + if (!filep) { + kvp_release_lock(pool); + KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool); + exit(EXIT_FAILURE); + } + for ( ; ; ) + { + readp = &record[records_read]; + records_read += fread(readp, sizeof(struct kvp_record), + ENTRIES_PER_BLOCK * num_blocks, + filep); + + if (ferror(filep)) { + KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n", pool); + exit(EXIT_FAILURE); + } + + if (!feof(filep)) { + /* + * Have more data to read. Expand the memory. + */ + num_blocks++; + record = realloc(record, alloc_unit * num_blocks); + + if (record == NULL) { + KVP_LOG(LOG_ERR, "malloc failed\n"); + exit(EXIT_FAILURE); + } + continue; + } + break; + } + + kvp_pools[pool].num_blocks = num_blocks; + kvp_pools[pool].records = record; + kvp_pools[pool].num_records = records_read; + + fclose(filep); + kvp_release_lock(pool); +} + + +static int +kvp_file_init(void) +{ + int fd; + FILE *filep; + size_t records_read; + char *fname; + struct kvp_record *record; + struct kvp_record *readp; + int num_blocks; + int i; + int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; + + if (access("/var/db/hyperv/pool", F_OK)) { + if (mkdir("/var/db/hyperv/pool", + S_IRUSR | S_IWUSR | S_IROTH)) { + KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n"); + exit(EXIT_FAILURE); + } + } + + for (i = 0; i < HV_KVP_POOL_COUNT; i++) + { + fname = kvp_pools[i].fname; + records_read = 0; + num_blocks = 1; + snprintf(fname, MAX_FILE_NAME, "/var/db/hyperv/pool/.kvp_pool_%d", i); + fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH); + + if (fd == -1) { + return (1); + } + + + filep = fopen(fname, "r"); + if (!filep) { + return (1); + } + + record = malloc(alloc_unit * num_blocks); + if (record == NULL) { + fclose(filep); + return (1); + } + for ( ; ; ) + { + readp = &record[records_read]; + records_read += fread(readp, sizeof(struct kvp_record), + ENTRIES_PER_BLOCK, + filep); + + if (ferror(filep)) { + KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n", + i); + exit(EXIT_FAILURE); + } + + if (!feof(filep)) { + /* + * More data to read. + */ + num_blocks++; + record = realloc(record, alloc_unit * + num_blocks); + if (record == NULL) { + fclose(filep); + return (1); + } + continue; + } + break; + } + kvp_pools[i].pool_fd = fd; + kvp_pools[i].num_blocks = num_blocks; + kvp_pools[i].records = record; + kvp_pools[i].num_records = records_read; + fclose(filep); + } + + return (0); +} + + +static int +kvp_key_delete(int pool, __u8 *key, int key_size) +{ + int i; + int j, k; + int num_records; + struct kvp_record *record; + + KVP_LOG(LOG_DEBUG, "kvp_key_delete: pool = %d, " + "key = %s\n", pool, key); + + /* Update in-memory state */ + kvp_update_mem_state(pool); + + num_records = kvp_pools[pool].num_records; + record = kvp_pools[pool].records; + + for (i = 0; i < num_records; i++) + { + if (memcmp(key, record[i].key, key_size)) { + continue; + } + + KVP_LOG(LOG_DEBUG, "Found delete key in pool %d.\n", + pool); + /* + * We found a match at the end; Just update the number of + * entries and we are done. + */ + if (i == num_records) { + kvp_pools[pool].num_records--; + kvp_update_file(pool); + return (0); + } + + /* + * We found a match in the middle; Move the remaining + * entries up. + */ + j = i; + k = j + 1; + for ( ; k < num_records; k++) + { + strcpy(record[j].key, record[k].key); + strcpy(record[j].value, record[k].value); + j++; + } + kvp_pools[pool].num_records--; + kvp_update_file(pool); + return (0); + } + KVP_LOG(LOG_DEBUG, "Not found delete key in pool %d.\n", + pool); + return (1); +} + + +static int +kvp_key_add_or_modify(int pool, __u8 *key, __u32 key_size, __u8 *value, + __u32 value_size) +{ + int i; + int num_records; + struct kvp_record *record; + int num_blocks; + + KVP_LOG(LOG_DEBUG, "kvp_key_add_or_modify: pool = %d, " + "key = %s, value = %s\n,", pool, key, value); + + if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || + (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { + KVP_LOG(LOG_ERR, "kvp_key_add_or_modify: returning 1\n"); + return (1); + } + + /* Update the in-memory state. */ + kvp_update_mem_state(pool); + + num_records = kvp_pools[pool].num_records; + record = kvp_pools[pool].records; + num_blocks = kvp_pools[pool].num_blocks; + + for (i = 0; i < num_records; i++) + { + if (memcmp(key, record[i].key, key_size)) { + continue; + } + + /* + * Key exists. Just update the value and we are done. + */ + memcpy(record[i].value, value, value_size); + kvp_update_file(pool); + return (0); + } + + /* + * Key doesn't exist; Add a new KVP. + */ + if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) { + /* Increase the size of the recodrd array. */ + record = realloc(record, sizeof(struct kvp_record) * + ENTRIES_PER_BLOCK * (num_blocks + 1)); + + if (record == NULL) { + return (1); + } + kvp_pools[pool].num_blocks++; + } + memcpy(record[i].value, value, value_size); + memcpy(record[i].key, key, key_size); + kvp_pools[pool].records = record; + kvp_pools[pool].num_records++; + kvp_update_file(pool); + return (0); +} + + +static int +kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, + int value_size) +{ + int i; + int num_records; + struct kvp_record *record; + + KVP_LOG(LOG_DEBUG, "kvp_get_value: pool = %d, key = %s\n,", + pool, key); + + if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || + (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { + return (1); + } + + /* Update the in-memory state first. */ + kvp_update_mem_state(pool); + + num_records = kvp_pools[pool].num_records; + record = kvp_pools[pool].records; + + for (i = 0; i < num_records; i++) + { + if (memcmp(key, record[i].key, key_size)) { + continue; + } + + /* Found the key */ + memcpy(value, record[i].value, value_size); + return (0); + } + + return (1); +} + + +static int +kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, + __u8 *value, int value_size) +{ + struct kvp_record *record; + + KVP_LOG(LOG_DEBUG, "kvp_pool_enumerate: pool = %d, index = %d\n,", + pool, index); + + /* First update our in-memory state first. */ + kvp_update_mem_state(pool); + record = kvp_pools[pool].records; + + /* Index starts with 0 */ + if (index >= kvp_pools[pool].num_records) { + return (1); + } + + memcpy(key, record[index].key, key_size); + memcpy(value, record[index].value, value_size); + return (0); +} + + +static void +kvp_get_os_info(void) +{ + char *p; + + uname(&uts_buf); + os_build = uts_buf.release; + os_name = uts_buf.sysname; + processor_arch = uts_buf.machine; + + /* + * Win7 host expects the build string to be of the form: x.y.z + * Strip additional information we may have. + */ + p = strchr(os_build, '-'); + if (p) { + *p = '\0'; + } + + /* + * We don't have any other information about the FreeBSD os. + */ + return; +} + +/* + * Given the interface name, return the MAC address. + */ +static char * +kvp_if_name_to_mac(char *if_name) +{ + char *mac_addr = NULL; + struct ifaddrs *ifaddrs_ptr; + struct ifaddrs *head_ifaddrs_ptr; + struct sockaddr_dl *sdl; + int status; + + status = getifaddrs(&ifaddrs_ptr); + + if (status >= 0) { + head_ifaddrs_ptr = ifaddrs_ptr; + do { + sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr; + if ((sdl->sdl_type == IFT_ETHER) && + (strcmp(ifaddrs_ptr->ifa_name, if_name) == 0)) { + mac_addr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl)))); + break; + } + } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL); + freeifaddrs(head_ifaddrs_ptr); + } + + return (mac_addr); +} + + +/* + * Given the MAC address, return the interface name. + */ +static char * +kvp_mac_to_if_name(char *mac) +{ + char *if_name = NULL; + struct ifaddrs *ifaddrs_ptr; + struct ifaddrs *head_ifaddrs_ptr; + struct sockaddr_dl *sdl; + int status; + size_t i; + char *buf_ptr; + + status = getifaddrs(&ifaddrs_ptr); + + if (status >= 0) { + head_ifaddrs_ptr = ifaddrs_ptr; + do { + sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr; + if (sdl->sdl_type == IFT_ETHER) { + buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl)))); + for (i = 0; i < strlen(buf_ptr); i++) + { + buf_ptr[i] = toupper(buf_ptr[i]); + } + + if (strncmp(buf_ptr, mac, strlen(mac)) == 0) { + /* Caller will free the memory */ + if_name = strdup(ifaddrs_ptr->ifa_name); + free(buf_ptr); + break; + }else if (buf_ptr != NULL) { + free(buf_ptr); + } + } + } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL); + freeifaddrs(head_ifaddrs_ptr); + } + return (if_name); +} + + +static void +kvp_process_ipconfig_file(char *cmd, + char *config_buf, size_t len, + size_t element_size, int offset) +{ + char buf[256]; + char *p; + char *x; + FILE *file; + + /* + * First execute the command. + */ + file = popen(cmd, "r"); + if (file == NULL) { + return; + } + + if (offset == 0) { + memset(config_buf, 0, len); + } + while ((p = fgets(buf, sizeof(buf), file)) != NULL) { + if ((len - strlen(config_buf)) < (element_size + 1)) { + break; + } + + x = strchr(p, '\n'); + *x = '\0'; + strlcat(config_buf, p, len); + strlcat(config_buf, ";", len); + } + pclose(file); +} + + +static void +kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer) +{ + char cmd[512]; + char dhcp_info[128]; + char *p; + FILE *file; + + /* + * Retrieve the IPV4 address of default gateway. + */ + snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name); + + /* + * Execute the command to gather gateway IPV4 info. + */ + kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, + (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); + + /* + * Retrieve the IPV6 address of default gateway. + */ + snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name); + + /* + * Execute the command to gather gateway IPV6 info. + */ + kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, + (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); + + /* + * we just invoke an external script to get the DNS info. + * + * Following is the expected format of the information from the script: + * + * ipaddr1 (nameserver1) + * ipaddr2 (nameserver2) + * . + * . + */ + /* Scripts are stored in /usr/libexec/hyperv/ directory */ + snprintf(cmd, sizeof(cmd), "%s", "sh /usr/libexec/hyperv/hv_get_dns_info"); + + /* + * Execute the command to get DNS info. + */ + kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr, + (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0); + + /* + * Invoke an external script to get the DHCP state info. + * The parameter to the script is the interface name. + * Here is the expected output: + * + * Enabled: DHCP enabled. + */ + + + snprintf(cmd, sizeof(cmd), "%s %s", + "sh /usr/libexec/hyperv/hv_get_dhcp_info", if_name); + + file = popen(cmd, "r"); + if (file == NULL) { + return; + } + + p = fgets(dhcp_info, sizeof(dhcp_info), file); + if (p == NULL) { + pclose(file); + return; + } + + if (!strncmp(p, "Enabled", 7)) { + buffer->dhcp_enabled = 1; + } else{ + buffer->dhcp_enabled = 0; + } + + pclose(file); +} + + +static unsigned int +hweight32(unsigned int *w) +{ + unsigned int res = *w - ((*w >> 1) & 0x55555555); + + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res + (res >> 4)) & 0x0F0F0F0F; + res = res + (res >> 8); + return ((res + (res >> 16)) & 0x000000FF); +} + + +static int +kvp_process_ip_address(void *addrp, + int family, char *buffer, + int length, int *offset) +{ + struct sockaddr_in *addr; + struct sockaddr_in6 *addr6; + int addr_length; + char tmp[50]; + const char *str; + + if (family == AF_INET) { + addr = (struct sockaddr_in *)addrp; + str = inet_ntop(family, &addr->sin_addr, tmp, 50); + addr_length = INET_ADDRSTRLEN; + } else { + addr6 = (struct sockaddr_in6 *)addrp; + str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50); + addr_length = INET6_ADDRSTRLEN; + } + + if ((length - *offset) < addr_length + 1) { + return (HV_KVP_E_FAIL); + } + if (str == NULL) { + strlcpy(buffer, "inet_ntop failed\n", length); + return (HV_KVP_E_FAIL); + } + if (*offset == 0) { + strlcpy(buffer, tmp, length); + } else{ + strlcat(buffer, tmp, length); + } + strlcat(buffer, ";", length); + + *offset += strlen(str) + 1; + return (0); +} + + +static int +kvp_get_ip_info(int family, char *if_name, int op, + void *out_buffer, size_t length) +{ + struct ifaddrs *ifap; + struct ifaddrs *curp; + int offset = 0; + int sn_offset = 0; + int error = 0; + char *buffer; + size_t buffer_length; + struct hv_kvp_ipaddr_value *ip_buffer; + char cidr_mask[5]; + int weight; + int i; + unsigned int *w = NULL; + char *sn_str; + size_t sn_str_length; + struct sockaddr_in6 *addr6; + + if (op == HV_KVP_OP_ENUMERATE) { + buffer = out_buffer; + buffer_length = length; + } else { + ip_buffer = out_buffer; + buffer = (char *)ip_buffer->ip_addr; + buffer_length = sizeof(ip_buffer->ip_addr); + ip_buffer->addr_family = 0; + } + + if (getifaddrs(&ifap)) { + strlcpy(buffer, "getifaddrs failed\n", buffer_length); + return (HV_KVP_E_FAIL); + } + + curp = ifap; + while (curp != NULL) { + if (curp->ifa_addr == NULL) { + curp = curp->ifa_next; + continue; + } + + if ((if_name != NULL) && + (strncmp(curp->ifa_name, if_name, strlen(if_name)))) { + /* + * We want info about a specific interface; + * just continue. + */ + curp = curp->ifa_next; + continue; + } + + /* + * We support two address families: AF_INET and AF_INET6. + * If family value is 0, we gather both supported + * address families; if not we gather info on + * the specified address family. + */ + if ((family != 0) && (curp->ifa_addr->sa_family != family)) { + curp = curp->ifa_next; + continue; + } + if ((curp->ifa_addr->sa_family != AF_INET) && + (curp->ifa_addr->sa_family != AF_INET6)) { + curp = curp->ifa_next; + continue; + } + + if (op == HV_KVP_OP_GET_IP_INFO) { + /* + * Get the info other than the IP address. + */ + if (curp->ifa_addr->sa_family == AF_INET) { + ip_buffer->addr_family |= ADDR_FAMILY_IPV4; + + /* + * Get subnet info. + */ + error = kvp_process_ip_address( + curp->ifa_netmask, + AF_INET, + (char *) + ip_buffer->sub_net, + length, + &sn_offset); + if (error) { + goto kvp_get_ip_info_ipaddr; + } + } else { + ip_buffer->addr_family |= ADDR_FAMILY_IPV6; + + /* + * Get subnet info in CIDR format. + */ + weight = 0; + sn_str = (char *)ip_buffer->sub_net; + sn_str_length = sizeof(ip_buffer->sub_net); + addr6 = (struct sockaddr_in6 *)(uintptr_t) + curp->ifa_netmask; + w = (unsigned int *)(uintptr_t)addr6->sin6_addr.s6_addr; + + for (i = 0; i < 4; i++) + { + weight += hweight32(&w[i]); + } + + snprintf(cidr_mask, sizeof(cidr_mask), "/%d", weight); + if ((length - sn_offset) < + (strlen(cidr_mask) + 1)) { + goto kvp_get_ip_info_ipaddr; + } + + if (sn_offset == 0) { + strlcpy(sn_str, cidr_mask, sn_str_length); + } else{ + strlcat(sn_str, cidr_mask, sn_str_length); + } + strlcat((char *)ip_buffer->sub_net, ";", sn_str_length); + sn_offset += strlen(sn_str) + 1; + } + + /* + * Collect other ip configuration info. + */ + + kvp_get_ipconfig_info(if_name, ip_buffer); + } + +kvp_get_ip_info_ipaddr: + error = kvp_process_ip_address(curp->ifa_addr, + curp->ifa_addr->sa_family, + buffer, + length, &offset); + if (error) { + goto kvp_get_ip_info_done; + } + + curp = curp->ifa_next; + } + +kvp_get_ip_info_done: + freeifaddrs(ifap); + return (error); +} + + +static int +kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3) +{ + int ret; + + ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); + + if (ret < 0) { + return (HV_KVP_E_FAIL); + } + + return (0); +} + + +static int +kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) +{ + int error = 0; + char if_file[128]; + FILE *file; + char cmd[512]; + char *mac_addr; + + /* + * FreeBSD - Configuration File + */ + snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv", + "hv_set_ip_data"); + file = fopen(if_file, "w"); + + if (file == NULL) { + KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); + return (HV_KVP_E_FAIL); + } + + /* + * Write out the MAC address. + */ + + mac_addr = kvp_if_name_to_mac(if_name); + if (mac_addr == NULL) { + error = HV_KVP_E_FAIL; + goto kvp_set_ip_info_error; + } + /* MAC Address */ + error = kvp_write_file(file, "HWADDR", "", mac_addr); + if (error) { + goto kvp_set_ip_info_error; + } + + /* Interface Name */ + error = kvp_write_file(file, "IF_NAME", "", if_name); + if (error) { + goto kvp_set_ip_info_error; + } + + /* IP Address */ + error = kvp_write_file(file, "IP_ADDR", "", + (char *)new_val->ip_addr); + if (error) { + goto kvp_set_ip_info_error; + } + + /* Subnet Mask */ + error = kvp_write_file(file, "SUBNET", "", + (char *)new_val->sub_net); + if (error) { + goto kvp_set_ip_info_error; + } + + + /* Gateway */ + error = kvp_write_file(file, "GATEWAY", "", + (char *)new_val->gate_way); + if (error) { + goto kvp_set_ip_info_error; + } + + /* DNS */ + error = kvp_write_file(file, "DNS", "", (char *)new_val->dns_addr); + if (error) { + goto kvp_set_ip_info_error; + } + + /* DHCP */ + if (new_val->dhcp_enabled) { + error = kvp_write_file(file, "DHCP", "", "1"); + } else{ + error = kvp_write_file(file, "DHCP", "", "0"); + } + + if (error) { + goto kvp_set_ip_info_error; + } + + free(mac_addr); + fclose(file); + + /* + * Invoke the external script with the populated + * configuration file. + */ + + snprintf(cmd, sizeof(cmd), "%s %s", + "sh /usr/libexec/hyperv/hv_set_ifconfig", if_file); + system(cmd); + return (0); + +kvp_set_ip_info_error: + KVP_LOG(LOG_ERR, "Failed to write config file\n"); + free(mac_addr); + fclose(file); + return (error); +} + + +static int +kvp_get_domain_name(char *buffer, int length) +{ + struct addrinfo hints, *info; + int error = 0; + + gethostname(buffer, length); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; /* Get only ipv4 addrinfo. */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + error = getaddrinfo(buffer, NULL, &hints, &info); + if (error != 0) { + strlcpy(buffer, "getaddrinfo failed\n", length); + return (error); + } + strlcpy(buffer, info->ai_canonname, length); + freeaddrinfo(info); + return (error); +} + + +static int +kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused) +{ + struct hv_kvp_ipaddr_value *ip_val; + char *if_name; + + assert(op_msg != NULL); + KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); + + ip_val = &op_msg->body.kvp_ip_val; + op_msg->hdr.error = HV_KVP_S_OK; + + if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id); + + if (if_name == NULL) { + /* No interface found with the mac address. */ + op_msg->hdr.error = HV_KVP_E_FAIL; + goto kvp_op_getipinfo_done; + } + + op_msg->hdr.error = kvp_get_ip_info(0, if_name, + HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2)); + + free(if_name); + +kvp_op_getipinfo_done: + return(op_msg->hdr.error); +} + + +static int +kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused) +{ + struct hv_kvp_ipaddr_value *ip_val; + char *if_name; + + assert(op_msg != NULL); + KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); + + ip_val = &op_msg->body.kvp_ip_val; + op_msg->hdr.error = HV_KVP_S_OK; + + if_name = (char *)ip_val->adapter_id; + + if (if_name == NULL) { + /* No adapter provided. */ + op_msg->hdr.error = HV_KVP_GUID_NOTFOUND; + goto kvp_op_setipinfo_done; + } + + op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val); + +kvp_op_setipinfo_done: + return(op_msg->hdr.error); +} + + +static int +kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) +{ + struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data; + int error = 0; + int op_pool; + + assert(op_msg != NULL); + assert(op_hdlr != NULL); + + op_pool = op_msg->hdr.kvp_hdr.pool; + op_msg->hdr.error = HV_KVP_S_OK; + + switch(op_hdlr->kvp_op_key) { + case HV_KVP_OP_SET: + if (op_pool == HV_KVP_POOL_AUTO) { + /* Auto Pool is not writeable from host side. */ + error = 1; + KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n", + op_pool); + } else { + error = kvp_key_add_or_modify(op_pool, + op_msg->body.kvp_set.data.key, + op_msg->body.kvp_set.data.key_size, + op_msg->body.kvp_set.data.msg_value.value, + op_msg->body.kvp_set.data.value_size); + } + break; + + case HV_KVP_OP_GET: + error = kvp_get_value(op_pool, + op_msg->body.kvp_get.data.key, + op_msg->body.kvp_get.data.key_size, + op_msg->body.kvp_get.data.msg_value.value, + op_msg->body.kvp_get.data.value_size); + break; + + case HV_KVP_OP_DELETE: + if (op_pool == HV_KVP_POOL_AUTO) { + /* Auto Pool is not writeable from host side. */ + error = 1; + KVP_LOG(LOG_ERR, "Ilegal to change pool %d from host\n", + op_pool); + } else { + error = kvp_key_delete(op_pool, + op_msg->body.kvp_delete.key, + op_msg->body.kvp_delete.key_size); + } + break; + + default: + break; + } + + if (error != 0) + op_msg->hdr.error = HV_KVP_S_CONT; + + return(error); +} + + +static int +kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) +{ + char *key_name, *key_value; + int error = 0; + int op_pool; + int op; + + assert(op_msg != NULL); + + op = op_msg->hdr.kvp_hdr.operation; + op_pool = op_msg->hdr.kvp_hdr.pool; + op_msg->hdr.error = HV_KVP_S_OK; + + /* + * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate + * pool and return the KVP according to the index requested. + */ + if (op_pool != HV_KVP_POOL_AUTO) { + if (kvp_pool_enumerate(op_pool, + op_msg->body.kvp_enum_data.index, + op_msg->body.kvp_enum_data.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE, + op_msg->body.kvp_enum_data.data.msg_value.value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { + op_msg->hdr.error = HV_KVP_S_CONT; + error = -1; + } + goto kvp_op_enumerate_done; + } + + key_name = (char *)op_msg->body.kvp_enum_data.data.key; + key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value; + + switch (op_msg->body.kvp_enum_data.index) + { + case FullyQualifiedDomainName: + kvp_get_domain_name(key_value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + strcpy(key_name, "FullyQualifiedDomainName"); + break; + + case IntegrationServicesVersion: + strcpy(key_name, "IntegrationServicesVersion"); + strcpy(key_value, lic_version); + break; + + case NetworkAddressIPv4: + kvp_get_ip_info(AF_INET, NULL, HV_KVP_OP_ENUMERATE, + key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + strcpy(key_name, "NetworkAddressIPv4"); + break; + + case NetworkAddressIPv6: + kvp_get_ip_info(AF_INET6, NULL, HV_KVP_OP_ENUMERATE, + key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); + strcpy(key_name, "NetworkAddressIPv6"); + break; + + case OSBuildNumber: + strcpy(key_value, os_build); + strcpy(key_name, "OSBuildNumber"); + break; + + case OSName: + strcpy(key_value, os_name); + strcpy(key_name, "OSName"); + break; + + case OSMajorVersion: + strcpy(key_value, os_major); + strcpy(key_name, "OSMajorVersion"); + break; + + case OSMinorVersion: + strcpy(key_value, os_minor); + strcpy(key_name, "OSMinorVersion"); + break; + + case OSVersion: + strcpy(key_value, os_build); + strcpy(key_name, "OSVersion"); + break; + + case ProcessorArchitecture: + strcpy(key_value, processor_arch); + strcpy(key_name, "ProcessorArchitecture"); + break; + + default: +#ifdef DEBUG + KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n", + op_msg->body.kvp_enum_data.index); +#endif + op_msg->hdr.error = HV_KVP_S_CONT; + error = -1; + break; + } + +kvp_op_enumerate_done: + return(error); +} + + +/* + * Load handler, and call init routine if provided. + */ +static int +kvp_op_load(int key, void (*init)(void), + int (*exec)(struct hv_kvp_msg *, void *)) +{ + int error = 0; + + if (key < 0 || key >= HV_KVP_OP_COUNT) { + KVP_LOG(LOG_ERR, "Operation key out of supported range\n"); + error = -1; + goto kvp_op_load_done; + } + + kvp_op_hdlrs[key].kvp_op_key = key; + kvp_op_hdlrs[key].kvp_op_init = init; + kvp_op_hdlrs[key].kvp_op_exec = exec; + + if (kvp_op_hdlrs[key].kvp_op_init != NULL) + kvp_op_hdlrs[key].kvp_op_init(); + +kvp_op_load_done: + return(error); +} + + +/* + * Initialize the operation hanlders. + */ +static int +kvp_ops_init(void) +{ + int i; + + /* Set the initial values. */ + for (i = 0; i < HV_KVP_OP_COUNT; i++) { + kvp_op_hdlrs[i].kvp_op_key = -1; + kvp_op_hdlrs[i].kvp_op_init = NULL; + kvp_op_hdlrs[i].kvp_op_exec = NULL; + } + + return(kvp_op_load(HV_KVP_OP_GET, NULL, kvp_op_setgetdel) | + kvp_op_load(HV_KVP_OP_SET, NULL, kvp_op_setgetdel) | + kvp_op_load(HV_KVP_OP_DELETE, NULL, kvp_op_setgetdel) | + kvp_op_load(HV_KVP_OP_ENUMERATE, kvp_get_os_info, + kvp_op_enumerate) | + kvp_op_load(HV_KVP_OP_GET_IP_INFO, NULL, kvp_op_getipinfo) | + kvp_op_load(HV_KVP_OP_SET_IP_INFO, NULL, kvp_op_setipinfo)); +} + + +int +main(int argc, char *argv[]) +{ + struct hv_kvp_msg *hv_kvp_dev_buf; + struct hv_kvp_msg *hv_msg; + struct pollfd hv_kvp_poll_fd[1]; + int op, pool; + int hv_kvp_dev_fd, error, len, r; + int ch; + + while ((ch = getopt(argc, argv, "dn")) != -1) { + switch (ch) { + case 'n': + /* Run as regular process for debugging purpose. */ + is_daemon = 0; + break; + case 'd': + /* Generate debugging output */ + is_debugging = 1; + break; + default: + break; + } + } + + openlog("HV_KVP", 0, LOG_USER); + + /* Become daemon first. */ + if (is_daemon == 1) + daemon(1, 0); + else + KVP_LOG(LOG_DEBUG, "Run as regular process.\n"); + + KVP_LOG(LOG_INFO, "HV_KVP starting; pid is: %d\n", getpid()); + + /* Communication buffer hv_kvp_dev_buf */ + hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf)); + /* Buffer for daemon internal use */ + hv_msg = malloc(sizeof(*hv_msg)); + + /* Memory allocation failed */ + if (hv_kvp_dev_buf == NULL || hv_msg == NULL) { + KVP_LOG(LOG_ERR, "Failed to allocate memory for hv buffer\n"); + exit(EXIT_FAILURE); + } + + /* Initialize op handlers */ + if (kvp_ops_init() != 0) { + KVP_LOG(LOG_ERR, "Failed to initizlize operation handlers\n"); + exit(EXIT_FAILURE); + } + + if (kvp_file_init()) { + KVP_LOG(LOG_ERR, "Failed to initialize the pools\n"); + exit(EXIT_FAILURE); + } + + /* Open the Character Device */ + hv_kvp_dev_fd = open("/dev/hv_kvp_dev", O_RDWR); + + if (hv_kvp_dev_fd < 0) { + KVP_LOG(LOG_ERR, "open /dev/hv_kvp_dev failed; error: %d %s\n", + errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Initialize the struct for polling the char device */ + hv_kvp_poll_fd[0].fd = hv_kvp_dev_fd; + hv_kvp_poll_fd[0].events = (POLLIN | POLLRDNORM); + + /* Register the daemon to the KVP driver */ + memset(hv_kvp_dev_buf, 0, sizeof(*hv_kvp_dev_buf)); + hv_kvp_dev_buf->hdr.kvp_hdr.operation = HV_KVP_OP_REGISTER; + len = write(hv_kvp_dev_fd, hv_kvp_dev_buf, sizeof(*hv_kvp_dev_buf)); + + + for (;;) { + r = poll (hv_kvp_poll_fd, 1, 100); + + KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n", + r, hv_kvp_poll_fd[0].revents); + + if (r == 0 || (r < 0 && errno == EAGAIN) || + (r < 0 && errno == EINTR)) { + /* Nothing to read */ + continue; + } + + if (r < 0) { + /* + * For pread return failure other than EAGAIN, + * we want to exit. + */ + KVP_LOG(LOG_ERR, "Poll failed.\n"); + perror("poll"); + exit(EIO); + } + + /* Read from character device */ + len = pread(hv_kvp_dev_fd, hv_kvp_dev_buf, + sizeof(*hv_kvp_dev_buf), 0); + + if (len < 0) { + KVP_LOG(LOG_ERR, "Read failed.\n"); + perror("pread"); + exit(EIO); + } + + if (len != sizeof(struct hv_kvp_msg)) { + KVP_LOG(LOG_ERR, "read len is: %d\n", len); + continue; + } + + /* Copy hv_kvp_dev_buf to hv_msg */ + memcpy(hv_msg, hv_kvp_dev_buf, sizeof(*hv_msg)); + + /* + * We will use the KVP header information to pass back + * the error from this daemon. So, first save the op + * and pool info to local variables. + */ + + op = hv_msg->hdr.kvp_hdr.operation; + pool = hv_msg->hdr.kvp_hdr.pool; + + if (op < 0 || op >= HV_KVP_OP_COUNT || + kvp_op_hdlrs[op].kvp_op_exec == NULL) { + KVP_LOG(LOG_WARNING, + "Unsupported operation OP = %d\n", op); + hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED; + } else { + /* + * Call the operateion handler's execution routine. + */ + error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, + (void *)&kvp_op_hdlrs[op]); + if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT) + KVP_LOG(LOG_WARNING, + "Operation failed OP = %d, error = 0x%x\n", + op, error); + } + + /* + * Send the value back to the kernel. The response is + * already in the receive buffer. + */ +hv_kvp_done: + len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0); + + if (len != sizeof(struct hv_kvp_msg)) { + KVP_LOG(LOG_ERR, "write len is: %d\n", len); + goto hv_kvp_done; + } + } +} diff --git a/contrib/hyperv/tools/scripts/hv_get_dhcp_info b/contrib/hyperv/tools/scripts/hv_get_dhcp_info new file mode 100644 index 000000000000..b56efd30f4e4 --- /dev/null +++ b/contrib/hyperv/tools/scripts/hv_get_dhcp_info @@ -0,0 +1,24 @@ +#!/bin/sh + +# This is the script retrieves the DHCP state of a given interface. +# The kvp daemon code invokes this external script to gather +# DHCP setting for the specific interface. +# +# Input: Name of the interface +# +# Output: The script prints the string "Enabled" to stdout to indicate +# that DHCP is enabled on the interface. If DHCP is not enabled, +# the script prints the string "Disabled" to stdout. +# + +. /etc/rc.subr +. /etc/network.subr + +load_rc_config netif + +if dhcpif hn0; +then +echo "Enabled" +else +echo "Disabled" +fi diff --git a/contrib/hyperv/tools/scripts/hv_get_dns_info b/contrib/hyperv/tools/scripts/hv_get_dns_info new file mode 100644 index 000000000000..7a34440fd902 --- /dev/null +++ b/contrib/hyperv/tools/scripts/hv_get_dns_info @@ -0,0 +1,12 @@ +#!/bin/sh +# This script parses /etc/resolv.conf to retrive DNS information. +# Khe kvp daemon code invokes this external script to gather +# DNS information. +# This script is expected to print the nameserver values to stdout. + +#if test -r /etc/resolv.conf +#then +# awk -- '/^nameserver/ { print $2 }' /etc/resolv.conf +#fi +cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }' + diff --git a/contrib/hyperv/tools/scripts/hv_set_ifconfig b/contrib/hyperv/tools/scripts/hv_set_ifconfig new file mode 100644 index 000000000000..3dc42e7bbf82 --- /dev/null +++ b/contrib/hyperv/tools/scripts/hv_set_ifconfig @@ -0,0 +1,73 @@ +#!/bin/sh + +# This script activates an interface based on the specified +# configuration. The kvp daemon code invokes this external script +# to configure the interface. +# +# The only argument to this script is the configuration file that is to +# be used to configure the interface. +# +# Here is the format of the ip configuration file: +# +# HWADDR=macaddr +# IF_NAME=interface name +# DHCP=yes (This is optional; if yes, DHCP is configured) +# +# IPADDR=ipaddr1 +# IPADDR_1=ipaddr2 +# IPADDR_x=ipaddry (where y = x + 1) +# +# NETMASK=netmask1 +# NETMASK_x=netmasky (where y = x + 1) +# +# GATEWAY=ipaddr1 +# GATEWAY_x=ipaddry (where y = x + 1) +# +# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc) +# +# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be +# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as +# IPV6NETMASK. +# +# The host can specify multiple ipv4 and ipv6 addresses to be +# configured for the interface. Furthermore, the configuration +# needs to be persistent. A subsequent GET call on the interface +# is expected to return the configuration that is set via the SET +# call. +# + +. $1 + +sed -i".bak" '/ifconfig_hn0="SYNCDHCP"/d' /etc/rc.conf +sed -i".bak" '/ifconfig_hn0="DHCP"/d' /etc/rc.conf + +# MAC Address +ifconfig $IF_NAME ether $HWADDR + +# IP and Subnet Mask +ifconfig $IF_NAME inet $IP_ADDR netmask $SUBNET + +# DNS +sed -i".bak" '/nameserver/d' /etc/resolv.conf +echo "nameserver" $DNS >> /etc/resolv.conf + +#Gateway +# Need to implment if Gateway is not present +route flush +route add default $GATEWAY +#route change default $GATEWAY + +#/etc/rc.d/netif restart +#/etc/rc.d/routing restart + + +# DHCP +if [ $DHCP -eq 1 ] +then + echo ifconfig_hn0=\"DHCP\" >> /etc/rc.conf + echo Enabled +else + echo Disabled DHCP >> /var/log/messages + echo Disabled +fi +echo "Set IP-Injection Success" diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index 084850014d04..977cf754d451 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -108,6 +108,8 @@ .. bsdinstall .. + hyperv + .. lpr ru .. diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist index 990c23c9abb3..7d4af0be5ab6 100644 --- a/etc/mtree/BSD.var.dist +++ b/etc/mtree/BSD.var.dist @@ -42,6 +42,8 @@ .. freebsd-update mode=0700 .. + hyperv mode=0700 + .. ipf mode=0700 .. pkg diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 64e83ac8ca50..d0897e3e905d 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -57,6 +57,7 @@ FILES= DAEMON \ hostid \ hostid_save \ hostname \ + ${_hv_kvpd} \ inetd \ initrandom \ ip6addrctl \ @@ -192,6 +193,10 @@ _ubthidhci= ubthidhci _casperd= casperd .endif +.if ${MK_HYPERV} != "no" +_hv_kvpd= hv_kvpd +.endif + .if ${MK_UNBOUND} != "no" _unbound= local_unbound .endif diff --git a/etc/rc.d/hv_kvpd b/etc/rc.d/hv_kvpd new file mode 100644 index 000000000000..78e4b7447320 --- /dev/null +++ b/etc/rc.d/hv_kvpd @@ -0,0 +1,15 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: hv_kvpd + +. /etc/rc.subr + +name="hv_kvp_daemon" +command="/usr/sbin/${name}" +required_dirs="/var/db/hyperv" + +load_rc_config $name +run_rc_command "$1" diff --git a/libexec/Makefile b/libexec/Makefile index 8a32694d4050..74cc6d8fb27f 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -13,6 +13,7 @@ SUBDIR= ${_atf} \ fingerd \ ftpd \ getty \ + ${_hyperv} \ ${_mail.local} \ ${_mknetid} \ ${_pppoed} \ @@ -54,6 +55,10 @@ _dma= dma _dma-mbox-create= dma-mbox-create .endif +.if ${MK_HYPERV} != "no" +_hyperv= hyperv +.endif + .if ${MK_NIS} != "no" _mknetid= mknetid _ypxfr= ypxfr diff --git a/libexec/hyperv/Makefile b/libexec/hyperv/Makefile new file mode 100644 index 000000000000..37abdf5b8b3b --- /dev/null +++ b/libexec/hyperv/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../contrib/hyperv/tools/scripts + +BINDIR= /usr/libexec/hyperv + +SCRIPTS= hv_set_ifconfig hv_get_dns_info hv_get_dhcp_info +NO_OBJ= + +.include diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index a4f3e25ce5cc..e6202b2f4637 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -212,6 +212,13 @@ __DEFAULT_NO_OPTIONS+=CLANG_IS_CC CLANG CLANG_BOOTSTRAP __DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX .endif +# HyperV is only available for x86 and amd64. +.if ${__T} == "amd64" || ${__T} == "i386" +__DEFAULT_YES_OPTIONS+=HYPERV +.else +__DEFAULT_NO_OPTIONS+=HYPERV +.endif + .include # diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a42e2522e16c..000e1c95d9c9 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -223,6 +223,7 @@ dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv +dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index a2f3bff45b08..2b3c1419aecf 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -215,6 +215,7 @@ dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv +dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 4257b371c717..8a45d89cd063 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -795,5 +795,34 @@ hv_get_phys_addr(void *virt) return (ret); } + +/** + * KVP related structures + * + */ +typedef struct hv_vmbus_service { + hv_guid guid; /* Hyper-V GUID */ + char *name; /* name of service */ + boolean_t enabled; /* service enabled */ + hv_work_queue *work_queue; /* background work queue */ + + /* + * function to initialize service + */ + int (*init)(struct hv_vmbus_service *); + + /* + * function to process Hyper-V messages + */ + void (*callback)(void *); +} hv_vmbus_service; + +extern uint8_t* receive_buffer[]; +extern hv_vmbus_service service_table[]; + +void hv_kvp_callback(void *context); +int hv_kvp_init(hv_vmbus_service *serv); +void hv_kvp_deinit(void); + #endif /* __HYPERV_H__ */ diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c new file mode 100644 index 000000000000..848d364a4b33 --- /dev/null +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -0,0 +1,1001 @@ +/*- + * Copyright (c) 2014 Microsoft Corp. + * 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 unmodified, 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 AUTHOR ``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 AUTHOR 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. + */ + +/* + * Author: Sainath Varanasi. + * Date: 4/2012 + * Email: bsdic@microsoft.com + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "unicode.h" +#include "hv_kvp.h" + +/* hv_kvp defines */ +#define BUFFERSIZE sizeof(struct hv_kvp_msg) +#define KVP_SUCCESS 0 +#define KVP_ERROR 1 +#define kvp_hdr hdr.kvp_hdr + +/* hv_kvp debug control */ +static int hv_kvp_log = 0; +SYSCTL_INT(_dev, OID_AUTO, hv_kvp_log, CTLFLAG_RW, &hv_kvp_log, 0, + "hv_kvp log"); + +#define hv_kvp_log_error(...) do { \ + if (hv_kvp_log > 0) \ + log(LOG_ERR, "hv_kvp: " __VA_ARGS__); \ +} while (0) + +#define hv_kvp_log_info(...) do { \ + if (hv_kvp_log > 1) \ + log(LOG_INFO, "hv_kvp: " __VA_ARGS__); \ +} while (0) + +/* character device prototypes */ +static d_open_t hv_kvp_dev_open; +static d_close_t hv_kvp_dev_close; +static d_read_t hv_kvp_dev_daemon_read; +static d_write_t hv_kvp_dev_daemon_write; +static d_poll_t hv_kvp_dev_daemon_poll; + +/* hv_kvp prototypes */ +static int hv_kvp_req_in_progress(void); +static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *); +static void hv_kvp_send_msg_to_daemon(void); +static void hv_kvp_process_request(void *context); + +/* hv_kvp character device structure */ +static struct cdevsw hv_kvp_cdevsw = +{ + .d_version = D_VERSION, + .d_open = hv_kvp_dev_open, + .d_close = hv_kvp_dev_close, + .d_read = hv_kvp_dev_daemon_read, + .d_write = hv_kvp_dev_daemon_write, + .d_poll = hv_kvp_dev_daemon_poll, + .d_name = "hv_kvp_dev", +}; +static struct cdev *hv_kvp_dev; +static struct hv_kvp_msg *hv_kvp_dev_buf; +struct proc *daemon_task; + +/* + * Global state to track and synchronize multiple + * KVP transaction requests from the host. + */ +static struct { + + /* Pre-allocated work item for queue */ + hv_work_item work_item; + + /* Unless specified the pending mutex should be + * used to alter the values of the following paramters: + * 1. req_in_progress + * 2. req_timed_out + * 3. pending_reqs. + */ + struct mtx pending_mutex; + + /* To track if transaction is active or not */ + boolean_t req_in_progress; + /* Tracks if daemon did not reply back in time */ + boolean_t req_timed_out; + /* Tracks if daemon is serving a request currently */ + boolean_t daemon_busy; + /* Count of KVP requests from Hyper-V. */ + uint64_t pending_reqs; + + + /* Length of host message */ + uint32_t host_msg_len; + + /* Pointer to channel */ + hv_vmbus_channel *channelp; + + /* Host message id */ + uint64_t host_msg_id; + + /* Current kvp message from the host */ + struct hv_kvp_msg *host_kvp_msg; + + /* Current kvp message for daemon */ + struct hv_kvp_msg daemon_kvp_msg; + + /* Rcv buffer for communicating with the host*/ + uint8_t *rcv_buf; + + /* Device semaphore to control communication */ + struct sema dev_sema; + + /* Indicates if daemon registered with driver */ + boolean_t register_done; + + /* Character device status */ + boolean_t dev_accessed; +} kvp_globals; + +/* global vars */ +MALLOC_DECLARE(M_HV_KVP_DEV_BUF); +MALLOC_DEFINE(M_HV_KVP_DEV_BUF, "hv_kvp_dev buffer", "buffer for hv_kvp_dev module"); + +/* + * hv_kvp low level functions + */ + +/* + * Check if kvp transaction is in progres + */ +static int +hv_kvp_req_in_progress(void) +{ + + return (kvp_globals.req_in_progress); +} + + +/* + * This routine is called whenever a message is received from the host + */ +static void +hv_kvp_transaction_init(uint32_t rcv_len, hv_vmbus_channel *rcv_channel, + uint64_t request_id, uint8_t *rcv_buf) +{ + + /* Store all the relevant message details in the global structure */ + /* Do not need to use mutex for req_in_progress here */ + kvp_globals.req_in_progress = true; + kvp_globals.host_msg_len = rcv_len; + kvp_globals.channelp = rcv_channel; + kvp_globals.host_msg_id = request_id; + kvp_globals.rcv_buf = rcv_buf; + kvp_globals.host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[ + sizeof(struct hv_vmbus_pipe_hdr) + + sizeof(struct hv_vmbus_icmsg_hdr)]; +} + + +/* + * hv_kvp - version neogtiation function + */ +static void +hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, + struct hv_vmbus_icmsg_negotiate *negop, + uint8_t *buf) +{ + int icframe_vercnt; + int icmsg_vercnt; + + icmsghdrp->icmsgsize = 0x10; + + negop = (struct hv_vmbus_icmsg_negotiate *)&buf[ + sizeof(struct hv_vmbus_pipe_hdr) + + sizeof(struct hv_vmbus_icmsg_hdr)]; + icframe_vercnt = negop->icframe_vercnt; + icmsg_vercnt = negop->icmsg_vercnt; + + /* + * Select the framework version number we will support + */ + if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) { + icframe_vercnt = 3; + if (icmsg_vercnt >= 2) + icmsg_vercnt = 4; + else + icmsg_vercnt = 3; + } else { + icframe_vercnt = 1; + icmsg_vercnt = 1; + } + + negop->icframe_vercnt = 1; + negop->icmsg_vercnt = 1; + negop->icversion_data[0].major = icframe_vercnt; + negop->icversion_data[0].minor = 0; + negop->icversion_data[1].major = icmsg_vercnt; + negop->icversion_data[1].minor = 0; +} + + +/* + * Convert ip related info in umsg from utf8 to utf16 and store in hmsg + */ +static int +hv_kvp_convert_utf8_ipinfo_to_utf16(struct hv_kvp_msg *umsg, + struct hv_kvp_ip_msg *host_ip_msg) +{ + int err_ip, err_subnet, err_gway, err_dns, err_adap; + int UNUSED_FLAG = 1; + + utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, + MAX_IP_ADDR_SIZE, + (char *)umsg->body.kvp_ip_val.ip_addr, + strlen((char *)umsg->body.kvp_ip_val.ip_addr), + UNUSED_FLAG, + &err_ip); + utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.sub_net, + MAX_IP_ADDR_SIZE, + (char *)umsg->body.kvp_ip_val.sub_net, + strlen((char *)umsg->body.kvp_ip_val.sub_net), + UNUSED_FLAG, + &err_subnet); + utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.gate_way, + MAX_GATEWAY_SIZE, + (char *)umsg->body.kvp_ip_val.gate_way, + strlen((char *)umsg->body.kvp_ip_val.gate_way), + UNUSED_FLAG, + &err_gway); + utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, + MAX_IP_ADDR_SIZE, + (char *)umsg->body.kvp_ip_val.dns_addr, + strlen((char *)umsg->body.kvp_ip_val.dns_addr), + UNUSED_FLAG, + &err_dns); + utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, + MAX_IP_ADDR_SIZE, + (char *)umsg->body.kvp_ip_val.adapter_id, + strlen((char *)umsg->body.kvp_ip_val.adapter_id), + UNUSED_FLAG, + &err_adap); + + host_ip_msg->kvp_ip_val.dhcp_enabled = umsg->body.kvp_ip_val.dhcp_enabled; + host_ip_msg->kvp_ip_val.addr_family = umsg->body.kvp_ip_val.addr_family; + + return (err_ip | err_subnet | err_gway | err_dns | err_adap); +} + + +/* + * Convert ip related info in hmsg from utf16 to utf8 and store in umsg + */ +static int +hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, + struct hv_kvp_msg *umsg) +{ + int err_ip, err_subnet, err_gway, err_dns, err_adap; + int UNUSED_FLAG = 1; + int guid_index; + struct hv_device *hv_dev; /* GUID Data Structure */ + hn_softc_t *sc; /* hn softc structure */ + char if_name[4]; + unsigned char guid_instance[40]; + char *guid_data = NULL; + char buf[39]; + + struct guid_extract { + char a1[2]; + char a2[2]; + char a3[2]; + char a4[2]; + char b1[2]; + char b2[2]; + char c1[2]; + char c2[2]; + char d[4]; + char e[12]; + }; + + struct guid_extract *id; + device_t *devs; + int devcnt; + + /* IP Address */ + utf16_to_utf8((char *)umsg->body.kvp_ip_val.ip_addr, + MAX_IP_ADDR_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, + MAX_IP_ADDR_SIZE, + UNUSED_FLAG, + &err_ip); + + /* Adapter ID : GUID */ + utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, + MAX_ADAPTER_ID_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, + MAX_ADAPTER_ID_SIZE, + UNUSED_FLAG, + &err_adap); + + if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) { + for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) { + sc = device_get_softc(devs[devcnt]); + + /* Trying to find GUID of Network Device */ + hv_dev = sc->hn_dev_obj; + + for (guid_index = 0; guid_index < 16; guid_index++) { + sprintf(&guid_instance[guid_index * 2], "%02x", + hv_dev->device_id.data[guid_index]); + } + + guid_data = (char *)guid_instance; + id = (struct guid_extract *)guid_data; + snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}", + id->a4, id->a3, id->a2, id->a1, + id->b2, id->b1, id->c2, id->c1, id->d, id->e); + guid_data = NULL; + sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt])); + + if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) { + strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name); + break; + } + } + free(devs, M_TEMP); + } + + /* Address Family , DHCP , SUBNET, Gateway, DNS */ + umsg->kvp_hdr.operation = host_ip_msg->operation; + umsg->body.kvp_ip_val.addr_family = host_ip_msg->kvp_ip_val.addr_family; + umsg->body.kvp_ip_val.dhcp_enabled = host_ip_msg->kvp_ip_val.dhcp_enabled; + utf16_to_utf8((char *)umsg->body.kvp_ip_val.sub_net, MAX_IP_ADDR_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.sub_net, + MAX_IP_ADDR_SIZE, + UNUSED_FLAG, + &err_subnet); + + utf16_to_utf8((char *)umsg->body.kvp_ip_val.gate_way, MAX_GATEWAY_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.gate_way, + MAX_GATEWAY_SIZE, + UNUSED_FLAG, + &err_gway); + + utf16_to_utf8((char *)umsg->body.kvp_ip_val.dns_addr, MAX_IP_ADDR_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, + MAX_IP_ADDR_SIZE, + UNUSED_FLAG, + &err_dns); + + return (err_ip | err_subnet | err_gway | err_dns | err_adap); +} + + +/* + * Prepare a user kvp msg based on host kvp msg (utf16 to utf8) + * Ensure utf16_utf8 takes care of the additional string terminating char!! + */ +static void +hv_kvp_convert_hostmsg_to_usermsg(void) +{ + int utf_err = 0; + uint32_t value_type; + struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *) + kvp_globals.host_kvp_msg; + + struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; + struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; + + memset(umsg, 0, sizeof(struct hv_kvp_msg)); + + umsg->kvp_hdr.operation = hmsg->kvp_hdr.operation; + umsg->kvp_hdr.pool = hmsg->kvp_hdr.pool; + + switch (umsg->kvp_hdr.operation) { + case HV_KVP_OP_SET_IP_INFO: + hv_kvp_convert_utf16_ipinfo_to_utf8(host_ip_msg, umsg); + break; + + case HV_KVP_OP_GET_IP_INFO: + utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, + MAX_ADAPTER_ID_SIZE, + (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, + MAX_ADAPTER_ID_SIZE, 1, &utf_err); + + umsg->body.kvp_ip_val.addr_family = + host_ip_msg->kvp_ip_val.addr_family; + break; + + case HV_KVP_OP_SET: + value_type = hmsg->body.kvp_set.data.value_type; + + switch (value_type) { + case HV_REG_SZ: + umsg->body.kvp_set.data.value_size = + utf16_to_utf8( + (char *)umsg->body.kvp_set.data.msg_value.value, + HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1, + (uint16_t *)hmsg->body.kvp_set.data.msg_value.value, + hmsg->body.kvp_set.data.value_size, + 1, &utf_err); + /* utf8 encoding */ + umsg->body.kvp_set.data.value_size = + umsg->body.kvp_set.data.value_size / 2; + break; + + case HV_REG_U32: + umsg->body.kvp_set.data.value_size = + sprintf(umsg->body.kvp_set.data.msg_value.value, "%d", + hmsg->body.kvp_set.data.msg_value.value_u32) + 1; + break; + + case HV_REG_U64: + umsg->body.kvp_set.data.value_size = + sprintf(umsg->body.kvp_set.data.msg_value.value, "%llu", + (unsigned long long) + hmsg->body.kvp_set.data.msg_value.value_u64) + 1; + break; + } + + umsg->body.kvp_set.data.key_size = + utf16_to_utf8( + umsg->body.kvp_set.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, + (uint16_t *)hmsg->body.kvp_set.data.key, + hmsg->body.kvp_set.data.key_size, + 1, &utf_err); + + /* utf8 encoding */ + umsg->body.kvp_set.data.key_size = + umsg->body.kvp_set.data.key_size / 2; + break; + + case HV_KVP_OP_GET: + umsg->body.kvp_get.data.key_size = + utf16_to_utf8(umsg->body.kvp_get.data.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, + (uint16_t *)hmsg->body.kvp_get.data.key, + hmsg->body.kvp_get.data.key_size, + 1, &utf_err); + /* utf8 encoding */ + umsg->body.kvp_get.data.key_size = + umsg->body.kvp_get.data.key_size / 2; + break; + + case HV_KVP_OP_DELETE: + umsg->body.kvp_delete.key_size = + utf16_to_utf8(umsg->body.kvp_delete.key, + HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, + (uint16_t *)hmsg->body.kvp_delete.key, + hmsg->body.kvp_delete.key_size, + 1, &utf_err); + /* utf8 encoding */ + umsg->body.kvp_delete.key_size = + umsg->body.kvp_delete.key_size / 2; + break; + + case HV_KVP_OP_ENUMERATE: + umsg->body.kvp_enum_data.index = + hmsg->body.kvp_enum_data.index; + break; + + default: + hv_kvp_log_info("%s: daemon_kvp_msg: Invalid operation : %d\n", + __func__, umsg->kvp_hdr.operation); + } +} + + +/* + * Prepare a host kvp msg based on user kvp msg (utf8 to utf16) + */ +static int +hv_kvp_convert_usermsg_to_hostmsg(void) +{ + int hkey_len = 0, hvalue_len = 0, utf_err = 0; + struct hv_kvp_exchg_msg_value *host_exchg_data; + char *key_name, *value; + + struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; + struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; + struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)hmsg; + + switch (hmsg->kvp_hdr.operation) { + case HV_KVP_OP_GET_IP_INFO: + return (hv_kvp_convert_utf8_ipinfo_to_utf16(umsg, host_ip_msg)); + + case HV_KVP_OP_SET_IP_INFO: + case HV_KVP_OP_SET: + case HV_KVP_OP_DELETE: + return (KVP_SUCCESS); + + case HV_KVP_OP_ENUMERATE: + host_exchg_data = &hmsg->body.kvp_enum_data.data; + key_name = umsg->body.kvp_enum_data.data.key; + hkey_len = utf8_to_utf16((uint16_t *)host_exchg_data->key, + ((HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2), + key_name, strlen(key_name), + 1, &utf_err); + /* utf16 encoding */ + host_exchg_data->key_size = 2 * (hkey_len + 1); + value = umsg->body.kvp_enum_data.data.msg_value.value; + hvalue_len = utf8_to_utf16( + (uint16_t *)host_exchg_data->msg_value.value, + ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), + value, strlen(value), + 1, &utf_err); + host_exchg_data->value_size = 2 * (hvalue_len + 1); + host_exchg_data->value_type = HV_REG_SZ; + + if ((hkey_len < 0) || (hvalue_len < 0)) + return (HV_KVP_E_FAIL); + + return (KVP_SUCCESS); + + case HV_KVP_OP_GET: + host_exchg_data = &hmsg->body.kvp_get.data; + value = umsg->body.kvp_get.data.msg_value.value; + hvalue_len = utf8_to_utf16( + (uint16_t *)host_exchg_data->msg_value.value, + ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), + value, strlen(value), + 1, &utf_err); + /* Convert value size to uft16 */ + host_exchg_data->value_size = 2 * (hvalue_len + 1); + /* Use values by string */ + host_exchg_data->value_type = HV_REG_SZ; + + if ((hkey_len < 0) || (hvalue_len < 0)) + return (HV_KVP_E_FAIL); + + return (KVP_SUCCESS); + + default: + return (HV_KVP_E_FAIL); + } +} + + +/* + * Send the response back to the host. + */ +static void +hv_kvp_respond_host(int error) +{ + struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp; + + hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *) + &kvp_globals.rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)]; + + if (error) + error = HV_KVP_E_FAIL; + + hv_icmsg_hdrp->status = error; + hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; + + error = hv_vmbus_channel_send_packet(kvp_globals.channelp, + kvp_globals.rcv_buf, + kvp_globals.host_msg_len, kvp_globals.host_msg_id, + HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); + + if (error) + hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n", + __func__, error); +} + + +/* + * This is the main kvp kernel process that interacts with both user daemon + * and the host + */ +static void +hv_kvp_send_msg_to_daemon(void) +{ + /* Prepare kvp_msg to be sent to user */ + hv_kvp_convert_hostmsg_to_usermsg(); + + /* Send the msg to user via function deamon_read - setting sema */ + sema_post(&kvp_globals.dev_sema); +} + + +/* + * Function to read the kvp request buffer from host + * and interact with daemon + */ +static void +hv_kvp_process_request(void *context) +{ + uint8_t *kvp_buf; + hv_vmbus_channel *channel = context; + uint32_t recvlen = 0; + uint64_t requestid; + struct hv_vmbus_icmsg_hdr *icmsghdrp; + int ret = 0; + uint64_t pending_cnt = 1; + + hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__); + kvp_buf = receive_buffer[HV_KVP]; + ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, + &recvlen, &requestid); + + /* + * We start counting only after the daemon registers + * and therefore there could be requests pending in + * the VMBus that are not reflected in pending_cnt. + * Therefore we continue reading as long as either of + * the below conditions is true. + */ + + while ((pending_cnt>0) || ((ret == 0) && (recvlen > 0))) { + + if ((ret == 0) && (recvlen>0)) { + + icmsghdrp = (struct hv_vmbus_icmsg_hdr *) + &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)]; + + hv_kvp_transaction_init(recvlen, channel, requestid, kvp_buf); + if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { + hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf); + hv_kvp_respond_host(ret); + + /* + * It is ok to not acquire the mutex before setting + * req_in_progress here because negotiation is the + * first thing that happens and hence there is no + * chance of a race condition. + */ + + kvp_globals.req_in_progress = false; + hv_kvp_log_info("%s :version negotiated\n", __func__); + + } else { + if (!kvp_globals.daemon_busy) { + + hv_kvp_log_info("%s: issuing qury to daemon\n", __func__); + mtx_lock(&kvp_globals.pending_mutex); + kvp_globals.req_timed_out = false; + kvp_globals.daemon_busy = true; + mtx_unlock(&kvp_globals.pending_mutex); + + hv_kvp_send_msg_to_daemon(); + hv_kvp_log_info("%s: waiting for daemon\n", __func__); + } + + /* Wait 5 seconds for daemon to respond back */ + tsleep(&kvp_globals, 0, "kvpworkitem", 5 * hz); + hv_kvp_log_info("%s: came out of wait\n", __func__); + } + } + + mtx_lock(&kvp_globals.pending_mutex); + + /* Notice that once req_timed_out is set to true + * it will remain true until the next request is + * sent to the daemon. The response from daemon + * is forwarded to host only when this flag is + * false. + */ + kvp_globals.req_timed_out = true; + + /* + * Cancel request if so need be. + */ + if (hv_kvp_req_in_progress()) { + hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__); + hv_kvp_respond_host(HV_KVP_E_FAIL); + kvp_globals.req_in_progress = false; + } + + /* + * Decrement pending request count and + */ + if (kvp_globals.pending_reqs>0) { + kvp_globals.pending_reqs = kvp_globals.pending_reqs - 1; + } + pending_cnt = kvp_globals.pending_reqs; + + mtx_unlock(&kvp_globals.pending_mutex); + + /* + * Try reading next buffer + */ + recvlen = 0; + ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, + &recvlen, &requestid); + hv_kvp_log_info("%s: read: context %p, pending_cnt %ju ret =%d, recvlen=%d\n", + __func__, context, pending_cnt, ret, recvlen); + } +} + + +/* + * Callback routine that gets called whenever there is a message from host + */ +void +hv_kvp_callback(void *context) +{ + uint64_t pending_cnt = 0; + + if (kvp_globals.register_done == false) { + + kvp_globals.channelp = context; + } else { + + mtx_lock(&kvp_globals.pending_mutex); + kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1; + pending_cnt = kvp_globals.pending_reqs; + mtx_unlock(&kvp_globals.pending_mutex); + if (pending_cnt == 1) { + hv_kvp_log_info("%s: Queuing work item\n", __func__); + hv_queue_work_item( + service_table[HV_KVP].work_queue, + hv_kvp_process_request, + context + ); + } + } +} + + +/* + * This function is called by the hv_kvp_init - + * creates character device hv_kvp_dev + * allocates memory to hv_kvp_dev_buf + * + */ +static int +hv_kvp_dev_init(void) +{ + int error = 0; + + /* initialize semaphore */ + sema_init(&kvp_globals.dev_sema, 0, "hv_kvp device semaphore"); + /* create character device */ + error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, + &hv_kvp_dev, + &hv_kvp_cdevsw, + 0, + UID_ROOT, + GID_WHEEL, + 0640, + "hv_kvp_dev"); + + if (error != 0) + return (error); + + /* + * Malloc with M_WAITOK flag will never fail. + */ + hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_HV_KVP_DEV_BUF, M_WAITOK | + M_ZERO); + + return (0); +} + + +/* + * This function is called by the hv_kvp_deinit - + * destroy character device + */ +static void +hv_kvp_dev_destroy(void) +{ + + if (daemon_task != NULL) { + PROC_LOCK(daemon_task); + kern_psignal(daemon_task, SIGKILL); + PROC_UNLOCK(daemon_task); + } + + destroy_dev(hv_kvp_dev); + free(hv_kvp_dev_buf, M_HV_KVP_DEV_BUF); + return; +} + + +static int +hv_kvp_dev_open(struct cdev *dev, int oflags, int devtype, + struct thread *td) +{ + + hv_kvp_log_info("%s: Opened device \"hv_kvp_device\" successfully.\n", __func__); + if (kvp_globals.dev_accessed) + return (-EBUSY); + + daemon_task = curproc; + kvp_globals.dev_accessed = true; + kvp_globals.daemon_busy = false; + return (0); +} + + +static int +hv_kvp_dev_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, + struct thread *td __unused) +{ + + hv_kvp_log_info("%s: Closing device \"hv_kvp_device\".\n", __func__); + kvp_globals.dev_accessed = false; + kvp_globals.register_done = false; + return (0); +} + + +/* + * hv_kvp_daemon read invokes this function + * acts as a send to daemon + */ +static int +hv_kvp_dev_daemon_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) +{ + size_t amt; + int error = 0; + + /* Check hv_kvp daemon registration status*/ + if (!kvp_globals.register_done) + return (KVP_ERROR); + + sema_wait(&kvp_globals.dev_sema); + + memcpy(hv_kvp_dev_buf, &kvp_globals.daemon_kvp_msg, sizeof(struct hv_kvp_msg)); + + amt = MIN(uio->uio_resid, uio->uio_offset >= BUFFERSIZE + 1 ? 0 : + BUFFERSIZE + 1 - uio->uio_offset); + + if ((error = uiomove(hv_kvp_dev_buf, amt, uio)) != 0) + hv_kvp_log_info("%s: hv_kvp uiomove read failed!\n", __func__); + + return (error); +} + + +/* + * hv_kvp_daemon write invokes this function + * acts as a recieve from daemon + */ +static int +hv_kvp_dev_daemon_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) +{ + size_t amt; + int error = 0; + + uio->uio_offset = 0; + + amt = MIN(uio->uio_resid, BUFFERSIZE); + error = uiomove(hv_kvp_dev_buf, amt, uio); + + if (error != 0) + return (error); + + memcpy(&kvp_globals.daemon_kvp_msg, hv_kvp_dev_buf, sizeof(struct hv_kvp_msg)); + + if (kvp_globals.register_done == false) { + if (kvp_globals.daemon_kvp_msg.kvp_hdr.operation == HV_KVP_OP_REGISTER) { + + kvp_globals.register_done = true; + if (kvp_globals.channelp) { + + hv_kvp_callback(kvp_globals.channelp); + } + } + else { + hv_kvp_log_info("%s, KVP Registration Failed\n", __func__); + return (KVP_ERROR); + } + } else { + + mtx_lock(&kvp_globals.pending_mutex); + + if(!kvp_globals.req_timed_out) { + + hv_kvp_convert_usermsg_to_hostmsg(); + hv_kvp_respond_host(KVP_SUCCESS); + wakeup(&kvp_globals); + kvp_globals.req_in_progress = false; + } + + kvp_globals.daemon_busy = false; + mtx_unlock(&kvp_globals.pending_mutex); + } + + return (error); +} + + +/* + * hv_kvp_daemon poll invokes this function to check if data is available + * for daemon to read. + */ +static int +hv_kvp_dev_daemon_poll(struct cdev *dev __unused, int events, struct thread *td __unused) +{ + int revents = 0; + + mtx_lock(&kvp_globals.pending_mutex); + /* + * We check global flag daemon_busy for the data availiability for + * userland to read. Deamon_busy is set to true before driver has data + * for daemon to read. It is set to false after daemon sends + * then response back to driver. + */ + if (kvp_globals.daemon_busy == true) + revents = POLLIN; + mtx_unlock(&kvp_globals.pending_mutex); + + return (revents); +} + + +/* + * hv_kvp initialization function + * called from hv_util service. + * + */ +int +hv_kvp_init(hv_vmbus_service *srv) +{ + int error = 0; + hv_work_queue *work_queue = NULL; + + memset(&kvp_globals, 0, sizeof(kvp_globals)); + + work_queue = hv_work_queue_create("KVP Service"); + if (work_queue == NULL) { + hv_kvp_log_info("%s: Work queue alloc failed\n", __func__); + error = ENOMEM; + hv_kvp_log_error("%s: ENOMEM\n", __func__); + goto Finish; + } + srv->work_queue = work_queue; + + error = hv_kvp_dev_init(); + mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex", + NULL, MTX_DEF); + kvp_globals.pending_reqs = 0; + + +Finish: + return (error); +} + + +void +hv_kvp_deinit(void) +{ + hv_kvp_dev_destroy(); + mtx_destroy(&kvp_globals.pending_mutex); + + return; +} diff --git a/sys/dev/hyperv/utilities/hv_kvp.h b/sys/dev/hyperv/utilities/hv_kvp.h index f7dccf77df29..b67373fa7aa5 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.h +++ b/sys/dev/hyperv/utilities/hv_kvp.h @@ -1,7 +1,5 @@ /*- - * Copyright (c) 2009-2012 Microsoft Corp. - * Copyright (c) 2012 NetApp Inc. - * Copyright (c) 2012 Citrix Inc. + * Copyright (c) 2014 Microsoft Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,13 +22,15 @@ * 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. + * + * $FreeBSD$ */ #ifndef _KVP_H #define _KVP_H /* - * An implementation of HyperV key value pair (KVP) functionality for FreeBSD + * An implementation of HyperV key value pair (KVP) functionality for FreeBSD * */ @@ -53,15 +53,15 @@ /* * bytes, including any null terminators */ -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) +#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) /* * Maximum key size - the registry limit for the length of an entry name * is 256 characters, including the null terminator */ +#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) /* * In FreeBSD, we implement the KVP functionality in two components: @@ -111,30 +111,20 @@ * (not supported), a NULL key string is returned. */ - + /* * Registry value types. */ +#define HV_REG_SZ 1 +#define HV_REG_U32 4 +#define HV_REG_U64 8 -#define HV_REG_SZ 1 -#define HV_REG_U32 4 -#define HV_REG_U64 8 - - -/* - * Daemon code not supporting IP injection (legacy daemon). - */ - -#define HV_KVP_OP_REGISTER 4 /* * Daemon code supporting IP injection. - * The KVP opcode field is used to communicate the - * registration information; so define a namespace that - * will be distinct from the host defined KVP opcode. */ +#define HV_KVP_OP_REGISTER 4 -#define KVP_OP_REGISTER1 100 enum hv_kvp_exchg_op { HV_KVP_OP_GET = 0, @@ -155,41 +145,41 @@ enum hv_kvp_exchg_pool { HV_KVP_POOL_COUNT /* Number of pools, must be last. */ }; + /* * Some Hyper-V status codes. */ -#define HV_KVP_S_OK 0x00000000 -#define HV_KVP_E_FAIL 0x80004005 -#define HV_KVP_S_CONT 0x80070103 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 -#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F -#define HV_INVALIDARG 0x80070057 -#define HV_KVP_GUID_NOTFOUND 0x80041002 +#define HV_KVP_S_OK 0x00000000 +#define HV_KVP_E_FAIL 0x80004005 +#define HV_KVP_S_CONT 0x80070103 +#define HV_ERROR_NOT_SUPPORTED 0x80070032 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7 +#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F +#define HV_INVALIDARG 0x80070057 +#define HV_KVP_GUID_NOTFOUND 0x80041002 -#define ADDR_FAMILY_NONE 0x00 -#define ADDR_FAMILY_IPV4 0x01 -#define ADDR_FAMILY_IPV6 0x02 +#define ADDR_FAMILY_NONE 0x00 +#define ADDR_FAMILY_IPV4 0x01 +#define ADDR_FAMILY_IPV6 0x02 -#define MAX_ADAPTER_ID_SIZE 128 -#define MAX_IP_ADDR_SIZE 1024 -#define MAX_GATEWAY_SIZE 512 +#define MAX_ADAPTER_ID_SIZE 128 +#define MAX_IP_ADDR_SIZE 1024 +#define MAX_GATEWAY_SIZE 512 struct hv_kvp_ipaddr_value { - uint16_t adapter_id[MAX_ADAPTER_ID_SIZE]; - uint8_t addr_family; - uint8_t dhcp_enabled; - uint16_t ip_addr[MAX_IP_ADDR_SIZE]; - uint16_t sub_net[MAX_IP_ADDR_SIZE]; - uint16_t gate_way[MAX_GATEWAY_SIZE]; - uint16_t dns_addr[MAX_IP_ADDR_SIZE]; -} __attribute__((packed)); - + uint16_t adapter_id[MAX_ADAPTER_ID_SIZE]; + uint8_t addr_family; + uint8_t dhcp_enabled; + uint16_t ip_addr[MAX_IP_ADDR_SIZE]; + uint16_t sub_net[MAX_IP_ADDR_SIZE]; + uint16_t gate_way[MAX_GATEWAY_SIZE]; + uint16_t dns_addr[MAX_IP_ADDR_SIZE]; +}__attribute__((packed)); struct hv_kvp_hdr { - uint8_t operation; - uint8_t pool; + uint8_t operation; + uint8_t pool; uint16_t pad; } __attribute__((packed)); @@ -197,9 +187,9 @@ struct hv_kvp_exchg_msg_value { uint32_t value_type; uint32_t key_size; uint32_t value_size; - uint8_t key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; + uint8_t key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; union { - uint8_t value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; + uint8_t value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; uint32_t value_u32; uint64_t value_u64; } msg_value; @@ -229,16 +219,16 @@ struct hv_kvp_register { struct hv_kvp_msg { union { - struct hv_kvp_hdr kvp_hdr; - int error; + struct hv_kvp_hdr kvp_hdr; + uint32_t error; } hdr; union { - struct hv_kvp_msg_get kvp_get; - struct hv_kvp_msg_set kvp_set; + struct hv_kvp_msg_get kvp_get; + struct hv_kvp_msg_set kvp_set; struct hv_kvp_msg_delete kvp_delete; struct hv_kvp_msg_enumerate kvp_enum_data; - struct hv_kvp_ipaddr_value kvp_ip_val; - struct hv_kvp_register kvp_register; + struct hv_kvp_ipaddr_value kvp_ip_val; + struct hv_kvp_register kvp_register; } body; } __attribute__((packed)); @@ -248,38 +238,17 @@ struct hv_kvp_ip_msg { struct hv_kvp_ipaddr_value kvp_ip_val; } __attribute__((packed)); -#define BSD_SOC_PATH "/etc/hyperv/socket" - -#define HV_SHUT_DOWN 0 -#define HV_TIME_SYNCH 1 -#define HV_HEART_BEAT 2 -#define HV_KVP 3 -#define HV_MAX_UTIL_SERVICES 4 - -#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */ -#define HV_ICTIMESYNCFLAG_PROBE 0 -#define HV_ICTIMESYNCFLAG_SYNC 1 -#define HV_ICTIMESYNCFLAG_SAMPLE 2 -#define HV_NANO_SEC_PER_SEC 1000000000 - -typedef struct hv_vmbus_service { - hv_guid guid; /* Hyper-V GUID */ - char* name; /* name of service */ - boolean_t enabled; /* service enabled */ - hv_work_queue* work_queue; /* background work queue */ - - // - // function to initialize service - // - int (*init)(struct hv_vmbus_service *); - - // - // function to process Hyper-V messages - // - void (*callback)(void *); -} hv_vmbus_service; - -extern uint8_t* receive_buffer[]; -extern hv_vmbus_service service_table[]; + +#define HV_SHUT_DOWN 0 +#define HV_TIME_SYNCH 1 +#define HV_HEART_BEAT 2 +#define HV_KVP 3 +#define HV_MAX_UTIL_SERVICES 4 + +#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */ +#define HV_ICTIMESYNCFLAG_PROBE 0 +#define HV_ICTIMESYNCFLAG_SYNC 1 +#define HV_ICTIMESYNCFLAG_SAMPLE 2 +#define HV_NANO_SEC_PER_SEC 1000000000 #endif /* _KVP_H */ diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c index e86cbd78498a..91bbc5345ad5 100644 --- a/sys/dev/hyperv/utilities/hv_util.c +++ b/sys/dev/hyperv/utilities/hv_util.c @@ -1,7 +1,5 @@ /*- - * Copyright (c) 2009-2012 Microsoft Corp. - * Copyright (c) 2012 NetApp Inc. - * Copyright (c) 2012 Citrix Inc. + * Copyright (c) 2014 Microsoft Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,9 +22,11 @@ * 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. + * + * $FreeBSD$ */ -/** +/* * A common driver for all hyper-V util services. */ @@ -53,7 +53,7 @@ static void hv_timesync_cb(void *context); static int hv_timesync_init(hv_vmbus_service *serv); -/** +/* * Note: GUID codes below are predefined by the host hypervisor * (Hyper-V and Azure)interface and required for correct operation. */ @@ -80,7 +80,16 @@ hv_vmbus_service service_table[] = { 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d}, .name = "Hyper-V Heartbeat Service\n", .enabled = TRUE, - .callback = hv_heartbeat_cb, + .callback = hv_heartbeat_cb, + }, + + /* KVP (Key Value Pair) Service */ + { .guid.data = {0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, + 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6}, + .name = "Hyper-V KVP Service\n", + .enabled = TRUE, + .init = hv_kvp_init, + .callback = hv_kvp_callback, }, }; @@ -90,6 +99,8 @@ hv_vmbus_service service_table[] = { */ uint8_t *receive_buffer[HV_MAX_UTIL_SERVICES]; +static boolean_t destroyed_kvp = FALSE; + struct hv_ictimesync_data { uint64_t parenttime; uint64_t childtime; @@ -143,7 +154,7 @@ hv_negotiate_version( static void hv_set_host_time(void *context) { - time_sync_data *time_msg = context; + time_sync_data* time_msg = (time_sync_data*) context; uint64_t hosttime = time_msg->data; struct timespec guest_ts, host_ts; uint64_t host_tns; @@ -253,12 +264,12 @@ hv_timesync_cb(void *context) static void hv_shutdown_cb(void *context) { - uint8_t* buf; + uint8_t* buf; hv_vmbus_channel* channel = context; - uint8_t execute_shutdown = 0; + uint8_t execute_shutdown = 0; hv_vmbus_icmsg_hdr* icmsghdrp; - uint32_t recv_len; - uint64_t request_id; + uint32_t recv_len; + uint64_t request_id; int ret; hv_vmbus_shutdown_msg_data* shutdown_msg; @@ -421,6 +432,11 @@ hv_util_detach(device_t dev) struct hv_vmbus_service* service; size_t receive_buffer_offset; + if (!destroyed_kvp) { + hv_kvp_deinit(); + destroyed_kvp = TRUE; + } + hv_dev = vmbus_get_devctx(dev); hv_vmbus_channel_close(hv_dev->channel); @@ -432,21 +448,22 @@ hv_util_detach(device_t dev) free(receive_buffer[receive_buffer_offset], M_DEVBUF); receive_buffer[receive_buffer_offset] = NULL; - return (0); } -static void hv_util_init(void) +static void +hv_util_init(void) { } -static int hv_util_modevent(module_t mod, int event, void *arg) +static int +hv_util_modevent(module_t mod, int event, void *arg) { switch (event) { case MOD_LOAD: break; case MOD_UNLOAD: - break; + break; default: break; } diff --git a/sys/dev/hyperv/utilities/unicode.h b/sys/dev/hyperv/utilities/unicode.h new file mode 100644 index 000000000000..696777cbbf26 --- /dev/null +++ b/sys/dev/hyperv/utilities/unicode.h @@ -0,0 +1,201 @@ +/* $NetBSD: unicode.h,v 1.1.1.1 2007/03/06 00:10:39 dillo Exp $ */ + +/*- + * Copyright (c) 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron. + * + * 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. + * + * $FreeBSD$ + */ + +#include + +#define UNICODE_DECOMPOSE 0x01 +#define UNICODE_PRECOMPOSE 0x02 +#define UNICODE_UTF8_LATIN1_FALLBACK 0x03 + +size_t utf8_to_utf16(uint16_t *, size_t, const char *, size_t, int, int *); +size_t utf16_to_utf8(char *, size_t, const uint16_t *, size_t, int, int *); + +size_t +utf8_to_utf16(uint16_t *dst, size_t dst_len, + const char *src, size_t src_len, + int flags, int *errp) +{ + const unsigned char *s; + size_t spos, dpos; + int error; + uint16_t c; + +#define IS_CONT(c) (((c)&0xc0) == 0x80) + + error = 0; + s = (const unsigned char *)src; + spos = dpos = 0; + while (spos= src_len || !IS_CONT(s[spos+1])) + && s[spos]>=0xa0) { + /* not valid UTF-8, assume ISO 8859-1 */ + c = s[spos++]; + } + else if (s[spos] < 0xc0 || s[spos] >= 0xf5) { + /* continuation byte without lead byte + or lead byte for codepoint above 0x10ffff */ + error++; + spos++; + continue; + } + else if (s[spos] < 0xe0) { + if (spos >= src_len || !IS_CONT(s[spos+1])) { + spos++; + error++; + continue; + } + c = ((s[spos] & 0x3f) << 6) | (s[spos+1] & 0x3f); + spos += 2; + if (c < 0x80) { + /* overlong encoding */ + error++; + continue; + } + } + else if (s[spos] < 0xf0) { + if (spos >= src_len-2 + || !IS_CONT(s[spos+1]) || !IS_CONT(s[spos+2])) { + spos++; + error++; + continue; + } + c = ((s[spos] & 0x0f) << 12) | ((s[spos+1] & 0x3f) << 6) + | (s[spos+2] & 0x3f); + spos += 3; + if (c < 0x800 || (c & 0xdf00) == 0xd800 ) { + /* overlong encoding or encoded surrogate */ + error++; + continue; + } + } + else { + uint32_t cc; + /* UTF-16 surrogate pair */ + + if (spos >= src_len-3 || !IS_CONT(s[spos+1]) + || !IS_CONT(s[spos+2]) || !IS_CONT(s[spos+3])) { + spos++; + error++; + + continue; + } + cc = ((s[spos] & 0x03) << 18) | ((s[spos+1] & 0x3f) << 12) + | ((s[spos+2] & 0x3f) << 6) | (s[spos+3] & 0x3f); + spos += 4; + if (cc < 0x10000) { + /* overlong encoding */ + error++; + continue; + } + if (dst && dpos < dst_len) + dst[dpos] = (0xd800 | ((cc-0x10000)>>10)); + dpos++; + c = 0xdc00 | ((cc-0x10000) & 0x3ffff); + } + + if (dst && dpos < dst_len) + dst[dpos] = c; + dpos++; + } + + if (errp) + *errp = error; + + return dpos; + +#undef IS_CONT +} + + +size_t +utf16_to_utf8(char *dst, size_t dst_len, + const uint16_t *src, size_t src_len, + int flags, int *errp) +{ + uint16_t spos, dpos; + int error; + +#define CHECK_LENGTH(l) (dpos > dst_len-(l) ? dst=NULL : NULL) +#define ADD_BYTE(b) (dst ? dst[dpos] = (b) : 0, dpos++) + + error = 0; + dpos = 0; + for (spos=0; spos>6)); + ADD_BYTE(0x80 | (src[spos] & 0x3f)); + } + else if ((src[spos] & 0xdc00) == 0xd800) { + uint32_t c; + /* first surrogate */ + if (spos == src_len - 1 || (src[spos] & 0xdc00) != 0xdc00) { + /* no second surrogate present */ + error++; + continue; + } + spos++; + CHECK_LENGTH(4); + c = (((src[spos]&0x3ff) << 10) | (src[spos+1]&0x3ff)) + 0x10000; + ADD_BYTE(0xf0 | (c>>18)); + ADD_BYTE(0x80 | ((c>>12) & 0x3f)); + ADD_BYTE(0x80 | ((c>>6) & 0x3f)); + ADD_BYTE(0x80 | (c & 0x3f)); + } + else if ((src[spos] & 0xdc00) == 0xdc00) { + /* second surrogate without preceding first surrogate */ + error++; + } + else { + CHECK_LENGTH(3); + ADD_BYTE(0xe0 | src[spos]>>12); + ADD_BYTE(0x80 | ((src[spos]>>6) & 0x3f)); + ADD_BYTE(0x80 | (src[spos] & 0x3f)); + } + } + + if (errp) + *errp = error; + + return dpos; + +#undef ADD_BYTE +#undef CHECK_LENGTH +} diff --git a/sys/modules/hyperv/utilities/Makefile b/sys/modules/hyperv/utilities/Makefile index 57a242801449..f94e4410aecd 100644 --- a/sys/modules/hyperv/utilities/Makefile +++ b/sys/modules/hyperv/utilities/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../dev/hyperv/utilities KMOD= hv_utils -SRCS= hv_util.c +SRCS= hv_util.c hv_kvp.c SRCS+= bus_if.h device_if.h CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \ diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 5465cb75963e..a0cffcfe0a07 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -4766,3 +4766,11 @@ OLD_FILES+=usr/libexec/dma-mbox-create OLD_FILES+=usr/share/man/man8/dma.8.gz OLD_FILES+=usr/share/examples/dma/mailer.conf .endif + +.if ${MK_HYPERV} == no +OLD_FILES+=etc/rc.d/hv_kvpd +OLD_FILES+=usr/libexec/hyperv/hv_set_ifconfig +OLD_FILES+=usr/libexec/hyperv/hv_get_dns_info +OLD_FILES+=usr/libexec/hyperv/hv_get_dhcp_info +OLD_FILES+=usr/sbin/hv_kvpd +.endif diff --git a/tools/build/options/WITHOUT_HYPERV b/tools/build/options/WITHOUT_HYPERV new file mode 100644 index 000000000000..ef63f70ea80e --- /dev/null +++ b/tools/build/options/WITHOUT_HYPERV @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to not build or install HyperV utilities. diff --git a/tools/build/options/WITH_HYPERV b/tools/build/options/WITH_HYPERV new file mode 100644 index 000000000000..a6bdf72ff3e3 --- /dev/null +++ b/tools/build/options/WITH_HYPERV @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to build and install HyperV utilities. diff --git a/usr.sbin/Makefile.amd64 b/usr.sbin/Makefile.amd64 index b82162580bbc..2d1a3e8daadd 100644 --- a/usr.sbin/Makefile.amd64 +++ b/usr.sbin/Makefile.amd64 @@ -18,6 +18,9 @@ SUBDIR+= boot0cfg SUBDIR+= btxld .endif SUBDIR+= cpucontrol +.if ${MK_HYPERV} != "no" +SUBDIR+= hyperv +.endif SUBDIR+= kgmon SUBDIR+= lptcontrol SUBDIR+= mount_smbfs diff --git a/usr.sbin/Makefile.i386 b/usr.sbin/Makefile.i386 index 7d66f783f28a..de7bb464f581 100644 --- a/usr.sbin/Makefile.i386 +++ b/usr.sbin/Makefile.i386 @@ -9,6 +9,9 @@ SUBDIR+= asf SUBDIR+= btxld .endif SUBDIR+= cpucontrol +.if ${MK_HYPERV} != "no" +SUBDIR+= hyperv +.endif SUBDIR+= kgmon SUBDIR+= kgzip SUBDIR+= lptcontrol diff --git a/usr.sbin/hyperv/Makefile b/usr.sbin/hyperv/Makefile new file mode 100644 index 000000000000..c11b3417c191 --- /dev/null +++ b/usr.sbin/hyperv/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +.include + +SUBDIR = tools + +.include diff --git a/usr.sbin/hyperv/Makefile.inc b/usr.sbin/hyperv/Makefile.inc new file mode 100644 index 000000000000..265f86d1ed55 --- /dev/null +++ b/usr.sbin/hyperv/Makefile.inc @@ -0,0 +1,3 @@ +# $FreeBSD$ + +.include "../Makefile.inc" diff --git a/usr.sbin/hyperv/tools/Makefile b/usr.sbin/hyperv/tools/Makefile new file mode 100644 index 000000000000..3cfc0013cf59 --- /dev/null +++ b/usr.sbin/hyperv/tools/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +.include + +HV_KVP_DAEMON_DISTDIR?= ${.CURDIR}/../../../contrib/hyperv/tools +.PATH: ${HV_KVP_DAEMON_DISTDIR} + +PROG= hv_kvp_daemon +MAN= hv_kvp_daemon.8 + +CFLAGS+= -I${.CURDIR}/../../../sys/dev/hyperv/utilities + +.include -- cgit v1.3 From 363a68722a23a6efdf1c27c5eb167f900acc66ec Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sat, 13 Sep 2014 18:54:15 +0000 Subject: Do not set net.inet.ip.{sourceroute,accept_sourceroute} in a vnet jail. The following warnings were displayed: sysctl: net.inet.ip.sourceroute=0: Operation not permitted sysctl: net.inet.ip.accept_sourceroute=0: Operation not permitted --- etc/rc.d/routing | 28 +++++++++++++++------------- etc/rc.subr | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/routing b/etc/rc.d/routing index 9cb07e576980..f511cd3a4b4e 100755 --- a/etc/rc.d/routing +++ b/etc/rc.d/routing @@ -326,20 +326,22 @@ options_inet() ${SYSCTL} net.inet.ip.forwarding=0 > /dev/null fi - if checkyesno forward_sourceroute; then - ropts_init inet - echo -n ' do source routing=YES' - ${SYSCTL} net.inet.ip.sourceroute=1 > /dev/null - else - ${SYSCTL} net.inet.ip.sourceroute=0 > /dev/null - fi + if ! check_jail vnet; then + if checkyesno forward_sourceroute; then + ropts_init inet + echo -n ' do source routing=YES' + ${SYSCTL} net.inet.ip.sourceroute=1 > /dev/null + else + ${SYSCTL} net.inet.ip.sourceroute=0 > /dev/null + fi - if checkyesno accept_sourceroute; then - ropts_init inet - echo -n ' accept source routing=YES' - ${SYSCTL} net.inet.ip.accept_sourceroute=1 > /dev/null - else - ${SYSCTL} net.inet.ip.accept_sourceroute=0 > /dev/null + if checkyesno accept_sourceroute; then + ropts_init inet + echo -n ' accept source routing=YES' + ${SYSCTL} net.inet.ip.accept_sourceroute=1 > /dev/null + else + ${SYSCTL} net.inet.ip.accept_sourceroute=0 > /dev/null + fi fi if checkyesno arpproxy_all; then diff --git a/etc/rc.subr b/etc/rc.subr index ff4e898597ca..97b631f82d92 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -1966,6 +1966,22 @@ check_required_after() return 0 } +# check_jail mib +# Return true if security.jail.$mib exists and set to 1. + +check_jail() +{ + local _mib _v + + _mib=$1 + if _v=$(${SYSCTL_N} "security.jail.$_mib" 2> /dev/null); then + case $_v in + 1) return 0;; + esac + fi + return 1 +} + # check_kern_features mib # Return existence of kern.features.* sysctl MIB as true or # false. The result will be cached in $_rc_cache_kern_features_ -- cgit v1.3 From 348aae239836c15d87b69d809146a52c8fe71ea9 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Mon, 15 Sep 2014 07:20:40 +0000 Subject: Make net.inet.ip.sourceroute, net.inet.ip.accept_sourceroute, and net.inet.ip.process_options vnet-aware. Revert changes in r271545. Suggested by: bz --- etc/rc.d/routing | 28 +++++++++++++--------------- sys/netinet/ip_fastfwd.c | 4 ++-- sys/netinet/ip_options.c | 33 ++++++++++++++++++--------------- sys/netinet/ip_options.h | 3 ++- 4 files changed, 35 insertions(+), 33 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/routing b/etc/rc.d/routing index f511cd3a4b4e..9cb07e576980 100755 --- a/etc/rc.d/routing +++ b/etc/rc.d/routing @@ -326,22 +326,20 @@ options_inet() ${SYSCTL} net.inet.ip.forwarding=0 > /dev/null fi - if ! check_jail vnet; then - if checkyesno forward_sourceroute; then - ropts_init inet - echo -n ' do source routing=YES' - ${SYSCTL} net.inet.ip.sourceroute=1 > /dev/null - else - ${SYSCTL} net.inet.ip.sourceroute=0 > /dev/null - fi + if checkyesno forward_sourceroute; then + ropts_init inet + echo -n ' do source routing=YES' + ${SYSCTL} net.inet.ip.sourceroute=1 > /dev/null + else + ${SYSCTL} net.inet.ip.sourceroute=0 > /dev/null + fi - if checkyesno accept_sourceroute; then - ropts_init inet - echo -n ' accept source routing=YES' - ${SYSCTL} net.inet.ip.accept_sourceroute=1 > /dev/null - else - ${SYSCTL} net.inet.ip.accept_sourceroute=0 > /dev/null - fi + if checkyesno accept_sourceroute; then + ropts_init inet + echo -n ' accept source routing=YES' + ${SYSCTL} net.inet.ip.accept_sourceroute=1 > /dev/null + else + ${SYSCTL} net.inet.ip.accept_sourceroute=0 > /dev/null fi if checkyesno arpproxy_all; then diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c index 5b41dfdd3b78..ded9103f31bb 100644 --- a/sys/netinet/ip_fastfwd.c +++ b/sys/netinet/ip_fastfwd.c @@ -296,9 +296,9 @@ ip_fastforward(struct mbuf *m) * Only IP packets without options */ if (ip->ip_hl != (sizeof(struct ip) >> 2)) { - if (ip_doopts == 1) + if (V_ip_doopts == 1) return m; - else if (ip_doopts == 2) { + else if (V_ip_doopts == 2) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_FILTER_PROHIB, 0, 0); return NULL; /* mbuf already free'd */ diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c index 94bec4e0a6f3..0d8bd6751c77 100644 --- a/sys/netinet/ip_options.c +++ b/sys/netinet/ip_options.c @@ -65,18 +65,21 @@ __FBSDID("$FreeBSD$"); #include -static int ip_dosourceroute = 0; -SYSCTL_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW, - &ip_dosourceroute, 0, "Enable forwarding source routed IP packets"); - -static int ip_acceptsourceroute = 0; -SYSCTL_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute, - CTLFLAG_RW, &ip_acceptsourceroute, 0, +static VNET_DEFINE(int, ip_dosourceroute); +SYSCTL_VNET_INT(_net_inet_ip, IPCTL_SOURCEROUTE, sourceroute, CTLFLAG_RW, + &VNET_NAME(ip_dosourceroute), 0, + "Enable forwarding source routed IP packets"); +#define V_ip_dosourceroute VNET(ip_dosourceroute) + +static VNET_DEFINE(int, ip_acceptsourceroute); +SYSCTL_VNET_INT(_net_inet_ip, IPCTL_ACCEPTSOURCEROUTE, accept_sourceroute, + CTLFLAG_RW, &VNET_NAME(ip_acceptsourceroute), 0, "Enable accepting source routed IP packets"); +#define V_ip_acceptsourceroute VNET(ip_acceptsourceroute) -int ip_doopts = 1; /* 0 = ignore, 1 = process, 2 = reject */ -SYSCTL_INT(_net_inet_ip, OID_AUTO, process_options, CTLFLAG_RW, - &ip_doopts, 0, "Enable IP options processing ([LS]SRR, RR, TS)"); +VNET_DEFINE(int, ip_doopts) = 1; /* 0 = ignore, 1 = process, 2 = reject */ +SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, process_options, CTLFLAG_RW, + &VNET_NAME(ip_doopts), 0, "Enable IP options processing ([LS]SRR, RR, TS)"); static void save_rte(struct mbuf *m, u_char *, struct in_addr); @@ -104,9 +107,9 @@ ip_dooptions(struct mbuf *m, int pass) struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; /* Ignore or reject packets with IP options. */ - if (ip_doopts == 0) + if (V_ip_doopts == 0) return 0; - else if (ip_doopts == 2) { + else if (V_ip_doopts == 2) { type = ICMP_UNREACH; code = ICMP_UNREACH_FILTER_PROHIB; goto bad; @@ -167,7 +170,7 @@ ip_dooptions(struct mbuf *m, int pass) code = ICMP_UNREACH_SRCFAIL; goto bad; } - if (!ip_dosourceroute) + if (!V_ip_dosourceroute) goto nosourcerouting; /* * Loose routing, and not at next destination @@ -180,7 +183,7 @@ ip_dooptions(struct mbuf *m, int pass) /* * End of source route. Should be for us. */ - if (!ip_acceptsourceroute) + if (!V_ip_acceptsourceroute) goto nosourcerouting; save_rte(m, cp, ip->ip_src); break; @@ -189,7 +192,7 @@ ip_dooptions(struct mbuf *m, int pass) if (V_ipstealth) goto dropit; #endif - if (!ip_dosourceroute) { + if (!V_ip_dosourceroute) { if (V_ipforwarding) { char buf[16]; /* aaa.bbb.ccc.ddd\0 */ /* diff --git a/sys/netinet/ip_options.h b/sys/netinet/ip_options.h index 7cb447e05469..4a6ea420e20e 100644 --- a/sys/netinet/ip_options.h +++ b/sys/netinet/ip_options.h @@ -47,7 +47,8 @@ struct ipopt_tag { struct ipoptrt ip_srcrt; }; -extern int ip_doopts; /* process or ignore IP options */ +VNET_DECLARE(int, ip_doopts); /* process or ignore IP options */ +#define V_ip_doopts VNET(ip_doopts) int ip_checkrouteralert(struct mbuf *); int ip_dooptions(struct mbuf *, int); -- cgit v1.3 From c2b6b3bea96329912043a3f730b68d399a7f7ffc Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Tue, 16 Sep 2014 05:45:38 +0000 Subject: Fix a typo; master server for iprop service should be singular. --- etc/defaults/rc.conf | 2 +- etc/rc.d/ipropd_slave | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 7a39a276cb89..b24e869cdd43 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -293,7 +293,7 @@ ipropd_slave_enable="NO" # Run Heimdal incremental propagation daemon ipropd_slave_program="/usr/libexec/ipropd-slave" ipropd_slave_flags="" # Flags to ipropd-slave. ipropd_slave_keytab="/etc/krb5.keytab" # keytab for ipropd-slave. -ipropd_slave_masters="" # master node names. +ipropd_slave_master="" # master node name. gssd_enable="NO" # Run the gssd daemon (or NO). gssd_program="/usr/sbin/gssd" # Path to gssd. diff --git a/etc/rc.d/ipropd_slave b/etc/rc.d/ipropd_slave index 803281e0e9fe..70c4c70e98cc 100755 --- a/etc/rc.d/ipropd_slave +++ b/etc/rc.d/ipropd_slave @@ -17,15 +17,15 @@ start_precmd=${name}_start_precmd ipropd_slave_start_precmd() { - if [ -z "$ipropd_slave_masters" ]; then - warn "\$ipropd_slave_masters is empty." + if [ -z "$ipropd_slave_master" ]; then + warn "\$ipropd_slave_master is empty." return 1 fi command_args=" \ $command_args \ --keytab=\"$ipropd_slave_keytab\" \ --detach \ - $ipropd_slave_masters" + $ipropd_slave_master" } load_rc_config $name -- cgit v1.3 From c13a313284047bb43dc3fabbf540b3ce47d855f0 Mon Sep 17 00:00:00 2001 From: Sean Bruno Date: Tue, 16 Sep 2014 20:02:16 +0000 Subject: Add proper disable/enable hooks to the default scripts so that this is only run when asked for by the user. Right now, hv_kvpd is run on every boot. Don't do that. Add hv_kvpd_enable= for this script to be run. MFC with 271493 MFC after: 2 weeks Relnotes: yes --- etc/defaults/rc.conf | 2 ++ etc/rc.d/hv_kvpd | 1 + 2 files changed, 3 insertions(+) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index b24e869cdd43..5efe78b9c166 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -684,6 +684,8 @@ jail_enable="NO" # Set to NO to disable starting of any jails jail_parallel_start="NO" # Start jails in the background jail_list="" # Space separated list of names of jails +hv_kvpd_enable="NO" # Start the Hyper-V key-value Pair Driver hv_kvp(4) + ############################################################## ### Define source_rc_confs, the mechanism used by /etc/rc.* ## ### scripts to source rc_conf_files overrides safely. ## diff --git a/etc/rc.d/hv_kvpd b/etc/rc.d/hv_kvpd index 78e4b7447320..284c7de8dff2 100644 --- a/etc/rc.d/hv_kvpd +++ b/etc/rc.d/hv_kvpd @@ -8,6 +8,7 @@ . /etc/rc.subr name="hv_kvp_daemon" +rcvar="kp_kvpd_enable" command="/usr/sbin/${name}" required_dirs="/var/db/hyperv" -- cgit v1.3 From cb8799d06f508f998ea8171037e95ba072adba85 Mon Sep 17 00:00:00 2001 From: Sean Bruno Date: Tue, 16 Sep 2014 20:48:13 +0000 Subject: Such typo, many email, very spelling. wow. MFC with 271688 271493 Submitted by: ngie ian MFC after: 2 weeks Relnotes: yes --- etc/rc.d/hv_kvpd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/hv_kvpd b/etc/rc.d/hv_kvpd index 284c7de8dff2..164ec53c2400 100644 --- a/etc/rc.d/hv_kvpd +++ b/etc/rc.d/hv_kvpd @@ -8,7 +8,7 @@ . /etc/rc.subr name="hv_kvp_daemon" -rcvar="kp_kvpd_enable" +rcvar="hv_kvpd_enable" command="/usr/sbin/${name}" required_dirs="/var/db/hyperv" -- cgit v1.3 From 76cd7220b53b6483fe2f2c44dccf152ae2b3f43c Mon Sep 17 00:00:00 2001 From: Xin LI Date: Wed, 17 Sep 2014 02:32:22 +0000 Subject: Use a devd event to start hv_kvpd instead of doing so in rc.d script. This is cleaner and eliminates the unneeded startup of KVP daemon on systems that do not run as a Hyper-V guest. Submitted by: hrs X-MFC-with: 271493, 271688, 271699 --- ObsoleteFiles.inc | 2 ++ etc/defaults/rc.conf | 2 -- etc/devd/Makefile | 4 ++++ etc/devd/hyperv.conf | 19 +++++++++++++++++++ etc/rc.d/Makefile | 5 ----- etc/rc.d/hv_kvpd | 16 ---------------- tools/build/mk/OptionalObsoleteFiles.inc | 2 +- 7 files changed, 26 insertions(+), 24 deletions(-) create mode 100644 etc/devd/hyperv.conf delete mode 100644 etc/rc.d/hv_kvpd (limited to 'etc') diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index ede94fdd130e..e2f431771f31 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20140917: hv_kvpd rc.d script removed in favor of devd configuration +OLD_FILES+=etc/rc.d/hv_kvpd # 20140814: libopie version bump OLD_LIBS+=usr/lib/libopie.so.7 OLD_LIBS+=usr/lib32/libopie.so.7 diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 5efe78b9c166..b24e869cdd43 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -684,8 +684,6 @@ jail_enable="NO" # Set to NO to disable starting of any jails jail_parallel_start="NO" # Start jails in the background jail_list="" # Space separated list of names of jails -hv_kvpd_enable="NO" # Start the Hyper-V key-value Pair Driver hv_kvp(4) - ############################################################## ### Define source_rc_confs, the mechanism used by /etc/rc.* ## ### scripts to source rc_conf_files overrides safely. ## diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 94cafdc66288..82a5000ff8ae 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -18,6 +18,10 @@ FILES+= uath.conf usb.conf FILES+= zfs.conf .endif +.if ${MK_HYPERV} != "no" +FILES+= hyperv.conf +.endif + NO_OBJ= FILESDIR= /etc/devd FILESMODE= 644 diff --git a/etc/devd/hyperv.conf b/etc/devd/hyperv.conf new file mode 100644 index 000000000000..8abafa9dba4e --- /dev/null +++ b/etc/devd/hyperv.conf @@ -0,0 +1,19 @@ +# $FreeBSD$ +# +# Hyper-V specific events + +notify 10 { + match "system" "DEVFS"; + match "subsystem" "CDEV"; + match "type" "CREATE"; + match "cdev" "/dev/hv_kvp_dev"; + action "/usr/sbin/hv_kvp_daemon"; +}; + +notify 10 { + match "system" "DEVFS"; + match "subsystem" "CDEV"; + match "type" "DESTROY"; + match "cdev" "/dev/hv_kvp_dev"; + action "pkill -x hv_kvp_daemon"; +}; diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index d0897e3e905d..64e83ac8ca50 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -57,7 +57,6 @@ FILES= DAEMON \ hostid \ hostid_save \ hostname \ - ${_hv_kvpd} \ inetd \ initrandom \ ip6addrctl \ @@ -193,10 +192,6 @@ _ubthidhci= ubthidhci _casperd= casperd .endif -.if ${MK_HYPERV} != "no" -_hv_kvpd= hv_kvpd -.endif - .if ${MK_UNBOUND} != "no" _unbound= local_unbound .endif diff --git a/etc/rc.d/hv_kvpd b/etc/rc.d/hv_kvpd deleted file mode 100644 index 164ec53c2400..000000000000 --- a/etc/rc.d/hv_kvpd +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: hv_kvpd - -. /etc/rc.subr - -name="hv_kvp_daemon" -rcvar="hv_kvpd_enable" -command="/usr/sbin/${name}" -required_dirs="/var/db/hyperv" - -load_rc_config $name -run_rc_command "$1" diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index a0cffcfe0a07..faa59cb77f27 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -4768,7 +4768,7 @@ OLD_FILES+=usr/share/examples/dma/mailer.conf .endif .if ${MK_HYPERV} == no -OLD_FILES+=etc/rc.d/hv_kvpd +OLD_FILES+=etc/devd/hyperv.conf OLD_FILES+=usr/libexec/hyperv/hv_set_ifconfig OLD_FILES+=usr/libexec/hyperv/hv_get_dns_info OLD_FILES+=usr/libexec/hyperv/hv_get_dhcp_info -- cgit v1.3 From 76479f1d3f6368b5bbc0e9c3a9b07e376cf4d8aa Mon Sep 17 00:00:00 2001 From: Will Andrews Date: Thu, 18 Sep 2014 14:41:57 +0000 Subject: Fix incremental builds involving non-root users with read-only source files. Makefiles should not assume that source files can be overwritten. This is the common case for Perforce source trees. This is a followup commit to r211243 in the same vein. MFC after: 1 month Sponsored by: Spectra Logic MFSpectraBSD: r1036319 on 2014/01/29, r1046711 on 2014/03/06 --- bin/csh/Makefile | 2 +- etc/mail/Makefile | 4 ++-- lib/libc/Makefile | 4 ++-- usr.bin/grep/Makefile | 2 +- usr.sbin/mtree/Makefile | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'etc') diff --git a/bin/csh/Makefile b/bin/csh/Makefile index 9f305b4f5f04..fd345245eb0b 100644 --- a/bin/csh/Makefile +++ b/bin/csh/Makefile @@ -94,7 +94,7 @@ GENHDRS+= iconv.h SRCS+= iconv_stub.c iconv.h: ${.CURDIR}/iconv_stub.h - cp ${.CURDIR}/iconv_stub.h ${.TARGET} + cp -f ${.CURDIR}/iconv_stub.h ${.TARGET} .endif .endif diff --git a/etc/mail/Makefile b/etc/mail/Makefile index 3f085cc2d780..510b0243f984 100644 --- a/etc/mail/Makefile +++ b/etc/mail/Makefile @@ -69,7 +69,7 @@ SENDMAIL_MC!= hostname SENDMAIL_MC:= ${SENDMAIL_MC}.mc ${SENDMAIL_MC}: - cp freebsd.mc ${SENDMAIL_MC} + cp -f freebsd.mc ${SENDMAIL_MC} .endif .ifndef SENDMAIL_SUBMIT_MC @@ -77,7 +77,7 @@ SENDMAIL_SUBMIT_MC!= hostname SENDMAIL_SUBMIT_MC:= ${SENDMAIL_SUBMIT_MC}.submit.mc ${SENDMAIL_SUBMIT_MC}: - cp freebsd.submit.mc ${SENDMAIL_SUBMIT_MC} + cp -f freebsd.submit.mc ${SENDMAIL_SUBMIT_MC} .endif INSTALL_CF= ${SENDMAIL_MC:R}.cf diff --git a/lib/libc/Makefile b/lib/libc/Makefile index 5a02e51b6ca4..ad3cc7415d7d 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -151,11 +151,11 @@ KSRCS= bcmp.c ffs.c ffsl.c fls.c flsl.c mcount.c strcat.c strchr.c \ libkern: libkern.gen libkern.${LIBC_ARCH} libkern.gen: ${KQSRCS} ${KSRCS} - cp -p ${LIBC_SRCTOP}/quad/quad.h ${.ALLSRC} ${DESTDIR}/sys/libkern + cp -fp ${LIBC_SRCTOP}/quad/quad.h ${.ALLSRC} ${DESTDIR}/sys/libkern libkern.${LIBC_ARCH}:: ${KMSRCS} .if defined(KMSRCS) && !empty(KMSRCS) - cp -p ${.ALLSRC} ${DESTDIR}/sys/libkern/${LIBC_ARCH} + cp -fp ${.ALLSRC} ${DESTDIR}/sys/libkern/${LIBC_ARCH} .endif .include diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile index c0c24dc27c17..a4c614f2f499 100644 --- a/usr.bin/grep/Makefile +++ b/usr.bin/grep/Makefile @@ -11,7 +11,7 @@ PROG= bsdgrep CLEANFILES+= bsdgrep.1 bsdgrep.1: grep.1 - cp ${.ALLSRC} ${.TARGET} + cp -f ${.ALLSRC} ${.TARGET} .endif SRCS= file.c grep.c queue.c util.c diff --git a/usr.sbin/mtree/Makefile b/usr.sbin/mtree/Makefile index e73815aaac35..1ceb52eeb6f5 100644 --- a/usr.sbin/mtree/Makefile +++ b/usr.sbin/mtree/Makefile @@ -17,6 +17,6 @@ LDADD= -lmd CLEANFILES+= fmtree.8 fmtree.8: mtree.8 - cp ${.ALLSRC} ${.TARGET} + cp -f ${.ALLSRC} ${.TARGET} .include -- cgit v1.3 From 02032ae5a27629d3f010872b7ba3f69055c4be3e Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 19 Sep 2014 07:18:45 +0000 Subject: Fix cdev. It is a device node name, not a pathname. --- etc/devd/hyperv.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'etc') diff --git a/etc/devd/hyperv.conf b/etc/devd/hyperv.conf index 8abafa9dba4e..bed7383d0816 100644 --- a/etc/devd/hyperv.conf +++ b/etc/devd/hyperv.conf @@ -6,7 +6,7 @@ notify 10 { match "system" "DEVFS"; match "subsystem" "CDEV"; match "type" "CREATE"; - match "cdev" "/dev/hv_kvp_dev"; + match "cdev" "hv_kvp_dev"; action "/usr/sbin/hv_kvp_daemon"; }; @@ -14,6 +14,6 @@ notify 10 { match "system" "DEVFS"; match "subsystem" "CDEV"; match "type" "DESTROY"; - match "cdev" "/dev/hv_kvp_dev"; + match "cdev" "hv_kvp_dev"; action "pkill -x hv_kvp_daemon"; }; -- cgit v1.3 From 7a536b02fa6f05bf1c2d517c7487c201989753b7 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Sat, 20 Sep 2014 05:49:15 +0000 Subject: Sort the optional rc.d scripts by their knobs MFC after: 1 week Sponsored by: EMC / Isilon Storage Division --- etc/rc.d/Makefile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 64e83ac8ca50..bb2c1773cf04 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -169,27 +169,27 @@ FILES= DAEMON \ zfs \ zvol -.if ${MK_OFED} != "no" -_opensm= opensm +.if ${MK_BLUETOOTH} != "no" +_bluetooth= bluetooth +_bthidd= bthidd +_hcsecd= hcsecd +_ubthidhci= ubthidhci .endif -.if ${MK_OPENSSH} != "no" -_sshd= sshd +.if ${MK_CASPER} != "no" +_casperd= casperd .endif .if ${MK_NS_CACHING} != "no" _nscd= nscd .endif -.if ${MK_BLUETOOTH} != "no" -_bluetooth= bluetooth -_bthidd= bthidd -_hcsecd= hcsecd -_ubthidhci= ubthidhci +.if ${MK_OFED} != "no" +_opensm= opensm .endif -.if ${MK_CASPER} != "no" -_casperd= casperd +.if ${MK_OPENSSH} != "no" +_sshd= sshd .endif .if ${MK_UNBOUND} != "no" -- cgit v1.3 From 79c38c9b005e8698b4a5cfe7fa93c449e5214671 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Sat, 20 Sep 2014 06:05:24 +0000 Subject: Don't install /etc/rc.d/rwho unless MK_RCMDS == yes MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- etc/rc.d/Makefile | 5 ++++- tools/build/mk/OptionalObsoleteFiles.inc | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index bb2c1773cf04..b5e14d4038f7 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -133,7 +133,6 @@ FILES= DAEMON \ rpcbind \ rtadvd \ rtsold \ - rwho \ savecore \ sdpd \ securelevel \ @@ -192,6 +191,10 @@ _opensm= opensm _sshd= sshd .endif +.if ${MK_RCMDS} != "no" +FILES+= rwho +.endif + .if ${MK_UNBOUND} != "no" _unbound= local_unbound .endif diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index faa59cb77f27..4ff329b29fcf 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -3766,6 +3766,7 @@ OLD_FILES+=usr/lib/private/libssh_p.a .if ${MK_RCMDS} == no OLD_FILES+=bin/rcp +OLD_FILES+=etc/rc.d/rwho OLD_FILES+=etc/periodic/daily/140.clean-rwho OLD_FILES+=etc/periodic/daily/430.status-rwho OLD_FILES+=rescue/rcp -- cgit v1.3 From f4d6293c72f99950af70bf61d7f346083003e8a7 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Sat, 20 Sep 2014 06:34:34 +0000 Subject: Don't install /etc/rc.d/ftp-proxy unless MK_PF == yes MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- etc/rc.d/Makefile | 5 ++++- tools/build/mk/OptionalObsoleteFiles.inc | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index b5e14d4038f7..186c9743d665 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -44,7 +44,6 @@ FILES= DAEMON \ dumpon \ faith \ fsck \ - ftp-proxy \ ftpd \ gbde \ geli \ @@ -191,6 +190,10 @@ _opensm= opensm _sshd= sshd .endif +.if ${MK_PF} != "no" +FILES+= ftp-proxy +.endif + .if ${MK_RCMDS} != "no" FILES+= rwho .endif diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 4ff329b29fcf..67b132c1d621 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -3606,6 +3606,7 @@ OLD_DIRS+=usr/share/examples/pc-sysinstall .if ${MK_PF} == no OLD_FILES+=etc/periodic/security/520.pfdenied OLD_FILES+=etc/pf.os +OLD_FILES+=etc/rc.d/ftp-proxy OLD_FILES+=sbin/pfctl OLD_FILES+=sbin/pflogd OLD_FILES+=usr/libexec/tftp-proxy -- cgit v1.3 From cd0b4a3c4014f2d77685bbf58d17c18403c19cca Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sat, 20 Sep 2014 21:02:54 +0000 Subject: Add unit tests for mkimg(1): --- etc/mtree/BSD.tests.dist | 2 + usr.bin/mkimg/Makefile | 6 + usr.bin/mkimg/tests/Makefile | 17 +++ usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu | 10 ++ usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu | 13 ++ usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu | 22 ++++ usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu | 19 +++ usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu | 87 +++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu | 10 ++ usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu | 10 ++ usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu | 13 ++ usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu | 22 ++++ usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu | 87 +++++++++++++ usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu | 82 ++++++++++++ usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu | 10 ++ usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu | 83 ++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu | 84 ++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu | 22 ++++ usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu | 19 +++ usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu | 88 +++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu | 84 ++++++++++++ usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu | 18 +++ .../mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu | 15 +++ .../mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu | 84 ++++++++++++ .../mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu | 11 ++ .../mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu | 18 +++ .../mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu | 14 ++ .../mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu | 83 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu | 83 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu | 17 +++ usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu | 14 ++ usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu | 81 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu | 84 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu | 22 ++++ usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu | 19 +++ usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu | 88 +++++++++++++ usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu | 84 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu | 12 ++ usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu | 18 +++ usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu | 15 +++ usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu | 84 ++++++++++++ usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu | 11 ++ usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu | 18 +++ .../mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu | 14 ++ .../mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu | 83 ++++++++++++ usr.bin/mkimg/tests/mkimg.sh | 141 +++++++++++++++++++++ 116 files changed, 3759 insertions(+) create mode 100644 usr.bin/mkimg/tests/Makefile create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-bsd.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-ebr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-ebr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-ebr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-mbr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-mbr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-mbr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-pc98.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-apm.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-bsd.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-ebr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-gpt.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-gpt.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-gpt.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-gpt.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-pc98.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-vtoc8.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-bsd.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-bsd.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-ebr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-ebr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-gpt.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-gpt.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-mbr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-pc98.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-apm.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-bsd.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-ebr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-gpt.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-mbr.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-pc98.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-pc98.vmdk.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu create mode 100644 usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu create mode 100755 usr.bin/mkimg/tests/mkimg.sh (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 5438176e0c5b..527e611d014b 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -253,6 +253,8 @@ .. m4 .. + mkimg + .. ncal .. printf diff --git a/usr.bin/mkimg/Makefile b/usr.bin/mkimg/Makefile index b802799f96ed..fe83526d7c7c 100644 --- a/usr.bin/mkimg/Makefile +++ b/usr.bin/mkimg/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + PROG= mkimg SRCS= format.c image.c mkimg.c scheme.c MAN= mkimg.1 @@ -29,4 +31,8 @@ LDADD= -lutil WARNS?= 6 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/mkimg/tests/Makefile b/usr.bin/mkimg/tests/Makefile new file mode 100644 index 000000000000..b84f440e3e53 --- /dev/null +++ b/usr.bin/mkimg/tests/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/usr.bin/mkimg + +ATF_TESTS_SH= mkimg + +SOURCES!= cd ${.CURDIR}; echo *.uu +FILES= ${SOURCES:S,.gz.uu,,g} +FILESDIR= ${TESTSDIR} + +${FILES}: + uudecode -p ${.CURDIR}/${.TARGET}.gz.uu | gunzip -c > ${.TARGET} + +rebase: + (cd ${.CURDIR}; atf-sh mkimg.sh rebase) + +.include diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu new file mode 100644 index 000000000000..3f148c01beb4 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-apm.raw.gz +M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN6#-2,^JH4 +MR/L%LWH;`CW.Z2,.S5RJ3R@Y2]]3UWVU$SB1ZW,]KAJKD]OS.P>T@":HQW"J +M+53KRD'=IJN/I]UI=]AO(HXL3C6N6?]'W7?=3:J3F6=+,V>[B$L9@/W9(NJC +MW+M'YW$H9[P=A$T2D!6((!HK7+J:O8^`RV/;/J]?'CZ6Z]0_HLSZU`S_1.*? +M_TE2_Y#J4[G]4S?]TQ6TGMC-BW\_OWX1H[[,_G$6_&/UQ'F]8%9E__%`"L!L +."DDX8/$'F8$ZXZ<%```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu new file mode 100644 index 000000000000..324579020e61 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-apm.vhd.gz +M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4?<^O +MN-+>*BT"#+A[7-7F;5*U:L\M#N=^ +M`"'N`9`-R!ZD!BEPW'*0WZ"]!C"3OC';4_\*A^[M57?[S%`Z,DM1J: +MHSUK@)M%6F`*%Y%K',,AP"R_W#U?;5Z>`QSS<&%A+H$S$`:$3]:1Y,@.D58W +M#[<6\BFR:Z;LHI7Y_^9`.%":?-$$=D]'CD\[ +M/>+'"J$BC_SH9*XI;Y?Y4&'A8\^`8SC/;1'P,<%BHLM1;Q='8O:IME)RK[5I_HV^LD3\C$ +MMQ#XZ=JQIZT[)`J/)Z2(9Q!;&^("Y\S[!'#UKK4YA;[^6CVD^FE>EQ\E)^C' +M$OU'29N)S:C?[J\+Q,"OMG[*ZT=4IB]/'.Z7PY\# +M9+Z85JO.+%:_.@RY!ZS&D,<NJ*WW)JG351;B*5UV$JWK5E;:@+OX!7ZN]MA\-```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu new file mode 100644 index 000000000000..3e83de7755bf --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-apm.vhdf.gz +M'XL(".W%'50``VEM9RTQ>#$M-#`Y-BUA<&TN=FAD9BYO=70`K571:L(P%'WW +M*R[L35A)DYM;][@Q?1O(9,]:;2N%J<4)VT,_?DF3V-16<2/I)23,NXEZ_G8):.`T/XPA83IH`R3OXO=<59_Y`!P/M5T#)_KL9-&,8X"$0X)` +M3[:G`BC7:G/R%W2ZM!MG)P-[BG=Y.[(!;P*ZW +MX/AAZ+.'C1VDA5=&J$`.4@`B\$P1ESJGYCW`V3'/7Q:OCQ^SA:\?8F!^=(=^ +MW-//7!)?/_#Y46C]Z*9^B8`D&3B;K7Y?W^8@.GZ!]8N9U8^E`_WU1#V/NH\! +M1`L8C"'9ZDS"WG4MHG`U8.(#\M;>!G!SV.>;4_GCWV"RU;DHAD.OYT+_"R@! +MGC8E)M-CC]_#=#LN=UL'YZJ?^[#R^FSQY2ZIN]V9,KB!7+7L1%\D\M5;(S"$ +M..YLW+);^>H9.#QO-B]@+1N:+CJ33F*P-FNXIOKY+__76P-'@8^*^E&.?@&@ +'6R\`T@<````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu new file mode 100644 index 000000000000..4b6923a8c6ff --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-apm.vmdk.gz.uu @@ -0,0 +1,82 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-apm.vmdk.gz +M'XL(".[%'50``VEM9RTQ>#$M-#`Y-BUA<&TN=FUD:RYO=70`K9Q;;]S($87? +M_2L([\LB0`2>X?W!0-:1#03!`L9ZDSQN>(V%V)8@"4D,S(\/F^S3.I1$-[$J +M[V@YY:FJZ:X>E>2O#IBFZY\DR;LDSY-\2(HR29',?[4^DC1[,.;'J>8+Y[]> +M_OSW"_[Y\>+B_&I-!AF!^G:+K,175/`GVZ +MT\X+N^GR^<73UN]GNK^\,K7SRWOLRM83[> +MLDFJ+"D[;R9EL=A94IV6U]*DFIVF.>$/R>75W;^3R_&NO[VZN;_VZSNYLYV= +M\]+YE[W+,&^L*MT3]X)+U[@4Y9AD0Y+!O9R<;]]??1XO_C/>WEU=?WT#;O?D +MSC;/DKQQRW'^Z<-C8[@W29,2[CV2\Y__ +MLDSDR).J29;E%"[W:7YY\%M>:M?? +MCNW]^.NWF_'-ZR_77T/MW-FZDC5+HGHI5)84F4OEM^;*5[B,[F.SG%IR_GQU +M_^FJ_SAO\VY\??%#PG2EJ]U\@+5?U[KK.:3=W_[N?]YL,_F2OF&Y9 +MQ+*)^;V+4U)4+M=\@,M1G)(L=\_FOYH7/.\DAW-*SM=?+W[YQ_PM[HKU\<-/ +MOS!=/4?-GO,"YY!Y0YL]%>O^B\M\G;]FZ\^.'R\FTXV=9M-E\>\])&EZ5<4[O/ +M]U+.N7#K2:\'O1S%,'07[=#>W(^W[GC#472N1(/?J3O6_.$8M^]3+2'JBUY[WRZ +M+/4M(/.M;%.BL)SU#:6!COW]]>VZL-?2C[/'/\M>VH_S)S]2J]^9<$UGO;XR +M??3S+-.X7(QBD]#]%$OGKS_-7Q\>UE>Z]97B66E4+4:S2??/.<7-T^V6[KNP +M%<].HWHQAB/5*UUK&\5S>EP]_JH!>;Z?CK\+T#/3J%R,8I-NKW:%KQT]*XVJ +MQ6@VZ?9J5_K:T;/3J%Z,X=!F*U\[>DX:Y2[\50KI@5_+RMK7CIZ91N5B%)MT +M>[5K?.WH66E4+4:S2;=7N];7CIZ=1O5B#(-F4;D8Q2;=7NW8[^A9:50M1K-)MU<[ +M]CMZ=AK5BS$IK1\],HW(QBDVZG=K5['?TK#2J +M%J/9I-NI7F8:E8M1;-+MU8[] +MCIZ51M5B-)MT>[5COZ-GIU&]&,.AS;+?T7/2*'?AOY\@S_?3L=_1,].H7(QB +MDVZO=NQW]*PTJA:CV:3;JQW['3T[C>K%&`YMEOV.GI-&N0OY(^3Y?CKV.WIF +M&I6+46S2[=6._8Z>E4;58C2;='NU8[^C9Z=1O1C#H_H.6F4 +MNPQ2NR&:COV.GIE&Y6(4FW1[M6._HV>E4;48S2;=7NW8[^C9:50OQG!HL^QW +M])PTREU&J=T83<=^1\],HW(QBDVZO=JQW]&STJA:C&:3;J]V['?T[#2J%V,X +MM%GV.WI.&N4ND]1NBJ9COZ-GIE&Y&,4FW5[MV._H66E4+4:S2;=7._8[>G8: +MU8LQ'-HL^QT])XU*97H&>;Z;KDW7V@7/3*-R,8I-NIW:M;[?!<]*HVHQFDVZ +MG=JUOM\%STZC>C&&0YOU_2YX3AKE2B;\#E&DU?I^!^%W4'X'X7>(\KO6]SL( +MOX/R.PB_0Y3?M;[?0?@=E-]!^-V!S?I^!^%W4'X'X7>((JW6]SL(OX/R.PB_ +M0Y3?M;[?0?@=E-]!^!VB_*[U_0["[Z#\#L+O#FS6]SL(OX/R.PB_0Q1IM;[? +M0?@=E-]!^!VB_*[U_0["[Z#\#L+O$.5WK>]W$'X'Y7<0?G=@L[[?0?@=E-]! +M^!VB2*M+?>V$WT'Y'83?(^$WT'Y'83?(8JT.O8[X7=0?@?A=XCRNX[]3O@=E-]!^!VB_*YCOQ-^ +M!^5W$'YW8+/L=\+OH/P.PN\015H=^YWP.RB_@_`[1/E=QWXG_`[*[R#\#E%^ +MU['?";^#\CL(OSNP6?8[X7=0?@?A=X@BK3[UM1-^!^5W$'Z'*+_KV>^$WT'Y +M'83?(O8[X7=0?@?A=P^$WT'Y'83? +M(O8[X7=0?@?A=XCRNY[]3O@=E-]!^-V!S;+?";^#\CL(OT,4:?7L=\+O +MH/P.PN\0Y7<]^YWP.RB_@_`[1/E=SWXG_`[*[R#\[L!FV>^$WT'Y'83?(8JT +MAM373O@=E-]!^!VB_&Y@OQ-^!^5W$'Z'*+\;V.^$WT'Y'83?'=@L^YWP.RB_ +M@_`[1)'6P'XG_`[*[R#\#E%^-[#?";^#\CL(OT.4WPWL=\+OH/P.PN\.;);] +M3O@=E-]!^!VB2&M@OQ-^!^5W$'Z'*+\;V.^$WT'Y'83?(2[IDO7+IQO3M7;/2LJ?^:M0N^39U8W&^D`L +M^L`P4UAW]?L2KNFLUQ?FVWR\2+^(,-_FXT7Z183Y-A\OTB\BS+?Y>)%^$6&^ +M;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%A +MOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X1 +M8;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^ +M$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X1G&_;Z!?!^;:-?A&<;]OH%\'YMHU^ +M$9QOV^@7P?FVC7X1G&_;Z!?!^;:-?A&<;]OH%\'YMHU^$9QOV^@7P?FVC7X1 +MG&_;Z!?!^;:-?A&<;]OH%\'YMHU^$9QOV^@7P?FVC7X1G&_;Z!?!^;:-?A&< +M;]OH%\'YMHU^$9QOV^@7P?FVC7X1G&_;Z!?!^;:-?A&<;]OH%\'YMHU^$9QO +MV^@7P?FVC7X1G&_;Z!?!^;:-?A%AODW/%^D7$>;;]'R1?A%AODW/%^D7$>;; +M]'R1?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI% +MA/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z +M183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF +M^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$9QOV^@7,9KJ%S&:ZAP@?3/=WLJ@_, +ME_7EA;MWJ=[K=[VK\7<2OOO%I?GQT?IR\_4M]^MUMU<=GL1EFA#;%\X??GZN +M?OERO]Y\N:VINXWI>K_>`^O[Z>;F\_A,NB?W8OZ]VUW394]75TS^1K_+G3MS +MWBV7]Q0N)J[NMYOV]O[J_NKZZV],M]RO=_"W<3V^NB_MS;.K,[X7?+<92\WW'A[J);+'?4/0WSP@OW6I$]3?C^=AS??KS\ +MX]_>?]3ZY;GQ^LH#]5-IR/I-HO5+='W6VN.\_&[]JBRIJF<^FP_UN_OO^D'D +J^HSK5Z2^?N[^SD_^O__"^X3FJTP=S>?35_]'S/@3HZ37@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu new file mode 100644 index 000000000000..d48f3435644a --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.raw.gz.uu @@ -0,0 +1,10 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-bsd.raw.gz +M'XL(".[%'50``VEM9RTQ>#$M-#`Y-BUB)W-9:9S8V(RC/=PB6![!-2XK +MB+1J22ZXE&/"U9Y5KSB54V<1^/ZK6%WJ[N;>=IN\L,^`'\`!L/,^XL"EO[#J +MN\0RB)6;T0=QN;W#M3Q>!CC:*1CV4[&P#$M-#`Y-BUB?T)1?GU5Y/EY6^FD6'8PSV\HU)WM, +M0*A),L"")I%[:D-C,*N'S6%Y_#@8'&J1X:P3?-V]3ZUL& +MTN6/NZ/$:[A>,+\%E^B]:U&2`1?JZ'!,L]B`$W/J*&>JNYQ-(R=SF8_L['4& +M7@/?`\NMK+:`_?K"H._1EX&.NS/ZP'>W(%SFCN<6#J^X"RYN-[NV\^J8KZZ, +MO!C[\<2Q-VY'0[C'@38GBPJ`]4HOPYW-"\K]^V`J(^J:&)`D7\2))N*@7 +02:G^(C"V^`74/'YQ?0P````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu new file mode 100644 index 000000000000..66607656c3de --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vhdf.gz.uu @@ -0,0 +1,13 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-bsd.vhdf.gz +M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUBJW6G2=-VJX%"E4/W2X[[)`?OQ@"Q'RUFPA1!'+\\-I.+$0[ +M`+0"D<^LRP9[B/ECHUW4T!0!30K:@$'(W'8Q3/;!#/;C^!Z'PWJ<7/-:QL6C +MT>'4/5PO6#Z"2\A+,DHRX)8,+4YXEAAP>DV=RX2H_A2LV2IW76VSD5]89Y`U +MR#.(S-L4!_;UA4'??BI#L7!7],$TW)QP*=\O`YRZ$RYP7+%:VW5U8JJNW+@8 +MR?AF/'AS"<)O;HM3VS8"U706=P+=KNFZ;+"O,7]:H/;`S3*(OO=A`E@#5H"& +MWE,-N('MND*=!73)-$H;9*S0(#5*RP+VZ$S_. +IA--]L%4-A6ED=I-],,-LJR*<$2.O_]:VQ>'&1\4=ON@7D=A:0S`'```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu new file mode 100644 index 000000000000..ac4864b37817 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-bsd.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-bsd.vmdk.gz +M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUB[P^'\9@D&YR4N2#6<+%;/JP>FVS$:+G->[86C#W?< +M>&`S7#X]>'S.A;L[S0_W[D+")2%0L@I7/)/39K(O[>Y/;WSQW/XRMX?I>,LF +MJ;*D;/TR*8MYG275<7XL3:K):)P"ODVN;^[_DUP/]]W=S8^'6[^_HSO;R3@O +MG7W9N0A38E7I+MP#+ESC0I1#DO5)!O=P[^YO;[>S#=HSO; +M/$ORQFW'V:>/M]7"/4F:E'#/D9S_^O?K]_Z5FQY^G.X8SGE-&YF>>\I#XY9E +MXKXO;_/NAN\/+N+HO\+NW-GZXA3S<^?NHLB3JDGF[10N]G%ZN/RF4\M.7^]>?AR +MTWV>TKP?K@YO$X8K7>VF`ZS]OI:L)Y=R\V2G;9\__N]ARC?I_,-R\B3F) +MZ;F+8U)4+M9T@/-1'),L=U?3/TT;GC+)X8R2\^WWPR^_3V]Q5ZS/G_[R"\/5 +MD]=D.6UPWW](9SLR26;S[=I:X.+4BZAW>M[+N=4 +MN.6DEX.>CZ+OV\.I/_UX&.[<\8:C:%V)>I^I.];\\1C7SU/-)S6Z5TQR?I]< +MW?33F;JP_QYNOS%X?JE=M-VEM-\/,SI`*<=/KO!J797\ZF&[3'VT_SB]^I%9_,.`2SGI_9?KDYUFF +M?KDLBE5`]U,LG;[_/'U_>MQ?Z?97BF6E7K4LFE6X?TTA?ERF6[IWX4DL6_7J +M9-'OJ5[I6ML@EN/3ZO%7#.EJUZ=;+H=R7;^MK1#M?YVM$R4Z]< +M%L4JW%;M>E\[6E;J5[RZ5V>2Q< +ME?K:T3)3KUP6Q2K<1NTJ]CM:5NI5RZ)9A=NH7<5^1\M6O3I9]+N29;^CY:A> +M[JZ0VA71<.QWM,S4*Y=%L0JW53OV.UI6ZE7+HEF%VZH=^QTM6_7J9-'O2I;] +MCI:C>KF[4FI71L.QW]$R4Z]<%L4JW%;MV.]H6:E7+8MF%6ZK=NQWM&S5JY-% +MORM9]CM:CNKE[OA+$.1Z.QS['2TS]#L=^1\M,O7)9%*MP +M6[5COZ-EI5ZU+)I5N*W:L=_1LE6O3A;]KF39[V@YJI>[(W^$7&^'8[^C9:9> +MN2R*5;BMVK'?T;)2KUH6S2K<5NW8[VC9JEUHF:E7+HMB%6ZC=@W['2TK]:IET:S";=2N8;^C9:M>G2SZ7G6RZ'+?E>R['>T'-4KE>D9Y'HSW"E=:A^$WT'Y'83?[4B6 +M_4[X'93?0?@=HDBK9;\3?@?E=Q!^ARB_:]GOA-]!^1V$WR'*[UKV.^%W4'X' +MX7<[DF6_$WX'Y7<0?H^$WT'Y'83?(8JT6O8[X7=0?@?A=XCRNY;]3O@=E-]!^!VB +M_*YEOQ-^!^5W$'ZW(UGV.^%W4'X'X7>((JTN];43?@?E=Q!^ARB_Z]COA-]! +M^1V$WR'*[SKV.^%W4'X'X7<[DF6_$WX'Y7<0?H^$WT'Y'83?(8JT.O8[X7=0?@?A +M=XCRNX[]3O@=E-]!^!VB_*YCOQ-^!^5W$'ZW(UGV.^%W4'X'X7>((JV._4[X +M'93?0?@=HORN8[\3?@?E=Q!^ARB_Z]COA-]!^1V$W^U(EOU.^!V4WT'X':)( +MJT]][83?0?D=A-\ARN]Z]COA=U!^!^%WB/*[GOU.^!V4WT'XW8YDV>^$WT'Y +M'83?(8JT>O8[X7=0?@?A=XCRNY[]3O@=E-]!^!VB_*YGOQ-^!^5W$'ZW(UGV +M.^%W4'X'X7>((JV>_4[X'93?0?@=HORN9[\3?@?E=Q!^ARB_Z]GOA-]!^1V$ +MW^U(EOU.^!V4WT'X':)(JV>_$WX'Y7<0?H7/_%.H7?+L[@9C?2!F +M?6"8*2Q9_;&`2SCK_87Y-F^OTB\BS+=Y>Y5^$6&^S=NK](L(\VW>7J5?1)AO +MF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28 +M;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$ +MF&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)? +M1)AOF^@7$>;;)OI%A/FVB7X18;YMHE\$Y]LV^D5POFVC7P3GVS;Z17"^;:-? +M!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$ +MY]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3G +MVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?; +M-OI%<+YMHU\$Y]LV^D5POFVC7T28;]/R5?I%A/DV+5^E7T28;]/R5?I%A/DV +M+5^E7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X1 +M8;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^ +M$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:) +M?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?!.?;-OI%#*;Z10RF^D4, +MIOI%#*;Z10RF^D4,IOI%#*;Z10RF^D4,IOI%#*;Z10RF^D4,IOI%#*;Z10RF +M^D4,IOI%C&EJJ%_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1H +MJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1HJE\\IFEJJ%\\7GR6\,YPE\DN^L!\ +MWM_RZ:"7?V\_6<.]\K'>/X?*7=J=SBGW)&G]X^ +M>+8O[^[=Y>XZX\.X^"C6G>]<%V3]SEW"'6T;03EWEF7X?_GW]@/G3X?UGR5@ +-/@=\\W^I>^KAH%T````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu new file mode 100644 index 000000000000..bbf68364ea1b --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-ebr.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-ebr.raw.gz +M'XL("._%'50``VEM9RTQ>#$M-#`Y-BUE8G(N8PL.M6@1;7DA<=H*7D\$&+<0?'&2"/ZSNYN&_N<+MC0"E!J0#X&O6A +M\1((3*WL<8.^E_Z<]`D#E!4("?(*->X-^/-XKZ5#\%S_S^)P"S<)YGMP%^/E +MG'0K(V[0K"A#YSR"[.^6R@# +MO7`3^B`,5QE#$M-#`Y-BUE8G(N=FAD+F]U=`"METU3PR`0AN_] +M%>MX\]"!#6S:JZ.>G7'4JVE,'`]^C'KPD!\O!$@@"=@H34J3@7WR[K)L*&/F +M`T`%4`O4`$E]70J@/90[`-5I3^Q;;F^AJ]]>F_KK^7MK/]W&P#CSK4)S;8\% +M"/60$K#2#Z%'?0V=PVQ/+Y_.GE^>'`XMSCU8$`@$J2!B]AQB@SI-NCJ_N>B1 +M#Z.Z8JYNM%+?@P`F@'-O1.'4/0P:!YQ05FW;GR5452_3G<%-T#$Z.\%)-K'R +M9"X%U7-V"4>SC\Q5T(<8?DW*;5G#$M-#`Y-BUE8G(N=FAD9BYO=70`K96Q;H,P$(;W +M/,5%W3)$MK$/LD9-YTI5VS5`(,J0=NG0@8>OC3'Q82"D,A@P.M_'?[ZS8

+M`/H:;=.&9CLXFM5FU=)X\3"PKD>!%E=J+SU`MUQU'=T8]W"<@>#3^M8^[A0[ +MW/HQH%*0YP'PW>D3QDL*8/G(?=K0[+?T[/5)`U0I2`4*(1-+`_X\?(RE0_)8 +M\V=QXAZN%\R7X!+CY8WT*V/:T-S*Q#X=3LZITPA6/12LBEQ[,AOX^7D&IE=) +M"2SK;(("^_S"3=\NE"%(N#/Z(`PW-[B4CN<>3MP)%RBNF,WMO+IUJ*Z,G`PU +M7!D+5ZZ!T)5K<2+N1B#:G457H!X5WJ<-S>N6GA8H.V"T&<3N5X0)8`U8`2K3 +M3R7@#M+,!PI:24WY_565/Y=?/\,&Q_L_1]B,OTC,:L$41&X^@B?3]_0]'#$M-#`Y-BUE8G(N=FUD:RYO=70`K5Q=C]S&$7SW +MKZ"EER`/"]:27)(/`A+G'"`(`AB68[^&G]$AMB2<#D$,[(\/AYR:*]YJ-+2O +M3SR1+7;W3O=PZT[5AC.4X-[QQ_?O= +M/WX\\>L/I]/UJRT97)2$(-=T8NQ>YWIZ]L5TYR]%[6XLQSF9KG!1_4V@3W>. +MW(BF*Y>;Y\^%<'7=>GMT%Y(N"XFR7;KJ,S5%B_W2ZO[XE6^>6U_AUK!L[Z7- +MZB*[]-[,+M5J%UE]7N_E6;TXS4O"U]G=_:?_9'?3I^'A_N/C![^^L]O;Q;F\ +M./_+X#(LA=47=^%NN'2M2W&9LF+,"KC;V?7AK_<_3Z?_3@^?[C^\?P.6>W9[ +M6Q99V;KE./_\Z=@9[D7R[`+W&MGU+W^[>^.?W/STL7M@.A>U+&1Y[:4.S7NY +M9.[[]EA7-[U_=!EG_Q56Y_;6-Z=:7[MT%U69U6VV+J=RN<_+[=&7O/9N>)BZ +MQ^F'7S].;U[]\N%]Z)W;6]>R=DW4K(TJLJIPJ7QIKGV5R^@>FW77LNO/]X_O +M[H>W2YF?IE>GUQG375SOE@UL_+JVJI>02W1GEV5?O_W?XU)O-OJ=O6>Z=1%K +M$LJEVN90/7K3AG1>FNEG]:%KQ44L(Y9=0Z=KM;>:_:EMZ!6.ENK#N;W76/7?9-]VDZO;Z[^R;L;.>*+==C6=KDLERVU.[Y7MNY +M-&[;Z6VCUZT8Q_[4C=W'Q^G!;6_8BMZU:/25NFTMG[9Q_SKUNE.S>V*RZYOL +MU?VX[*E+^^_IPR],-VR/\;(.]TBT:V#A+I:G9TT_^5?8GABW32[=]/CPZVGX +M]>?[]^/R1LO>,-VX]6Y9SK:;3YNY;."RPL\N<.G=JW57P_*8;G*K&V\6N.ZG +M;V185'C9[/K+NKQW4SR78O"%\]_EKT4C\N;'ZGU[TRXI;->WR5_]O.L +MT+A2C&J7T/T4RY?O/RW?WSVM[^+6=Q'/6J,:,=I=NG\M*3[>EGMQ[\)./'N- +M&L08CW3OXJ!M$L_Y>??XJP;D.IZ.OPO0L]"H4HQJER[6N\KWCIZU1C5BM+MT +ML=Y=?._HV6O4(,9XJ-C:]XZ>LT:Y$W^50G[@U[)+XWM'ST*C2C&J7;I8[UK? +M.WK6&M6(T>[2Q7K7^=[1L]>H08SQ4+&][QT]9XUR)P($Y#J>;O"]HV>A4:48 +MU2Y=K'>C[QT]:XUJQ&AWZ6*]FWSOZ-EKU"#&>*C8V?>.GK-&N5,IO2M3Z>K< +M]XZ>A4:58E2[=)'>U<0[>M8:U8C1[M)%>E<3[^C9:]0@QGBH6.(=/6>-E- +M+].Z23$>\HV>A4:48U2Y=K'?$.WK6&M6(T>[2Q7I'O*-GKU&#&..A8HEW +M])PURIWX2Q#D.IZ.>$?/0J-*,:I=NECOB'?TK#6J$:/=I8OUCGA'SUZC!C'& +M0\42[^@Y:Y0[D9"!7$?3-;GO'3T+C2K%J';I(KUKB'?TK#6J$:/=I8OTKB'> +MT;/7J$&,\5"QQ#MZSAKE3JWTKDVF(][1L]"H4HQJER[6.^(=/6N-:L1H=^EB +MO2/>T;/7J$&,\5"QQ#MZSAKE3OS_$^0ZGHYX1\]"HTHQJEVZ6.^(=_2L-:H1 +MH]VEB_6.>$?/7J,&,<9#Q1+OZ#EKE#N1?X1 +MM48U8K2[=+'>$>_HV6O4(,9XJ%CB'3UGC7*G07HWI-*UN>\=/0N-*L6H=NDB +MO6N)=_2L-:H1H]VEB_2N)=[1L]>H08SQ4+'$.WK.&N5.H_1N3*8CWM&ST*A2 +MC&J7+M8[XAT]:XUJQ&AWZ6*](][1L]>H08SQ4+'$.WK.&N5.D_1N2J8CWM&S +MT*A2C&J7+M8[XAT]:XUJQ&AWZ6*](][1L]>H08SQ4+'$.WK.&N5.L_1N3J8C +MWM&ST*A2C&J7+M8[XAT]:XUJQ&AWZ6*](][1L]>H08SQ4+'$.WK.&I7+]`QR +M'4W7Y5OO@F>A4:48U2Y=I'>=Q[O@66M4(T:[2Q?I7>?Q+GCV&C6(,1XJUN-= +M\)PURK5,^#LD*:W.XQV$OX/R=Q#^#DG^KO-X!^'OH/P=A+]#DK_K/-Y!^#LH +M?P?A[PX4Z_$.PM]!^3L(?X=QSL(?P?E[R#\W8%B/=Y!^#LH?P?A[Y"DM#J/=Q#^#LK?0?@[)/F[SN,= +MA+^#\G<0_@Y)_J[S>`?A[Z#\'82_.U"LQSL(?P?E[R#\'9*45I_[W@E_!^7O +M(/P=DOQ=3[P3_@[*WT'X.R3YNYYX)_P=E+^#\'<'BB7>"7\'Y>\@_!V2E%9/ +MO!/^#LK?0?@[)/F[GG@G_!V4OX/P=TCR=SWQ3O@[*'\'X>\.%$N\$_X.RM]! +M^#LD*:V>>"?\'92_@_!W2/)W/?%.^#LH?P?A[Y#D[WKBG?!W4/X.PM\=*)9X +M)_P=E+^#\'=(4EH]\4[X.RA_!^'OD.3O>N*=\'=0_@["WR')W_7$.^'OH/P= +MA+\[4"SQ3O@[*'\'X>^0I+2&W/=.^#LH?P?A[Y#D[P;BG?!W4/X.PM\AR=\- +MQ#OA[Z#\'82_.U`L\4[X.RA_!^'OD*2T!N*=\'=0_@["WR')WPW$.^'OH/P= +MA+]#DK\;B'?"WT'Y.PA_=Z!8XIWP=U#^#L+?(4EI#<0[X>^@_!V$OT.2OQN( +M=\+?0?D["'^')'\W$.^$OX/R=Q#^[D"QQ#OA[Z#\'82_0Y+2&HAWPM]!^3L( +M?X:^ +M=\+?0?D["'^')'\W$N^$OX/R=Q#^#DG^;B3>"7\'Y>\@_-V!8HEWPM]!^3L( +M?X"7\'Y>\@_!V2E-9(O!/^#LK?0?@[)/F[D7@G_!V4OX/P=TCR=R/Q +M3O@[*'\'X>\.%$N\$_X.RM\%,1WD6M)EV[=/-^5;[X)GH5%Y_OECZ=V2(L]N +M5C<9ZP.QZ@/#3&&KZO+](L( +M\VT>+](O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$ +MOX@PWS;1+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M$_TBPGS; +M1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS;1/](L)\ +MVT2_B##?-M$O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2^"\VT;_2(XW[;1+X+S +M;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT;_2(XW[;1+X+S;1O](CC?MM$O@O-M +M&_TB.-^VT2^"\VT;_2(XW[;1+X+S;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT; +M_2(XW[;1+X+S;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT;_2(XW[;1+X+S;1O] +M(CC?MM$O@O-M&_TB.-^VT2^"\VT;_2(XW[;1+R+,M^GY(OTBPGR;GB_2+R+, +MM^GY(OTBPGR;GB_2+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M +M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS +M;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2\BS+=-](L( +M\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O@O-M&_TB +M)E/](B93_2(F4_TB)E/](B93_2(F4_TB)E/](B93_2(F4_TB)E/](B93_2(F +M4_TB)E/](B93_2(F4_TBYCPWU"]B-M4O8C;5+V(VU2]B-M4O8C;5+V(VU2]B +M-M4O8C;5+V(VU2]B-M4O8C;5+V(VU2]B-M4O8C;5+V(VU2^>\SPWU"^>;SY+ +M>!<53W=;[*8/+-'_YH3S'.U>"?>H+`[+T57^8CDV(9GT#?'U?:WI1NMRY]^6 +ML*JRKKM)^$^N;_TTX>VS56__CM^X?G/:_PGK6S\.LZK=Q\16EZPY'RWXIV]_ +M?%;PEL[L<=G2W7ST]/-T8<$'/LFZ+->/GA9/?3+B-ZY/C\EV9KKR2ZO3*<^Q +M8HT_>KHLFV=QNL_KC&!X4C,\0Y:PO]G3^MK;99QWY7YA?3?(4I;N1Y!^^*KN +MX@[K(N5F^W3]%_?VRZO[^G9U@_%F5,_?&0??N2[)_IV[I3O;`L%E199-.G'[ +>=_S&];O3_L^6L/0)S3I8N@].R[_Z/_V4$^TO7P`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu new file mode 100644 index 000000000000..c8adeb3c699a --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.raw.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-gpt.raw.gz +M'XL("/#%'50``VEM9RTQ>#$M-#`Y-BUG<'0NU52W;V`262JW42MW2JMW:@3]FC-2=#U\?A@2(C1KIP$)(Q_UR]_#C(F4X +M`*,AJ\@U'>B?Q?+L=W>[@:;JVX#^]ZF$%5!X8,`U/B@U/>,3SAQ.?9BAFO/6=K7-O+Z7US<VLL(>^M^[#3@KEUG%/"MSJ#-T%:HV@7MG&12+VH +M9?I)M7^I;M.KTU +F^C>&>/QE.,8A3KCM(>YN;99QB!..=8@;_W]*RMT?5F[7A(@+```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu new file mode 100644 index 000000000000..6936b1379dc6 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhd.gz.uu @@ -0,0 +1,22 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-gpt.vhd.gz +M'XL("/'%'50``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD+F]U=`"MF$MOVS`,Q^_Y +M%!QVZS#7DB79N0Q8L1;8K7O==JCER$4/RQ[IH1C\X2?*\D.VY"$M$]5(H/#G +M/RF*8IWG_0M`%:!:4`:4Q,^E`+6'L@*PDWYP=V7^*W3-SZ-I'A^>,O_J=CV, +MY7.KT!SM>0'"WJ0$7N--U`$_0S=@LM?7]QXX<9"@>`@+42L[J/R +M41V2;JZ^?'#(NTE=L58W6=D_+2`7P-CL%\6@[F[4..*$M6I;-THH:[0=1_`E +MF$#LK@U"+H<)[MP/HS>A8*Y/L7PCYNG%2.JK49_=6WD=N:8GNJLL?(]`K<\# +M#A$,<:/#NL'XN3IBS.11GR138(N-!`1+ADT[BP_*#S(H++;I'(0#MQ*M`>[/84U`KOCI^S8 +MP]YFO]]X?8;YC(B-]$0J>L;5Y2KE;CD5[(2[$.*HZ[*I,'J2+'I[GRRQD9Y( +M1J_NHQR#WQQ#9N<9] +M(253*#R03*'P^Y=0(3.;BWGN*BN_*$05!G&$%09QA!4&<:05!H&$%09QA!4& +M<805!G&D%4;1-D+*-T)%!8;A/RXZS)IT2]-5V:D7=AFXZQJA9/NTT0C%%X.R +M$5+_:X1:DW)VY"R<)6R$%'4CI'PA)7J6H89&:*WA.<\RU-`(S6[\@F<9*MX( +>/?=9!N((GV4@CO!9!N*(4X79WF7W#]HOQ!D`$P`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu new file mode 100644 index 000000000000..0c18ed8876e1 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vhdf.gz.uu @@ -0,0 +1,19 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-gpt.vhdf.gz +M'XL("/'%'50``VEM9RTQ>#$M-#`Y-BUG<'0N=FAD9BYO=70`K9<[;]PP#(#W +M^Q4LNJ6HH_?IE@`-F@#=TD>V#O%#"C+DBJ(=.OC'5Y3LL^23C%XAFS!TH/F9 +MI$G11T@X``0#TF:N9<5XVZ3GN+O:>1KM+@.ZYZ,+*V#C@`'7.R5A>(\Q8.TD +MA'JK8.R$DV7M<=CEWWLW]W])WCX\.4;PKXOX3+JE`,#W4-_`-NMO*/_'F[` +M.8QQ$W;.!R4L:)+:M00Y<$*TEJI6,K;J#C8%MHAP+N9H53 +ME2M/H+I3L.]!&9`4>HN+00&E`-JUB?80!LRY>(`]!=8A<#Q^;HX!]K[Y^6[R +M3]"I(G)25I2R)[!4B"Z%N\?:W@P74AROG3V-V9/5LG>8BB4G944Q>VW(7CY) +MF+UP'*M92.@6RI&0_L?QQ-__OE3YP]Y7=F6#Z25X+VC&-A*MN33XEUFFU)Q]CH!1.`6 +M$P<^>?>4EHKR7T!SL,:"EFA[DN1'HL@6,N)\J<0W_^^[#;C:I>+^&NS^`N3M +&#A:S#0`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu new file mode 100644 index 000000000000..782cb6c93c80 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-gpt.vmdk.gz.uu @@ -0,0 +1,87 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-gpt.vmdk.gz +M'XL("/'%'50``VEM9RTQ>#$M-#`Y-BUG<'0N=FUD:RYO=70`K5Q=C]S&$7SW +MKYC(#S829,%:DLOE@X+8D1T800!%=I*7/(2?\2&VI)P.A@WLCP^'G)HKWNT< +M*5^?]K3;8G?M=,^RN:HN,,N6'^>*UA6%*WI7GEP&-_W3\G!9?F],C^.9!RY_ +M>?77?QSX\_GAS5\Z&YOWM^]"^L[^KV=G(N3 +M]S]U'F%*K#KY%_Z`AZL]Q&EP>>]R^,/N9.\._A+G_ZYM7+\,G-#N^;6\+YJ&DATWM/>2CNZ>3\ +M[^/'O+KA[9U'',-/7)W?VU"<#R]?_/CN;:R=WUM?LGH&.L^%REV9>ZB0FB]?Z1']QV;>-7?YX>;N^YON +MVRG-#\.+PZ>.<"=?NVD#SV%=2]93R"FYL].R+U_]?#?EZ_JPLS>$FQ6QI@V_',ZQ7VQOGW]Q1O"G:>H +MR7-:X!0R);3*J5SR+Q]^+-WEVZ_<"Y_D=]\/\R>0:=&_XEQEY?NQ4T_ +M[:F'_<_P[D?"=%J'_TC4[VET/WRP\W +M;_OI1',O"=_%G8B&>K49T8_9[J +MG7QK&\1S?%@]?M6`O$[#\;L`/7.-*L0H5W"IVI6A=O2L-.HL1KV"2]7N%&I' +MSU:C.C'Z7N8:58A1KN!2M:M#[>A9:=19 +MC'H%EZI=$VI'SU:C.C'Z7JW1!J1\]6HSHQ^EW)CJ%V]!PURC\54KMB"Z[*0NWHF6M4 +M(4:Y@DO4KF*_HV>E46E4:=Q:A7<*G:L=_1L]6H3HQ^5[+L=_0<-N4848Y0HN53OV.WI6&G46HU[!I6K'?D?/5J,Z,?I=R;+? +MT7/4*/]$0@;R.@EWSD+MZ)EK5"%&N8)+U.[,?D?/2J/.8M0KN$3MSNQW]&PU +MJA.CWY4L^QT]1XWR3[74KMZ$8[^C9ZY1A1CE"BY5._8[>E8:=1:C7L&E:L=^ +M1\]6HSHQ^EW)LM_1<]0H_\3_/T%>I^'8[^B9:U0A1KF"2]6._8Z>E4:=Q:A7 +M<*G:L=_1L]6H3HQ^5[+L=_0<-H0HQR!9>J'?L=/2N- +M.HM1K^!2M6._HV>K49T8_:YDV>_H.6J4?^JD=MT67)V%VM$SUZA"C'(%EZA= +MS7Y'STJCSF+4*[A$[6KV.WJV&M6)T>]*EOV.GJ-&^:=>:M=OPK'?T3/7J$*, +M<@67JAW['3TKC3J+4:_@4K5COZ-GJU&=&/VN9-GOZ#EJE'\:I';#)AS['3US +MC2K$*%=PJ=JQW]&STJBS&/4*+E4[]CMZMAK5B='O2I;]CIZC1OFG46HW;L*Q +MW]$SUZA"C'(%EZH=^QT]*XTZBU&OX%*U8[^C9ZM1G1C]KF39[^@Y:E0FTS/( +MZR1^@_!V$O\,F?]>$?@?A[Z#\'82_PR9_UX1^!^'O +MH/P=A+_;D6SH=Q#^#LK?0?@[;%):3>AW$/X.RM]!^#ML\G=-Z'<0_@[*WT'X +M.VSR=TWH=Q#^#LK?0?B['^@_!V$O\,F?]>$?@?A[Z#\'82_VY%LZ'<0_@[*WT'X.VQ26FT6:B?\ +M'92_@_!WV.3O6O8[X>^@_!V$O\,F?]>RWPE_!^7O(/S=CF39[X2_@_)W$/X. +MFY16RWXG_!V4OX/P=]CD[UKV.^'OH/P=A+_#)G_7LM\)?P?E[R#\W8YDV>^$ +MOX/R=Q#^#IN45LM^)_P=E+^#\'?8Y.]:]COA[Z#\'82_PR9_U[+?"7\'Y>\@ +M_-V.9-GOA+^#\G<0_@Z;E%;+?B?\'92_@_!WV.3O6O8[X>^@_!V$O\,F?]>R +MWPE_!^7O(/S=CF39[X2_@_)W$/X.FY16EX7:"7\'Y>\@_!TV^;N._4[X.RA_ +M!^'OL,G?=>QWPM]!^3L(?[^@_!V$O\,FI=6QWPE_!^7O(/P=-OF[ +MCOU.^#LH?P?A[[#)WW7L=\+?0?D["'^W(UGV.^'OH/P=A+_#)J75L=\)?P?E +M[R#\'3;YNX[]3O@[*'\'X>^PR=]U['?"WT'Y.PA_MR-9]COA[Z#\'82_PR:E +MU;'?"7\'Y>\@_!TV^;N._4[X.RA_!^'OL,G?=>QWPM]!^3L(?[^@ +M_!V$O\,FI=5GH7;"WT'Y.PA_ATW^KF>_$_X.RM]!^#ML\G<]^YWP=U#^#L+? +M[4B6_4[X.RA_!^'OL$EI]>QWPM]!^3L(?X=-_JYGOQ/^#LK?0?@[;/)W/?N= +M\'=0_@["W^U(EOU.^#LH?P?A[[!):?7L=\+?0?D["'^'3?ZN9[\3_@[*WT'X +M.VSR=SW[G?!W4/X.PM_M2);]3O@[*'\'X>^P26GU['?"WT'Y.PA_ATW^KF>_ +M$_X.RM]!^#ML\G<]^YWP=U#^#L+?[4B6_4[X.RA_%\5TD-<"YY;?`#=D2^VN +M2LJO_%.LG;NZNL%:'SB.>P'SZ^GZ/8[I(GMR&1^_/LSZQ3CS6*K^ZP`7../Z +M(<[?I4SW<1^KKT2+\W41?B3A_-]%7(L[?3?25 +MB/-W$WTEXOS=1%^).'\WT5+\W41?B3A_-]%7(L[?3?25B/-W$WTEXOS=1%^).'\WT5#\W49?"<[?;?25X/S=1E\)SM]M])7@_-U& +M7PG.WVWTE>#\W49?"<[?;?25X/S=1E\)SM]M])7@_-U&7PG.WVWTE>#\W49? +M"<[?;?25X/S=1E\)SM]M])7@_-U&7PG.WVWTE>#\W49?"<[?;?25X/S=1E\) +MSM]M])7@_-U&7PG.WVWTE>#\W49?"<[?;?25X/S=1E\)SM]M])7@_-U&7PG. +MWVWTE>#\W49?B3A_I^>S])6(\W=Z/DM?B3A_I^>S])6(\W=Z/DM?B3A_-]%7 +M(L[?3?25B/-W$WTEXOS=1%^).'\WT5+\W41?B3A_-]%7(L[?3?25B/-W$WTEXOS=1%^).'\W +MT5+\W41?B3A_ +M-]%7(L[?3?25B/-W$WTEXOS=1%\)SM]M])483/65&$SUE1A,]9483/65&$SU +ME1A,]9483/65&$SUE1A,]9483/65&$SUE1A,]9483/65&$SUE1A,]948L\Q0 +M7XG15%^)T51?B=%47XG15%^)T51?B=%47XG15%^)T51?B=%47XG15%^)T51? +MB=%47XG15%^)T51?B=%47WG,LLQ07WE\=*_CG7"/DUWT@4>8ZBN/QR>7\?'K +M*^;Z+7=7??QW^L#ER\/Z3P1$^W&`7.$:C@D7\.?&HO4:!C>.X;$HY^XSC'>Q +MOI+PYP>!ZXWKMW]_ET=9NJ9Y!/AWKF_>WZ+T]V,NZOGFO+PS;UE$N#GWLM/U +M??7U-^[U%V^^\V#_ND]WOKUSEWNRK:@\RGIU2*?[YS>/SXYBOKWS5/UC=379 +M/`GWV;63K9AO[SSV3\!=>Z3ABJ>B/O9.X,5\>V>-4O6MRP?7YFYL7-,GX/[P +M`.YD_,F;[SS;GES5^?L'EW#=?+/G_N1I:7>>3I/EG#BZ8^^5"!7!X5?O-&JZUK5XY7S46X'9X.-.S +MH_`WC+2[B'LX+-^8JY,;*_\%8K6,Y.7XN; +G,1A>Q#WQ#V#$M-#`Y-BUM8G(N(/I!8JM[0R04F8"W_PA!$1I`(8`W9=QWN'/ +M*NV^VE$WDW^/,DCI&X/^F8&WANV?JR;XXSX!<)0U@ +MW?DH!0[YA5'?*9=!2;@+^B`/UP7<,5VO(QS]"!=2W',QM\OJ=KFZIG`R[+0R +L5E9N@*25*S@J^Q#0YV7A&\BK\G'>X:\J[0(T';#8"1H*P.H-:WH%_)0&```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu new file mode 100644 index 000000000000..92039f8fa627 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-mbr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-mbr.vhd.gz +M'XL("/+%'50``VEM9RTQ>#$M-#`Y-BUM8G(N=FAD+F]U=`"METU3@S`0AN_] +M%>MX\]!)EF2A5T<].^.H5P'!\>#'J` +M`)0!M4`-D-37N0`Z0%X`J$%S8'_FYA:Z^NVUJ;^>O_?FU>T&&&>^56BN[3$# +MH1Z2`Y;Z(?2HKZ&SF/WIY=/9\\N3Q:'!V0<+`H$@%43,GD/,J=.DJ_.;BQ[Y +M,*K+YNI&*_6I!#`!G'LS,JONP6ET.*&LVK8_?GPV$WT8 +M*15R^OAL+(N[BZ94T$XV"H0NYS5WH:=\37$+I?*OZ%%H)\R%"@*3=@![]\/H +MC2CP]1%G*S&/)R.JK]3ZU-IBY<(Y/M"=[\.W`U;5-F#!!H4ASCE +M#44R!A-Y/"$G7ORJQ\3YK=IM0"EUQY@";ZV^.G4Z&@V4N>Z^DJ#`8QV^O[Q; +M6FY-9/7^L5DU^!O.">;'X#+32NU,OS+B`]U8)L.WQ8DU=7H)-YN@:E54@,KO";C`5U^8=1WF,O`P-T5?3!WM]2X/)S//1S^XBZ$N&HUM^OJ +M3N;JZL3):*#$M-#`Y-BUM8G(N=FAD9BYO=70`K96Q;H,P$(;W +M/,5%W3(@^[`/LD9-YTI5VS5`(,J0=NG0@8>OC3'8.)"D,AQ@=/;'?[ZS85J<6%*G$*Q^*%@9 +MN?9$/AGGYAF86B45L+SWH0\<\@NCOFTH`[UP%_1!&&ZA<9G?GSLXO!$N^+AR +M,;?+ZM:ANBIR,N1T9=RYTKXE_&J#H@=%F +MD/I?$:5`#5`-)'4[$T!;R'(7B'XEM=7W5UW]G'_=#&L<'_XGQF.K50AE@ +MH3]"1]UV]#WM3YOSY61Q=JNR'Q:D)UTJB`C")3_#$M-#`Y-BUM8G(N=FUD:RYO=70`K5Q=C]S&$7SW +MKZ"EER`/"]:27)(/`A+G'"`(`AB68[^&G]$AMB2<#D$,[(_/##DU5[P5-;2O +MY3V1H^VNG>[9JSM7%S;/US]95O9966;EF%67+$?F_FE]9'GQM'"/<\,GKG^_ +M^\>/)_[YP^ET_6H%@\^2%.0*)XO-ZUQ/S_X0[OREK,T3[G%.PA4^J[])#'#G +MG2=VX4KWY/ES*=Q=MSP]^AN!RR)0MH&K/E/3;K%?VMT?OPK-\_LK_![<\5[: +MK"ZR2Q^6V:5:UD56GY?G\JQV0;,#?)W=W7_Z3W8W?1H>[C\^?@C[._NS=<'E +MQ<=?!H_@"JLO_L8_X>%:#W&9LF+,"OBGL^O#7^]_GD[_G1X^W7]X_P8L]^S/ +MMBRRLO7;\?'YTV.S\"^29Q?XU\BN?_G;W9OPSLU/'[L'PODLMQ'WVJX.Q;U< +M,O]U^UAV-[U_](AS^!-WY\\V-*=:7KOT-U69U6VV;*?RV&?W]!A*7GHW/$S= +MX_3#KQ^G-Z]^^?`^]LZ?K6]9NP`U2Z.*K"H\5"C-MZ_RB/YMLYQ:=OWY_O'= +M_?#6E?EI>G5ZG1'NXGOG#K`)^UJK=BF7W9-UV[Y^^[]'5V\VAI.])]RRB:4( +M]]K5.:MJC^4.<#F*/6 +MDUX/>CF*<>Q/W=A]?)P>_/'&H^A]B\90J3_6\ND8MZ]3+R/0O\%%YA?G^7_-G/LT+S2EE4 +M&T#_4RQW7W]R7]\][>_B]W>1R%JS&EFT&[A_.8B/M^5>_'=A)Y&]9@VR&(]T +M[^*I;9+(^7GW^*L&Y'X?CK\+,++0K%(6U09NKW=5Z!TC:\UJ9-%NX/9Z=PF] +M8V2O68,LQD/%UJ%WC)PURU_XJQ3R`[^679K0.T86FE7*HMK`[?6N#;UC9*U9 +MC2S:#=Q>[[K0.T;VFC7(8CQ4;!]ZQ\A9L_R%!`&YWX<;0N\866A6*8MJ`[?7 +MNS'TCI&U9C6R:#=P>[V;0N\8V6O6((OQ4+%SZ!TC9\WREU)Z5Z;@ZCSTCI&% +M9I6RJ#9P.[VKR7>,K#6KD46[@=OI74V^8V2O68,LQD/%DN\8.6N6OU32NRH) +M1[YC9*%9I2RJ#=Q>[\AWC*PUJY%%NX';ZQWYCI&]9@VR&`\52[YCY*Q9_G*1 +MWEV2<.0[1A::50[1LZ: +MY2_\)0AROP]'OF-DH5FE+*H-W%[OR'>,K#6KD46[@=OK'?F.D;UF#;(8#Q5+ +MOF/DK%G^0D$&#V>D>^8V2M68TLV@W<7N_( +M=XSL-6N0Q7BH6/(=(V?-\A?^_Q/D?A^.?,?(0K-*650;N+W>D>\866M6(XMV +M`[?7._(=(WO-&F0Q'BJ6?,?(6;/\A?HCY'X?CGS'R$*S2EE4&[B]WI'O&%EK +M5B.+=@.WUSOR'2-[S1ID,1XJEGS'R%FS_&60W@TIN#8/O6-DH5FE+*H-W$[O +M6O(=(VO-:F31;N!V>M>2[QC9:]8@B_%0L>0[1LZ:Y2^C]&Y,PI'O&%EH5BF+ +M:@.WUSOR'2-KS6IDT6[@]GI'OF-DKUF#+,9#Q9+O&#EKEK],TKLI"4>^8V2A +M6:4LJ@W<7N_(=XRL-:N11;N!V^L=^8Z1O68-LA@/%4N^8^2L6?XR2^_F)!SY +MCI&%9I6RJ#9P>[TCWS&RUJQ&%NT&;J]WY#M&]IHUR&(\5"SYCI&S9N4R/8/< +M[\)U^=J[&%EH5BF+:@.WT[LN\%V,K#6KD46[@=OI71?X+D;VFC7(8CQ4;."[ +M&#EKEF^9Z'=(2EI=X#N(?@?5[R#Z'9+Z71?X#J+?0?4[B'Z'I'[7!;Z#Z'=0 +M_0ZBWQTH-O`=1+^#ZG<0_0Y)2:L+?`?1[Z#Z'42_0U*_ZP+?0?0[J'X'T>^0 +MU.^ZP'<0_0ZJWT'TNP/%!KZ#Z'=0_0ZBWR$I:76![R#Z'52_@^AW2.IW7>`[ +MB'X'U>\@^AV2^ET7^`ZBWT'U.XA^=Z#8P'<0_0ZJWT'T.R0EK3X/O1/]#JK? +M0?0[)/6[GGPG^AU4OX/H=TCJ=SWY3O0[J'X'T>\.%$N^$_T.JM]!]#LD):V> +M?"?Z'52_@^AW2.IW/?E.]#NH?@?1[Y#4[WKRG>AW4/T.HM\=*)9\)_H=5+^# +MZ'=(2EH]^4[T.ZA^!]'OD-3O>O*=Z'=0_0ZBWR&IW_7D.]'OH/H=1+\[4"SY +M3O0[J'X'T>^0E+1Z\IWH=U#]#J+?(:G?]>0[T>^@^AU$OT-2O^O)=Z+?0?4[ +MB'YWH%CRG>AW4/T.HM\A*6D->>B=Z'=0_0ZBWR&IWPWD.]'OH/H=1+]#4K\; +MR'>BWT'U.XA^=Z!8\IWH=U#]#J+?(2EI#>0[T>^@^AU$OT-2OQO(=Z+?0?4[ +MB'Z'I'XWD.]$OX/J=Q#][D"QY#O1[Z#Z'42_0U+2&LAWHM]!]3N(?H>D?C>0 +M[T2_@^IW$/T.2?UN(-^)?@?5[R#ZW8%BR7>BWT'U.XA^AZ2D-9#O1+^#ZG<0 +M_0Y)_6X@WXE^!]7O(/H=DOK=0+X3_0ZJWT'TNP/%DN]$OX/J=Q#]#DE):\Q# +M[T2_@^IW$/T.2?UN)-^)?@?5[R#Z'9+ZW4B^$_T.JM]!]+L#Q9+O1+^#ZG<0 +M_0Y)26LDWXE^!]7O(/H=DOK=2+X3_0ZJWT'T.R3UNY%\)_H=5+^#Z'<'BB7? +MB7X'U>\@^AV2DM9(OA/]#JK?0?0[)/6[D7PG^AU4OX/H=TCJ=R/Y3O0[J'X' +MT>\.%$N^$_T.JM]!]#LD):V1?"?Z'52_@^AW2.IW(_E.]#NH?@?1[Y#4[T;R +MG>AW4/T.HM\=*)9\)_H=5+^+9CK(O`F_*U=S&RT*P\__S#]#WOZ]_\3UF]/VOPB(_KYQM`%ES"O_=<@'MT +M5;AQC]69)@>!_8*_/@G<:-P_S+\-L*JRKKL!_"?W=[8^CN7S-:O:?^YL='.MD1P +E69AE]6+<_KW_Q/6[T_:_%;`,@&8=+/TGL>5?_1_0^/1A@%\````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu new file mode 100644 index 000000000000..5398eaef066e --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-pc98.raw.gz +M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G)A=RYO=70`K91!#H,@$$7W +MGF+<=F%@'*INFW3?3=NU-?44'+X@5`4$-0$,,?GP\C\#,&8:`"&P?F.,"_)6 +MN5T6EV*B\?$<4`CH0^!3`2<<:G\=P4"@_KP/QG'Y'$%67OOCN!)#D%T5%39P +M-BYEWC^<`HL&2("X0HM'';[OKXW`F"^PP>$>;C;,C^!JO6HU4[E%/N-B@L&5 +MEE4N.$JY4PCV/156Y#TLB*VW;EUG8.H,#\!:JZ$+G.L+B[\NM(%.W(0_"./V +M&M>X\_D*ASMQP<5]DK5-NRM#=T/F8M3^S3AX9G4"]1L9 +9C'%!/BJW&R!98+8=)-3`X@?$\J!S108````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu new file mode 100644 index 000000000000..8df641e4f705 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-pc98.vhd.gz +M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;X,P#(;O +M_16N=NNA2HP3VNNT[CQIVG8M9;3:81]:>^B!'[\8$DCX6KL%*`H*?O+:<4PJ +M1'T`Z`3T'G0!6G$[)=!K2%<`IM->6-VE?80R__PH\M/;>6F/GK*[!+69V+NI4,8F1FKL)G804N6W2QL6A=YE4.1^_LN]CT=&' +M(ZFB&WVRUY>,NXLV5="];!40I_.4NU!13EW<0*K\*WHZM"/;,$$0RG5@Y7X8 +MO18%OCXMQ43,QR=C5%_&^LS:$MG`?;RCO%V&9P/<[:\#*L5+J`M\<@[GK&]- +MD--0W'TG+UH=^4CV_7E^B\CQP\IAE7*Y5!I6>*G"E\WS@,,8S^$:A[_A&L'R +M$EQB:Y][TZC%YFLSVE'CYI8U;W$TI8[77'&5LRINLF"^ZMCY\PS"Y'`.8N55 +M!0_8S"^T^M9]&1BX.Z$/^NYFC$O#]Z6'PU_'*K7$8MQ!059E-!G*-[-W'.\J'97C60+2E/MJW`VUMCJ:0+#":0K+5 +M.:)"*B:3[=HLU%9AI(TXXR)NQ!D7<2/.N(@;<<9%W(@S+N)&G'%1-^+:_,42 ++8O8#/[LV_KT-```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu new file mode 100644 index 000000000000..49a64aac2ce1 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-pc98.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-pc98.vhdf.gz +M'XL("//%'50``VEM9RTQ>#$M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5L6Z#,!"& +M]SS%1=TR1/BP#UBCIG.EJNT:0B'*T';IT(&'KVU,\&$@266PD-'AC__WV>,DO#/J*4`8RNPOZ(+1;&ES&OQ<>#J_8!8X[+N9V6=TZ5%=%3D8ZWADW[EP# +MX3NWPV'<0B!M9=8KT-3(X#D?:)^W_.Z`T@&CS2"YLX-2H`:H!E*FGTF@`K+< +M!R)?26WU_557/^=?/\,&)T85W6]F/*9FMU`&6)J?T(?I>_H>]J?-^?/4X_I2 +MU?]8DIETI2$RL$O<[M/NY=$B#X.Z-)PD\F?OJ$\H"4(PXT[=@2]GLOGMS=8- +D')65V3?VP@*3I#$M-#`Y-BUP8SDX+G9M9&LN;W5T`*U<76_#@>0B!PB"`,;Y>7E>+MKIWMV2W)U8=-T_4J2O$OR/,F'I"B3%,G\3^LM2;.'Q7P[UWS@\O>; +M?_QTXM7AP%P*7!*!D`U<\4=-NL<_M[H^O?//<_C*WA_EXRR:I +MLJ3L_#(IBV6=)=5Y>2Q-JCEHF@&_2VYNO_XGN1F_]G>W7^X_^_V=W=G.P7GI +MXLO>(@N6>W=GF +M69(W;CLN/GVX;1;N2=*DA'N.Y/*7O]V\]:_<]/2EO2.?,E+[_J[L;T? +M?_SV97S[YN/G3Z%W[FQ=RYH%J%X:E25%YJ!\::Y]A4-T+YOEU)++K[?WO]SV +M'^8ROXYO3M\EA"M=[^8#K/V^UJKGE'+W9.=M7][][WZN-QG\R=X2;MG$4L3\ +MW,4Y*2J'-1_@>.*_/&7<7D%$JY9WV8N>#T'+,NSN_!= +M6^$=B>7N@>5DDYOVODV^;[^.I^]N;KX/)]NZ8O/E-F]M="CE"NU>WTL[Y\:M +M)[T>]'(4P]"=VJ']N>,-1]&Y%@V^4G>L^<,Q;I^G6DYJ7,[ +MS&?J8/\]?OY(N'Y]&<_[<"^)9DG,W,7\ZEG@1_\,ZRO&'9.#&^_OOIWZ;[_> +M?AKF-UKREG##VKMY.^MI/ASF?(#S#I_YW9V?WH?OU*.GFM&3RT/7%MRO'BY+/05DGLHV +M+0K;69]0"'3L[S_?K1M[(WR99I7BZ+ +M8@/H?HJE\_>?YN_W#_LKW?Y*B:PTJY9%LX'[UPSQY;KZ6CME$BI\?=XZ\:D.M]./XNP,A,LW)9%!NXO=X5OG>,K#2KED6S@=OK7>E[ +MQ\A.LWI9#(>*K7SO&#EIEKOCKU)(#_Q:5M:^=XS,-"N71;&!V^M=XWO'R$JS +M:EDT&[B]WK6^=XSL-*N7Q7"HV,[WCI&39KD[$@3D>A^N][UC9*99N2R*#=Q> +M[P;?.T96FE7+HMG`[?5N]+UC9*=9O2R&0\5.OG>,G#3+W>72NSP&5Z6^=XS, +M-"N71;&!V^E=1;YC9*59M2R:#=Q.[RKR'2,[S>IE,1PJEGS'R$FSW%TAO2NB +M<.0[1F::E0[1DZ:Y>Y* +MZ5T9A2/?,3+3K%P6Q09NKW?D.T96FE7+HMG`[?6.?,?(3K-Z60R'BB7?,7+2 +M+'?'7X(@U_MPY#M&9IJ5RZ+8P.WUCGS'R$JS:EDT&[B]WI'O&-EI5B^+X5"Q +MY#M&3IKE[BC(0*YWX>K4]XZ1F6;ELB@V<#N]J\EWC*PTJY9%LX';Z5U-OF-D +MIUF]+(9#Q9+O&#EIEKMKI'=-%(Y\Q\A,LW)9%!NXO=Z1[QA9:58MBV8#M]<[ +M\ATC.\WJ93$<*I9\Q\A)L]P=__\$N=Z'(]\Q,M.L7!;%!FZO=^0[1E::5*)=\Q^8V2F6;DLB@W<7N_(=XRL +M-*N61;.!V^L=^8Z1G6;ULA@.%4N^8^2D6>ZNE][U,;@F];UC9*99N2R*#=Q. +M[QKR'2,KS:IET6S@=GK7D.\8V6E6+XOA4+'D.T9.FN7N!NG=$(4CWS$RTZQ< +M%L4&;J]WY#M&5II5RZ+9P.WUCGS'R$ZS>ED,AXHEWS%RTBQW-TKOQB@<^8Z1 +MF6;ELB@V<'N](]\QLM*L6A;-!FZO=^0[1G::U,S#0KET6Q@=OK'?F.D95FU;)H-G![O2/?,;+3K%X6PZ%BR7>,G#0KE>D9 +MY'H7KDW7WH7(3+-R610;N)W>M9[O0F2E6;4LF@W<3N]:SW\0U>]:SW<0_0ZJWT'T.T3UN];S'42_ +M@^IW$/WN0+&>[R#Z'52_@^AWB$I:K><[B'X'U>\@^AVB^EWK^0ZBWT'U.XA^ +MAZA^UWJ^@^AW4/T.HM\=*-;S'42_@^IW$/T.44FK]7P'T>^@^AU$OT-4OVL] +MWT'T.ZA^!]'O$-7O6L]W$/T.JM]!]+L#Q7J^@^AW4/T.HM\A*FEUJ>^=Z'=0 +M_0ZBWR&JWW7D.]'OH/H=1+]#5+_KR'>BWT'U.XA^=Z!8\IWH=U#]#J+?(2II +M=>0[T>^@^AU$OT-4O^O(=Z+?0?4[B'Z'J'[7D>]$OX/J=Q#][D"QY#O1[Z#Z +M'42_0U32ZLAWHM]!]3N(?H>H?M>1[T2_@^IW$/T.4?VN(]^)?@?5[R#ZW8%B +MR7>BWT'U.XA^AZBDU9'O1+^#ZG<0_0Y1_:XCWXE^!]7O(/H=HOI=1[X3_0ZJ +MWT'TNP/%DN]$OX/J=Q#]#E%)JT]][T2_@^IW$/T.4?VN)]^)?@?5[R#Z':+Z +M74^^$_T.JM]!]+L#Q9+O1+^#ZG<0_0Y12:LGWXE^!]7O(/H=HOI=3[X3_0ZJ +MWT'T.T3UNYY\)_H=5+^#Z'<'BB7?B7X'U>\@^AVBDE9/OA/]#JK?0?0[1/6[ +MGGPG^AU4OX/H=XCJ=SWY3O0[J'X'T>\.%$N^$_T.JM]!]#M$):V>?"?Z'52_ +M@^AWB.IW/?E.]#NH?@?1[Q#5[WKRG>AW4/T.HM\=*)9\)_H=5+^#Z'>(2EI# +MZGLG^AU4OX/H=XCJ=P/Y3O0[J'X'T>\0U>\&\IWH=U#]#J+?'2B6?"?Z'52_ +M@^AWB$I:`_E.]#NH?@?1[Q#5[P;RG>AW4/T.HM\AJM\-Y#O1[Z#Z'42_.U`L +M^4[T.ZA^!]'O$)6T!O*=Z'=0_0ZBWR&JWPWD.]'OH/H=1+]#5+\;R'>BWT'U +M.XA^=Z!8\IWH=U#]#J+?(2II#>0[T>^@^AU$OT-4OQO(=Z+?0?4[B'Z'J'XW +MD.]$OX/J=Q#][D"QY#O1[Z#Z73#30:X%+EF_/=R8KKT+D9EFI>G3M[EW,T2: +M7.UN-/8'8O$'AIG"6M7O`USAK/<7YMO2OX>\W^I?1)AO\_8B_R+"?)NW%_D7 +M$>;;O+W(OX@PWS;Q+R+,MTW\BPCS;1/_(L)\V\2_B##?-O$O(LRW3?R+"/-M +M$_\BPGS;Q+^(,-\V\2\BS+=-_(L(\VT3_R+"?-O$OX@PWS;Q+R+,MTW\BPCS +M;1/_(L)\V\2_B##?-O$O(LRW3?R+"/-M$_\BPGS;Q+^(,-\V\2\BS+=-_(L( +M\VT3_R+"?-O$OX@PWS;Q+R+,MTW\BPCS;1/_(L)\V\2_",ZW;?R+X'S;QK\( +MSK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+X'S;QK\(SK=M_(O@?-O&OPC. +MMVW\B^!\V\:_",ZW;?R+X'S;QK\(SK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW +M;?R+X'S;QK\(SK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+X'S;QK\(SK=M +M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+X'S;QK^(,-]FY(O\BPCS;4:^R+^( +M,-]FY(O\BPCS;4:^R+^(,-\V\2\BS+=-_(L(\VT3_R+"?-O$OX@PWS;Q+R+, +MMTW\BPCS;1/_(L)\V\2_B##?-O$O(LRW3?R+"/-M$_\BPGS;Q+^(,-\V\2\B +MS+=-_(L(\VT3_R+"?-O$OX@PWS;Q+R+,MTW\BPCS;1/_(L)\V\2_B##?-O$O +M(LRW3?R+"/-M$_\BPGS;Q+^(,-\V\2\BS+=-_(L(\VT3_R+"?-O$OPC.MVW\ +MBQA-_8L83?V+&$W]BQA-_8L83?V+&$W]BQA-_8L83?V+&$W]BQA-_8L83?V+ +M&$W]BQA-_8L83?V+&$W]BYC2U-"_B,G4OXC)U+^(R=2_B,G4OXC)U+^(R=2_ +MB,G4OXC)U+^(R=2_B,G4OXC)U+^(R=2_B,G4OXC)U+^(R=2_>$[3U-"_>+[Z +M+.%-UC[<=;&K/S!?]K=^.NCUW_L/7+X_;?\$0$R_#;`HDO8:\)^^X'SYO-XF +M3_K\J;JFZ>$6*WB%L^Y?;MR_>;/.RON=[&>5/N,_N[XI9R^1!@_?A5/<4-V^V4FVSA +MNF?/]OG=O;[>76]\&%M`MN_<%>YL2P3UPLRK>>+Z[_T'+N]/VS\K +.8+X`OOH_SBV/UN!>```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu new file mode 100644 index 000000000000..f5ae94e4a3e3 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.raw.gz.uu @@ -0,0 +1,10 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-vtoc8.raw.gz +M'XL("/3%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YR87@#7/;QMA@0*Y<>$H73S>%_F,2,$%Z`T3@1= +MA:,(50FE4"HO&'A]>N!N7VLOSZNZ%UPN8YCT8M(BE@17C,IEQPYXCGQR&7B& +MJ"$H"61;CN#+$9?-XPK,X+[A\TA_C^K@TL%"$DZGN4/`;XTR/DW^M2I[LSNZZ*O*S +M%6<:M!9$*/4$=]`=CH*K\M\WB7M><(\B?GA55`?<;?<4!6#V`]&)2;VR!``` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu new file mode 100644 index 000000000000..aadaa429871a --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhd.gz.uu @@ -0,0 +1,17 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-vtoc8.vhd.gz +M'XL("/3%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&0N;W5T`*V6R6[",!"& +M[SS%2+UQ0-[BP+5JN56JU!?`21S40Q.0"AICVC1Q,E?/QUQR.=J!/ +M!%)%M_KX:$Z&W14N543SLE.@*)WGW(6*AIWTZY`0:!)AH*]/4;H&D.V=2XT01C6"::+V716F\K@\\F9D +M(W\ZN=PDA5'^$B5GV$BUCU$2YBU4>XB%4?X2)6 +2?82+6O7I*O<6?^^O%OLJ#``` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu new file mode 100644 index 000000000000..bcf2071ac264 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-vtoc8.vhdf.gz +M'XL("/7%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YV:&1F+F]U=`"ME,MN@S`0 +M1??YBBMUEP7RJC"#!1KF>*X] +M#&-A`(I0"Y#VI@2TA%*0Y!P]G']NL-MO8Q[?GNBE"L.N`HP[9S&$77/8*AMV +MM8[`31+'KP,W8`V8*`(#KCE'-3=QU_(+N'8IN0'7W8LC-_?H#8S)<+L);K_P +M8?"97`-WX/(^(,OE +MXPVQK)B=6;14^'`OKF_1&4@)J6K]\R2_A^?#^OWC,.)$5#4N[%KJJ9/F*BF5NW5]=/QU1YR<;Q)-=Z]38`J< +M)\)C=KNT6#Q.G<2:`9T^ICE:\I(XBK7G<9IE4?\O98^CA4O%U=[J#P!,R,C= +#!@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu new file mode 100644 index 000000000000..238837c7ad0c --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-4096-vtoc8.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-1x1-4096-vtoc8.vmdk.gz +M'XL("/7%'50``VEM9RTQ>#$M-#`Y-BUV=&]C."YV;61K+F]U=`"M7%UOY,81 +M?/>O&)Q?#@D@L);?#PQ>YWKSY(MPER]E[9Y8'I)`>YR +M\,0A7+$\>7DIA;OKUJ='?R-P+@*Y'5SY0DV'Q7YI=W_Z*C3/[R_W>UB.MVI= +MG;NJ#TM7E>LZ=_5E?2YS]1(T+X!?N]N[S_]QM]/GX?[NT\/'L+^+/]LEN*A\ +M?#5XA*6PNO(W_@D/UWJ(:G+YZ'+XI]WU_KN[7Z>;_T[WG^\^?G@'EGOQ9UOD +MKFC]=GQ\]OC8+?R+9*Z"?PUW_=O?;]^%=VYV\ZF[)YS/6C:RO/92A^)6E?/? +MSQ_K[J8/#QYQ#E]Q=_YL0W/*];4+?U,6KF[=NIW28U^6I\=0\MJ[X7[J'J:? +M?O\TO7OSV\7%E[;&6`UR/XN+RPM\M_[1L>*FD@`]RUX\?;G[\U_(C[IOU_H>__DBX9LE: +M(I<-+BE+0;N:RJW^\NG;TEW??^O>^")_^F5:WX&$:[K+NMGOHW#?=Y^GFZ]O;;^+)=K[88GTL6YL\2K5!^_?WVLZE<=M) +M;P>]'L4X]C?=V'UZF.[]\<:CZ'V+QE"I/];B\1CWKU.O)S7[=XR[OG-O[L;E +M3#WLOZ>/OQ%NV-[&RS[\6Z)=$W-_L[Q[5O@IO,+VCO''Y.&FA_O?;X;??[W[ +M,"X_:.X=X<:M=\MVMM-\/,SE`)<=OKC!I7=OUE.-VR/IZAD7%3 +M\67=];=U>[],W;AL;<$FW.QW=WEY'Z%33UYJ07?7QZZMN)\#7)X%"L@#E>U: +M%+>SO:`0Z#0\?+S?-O9&^#A_^KOLM7QG]5]N3W6:YYA2S* +M':#_+98MWW]9OG]XW%_E]U=)9*U9C2S:'=S/"\2GY^56_J>PD\A>LP99C&>Z +M5WEJFR1R?MH]_JD!N3^&X]\"C,PUJY!%N8,[ZET9>L?(6K,:6;0[N*/>5:%W +MC.PU:Y#%>*K8.O2.D;-F^0O_E$)VXL^RJ@F]8V2N684LRAW<4>_:T#M&UIK5 +MR*+=P1WUK@N]8V2O68,LQE/%]J%WC)PURU]($)#[8[@A](Z1N685LBAW<$>] +M&T/O&%EK5B.+=@=WU+LI](Z1O68-LAA/%3N'WC%RUBQ_*:1W10JNSD+O&)EK +M5B&+<@=WT+N:?,?(6K,:6;0[N(/>U>0[1O::-\8F6M6(8MR!W?4._(=(VO-:F31[N".>D>^8V2O68,LQE/%DN\8.6N6 +MO_"/(,C],1SYCI&Y9A6R*'=P1[TCWS&RUJQ&%NT.[JAWY#M&]IHUR&(\52SY +MCI&S9OD+!1G(_2%,3+7K$(6Y0[NH'<-^8Z1M68ULFAW<`>]:\AWC.PU +M:Y#%>*I8\ATC9\WREU9ZUR;AR'>,S#6KD$6Y@SOJ'?F.D;5F-;)H=W!'O2/? +M,;+7K$$6XZEBR7>,G#7+7_C_GR#WQW#D.T;FFE7(HMS!'?6.?,?(6K,:6;0[ +MN*/>D>\8V6O6((OQ5+'D.T;.FN4OU!\A]\=PY#M&YII5R*+[@#GK7 +MDN\866M6(XMV!W?0NY9\Q\A>LP99C*>*)=\QD>^8V2M68TLVAW<4>_(=XSL-6N0Q7BJ6/(=(V?-\I=9>C3^ +M$*[+MM[%R%RS"EF4.[B#WG6![V)DK5F-+-H=W$'ONL!W,;+7K$$6XZEB`]_% +MR%FS?,M$OT-2TNH"WT'T.ZA^!]'OD-3ONL!W$/T.JM]!]#LD];LN\!U$OX/J +M=Q#][D2Q@>\@^AU4OX/H=TA*6EW@.XA^!]7O(/H=DOI=%_@.HM]!]3N(?H>D +M?M<%OH/H=U#]#J+?G2@V\!U$OX/J=Q#]#DE)JPM\!]'OH/H=1+]#4K_K`M]! +M]#NH?@?1[Y#4[[K`=Q#]#JK?0?2[$\4&OH/H=U#]#J+?(2EI]5GHG>AW4/T. +MHM\AJ=_UY#O1[Z#Z'42_0U*_Z\EWHM]!]3N(?G>B6/*=Z'=0_0ZBWR$I:?7D +M.]'OH/H=1+]#4K_KR7>BWT'U.XA^AZ1^UY/O1+^#ZG<0_>Y$L>0[T>^@^AU$ +MOT-2TNK)=Z+?0?4[B'Z'I'[7D^]$OX/J=Q#]#DG]KB??B7X'U>\@^MV)8LEW +MHM]!]3N(?H>DI-63[T2_@^IW$/T.2?VN)]^)?@?5[R#Z'9+Z74^^$_T.JM]! +M]+L3Q9+O1+^#ZG<0_0Y)26O(0N]$OX/J=Q#]#DG];B#?B7X'U>\@^AV2^MU` +MOA/]#JK?0?2[$\62[T2_@^IW$/T.24EK(-^)?@?5[R#Z'9+ZW4"^$_T.JM]! +M]#LD];N!?"?Z'52_@^AW)XHEWXE^!]7O(/H=DI+60+X3_0ZJWT'T.R3UNX%\ +M)_H=5+^#Z'=(ZG<#^4[T.ZA^!]'O3A1+OA/]#JK?0?0[)"6M@7PG^AU4OX/H +M=TCJ=P/Y3O0[J'X'T>^0U.\&\IWH=U#]#J+?G2B6?"?Z'52_@^AW2$I:8Q9Z +M)_H=5+^#Z'=(ZG^0U.]&\IWH=U#]#J+?(:G?C>0[T>^@^AU$OSM1+/E. +M]#NH?@?1[Y"4M$;RG>AW4/T.HM\AJ=^-Y#O1[Z#Z'42_0U*_&\EWHM]!]3N( +M?G>B6/*=Z'=0_0ZBWR$I:8WD.]'OH/H=1+]#4K\;R7>BWT'U.XA^AZ1^-Y+O +M1+^#ZG<0_>Y$L>0[T>^@^ETTTT'N!O6@I?^&?8N_)?1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE]$ +MG&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)? +M1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE]$G&^;^!<1Y]LF_D7$^;:)?Q%QOFWB +M7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)?!.?;-OY%<+YMXU\$Y]LV_D5POFWC +M7P3GVS;^17"^;>-?!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3GVS;^17"^;>-? +M!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3GVS;^17"^;>-?!.?;-OY%<+YMXU\$ +MY]LV_D5POFWC7P3GVS;^17"^;>-?!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3G +MVS;^17"^;>-?!.?;-OY%<+YMXU]$G&\S\E7^1<3Y-B-?Y5]$G&\S\E7^1<3Y +M-B-?Y5]$G&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_ +M$7&^;>)?1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE]$G&^;^!<1Y]LF_D7$^;:) +M?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)?1)QOF_@7$>?;)OY%Q/FV +MB7\1<;YMXE]$G&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7P3GVS;^14RF_D5,IOY% +M3*;^14RF_D5,IOY%3*;^14RF_D5,IOY%3*;^14RF_D5,IOY%3*;^14RF_D5, +MIOY%3*;^17];?K_;7V&_OV:7AR\#-NM( +M\W)XND76/F:U2;@O[6^#ZZS*W>#ZLW#;V&6GOGVVOPWNL5S]:;OLX/#2[L*/[!.X\1&N>9;U +MI6+?OKB[R?2M@ODLW-BY?G*7WN75,[@_5P%N_5CL;5+__+_'3UQ_N-G_;WNK +5%`'0[+U7^,]AS;[Z/YH4:2:>70`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu new file mode 100644 index 000000000000..025d7ad4a149 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-apm.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-1x1-512-apm.raw.gz +M'XL(".3%'50``VEM9RTQ>#$M-3$R+6%P;2YR87]/"5(HG(/PDN:+T(BV4_QK-KQGP` +M)"$%F$T64G`PPN4^2)B7M]+&71G#%![&V8VNZ[AR$*:X]T#ARI*!FE%?E0)Y +MOV#6KT.@QSE]Q*&92_4!)6?I6W;=9SN!$[D^U^.JL3JY.[]S0`MH@EJ$4^V@ +M6E<.ZK9=?3SM3_OOPS;BR.)4XYKU?]1]U=VD.IEYMC1SMA27,@#[LT741[EW +MC\[C4,YX.PB;)"`K$$$T5KAT-7L?`5?'MGW:/#^\KS:I?T29]:D9_HG$/_^3 +MI/XAU:=R^Z=N^JN*\7C#KLO]X(`5@-H4D +,'+#X`^%)]I"G!0`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu new file mode 100644 index 000000000000..ad1859a2056c --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-512-apm.vhd.gz +M'XL(".7%'50``VEM9RTQ>#$M-3$R+6%P;2YV:&0N;W5T`*U6RVX;(13=^RNN +ME%VD6L#`G739JO&N4I2HZV0Z9B)+36+%EIJ%/SY<'H9Y,+5=QA@Q8N[A<.X# +M&',/`%:`':`&5#2N)>!7J&\`S*1OPO;'`.$NM^N9D +M+RJ09I$:1$.+X)K&<`@PRZO;Y^O-RW.`$QXN+"P1I`!E0.1H'61'=H2T^O[P +MPT(^17;5F%VT,O_?$I@$SI,OJL#NZ-5=?95D/36)JA]5YZ$W&S`SC% +M!E8)S2E1D\U.P>&%CST!2.,]M%RS*?@@W$2K_I1[V[:0?&!&8"A/" +M;K^O7H2"E!]R-J-YWAE9?@WQ,ZFI1$AVVZI_;?CVGF#8T!U-QKL7Z]?2M,D0 +MN9Z*BO@RS-V[GY/ATA(_R2F,*9);BN%3^'W;;O_H"3A1:KL.KAJS4YW/.9MT +MKD3;WI5NU05VCR;;]IO]YNWU,3D@5SR"Q-L05S9GW$>#J76MS"GWYM7I(]=.R+#_.3M!/ +M)/JY)$GU2VL+SQWBE_.;U8\.DWHB-J-^N[\N$`._TOH)KQ]K)OK\Q.%NV?\Y +M0.&+:;'J+&+U*\-0>L!B#&7,X5(,.==&7 +BK*P5.^NJB[YD%;KJ$ES!JR[!%;WJHBVHBT^(Z?)+'PT````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu new file mode 100644 index 000000000000..189b488a594b --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-apm.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-1x1-512-apm.vhdf.gz +M'XL(".7%'50``VEM9RTQ>#$M-3$R+6%P;2YV:&1F+F]U=`"M54UOPC`,O?,K +M+.V&M*I-'(<=-PUND]#0SE!HBRH-J!C2=NB/7SYI2@MB4U,K2N3F]?G9<>/8 +M#@`4(!C$RF)GW,S-_L*@GKY':L21'_7(@B6W3EV'BRY&/1I;0*;=(@;,.N=X +M")BT'?7\[1+0PFE^F(",M=$&2-S%[[FJ/O,>.#94N!:.=]F)PJP3`,E`(M"3 +MFZD`RK7;L5M6Z?%4GLK#?NGA4,%1I@_+O[#;I54O.S%P;O'.W*);,`?8SBUX +M?CAT[:%)!VGA52*4(0/!`1%8IH@+[5/[#N#LF.DE`_"/G1T/K13?TD!RE[:K/1[^O;%J+G-[1^$Z=?G/;,UQWU/&H_%A`= +MX&`,R75GXNZN:Q&Y[P&3$)`UZ36`F\,^WYS*G_`&D^O.1=%O^CSC^E]`$EAJ +M6DRFUP&_A^EV7.ZV'LYW/_]AE>MSBB^CI':X,Y5@`[EJV/&N2!2JMT9=RTG2 +M"MRQ6X7J63@\!YL7L!:&IK?6IN7H[#$M-3$R+6%P;2YV;61K+F]U=`"MG%MOW,@1A=_] +M*PCORR)`!)[A_<%`UI$-!,$"QGJ3/&YXC878EB`)20S,CP^;[-,ZE$0WL2IE +MM)SR5-5T5X]*RE<'3-/U*TGR+LGS)!^2HDQ2)/,_K8\DS1Z,^7&J^<+YKY<_ +M__V"7S]>7)Q?KR+IDI`HV:0KGMG3[F:_M[H_O/+%<^O+W!KFXRV; +MI,J2LO-F4A:+G275:7DM3:K9:9H3_I!<7MW].[D<[_K;JYO[:[^^DSO;V3DO +MG7_9NPSSQJK2/7$ON'2-2U&.238D&=S+R?GV_=7G\>(_X^W=U?77-^!V3^YL +M\RS)&[<Y,T*>'>(SG_^2^7;_PG-[VX:6^9SD7-"YG?>]Z'YBW+ +MQ'T_?2RK&[_>NXR3_PJK5$VR+*=PN4_SRX/?\E*[_G9L +M[\=?O]V,;UY_N?X::N?.UI6L61+52Z&RI,A<*K\U5[["970?F^74DO/GJ_M/ +M5_W'>9MWX^N+'Q*F*UWMY@.L_;K67<\AY>[)SLL^O_O?_;S?9/`G>\5TRR*6 +M3HY:O:<%SB'S!O:[*E8]U\\_E@FYX_ODM=ND[]^&I=/(-,UZX^9CE*(:ANVB']N9^O'7'&XZB8/Q[A]GVHYJS)^>)?WHWV']Q+AC9_&=IB7-N=FNLFM[O3\.GRE'KW5G#TY/U1MR7OGTV6I +M;P&9;V6;$H7EK&\H#73L[Z]OUX6]EGZFC +MWV>9QN5B%)N$[K=8.G__:?[^\+"^TJVO%,]*HVHQFDVZ?\XI;IYNMW0_A:UX +M=AK5BS$F4;E8A2;='NU*WSMZ%EI5"U& +MLTFW5[O2UXZ>G4;U8@R'-EOYVM%STBAWX9]22`_\65;6OG;TS#0J%Z/8I-NK +M7>-K1\]*HVHQFDVZO=JUOG;T[#2J%V,XM-G.UXZ>DT:Y"QL$Y/E^NM[7CIZ9 +M1N5B%)MT>[4;?.WH66E4+4:S2;=7N]'7CIZ=1O5B#(F4;E8A2;='NU8[^C9Z51M1C-)MU>[=COZ-EI5"_&<&BS +M['?TG#3*74JI71E-QWY'STRCDX:Y2[\(PCR?#\=^QT],XW*Q2@VZ?9JQWY'STJC:C&:3;J]VK'? +MT;/3J%Z,X=!FV>_H.6F4NQ#(0)[OIJM37SMZ9AJ5BU%LTNW4KF:_HV>E4;48 +MS2;=3NUJ]CMZ=AK5BS$DT:Y"___$^3Y?CKV.WIF&I6+46S2 +M[=6._8Z>E4;58C2;='NU8[^C9Z=1O1C#HDX:Y2Z]U*Z/I6M2 +M7SMZ9AJ5BU%LTNW4KF&_HV>E4;48S2;=3NT:]CMZ=AK5BS$ +MDT:YRRBU&Z/IV._HF6E4+D:Q2;=7._8[>E8:58O1;-+MU8[]CIZ=1O5B#(CV*3;JQW['3TKC:K%:#;I]FK'?D?/3J-Z +M,89#FV6_H^>D4:E,SR#/=].UZ5J[X)EI5"Y&L4FW4[O6][O@66E4+4:S2;=3 +MN];WN^#9:50OQG!HL[[?!<])HUS)A-\ABK1:W^\@_`[*[R#\#E%^U_I^!^%W +M4'X'X7>(\KO6]SL(OX/R.PB_.[!9W^\@_`[*[R#\#E&DU?I^!^%W4'X'X7>( +M\KO6]SL(OX/R.PB_0Y3?M;[?0?@=E-]!^-V!S?I^!^%W4'X'X7>((JW6]SL( +MOX/R.PB_0Y3?M;[?0?@=E-]!^!VB_*[U_0["[Z#\#L+O#FS6]SL(OX/R.PB_ +M0Q1I=:FOG?`[*+^#\#M$^5W'?B?\#LKO(/P.47[7L=\)OX/R.PB_.[!9]COA +M=U!^!^%WB"*MCOU.^!V4WT'X':+\KF._$WX'Y7<0?HQWPN^@ +M_`["[PYLEOU.^!V4WT'X':)(JV._$WX'Y7<0?H_$WX'Y7<0?G=@L^QWPN^@_`["[Q!%6CW[G?`[*+^#\#M$ +M^5W/?B?\#LKO(/P.47[7L]\)OX/R.PB_.[!9]COA=U!^!^%WB"*MGOU.^!V4 +MWT'X':+\KF>_$WX'Y7<0?HQWPN^@_`["[Q#E=P/[G?`[*+^#\+L#FV6_$WX'Y7<0 +M?HQWPN^@_`["[Q#E=P/[G?`[*+^#\#M$^=W`?B?\#LKO(/SN +MP&;9[X3?0?D=A-\ABK0&]COA=U!^!^%WB/*[@?U.^!V4WT'X':+\;F"_$WX' +MY7<0?G=@L^QWPN^@_"Z(Z2#/)5VR?OMT8[K6[EE)^3/_%&J7/+NZT5@?B$4? +M&&8*ZZY^7\(UG?7ZPGR;CQ?I%Q'FVWR\2+^(,-_FXT7Z183Y-A\OTB\BS+=- +M](L(\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O(LRW +M3?2+"/-M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@PWS;1+R+, +MMTWTBPCS;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2\B +MS+=-](L(\VT3_2+"?-M$OX@PWS;1+X+S;1O](CC?MM$O@O-M&_TB.-^VT2^" +M\VT;_2(XW[;1+X+S;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT;_2(XW[;1+X+S +M;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT;_2(XW[;1+X+S;1O](CC?MM$O@O-M +M&_TB.-^VT2^"\VT;_2(XW[;1+X+S;1O](CC?MM$O@O-M&_TB.-^VT2^"\VT; +M_2(XW[;1+X+S;1O](CC?MM$O(LRWZ?DB_2+"?)N>+](O(LRWZ?DB_2+"?)N> +M+](O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@P +MWS;1+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M$_TBPGS;1+^( +M,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS;1/](L)\VT2_ +MB##?-M$O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2^"\VT;_2)&4_TB1E/](D93 +M_2)&4_TB1E/](D93_2)&4_TB1E/](D93_2)&4_TB1E/](D93_2)&4_TB1E/] +M(D93_2*F-#74+V(RU2]B,M4O8C+5+V(RU2]B,M4O8C+5+V(RU2]B,M4O8C+5 +M+V(RU2]B,M4O8C+5+V(RU2]B,M4O8C+5+Y[2-#74+YZ>W$OX8+JGFUWU@?FR +MOKQP]R[5>_VN=S7^3L)WO[@T/SY:7VZ^ON5^O>[VJL.3N$P38OO"^GTGWY%[,OW>[:[KLZ>J*R=_H=[ES9\Z[ +MY?*>PL7$U?UVT][>7]U?77_]C>F6^_4._C:NQU?WI;UY=G7&]V+.\X-G2R)R +M\@FW9YMP?=;W_LSSY3A*WN^X<'?1+98[ZIZ&>>&%>ZW(GB9\?SN.;S]>_O%O +M[S]J_?+<>'WE@?JI%&[](='Z);H^:^UQ7GZW?E665-4SG\V'^MW]=_T@+[?_6A+E/:+;"W-U\-GWU?YW"XEV37@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu new file mode 100644 index 000000000000..874e5704f2f0 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.raw.gz.uu @@ -0,0 +1,10 @@ +# $FreeBSD$ +begin 644 img-1x1-512-bsd.raw.gz +M'XL(".;%'50``VEM9RTQ>#$M-3$R+6)S9"YR87Y`2H7IKDMVWVD[.[,]!0\_4%0J`UU",22D[9>_U((X&8`BP/['GG:8J^#+ +M5*=JI)$#ZA:4!GV&SH;C^K$#KNYMYVF[RPSX`?P`&P\S[BP*6_L.J[ +MQ#*(E9O1!W&YO<.U/%X&.-HI%SCNE>UM7ET=JQL*-Z/93L;!R740/KD3CLH^ +B!#2^+/8/M%'QGG:8N^!K`BH/+':#BARP^@+33Z#K!04````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu new file mode 100644 index 000000000000..ef644e42fab2 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vhd.gz.uu @@ -0,0 +1,17 @@ +# $FreeBSD$ +begin 644 img-1x1-512-bsd.vhd.gz +M'XL(".;%'50``VEM9RTQ>#$M-3$R+6)S9"YV:&0N;W5T`*V7/6_#(!"&]_R* +MD[IEB.",L;M&3>=*E=HUCF-'&?JA)D,&__AR-MA@C).TV`1AP3V\=QR(,-8] +M`#(!68.L0*;4S@3(1\AR`-6I"[8UUY_0E%^?57D^7E;Z:18=C#/;RC4G>TQ` +MJ$DRP((FD7MJ0V,PJX?-87G\.!@<:IR96$@0"*F""&\>R7IU1'I>OSZUR.V@ +M+O'5#5;JMQ/`!'!NC4B,NFVOL<<)9577;8R;2)5_14^Z=D(W5!!8:CJP==^-WH`" +M6Y_D;";FX<4(ZBM(G]I;K)BHPQW->N6^/;`D8)K1=D\EY'AK!-\W;U/K6P;2 +MY8^[H\1KN%XPOP67Z+UK49(!%^KH<$RSV(`3<^HH9ZJ[G$TC)W.9C^SL=09> +M`]\#RZVLMH#]^L*@[]&7@8Z[,_K`=[<@7.:.YQ8.K[@++FXWN[;SZIBOKHR\ +M&/OQSKAQYQ+$W;D=#N,>!-B>+"H#U2B_#G#$M-3$R+6)S9"YV:&1F+F]U=`"ME$UO@S`,AN_\ +M"DN[]8"2D!AZK=:=)TW:K@4*50_=+COLD!^_&`+$?+6;"%$$IQ<\UK&Q:/1 +MX=0]7"]8/H)+R$LR2C+@E@PM3GB6&'!Z39W+A*C^%*S9*G==;;.17UAGD#7( +M,XC,VQ0']O6%0=]^*D.Q<%?TP33',)PF]NBU/;-@+5=!9W`MVNZ;ILL*\Q?UJ@]L#-,HB^]V$"6`-6@(;> +M4PVXAS0+@8J?)%M^?5;E]_4GK##AJ"!U/3_)7R5T6S`%E=-/\$SO@;ZGXV5W +MO5TZ7->JNA]KI*0;!]&3<)&'^W)X>VZ0IT%=,DT2AMDK-`@-4K+`O;H3/\Z$ +HTWVP50V%:61VDWTPPVRK(IP1(Z__UK;%X<9'Q1V^Z!>1V%I#,`<````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu new file mode 100644 index 000000000000..84e2c3e48411 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-bsd.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-1x1-512-bsd.vmdk.gz +M'XL(".?%'50``VEM9RTQ>#$M-3$R+6)S9"YV;61K+F]U=`"MG-UOV\H1Q=_S +M5Q#.2]`'@4?\?@C0IDZ!HB@0W%S<^UKQJS&:Q(%M%`V@/[Y<DNW`,N7.-"E$.2]4D&]W!ROOO;S=?A\-_A[O[F]OM[,-VC.]L\ +M2_+&;4T;F9Y[RD/CEF7B +MOB]O\^Z&[P\NXNB_PN[;M%"[V<7JX]RG/M>ONAM/# +M\.O/'\/[JV^WWT/MW-FZDC5SH'HN5)84F0OE4W/E*UQ$][*93RTY?[UY^'+3 +M?9[2O!^N#F\3ABM=[:8#K/V^EJPGEW+S9*=MGS_^[V'*-^G]R=XPW+R).8GI +MN8MC4E0NUG2`\U$,LGAC)+S[??#+[]/;W%7K,^?_O(+P]63 +MUV0Y;7!RF1):Y50L^1=/7Y;)^?/'Y,HE^>N787X%,ERSO,V<\7(.F)='=^&K +MMH1W32QW#\PGFUR?'D[)A]/]<'A[??TAG.S))9O/MVEK@XM2+J'=ZWLNYU2X +MY:27@YZ/HN_;PZD__7@8[MSQAJ-H78EZGZD[UOSQ&-?/4\TG-;I73')^GUS= +M]-.9NK#_'FZ_,5RWO(RG?;B71#,[9NYB>O7,X0?_#,LKQAV3"S<\W/T\=#^_ +MWGSOIS=:\I[A^J5VTW:6TWP\S.D`IQT^N\&I=E?SJ8;M,=S@=M=?;'`^3U_( +ML*GPM,GYV[R]+\.IG[8VQ6:XT>WN^/P^?*6>/-44/3D_5FV.>^_#9:EO`9EO +M9:L2A>TL3R@-=.@>;N^6C5U)/\Z>_BQ[;3_.+WZD5G\PX!+.>G]E^N3G6:9^ +MN2R*54#W4RR=OO\\?7]ZW%_I]E>*9:5>M2R:5;A_32%^7*9;NG?A22Q;]>ID +MT>^I7NE:VR"6X]/J\5<-R/5V./XN0,M,O7)9%*MP6[4K?.UH6:E7+8MF%6ZK +M=J6O'2U;]>IDT>]*MO*UH^6H7NZ.OTHAW?%K65G[VM$R4Z]<%L4JW%;M&E\[ +M6E;J5!K1\M6O3I9]+N2'7WM:#FJE[O+I79Y+%R5 +M^MK1,E.O7!;%*MQ&[2KV.UI6ZE7+HEF%VZA=Q7Y'RU:].EGTNY)EOZ/EJ%[N +MKI#:%=%P['>TS-0KET6Q"K=5._8[6E;J5IDT>]*EOV. +MEJ-ZN;M2:E=&P['?T3)3KUP6Q2K<5NW8[VA9J5T;-6KDT6_ +M*UGV.UJ.ZN7N^$L0Y'H['/L=+3/URF51K,)MU8[]CI:5>M6R:%;AMFK'?D?+ +M5KTZ6?2[DF6_H^6H7NZ.0`9RO1FN3GWM:)FI5RZ+8A5NHW8U^QTM*_6J9=&L +MPFW4KF:_HV6K7ITL^EW)LM_1+?E>R['>T'-7+W752NRX6KDE] +M[6B9J5CU&Z,AF._HV6F7KDLBE6XK=JQW]&R4J]:%LTJW%;MV.]HV:I7 +M)XM^5[+L=[0C/<*5UJ%RPS]((JV3[W<0?@?E=Q!^ +MARB_._E^!^%W4'X'X7>(\KN3[W<0?@?E=Q!^MR-9W^\@_`[*[R#\#E&D=?+] +M#L+OH/P.PN\0Y7^$WT'Y'83?((\KN6_4[X +M'93?0?C=CF39[X3?0?D=A-\ABK1:]COA=U!^!^%WB/*[EOU.^!V4WT'X':+\ +MKF6_$WX'Y7<0?K(\KN._4[X'93?0?C=CF39[X3?0?D=A-\ABK0Z]COA=U!^!^%W +MB/*[COU.^!V4WT'X':+\KF._$WX'Y7<0?K(\KN>_4[X'93?0?C=CF39[X3?0?D= +MA-\ABK1Z]COA=U!^!^%WB/*[GOU.^!V4WT'X':+\KF>_$WX'Y7<0?K^$WT'Y'83? +M[4B6_4[X'93?0?@=HDBK9[\3?@?E=Q!^ARB_Z]GOA-]!^1V$WR'*[WKV.^%W +M4'X'X7<[DF6_$WX'Y7=!3`>YEG#)\NW##>E2NVI5]$F&^; +MZ!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AO +MF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28 +M;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$ +MF&^;Z!<1YMLF^D6$^;:)?A%AOFVB7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$ +MY]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3G +MVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?; +M-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV +M^D5POFVC7P3GVS;Z17"^;:-?1)AOT_)5^D6$^38M7Z5?1)AOT_)5^D6$^38M +M7Z5?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%A +MOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X1 +M8;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^ +M$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE\$Y]LV^D4,IOI%#*;Z10RF +M^D4,IOI%#*;Z10RF^D4,IOI%#*;Z10RF^D4,IOI%#*;Z10RF^D4,IOI%#*;Z +M10RF^D6,:6JH7\1HJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ +M7\1HJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7SRF:6JH7SQ>?);PSG"7R2[ZP'S> +MW_+IH)=_;S]P_G!8_PD!YP_8+2KW0:=%F=3'O3O\_>-OSR2<'\T27L)=?'CR +MTW!APSL^BSF?/V!7+5/]0.C-!Y9P[WRL=X_A\I=VIW.*?,JW1?VEURFZYJH?GRHGN+JW;J1;K(.U[YX +MMB_O[MWE[CKCP[CX*-:=[UP79/W.7<(=;1M!.7>69?A_^??V`^=/A_6?)6`^ +,!WSS?ZE[ZN&@70`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu new file mode 100644 index 000000000000..70326d339dae --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-1x1-512-ebr.raw.gz +M'XL(".?%'50``VEM9RTQ>#$M-3$R+65B2%QV@I>3P08MQ!\<9((_K.[FX;^YPNV-`*4&I`/@:]:'Q +M$@A,K>QQ@[Z7_IST"0.4%0@)\@HU[@WX\WBOI4/P7/_/XG`+-PGF>W`7X^6< +M="LC;M!SF=CWB!,I=81@OT/!RLRU)^J%GYMG8-0E+;!ZL*$/G/(+L[Y;*`.] +M"U4@G0KWN$$_2W]:H!B`V?Z@0`,L_F-6J)F4!@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu new file mode 100644 index 000000000000..c1f997c4041b --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-512-ebr.vhd.gz +M'XL(".?%'50``VEM9RTQ>#$M-3$R+65BO"0'R\$2"`)V"A-2I.!??+NLFPH8^8# +M0`50"]0`27U="J`]E#L`U6E/[%MN;Z&KWUZ;^NOY>VL_W<;`./.M0G-MCP4( +M]9`2L-(/H4=]#9W#;$\OG\Z>7YX<#BW./5@0"`2I(&+V'&*#.DVZ.K^YZ)$/ +MH[IBKFZT4M^#`":`4N])2O*6XA5?X5/0KMA+U006#2=6#O?AB] +M$06^/N(L$?/X9$3U54F__N#PX;`:&%%H<[O; +MK@-*J2O&%'CK]-7:2I4Z5BVT\8[N?!L>@[Y&`V6IJZ\DV.&Q#M]?WBU-1Q-9 +MO>OC9W#X&VX0S(_!%;:4NI%^9L0[NC%-S*_#B90ZO82;5<[*S+G7["9V_CP# +M4ZND!K:S?1@"A_F%4=]^+@,#=Q/Z8.YNI7%E.)Y[./S%70AQA^3CG:Z,(U>NAH0KU^`P;R'`OK*H#%2CYFV\H[O>AH+G_R[Z>O'*?85]/KMS'K-BJ?3W9#$M-3$R+65B0:F5TD) +M+.ML@@+[_,)-WRZ4(4BX,_H@##V\NG6HKHR<##5< +M&0M7KH'0E6MQ(NY&(-J=15>@'A7>IPW-ZY:>%B@[8+09Q.Y7A`E@#5@!*M-/ +M)>`.TLP'"EI)3?G]594_EU\_PP;'^S]'V(R_2,QJP11$;CZ")]/W]#T=SIO+ +M]>QP;JMR'Y9H)EUIB`S"11KNR_[MN44>;^J2<)+0G[U"`I/`.0F\4W>DY8SM +H/N^"K6HH5"O3-?)"#*-;E<$I-O#Z;VXM#B.7BJZ]U1_9@4$XOP@````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu new file mode 100644 index 000000000000..9ad3787b91bc --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-ebr.vmdk.gz.uu @@ -0,0 +1,82 @@ +# $FreeBSD$ +begin 644 img-1x1-512-ebr.vmdk.gz +M'XL(".C%'50``VEM9RTQ>#$M-3$R+65BO +MH*67(`\+UI)GKVQ73G+T7M;BS'.9FN<%']3:!/=X[< +MB*8KEYOGSX5P==UZ>W07DBX+B;)=NNHS-46+_=+J_OB5;YY;7^'6L&SOI[^59O3C-2\+7V=W]I_]D=].GX>'^X^,'O[ZSV]O%N;PX +M_\O@,BR%U1=WX6ZX=*U+<9FR8LP*N-O9]>&O]S]/I_].#Y_N/[Q_`Y9[=GM; +M%EG9NN4X__SIV!GN1?+L`O<:V?4O?[M[XY_<_/2Q>V`Z%[4L9'GMI0[->[ED +M[OOV6%\]FYXF+K' +MZ8=?/TYO7OWRX7WHG=M;U[)V3=2LC2JRJG"I?&FN?97+Z!Z;==>RZ\_WC^_N +MA[=+F9^F5Z?7&=-=7.^6#6S\NK:JEY!+=&>795^__=_C4F\V^IV]9[IU$6L1 +MRVM7YZRJ7:YE`]>M.&=%Z:Z6?UH6O%12PCEEUP_O3]__M+S%7;/>?O?G[YFN +M6:(6SV6!2\A2T*ZF:JN_>OY89M>WWV:O7)$_O)O6)Y#IVNUMYIRW?V[DT +M;MOI;:/7K1C'_M2-W&+=-+MWT^/#K:?CU +MY_OWX_)&R]XPW;CU;EG.MIM/F[ELX++"SRYPZ=VK=5?#\IAN-GL^LNZO'=3-RY+6W(SW>Q6=_[\.GRGGKW4DCV[/G5MS?O)IRMR#P&% +MA[)=B\)RMA<4`)V&QP\/V\)>"1X7SW^6O12/RYL?J?7O3+BELU[?)7_V\ZS0 +MN%*,:I?0_13+E^\_+=_?/:WOXM9W$<]:HQHQVEVZ?RTI/MZ6>W'OPDX\>XT: +MQ!B/=._BH&T2S_EY]_BK!N0ZGHZ_"]"ST*A2C&J7+M:[RO>.GK5&-6*TNW2Q +MWEU\[^C9:]0@QGBHV-KWCIZS1KD3?Y5"?N#7LDOC>T?/0J-*,:I=NECO6M\[ +M>M8:U8C1[M+%>M?YWM&SUZA!C/%0L;WO'3UGC7(G`@3D.IYN\+VC9Z%1I1C5 +M+EVL=Z/O'3UKC6K$:'?I8KV;?._HV6O4(,9XJ-C9]XZ>LT:Y4RF]*U/IZMSW +MCIZ%1I5B5+MTD=[5Q#MZUAK5B-'NTD5Z5Q/OZ-EKU"#&>*A8XAT]9XURITIZ +M5R73$>_H66A4*4:U2Q?K'?&.GK5&-6*TNW2QWA'OZ-EKU"#&>*A8XAT]9XUR +MIXOT[I),1[RC9Z%1I1C5+EVL=\0[>M8:U8C1[M+%>D>\HV>O48,8XZ%BB7?T +MG#7*G?A+$.0ZGHYX1\]"HTHQJEVZ6.^(=_2L-:H1H]VEB_6.>$?/7J,&,<9# +MQ1+OZ#EKE#N1D(%<1],UN>\=/0N-*L6H=NDBO6N(=_2L-:H1H]VEB_2N(=[1 +ML]>H08SQ4+'$.WK.&N5.K?2N3:8CWM&ST*A2C&J7+M8[XAT]:XUJQ&AWZ6*] +M(][1L]>H08SQ4+'$.WK.&N5._/\3Y#J>CGA'ST*C2C&J7;I8[XAW]*PUJA&C +MW:6+]8YX1\]>HP8QQD/%$N_H.6N4.Y%_A%S'TQ'OZ%EH5"E&M4L7ZQWQCIZU +M1C5BM+MTL=X1[^C9:]0@QGBH6.(=/6>-C>DTK6Y[QT]"XTJQ:AVZ2*] +M:XEW]*PUJA&CW:6+]*XEWM&SUZA!C/%0L<0[>LX:Y4ZC]&Y,IB/>T;/0J%*, +M:ILX:Y4Z3]&Y*IB/>T;/0 +MJ%*,:ILX:Y4ZS]&Y.IB/> +MT;/0J%*,:ILX:E/8:-8@Q'BK6XUWP +MG#7*M4SX.R0IK<[C'82_@_)W$/X.2?ZN\W@'X>^@_!V$OT.2O^L\WD'X.RA_ +M!^'O#A3K\0["WT'Y.PA_AR2EU7F\@_!W4/X.PM\AR=]U'N\@_!V4OX/P=TCR +M=YW'.PA_!^7O(/S=@6(]WD'X.RA_!^'OD*2T.H]W$/X.RM]!^#LD^;O.XQV$ +MOX/R=Q#^#DG^KO-X!^'OH/P=A+\[4*S'.PA_!^7O(/P=DI16G_O>"7\'Y>\@ +M_!V2_%U/O!/^#LK?0?@[)/F[GG@G_!V4OX/P=P>*)=X)?P?E[R#\'9*45D^\ +M$_X.RM]!^#LD^;N>>"?\'92_@_!W2/)W/?%.^#LH?P?A[PX42[P3_@[*WT'X +M.R0IK9YX)_P=E+^#\'=(\G<]\4[X.RA_!^'OD.3O>N*=\'=0_@["WQTHEG@G +M_!V4OX/P=TA26CWQ3O@[*'\'X>^0Y.]ZXIWP=U#^#L+?(^@_!V$ +MOSM0+/%.^#LH?P?A[Y"DM(;<]T[X.RA_!^'OD.3O!N*=\'=0_@["WR')WPW$ +M.^'OH/P=A+\[4"SQ3O@[*'\'X>^0I+0&XIWP=U#^#L+?(^@_!V$ +MOT.2OQN(=\+?0?D["']WH%CBG?!W4/X.PM\A26D-Q#OA[Z#\'82_0Y*_&XAW +MPM]!^3L(?X"7\'Y>\@_!V2_-U(O!/^#LK?0?@[)/F[D7@G_!V4OX/P +M=P>*)=X)?P?E[R#\'9*4UDB\$_X.RM]!^#LD^;N1>"?\'92_@_!W2/)W(_%. +M^#LH?P?A[PX42[P3_@[*WP4Q'>1:TF7;MT\WY5OO@F>A47G^^6/IW9(BSVY6 +M-QGK`['J`\-,8:OJ]R7+](O(LRW +MZ?DB_2+"?)N>+](O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3 +M_2+"?-M$OX@PWS;1+R+,MTWTBPCS;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M +M$_TBPGS;1+^(,-\VT2\BS+=-](L(\VT3_2+"?-M$OX@PWS;1+R+,MTWTBPCS +M;1/](L)\VT2_B##?-M$O(LRW3?2+"/-M$_TBPGS;1+^(,-\VT2^"\VT;_2(F +M4_TB)E/](B93_2(F4_TB)E/](B93_2(F4_TB)E/](B93_2(F4_TB)E/](B93 +M_2(F4_TB)E/](B93_2+F/#?4+V(VU2]B-M4O8C;5+V(VU2]B-M4O8C;5+V(V +MU2]B-M4O8C;5+V(VU2]B-M4O8C;5+V(VU2]B-M4O8C;5+Y[S/#?4+YYO/DMX +M%Q5/=UOLI@\LT?_FA/,<[5X)]Z@L#LO15?YB.38AF?0-\?5]K>E&ZW+GWY:P +MJK*NNTGX3ZYO_33A[;-5;_^.W[A^<]K_">M;/PZSJMW'Q%:7K#D?+?BG;W]\ +M5O"6SNQQV=+=?/3T\W1AP0<^R;HLUX^>%D]],N(WKD^/R79FNO)+J],IS[%B +MC3]ZNBR;9W&ZS^N,8'A2,SQ#EK"_V=/ZVMMEG'?E?F%]-\A2ENY'D'[XJN[B +M#NLBY6;[=/T7]_;+J_OZ=G6#\694S]\9!]^Y+LG^G;NE.]L"P65%EDTZ#$M-3$R+6=P="YR87.*>+8T+K=IG%GSBCWTO[.-."OG7G[JY2UX#:Z!MB)QGS.<8^X\ +M@^;:0=F`.X!5T'3XT#I0*L079.('2*AO"W('I0)=([`_OHACA-V(K^LQ/J/& +MCLAMVD!5S^BUCL"@_D@7YKB"NWH>JV?9JK<;FR6W:0-9O2I6+U\D4C)]JEI2 +M2,+5S-5S:`[Z"/_O\SMMZ/=B?D6@&8%L$8;F#$M-3$R+6=P="YV:&0N;W5T`*V82V^<,!"`[_D5 +M4_66JA0;V[#'1DVDWM+7+8>`@6BE=OM(#E'%CZ_'V(`7FW238;V(E7<^YN7Q +MR'D^7@"J`-6#ZD!)?"X%J!V4%8"9=(/;.W,_8=`_#YU^V#]F[AK.1AC+EU*A +M.,KS`H1Y20F\QI>H%I]A\)CL]>7=^?['G<=QA_,O%@H$!VD@8O4>E4_:(>GJ +MXLL'B[R=M2O6VLU2YML(R`4PMOA'X;6[G72<<,)(];T=)90URDXC^!%,(.YO +MEJUQ,C^26J@9<^K"V!A.;4F=@CL_<[$84\4D1FGNQG4,2H[/)FV\'U;#I,KC +M_:_ZSWUWI!]/I(J:]&.KN2)M+G>IPOV?G08"TWG+7+"4AV-<)%5>Y#T5ROGH +M&B?DTD]P:W[HO1D%2_T4RS=\G@Y&4K\:]3-K*Z\C]_3$<)&%GPG8-*[<(/`X?`I +M.XRPM]GO-TZ_CKF,B(WT1,I['=_*"%3J"7,AQ%'7Y:Y"[TDR[^UB+I +MO7KT7MQ)J%1LZ4Z[6I:]"G$-K?>8;1_-^C#U>WU/3PS76?@9@=QM0V3[&G>% +ME$Q#X8!D&@JW?@DU9&(SF*=&6;F@$%48Q!%6&,015AC$D588!!)6&,015AC$ +M$588Q)%6&$7;""G7".6E#4`!31>JD6QI!A\(WW)X'-]JGS8:H7@P*!LA]50C +MU'=)8_UU9"QA(Z2H&R'E"BG168;RC=!:A^><92C?""U>_(*S#!5OA)Y[EH$X +8PK,,Q!&>92"..%6P;SG[!W#$M-3$R+6=P="YV:&1F+F]U=`"METMOU#`0@._[ +M*P;U5D2P'=O)'EO12MS*Z]9#\["KE6`1$@<.^?%X_"!VU@X4.1E%64W\99X9 +M+R'N`.`,R)"YEA7+;9.>R^'Z8&ET?!G0O!]-V``;`W2XR2@)PV>4`JV]$&I7 +MN<5&6K+>6URS'J2)<'.\:B-E18QK'"ZXJU\&%`*&X0+X)=C';#H$<`G\",P\ +M3X!3$`P$_X.SOHLIMN_N_CT\W'S\C+#'U5U&C5+-0%J01]#SQCI:=O>T<=?A +MC$$8?::SSK9%W-MM]!RN1=R\@\M)&:A +MB/N:X&3ERN.H'B5T$T@%@L*D\6:60*FQS[1);R$,F,G[$3H*;$3@/4U\1.2DK2M'C;*\BT*B_N`LIKJT=O1ZC)ZI%[^B+)2=E13%Z@XM> +M/DAH5*YU#6C2TP&Y!U:S4&@]5>P.Q%7L +M#L15[`[$5>T.!%;L#L15[`[$5>P.Q%7M#@-4I-X01YRMOX5D5GP[%QMN(01US5(2[]]EN:W9GM+RGP +MON.X6>OZ&,C6FK'`Z?M933]/O^+H(8ZZBL@*KFG;<\`Q[U5X,5:TJ6(#X1?NRM3=^]M/[RSR:;4N\YF2#$M-3$R+6=P="YV;61K+F]U=`"M7%V/W,81?/>O +MF,@/#A)DP5J22_)!0.S(!HP@@&(I\4L>LOR*#Y$EY70(8F!_?#CDU%SQ;N=( +M^?I,B=O:[MKI'K+W7%U@EBT_SA6M*PI7]*X\N0QN^J?E<%E^;TS'L>8;ES^_ +M^LO?#_SY[>%P^6(!@X^2$&0*)\;J;P6PM6=Y[=[_T+@7`1R*[CR2D[)9)]:W>^^",7SZ\O]&J;M/36N +MRMVI#:8[E;.=N^HXOY>Y:G(:)\`OW:N;3_]VKX9/W>W-Q[L/87U'O[>3XRY^^?_4R7+G9X>/YEG`^:EK(]-E3'HI[.CG_ +MY_$QKVYX?^<1Q_`35^?W-A2GG#^[\"_*PE6-FY=3>NSC]'8?4IYKU]T.Y[OA +M[2\?AYD1_V +M3&E^&EX=O2'FS +MRZ,K*X\U;>"\%4>7%_[5]$_3@J=,"G@G=_GP_O##C],M[HOUYO77/Q"NGJ(F +MSVF!4\B4T"JGK5-W%GSS[98CZFI0T>Y;1`^^M[+N=4N&6G +MEXV>MZ+OV\.Y/W^\&V[]]L:M:'V)^I"IW];B?AO7GU/-.S7Z*\9=7KH7-_VT +MIQ[V7\.'GPG7+9?QM`Y_231S8.Y?3%?/##^$3UBN&+]-'FZXN_WET/WR[N9] +M/]UH[B7A^J5VTW*6W;S?S&D#IQ5>7>!4NQ?SKL;E$6[PJ^L?+7#>SU#(N*CX +ML>[R\[R\GX9S/RUMPB;7V_OI-?WTD\*XVJQ6A6+8:U8G1[ZG> +MR;>V03S'A]7CKQJ0UVDX_BY`SURC"C'*%5RJ=F6H'3TKC:K%:%9PJ=J=0NWH +MV6I4)T:_*]DJU(Z>HT;Y$W^50K;CU[)3'6I'SURC"C'*%5RJ=DVH'3TKC:K% +M:%9PJ=J=0^WHV6I4)T:_*]DVU(Z>HT;Y$QL$Y'4:K@NUHV>N4848Y0HN5;L^ +MU(Z>E4;58C0KN%3MAE`[>K8:U8G1[TIV#+6CYZA1_E1([8HMN"H+M:-GKE&% +M&.4*+E&[BOV.GI5&U6(T*[A$[2KV.WJV&M6)T>]*EOV.GJ-&^5,IM2LWX=CO +MZ)EK5"%&N8)+U8[]CIZ51M5B-"NX5.W8[^C9:E0G1K\K6?8[>HX:Y4\GJ=UI +M$X[]CIZY1A5BE"NX5.W8[^A9:50M1K."2]6._8Z>K49U8O2[DF6_H^>H4?[$ +M7X(@K]-P['?TS#6J$*-]*EOV.GJ-&^5,CM6LVX=COZ)EK5"%&N8)+U8[]CIZ51M5B-"NX5.W8[^C9 +M:E0G1K\K6?8[>HX:Y4_\_R?(ZS0<^QT]J +M'?L=/5N-ZL3H=R7+?D?/4:/\B?PCY'4:COV.GKE&%6*4*[A4[=COZ%EI5"U& +MLX)+U8[]CIZM1G5B]+N29;^CYZA1_M1)[;HMN"8+M:-GKE&%&.4*+E&[AOV. +MGI5&U6(T*[A$[1KV.WJV&M6)T>]*EOV.GJ-&^5,OM>LWX=COZ)EK5"%&N8)+ +MU8[]CIZ51M5B-"NX5.W8[^C9:E0G1K\K6?8[>HX:Y4^#U&[8A&._HV>N4848 +MY0HN53OV.WI6&E6+T:S@4K5COZ-GJU&=&/VN9-GOZ#EJE#^-4KMQ$X[]CIZY +M1A5BE"NX5.W8[^A9:50M1K."2]6._8Z>K49U8O2[DF6_H^>H49E,SR"ODW#G +M;*E=],PUJA"C7,$E:G<._2YZ5AI5B]&LX!*U.X=^%SU;C>K$Z'^@_!V$O]N1+/N=\'=0 +M_@["WV&3TFK9[X2_@_)W$/X.F_Q=RWXG_!V4OX/P=]CD[UKV.^'OH/P=A+_; +MD2S[G?!W4/X.PM]AD])JV>^$OX/R=Q#^#IO\7]V),M^)_P=E+^#\'?8I+0Z]COA[Z#\'82_PR9_U['? +M"7\'Y>\@_!TV^;N._4[X.RA_!^'O=B3+?B?\'92_@_!WV*2T.O8[X>^@_!V$ +MO\,F?]>QWPE_!^7O(/P=-OF[COU.^#LH?P?A[W8DRWXG_!V4OX/P=]BDM#KV +M.^'OH/P=A+_#)G_7L=\)?P?E[R#\'3;YNX[]3O@[*'\'X>]V),M^)_P=E+^# +M\'?8I+3Z+-1.^#LH?P?A[[#)W_7L=\+?0?D["'^'3?ZN9[\3_@[*WT'XNQW) +MLM\)?P?E[R#\'38IK9[]3O@[*'\'X>^PR=_U['?"WT'Y.PA_ATW^KF>_$_X. +MRM]!^+L=R;+?"7\'Y>\@_!TV*:V>_4[X.RA_!^'OL,G?]>QWPM]!^3L(?X=- +M_JYGOQ/^#LK?0?B['NKFZPU@>.XU[`_'JZ?H]CNLB>7,;GKP^S?C'./):J_SK`!?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2 +M?O)OI*6+1>P^#&,1R+N;][QT?=]^ +M][U[_?4/;SW8/^[3G1_O/':NZ=U0>8CUZO!$NF\?WQW%_'CGJ?K'ZFJR>1+N +MJVLW6S$_WGGLGX"[=J3ABJ>B/O=)X,7\>&>-4O6MJTM7'_WS>_MS$N[="NYD +M?.7-3YYM3Z[J_/.#2[AN?MAS?_*TM*NGVV2Y)X[NV'LE0@5W]$]D/ES>__7P +M?@'[P^$_OP_K6YX\B^M'^HU4]8KC4U>$7]1&NFX-EUM7S_^^TI9FU6O"Q7+M +M2+^1K-YYJ5[B6VU:U+5;=X+CM]IOUG"MX.#V=X=W@XP[O#PYG>'1[0\.[P<(9WAXV%>K=&?.,?G5_\27^/7-&`R_Q#W< +BDU_BXY!.-OP\2-;P2]S#F7Z)%_[IG=D7_P=,%9H/M&4````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu new file mode 100644 index 000000000000..494fe712eb74 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-1x1-512-mbr.raw.gz +M'XL(".G%'50``VEM9RTQ>#$M-3$R+6UBX<\J +M[;[:5Q^:?FX#U@AMFP$5`P77,(X7L#G;3=A00Q#.'YM&(-W-Q<"KL>U4A'L- +MNW*;=\0X);@^W'8;T%IP+@/>>GU4.ATF`.T1C`7[!S6M#?AQN4\"%IPN=7Z" +MHU^X0;!>@SN$7='*^&;,._QX3>3?X\R2.D;@_Z9@;>&[9^K)OCC/@%PE#6#= +M^2@%#OF%4=\IET%)N`OZ(`_7!=PQ7:\C'/T(%U+<$;R*OR<=[AKRKM`C0=L-@)&@K`Z@UK>@7\E`8````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu new file mode 100644 index 000000000000..69446fd3e64d --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-512-mbr.vhd.gz +M'XL(".K%'50``VEM9RTQ>#$M-3$R+6UBH!P_\>!-(0@($BZ:E%";9AW<_LDT9&UX` +ME`&U0`V0U->Y`#I`7@"H07-@?^;F%KKZ[;6IOYZ_]^;5[0889[Y5:*[M,0.A +M'I(#EOHA]*BOH;.8_>GET]GSRY/%H<'9!PL"@2`51,R>0\RITZ2K\YN+'ODP +MJLOFZD8K]:D$,`&<>S,RJ^[!:70XH:S:MC]R*,M>ICV"FV!@=':"DVQBYAIWQ-<0NE\J_H46@GS(4*`I-V`'OWP^B- +M*/#U$6_*K'Q/FMVFU`*77'F`)OK;XZ=3H:#92Y[KZ2H,!C';Z_O%M: +M;DUD]?ZQ637X&\X)YL?@,M-*[4R_,N(#W5@FP[?%B35U>@DWFYR5B6NO*29V +M?IZ!J552`RN\)N,!77YAU'>8R\#`W15],'>WU+@\G,\]'/[B+H2X:C6WZ^I. +MYNKJQ,EHIROCR)6K(>'*'7"8MA%@WUE4!:I9\W-\H+O>A^\!B.:7(]E/$9K> +METRA,,!D"H5MIND49FRUV+96(1F%B?;U%&_W?]G7D]?N$^SKR;;[F!7;M*\G +>T^X3[>O)MOLT^WJ-2[JO)_6/C;'=#W^X!V4,#@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu new file mode 100644 index 000000000000..b9c8a97c9d63 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-1x1-512-mbr.vhdf.gz +M'XL(".K%'50``VEM9RTQ>#$M-3$R+6UB[VJPZ&B\?`^8,FB8`)@IH<)7"J0[*"MDWE#$.6KBZE'$& +MR/NV,6B3\5@G#NXXC`IMWN'B$H.SX3:/`:6$H@B`[U8?QDZ'T$"9@9`@"7*\ +M-^#/_<;/X/`6;A#,[\&E>I33TZV,>4<[EHEY6IQ84J<0K'XH6!FY +M]D0^&>?F&9A:)16PO/>A#QSR"Z.^;2@#O7`7]$$8;J%QF=^?.SB\$2[XN'(Q +MM\OJUJ&Z*G(RY'1EW+ER-<1?N0:'<3<"['8658&J5WB?=[2OB7\:H.B!T6:0 +M^E\1I4`-4`TD=3L30%O((?B6UU?=77?VU/F_/E9'%VJ[(?%J0G72J(",(E/]R7W=MSASR,ZM)PDLB=O5(` +M$\"Y%WBO[N"7,W7[O`VV;J"4G4QKWHOGN+I5:9QDDU'_S:W!4>124;6W^@.> +'9*U,OP@````` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu new file mode 100644 index 000000000000..24643628ba1f --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-mbr.vmdk.gz.uu @@ -0,0 +1,82 @@ +# $FreeBSD$ +begin 644 img-1x1-512-mbr.vmdk.gz +M'XL(".K%'50``VEM9RTQ>#$M-3$R+6UBO +MH*67(`\+UI)?&T<(]SPR>N?[_[ +MQX\G_OG#Z73]:@6#SY(4Y`HGB\WK7$_/_A#N_*6LS1/N<4["%3ZKOTD,<.>= +M)W;A2O?D^7,IW%VW/#WZ&X'+(E"V@:L^4]-NL5_:W1^_"LWS^RO\'MSQ7MJL +M+K)+'Y;9I5K615:?E^?RK'9!LP-\G=W=?_I/=C=]&A[N/SY^"/L[^[-UP>7% +MQU\&C^`*JR_^QC_AX5H/<9FR8LP*^*>SZ\-?[W^>3O^='C[=?WC_!BSW[,^V +M++*R]=OQ\?G38[/P+Y)G%_C7R*Y_^=O=F_#.S4\?NP?"^2RW$??:K@[%O5PR +M_W7[6'8WO7_TB'/X$W?GSS8TIUI>N_0W59G5;;9LI_+89_?T&$I>>C<\3-WC +M],.O'Z[B>^<.L`G[6JMV*9?=DW7;OG[[OT=7;S:&D[TGW+*)I0CW +MVM4YJVJ/Y0YP.8IS5I3^SOV3V["KI(0/RJX?WI^^_\E]B_MFO?WNS]\3KG%9 +M+M)MT*6X@C8U56O]U?.W979]^VWVRA?YP[MI>0<2KEV_S7SP>@Y8EF=_$[JV +MPGL2*_T3R\EF=]UCEWW3?9I.K^_NOHDGV_EBR^7AMC9YE,L*[=_?2SM=X]:3 +M7@]Z.8IQ[$_=V'U\G![\\<:CZ'V+QE"I/];RZ1BWKU,O)S7[=TQV?9.]NA_= +MF7K8?T\??B'II/A^D.T.WPLQMTO7NUG&K<'N$FO[OQ9H/+>89&QDW% +ME\VNORS;>S=UH]N:PR;<['=W_OP^0J>>O91#SZY/75MP/P6X(@\44`0JV[0H +M;F=]02'0:7C\\+!N[)7P??XJP;D?A^.OPLPLM"L4A;5!FZO=U7H'2-KS6IDT6[@]GIW";UC +M9*]9@RS&0\76H7>,G#7+7_BK%/(#OY9=FM`[1A::5[ +M,?2.D;5F-;)H-W![O9M"[QC9:]8@B_%0L7/H'2-GS?*74GI7IN#J//2.D85F +ME;*H-G`[O:O)=XRL-:N11;N!V^E=3;YC9*]9@RS&0\62[Q@Y:Y:_5-*[*@E' +MOF-DH5FE+*H-W%[OR'>,K#6KD46[@=OK'?F.D;UF#;(8#Q5+OF/DK%G^ +M79)PY#M&%II5RJ+:P.WUCGS'R%JS&EFT&[B]WI'O&-EKUB"+\5"QY#M&SIKE +M+_PE"'*_#T>^8V2A6:4LJ@W<7N_(=XRL-:N11;N!V^L=^8Z1O68-LA@/%4N^ +M8^2L6?Y"009ROPO7Y*%WC"PTJY1%M8';Z5U#OF-DK5F-+-H-W$[O&O(=(WO- +M&F0Q'BJ6?,?(6;/\I97>M4DX\ATC"\TJ95%MX/9Z1[YC9*U9C2S:#=Q>[\AW +MC.PU:Y#%>*A8\ATC9\WR%_[_$^1^'XY\Q\A"LTI95!NXO=Z1[QA9:U8CBW8# +MM]<[\ATC>\T:9#$>*I9\Q\A9L_R%^B/D?A^.?,?(0K-*650;N+W>D>\866M6 +M(XMV`[?7._(=(WO-&F0Q'BJ6?,?(6;/\99#>#2FX-@^]8V2A6:4LJ@W<3N]: +M\ATC:\UJ9-%NX'9ZUY+O&-EKUB"+\5"QY#M&SIKE+Z/T;DS"D>\866A6*8MJ +M`[?7._(=(VO-:F31;N#V>D>^8V2O68,LQD/%DN\8.6N6OTS2NRD)1[YC9*%9 +MI2RJ#=Q>[\AWC*PUJY%%NX';ZQWYCI&]9@VR&`\52[YCY*Q9_C)+[^8D'/F. +MD85FE;*H-G![O2/?,;+6K$86[09NKW?D.T;VFC7(8CQ4+/F.D;-FY3(]@]SO +MPG7YVKL866A6*8MJ`[?3NR[P78RL-:N11;N!V^E=%_@N1O::-D?M<%OH/H=U#] +M#J+?'2@V\!U$OX/J=Q#]#DE)JPM\!]'OH/H=1+]#4K_K`M]!]#NH?@?1[Y#4 +M[[K`=Q#]#JK?0?2[`\4&OH/H=U#]#J+?(2EI=8'O(/H=5+^#Z'=(ZG==X#N( +M?@?5[R#Z'9+Z71?X#J+?0?4[B'YWH-C`=Q#]#JK?0?0[)"6M/@^]$_T.JM]! +M]#LD];N>?"?Z'52_@^AW2.IW/?E.]#NH?@?1[PX42[X3_0ZJWT'T.R0EK9Y\ +M)_H=5+^#Z'=(ZG<]^4[T.ZA^!]'OD-3O>O*=Z'=0_0ZBWQTHEGPG^AU4OX/H +M=TA*6CWY3O0[J'X'T>^0U.]Z\IWH=U#]#J+?(:G?]>0[T>^@^AU$OSM0+/E. +M]#NH?@?1[Y"4M'KRG>AW4/T.HM\AJ=_UY#O1[Z#Z'42_0U*_Z\EWHM]!]3N( +M?G>@6/*=Z'=0_0ZBWR$I:0UYZ)WH=U#]#J+?(:G?#>0[T>^@^AU$OT-2OQO( +M=Z+?0?4[B'YWH%CRG>AW4/T.HM\A*6D-Y#O1[Z#Z'42_0U*_&\AWHM]!]3N( +M?H>D?C>0[T2_@^IW$/WN0+'D.]'OH/H=1+]#4M(:R'>BWT'U.XA^AZ1^-Y#O +M1+^#ZG<0_0Y)_6X@WXE^!]7O(/K=@6+)=Z+?0?4[B'Z'I*0UD.]$OX/J=Q#] +M#DG];B#?B7X'U>\@^AV2^MU`OA/]#JK?0?2[`\62[T2_@^IW$/T.24EKS$/O +M1+^#ZG<0_0Y)_6XDWXE^!]7O(/H=DOK=2+X3_0ZJWT'TNP/%DN]$OX/J=Q#] +M#DE):R3?B7X'U>\@^AV2^MU(OA/]#JK?0?0[)/6[D7PG^AU4OX/H=P>*)=^) +M?@?5[R#Z'9*2UDB^$_T.JM]!]#LD];N1?"?Z'52_@^AW2.IW(_E.]#NH?@?1 +M[PX42[X3_0ZJWT'T.R0EK9%\)_H=5+^#Z'=(ZG)%_$7&^ +MS<>+_(N(\VT3_R+B?-O$OX@XWS;Q+R+.MTW\BXCS;1/_(N)\V\2_B#C?-O$O +M(LZW3?R+B/-M$_\BXGS;Q+^(.-\V\2\BSK=-_(N(\VT3_R+B?-O$OX@XWS;Q +M+R+.MTW\BXCS;1/_(N)\V\2_B#C?-O$O(LZW3?R+B/-M$_\BXGS;Q+^(.-\V +M\2\BSK=-_(N(\VT3_R+B?-O$OX@XWS;Q+R+.MTW\B^!\V\:_",ZW;?R+X'S; +MQK\(SK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+X'S;QK\(SK=M_(O@?-O& +MOPC.MVW\B^!\V\:_",ZW;?R+X'S;QK\(SK=M_(O@?-O&OPC.MVW\B^!\V\:_ +M",ZW;?R+X'S;QK\(SK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+X'S;QK\( +MSK=M_(O@?-O&OPC.MVW\B^!\V\:_",ZW;?R+B/-M1K[(OX@XWV;DB_R+B/-M +M1K[(OX@XWV;DB_R+B/-M$_\BXGS;Q+^(.-\V\2\BSK=-_(N(\VT3_R+B?-O$ +MOX@XWS;Q+R+.MTW\BXCS;1/_(N)\V\2_B#C?-O$O(LZW3?R+B/-M$_\BXGS; +MQ+^(.-\V\2\BSK=-_(N(\VT3_R+B?-O$OX@XWS;Q+R+.MTW\BXCS;1/_(N)\ +MV\2_B#C?-O$O(LZW3?R+B/-M$_\BXGS;Q+^(.-\V\2\BSK=-_(O@?-O&OXC) +MU+^(R=2_B,G4OXC)U+^(R=2_B,G4OXC)U+^(R=2_B,G4OXC)U+^(R=2_B,G4 +MOXC)U+^(R=2_B,G4OX@YSPW]BYA-_8N83?V+F$W]BYA-_8N83?V+F$W]BYA- +M_8N83?V+F$W]BYA-_8N83?V+F$W]BYA-_8N83?V+F$W]B^<\SPW]B^>;SQ+> +M9.W#W1:[^@/+97_KIX/>_KW_Q/6;T_:_"(C^MP&Z\Y[G&T`67,*_]UR`>W15 +MN'&/U9DF!X']@K\^"=QHW#_,OPVPJK*NNP'\)_=WMCZ.Y?,UJ]I_[FQUR9KS +MT8)_^O;'9P6O<&;OOQ7NYK.LG\/%#1_X:.RR7#[+6B+UG;'_Q/7I;;)>"5=^ +M:77=?W^YN,#Z,ZOEWQL'O7`^R_QY5_]']#X]&&`7P`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu new file mode 100644 index 000000000000..4145c82b041d --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-1x1-512-pc98.raw.gz +M'XL(".K%'50``VEM9RTQ>#$M-3$R+7!C.3@N> +M8MQV86`^^.X$D.07145-G`V +M+F7>/YP"BP9(@+A"BT<=ON^OC<"8+[#!X1YN-LR/X&J]:C53N44^XV*"P966 +M52XX2KE3"/8]%5;D/2R(K;=N76=@Z@P/P%JKH0N1\"FEYF=0+U&QF, +8<4$^*K<;(%E@MATDU,#B!\3RH'-%!@`` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu new file mode 100644 index 000000000000..01016a55890e --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-1x1-512-pc98.vhd.gz +M'XL(".O%'50``VEM9RTQ>#$M-3$R+7!C.3@N=FAD+F]U=`"METUO@S`,AN_] +M%:YVZZ%*C!/:Z[3N/&G:=BUEM-IA'UI[Z($?OQ@22/A:NP4H"@I^\MIQ3"I$ +M?0#H!/0>=`%:<3LET&M(5P"FTUY8W:5]A#+__"CRT]MY:8]R5L.D\*U"<[;' +M!,@,D@)F/(A^Y3:4#K.\V1P6;^\'AT.+LKL$M9G8NZE0QB9&:NPF=A!2Y;=+&Q:%WF50Y'[^R[V/1T8CJT(]LP01#*=6#E?AB] +M%@6^/BW%1,S')V-47\;ZS-H2VL;TV0 +MTU#7Z+R/'#RF&5/FEC5O<32ECM=<<96S*FZR8+[JV/GS#,+D<`YBY54% +M#]C,+[3ZUGT9&+@[H0_Z[F:,2\/WI8?#7]R%$+>;G-MI=?.^NCSR9+QV5\:% +M*Y-9`M*4^VK<#;6V.II`L,)I"LM4Y +MHD(J)I/MVBS45F&DC3CC(F[$&1=Q(\ZXB!MQQD7#$M-3$R+7!C.3@N=FAD9BYO=70`K96Q;H,P$(;W +M/,5%W3)$^+`/6*.FO;4SP82!)9;"0T>&/__?9YR3I +M+@")D)03S_E`N]ORNUUM5I8FFON`2D$9`E\UT.+0Z"LD5!)T;]2@:8;&`NUV +M=/4XH8,AR(V:#4S@G%T9>?[0&E892`6*(,=;%;[OWR8,8SS#'0ZOX2Z"Q2VX +MU(SROM1J45QP@U7D.0NAAQX +MR2\,^HI0!C*["_H@M%L:7,:_%QX.K]@%CCLNYG99W3I45T5.1CK>&3?N7`/A +M.[?#8=Q"(&UEUBO0U,C@.1]HG[?\[H#2`:/-(+FS@U*@!J@&4J:?2:`"LMP' +M(E]);?7]55<_YU\_PP8G1A7=;V8\IF:W4`98FI_0A^E[^A[VI\WY\]3C^E+5 +M_UB2F72E(3*P2]SNT^[ET2(/@[HTG"3R9^^H3R@)0C#C3MV!+V>R^>W-U@T< +CE979-_;"`I.ERN!4,AKUW]QV.(J\5/2IMOH#34'Y,G`(```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu new file mode 100644 index 000000000000..7f13ae450062 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-pc98.vmdk.gz.uu @@ -0,0 +1,82 @@ +# $FreeBSD$ +begin 644 img-1x1-512-pc98.vmdk.gz +M'XL(".O%'50``VEM9RTQ>#$M-3$R+7!C.3@N=FUD:RYO=70`K5Q=;]S($7SW +MKZ!]+T$>%JSE]X.!Y"('"((`QOER]QI^YH25XNVNG>W9+D*),4R?Q/ZRU)LX?%?#O7?.#R]YM_ +M_'3BUQ].I\NK%0PN2U*0*IPL-L]S.3WZ(MSYN:S-`_/M'(7+7%9WE>CASCL/ +M[,+E\X/GIU*XNW9Y>'`7`I<$H&0#5SQ1TVZQS^WNCZ]\\]S^,K>'^7C+)JFR +MI.S\,BF+99TEU7EY+$VJ.6B:`;]+;FZ__B>Y&;_V=[=?[C_[_9W=V<[!>>GB +MR]XAS(55I;MP#SBXQD&48Y(-20;W<'*Y^^OMK^/IO^/=U]O/G]Z"Y9[=V>99 +MDC=N.RX^?;AM%NY)TJ2$>X[D\I>_W;SUK]ST]*6](YS+FC*^ +MKV_+[L9/]PYQ\E]A=^YL?7.*Y;ES=U'D2=4DRW8*AWV>'QY\R4OO^KNQO1]_ +M_/9E?/OFX^=/H7?N;%W+F@6H7AJ5)47FH'QIKGV%0W0OF^74DLNOM_>_W/8? +MYC*_CF].WR6$*UWOY@.L_;[6JN>4WN&O6A_=__H%P]9PU +M1\X;G%/F@C8U%6O]Q>.797+Y\"YYXXK\\9=Q>042KEG?9BYX/0Z!Y623F_:^3;YOOXZG[VYNO@\GV[IB\^4V;VUT*.4*[5[?2SOGQJTG +MO1[T!'_PSK*\8=DX,;[^^^G?IOO]Y^ +M&N8W6O*6<,/:NWD[ZVD^'.9\@/,.G]S@W+LWRZF&[1%N=+L;KC:XG*=O9-A4 +M>-KD\G'9WB]C.\Q;F[$)-[G=G9_>A^_4HZ>:T9/+0]<6W*\>+DL]!62>RC8M +M"MM9GU`(=.SO/]^M&WLC?)P]_EGV4C[.KWZD5K\3<(6SWE^9/OIYEFE>+HMB +M`^A^BJ7S]Y_F[_PTJY?%<*1[ +MI:.V42*GQ]WCKQJ0ZWTX_B[`R$RSED,AXJM?.\8.6F6N^.O4D@/_%I6UKYWC,PT*Y=%L8';ZUWC>\?(2K-J +M630;N+W>M;YWC.PTJY?%<*C8SO>.D9-FN3L2!.1Z'Z[WO6-DIEFY+(H-W%[O +M!M\[1E::5*)=\QD>\8V6E6+XOA4+'D +M.T9.FN7N*,A`KG?AZM3WCI&99N6R*#9P.[VKR7>,K#2KED6S@=OI74V^8V2G +M6;TLAD/%DN\8.6F6NVND=TT4CGS'R$RSIE,1PJEGS'R$FSW!W__P2YWHED,AXHEWS%RTBQW1_T1[\AWC*PT +MJY9%LX';ZQWYCI&=9O6R&`X52[YCY*19[JZ7WO4QN";UO6-DIEFY+(H-W$[O +M&O(=(RO-JF71;.!V>M>0[QC9:58OB^%0L>0[1DZ:Y>X&Z=T0A2/?,3+3K%P6 +MQ09NKW?D.T96FE7+HMG`[?6.?,?(3K-Z60R'BB7?,7+2+'[TCWS&RTJQ:%LT&;J]WY#M&=IK5RV(X5"SYCI&39KF[27HW1>'( +M=XS,-"N71;&!V^L=^8Z1E6;5LF@V<'N](]\QLM.L7A;#H6+)=XR<-"N5Z1GD +M>A>N3=?>A%L.A8CW? +MAY`L9[O(/H=5+^#Z'>(2EJMYSN(?@?5[R#Z':+Z7>OY#J+?0?4[B'Z' +MJ'[7>KZ#Z'=0_0ZBWQTHUO,=1+^#ZG<0_0Y12:OU?`?1[Z#Z'42_0U2_:SW? +M0?0[J'X'T>\0U>]:SW<0_0ZJWT'TNP/%>KZ#Z'=0_0ZBWR$J:76I[YWH=U#] +M#J+?(:K?=>0[T>^@^AU$OT-4O^O(=Z+?0?4[B'YWH%CRG>AW4/T.HM\A*FEU +MY#O1[Z#Z'42_0U2_Z\AWHM]!]3N(?H>H?M>1[T2_@^IW$/WN0+'D.]'OH/H= +M1+]#5-+JR'>BWT'U.XA^AZA^UY'O1+^#ZG<0_0Y1_:XCWXE^!]7O(/K=@6+) +M=Z+?0?4[B'Z'J*35D>]$OX/J=Q#]#E']KB/?B7X'U>\@^AVB^EU'OA/]#JK? +M0?2[`\62[T2_@^IW$/T.44FK3WWO1+^#ZG<0_0Y1_:XGWXE^!]7O(/H=HOI= +M3[X3_0ZJWT'TNP/%DN]$OX/J=Q#]#E%)JR??B7X'U>\@^AVB^EU/OA/]#JK? +M0?0[1/6[GGPG^AU4OX/H=P>*)=^)?@?5[R#Z':*25D^^$_T.JM]!]#M$];N> +M?"?Z'52_@^AWB.IW/?E.]#NH?@?1[PX42[X3_0ZJWT'T.T0EK9Y\)_H=5+^# +MZ'>(ZG<]^4[T.ZA^!]'O$-7O>O*=Z'=0_0ZBWQTHEGPG^AU4OX/H=XA*6D/J +M>R?Z'52_@^AWB.IW`_E.]#NH?@?1[Q#5[P;RG>AW4/T.HM\=*)9\)_H=5+^# +MZ'>(2EH#^4[T.ZA^!]'O$-7O!O*=Z'=0_0ZBWR&JWPWD.]'OH/H=1+\[4"SY +M3O0[J'X'T>\0E;0&\IWH=U#]#J+?(:K?#>0[T>^@^AU$OT-4OQO(=Z+?0?4[ +MB'YWH%CRG>AW4/T.HM\A*FD-Y#O1[Z#Z'42_0U2_&\AWHM]!]3N(?H>H?C>0 +M[T2_@^IW$/WN0+'D.]'OH/I=,--!K@4N6;\]W)BNO0N1F6:EZ=.WN7&F<):U>\#7.&L]Q?FV]*_A[S?ZE]$F&_S]B+_(L)\F[<7^1<1 +MYMN\O(6S[E]NW+]R*;BHW`?%%F52GX_N\.=W/SU1<&E7\`IW]>'3 +MC^'"A@]\EG6Y?$"Q1KKWU(-HN??`"O?:8[U^@,N?VYW.>8X5:_SAT^7R(<`: +MJ^>\3`GZ!S_#(VX)YYL\[*^YWL9Y4^XS^[OBEG+Y$&#]^%4]Q0W;[92;;.&Z +M9\_V^=V]OMY=;WP85Q]E>_"=ZT"V[]P5[FQ+!/7"S*MYXOKO_0#$M-3$R+79T;V,X+G)A=RYO=70`K9)-#H(P$(7W +MG.+AT@5IAU)E:XP[$Q,O(-AZ`-<]O&V&!`KEQX2A=/-X7^8Q(P07H#1.!%V% +MHPA5":50*B\8>'UZX&Y?:R_/J[H77"YCF/1BTB*6!%>,RF7'#GB.?'(9>(:H +M(2@)9%S=N^I5W%)_C&OVBLNX=BM.^]O`6%@[PKT&N/?.PY"3N!9^X"3#GUP% +MYN.X,L1E\WC"LS@ON'S2'^/ZN#2P4(23J>Y0\!OC3(^3?ZU*GNS.[KHJ\K,5 +L9QJT%D0H]01WT!V.@JORWS>)>UYPCR)^>%54!]QM]Q0%8/8#T8E)O;($```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu new file mode 100644 index 000000000000..e3f9594789d8 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhd.gz.uu @@ -0,0 +1,17 @@ +# $FreeBSD$ +begin 644 img-1x1-512-vtoc8.vhd.gz +M'XL(".S%'50``VEM9RTQ>#$M-3$R+79T;V,X+G9H9"YO=70`K9;);L(P$(;O +M/,5(O7%`WN+`M6JY5:K4%\!)'-1#%P$'#CQ\9Q)G<1('*`[&,G+F\S_CL1G& +MZ@=`2]`E:`LZH7&J0&\@70/@I&NBZKG["9?\Y]OFI\_SRCV710WCK&_EFY.] +MD*!PD12$H45T06.X-)C5T^M^^?FU;W#"X9J%E08E($&(&JVC6:N.2-OGCY<* +MN>O4R;&ZS@J_F0*F@//>&[)1MVLUMCB%5F59M12,J60VS?OA373.#G`)&UCU +M9$X%M>?L%$[/6=V#6R[<7M2I@HF18H^AXY`*&F/:-'$8-4R5\_'7'(YVH$\$ +M4D6W^OAH3H;=%2Y51/.R4Z`HG>?C +MUZ&@KT]S-A/S\&8$]1G2A\<+=Y1N@:0[9U+C1!%R>'NP%D^:?O/C9P*[^^_X +MF;5G=^5TK(%MZ-8)IHO9=%:;QP^;,;'NZ)D(#S>Z7$@=M,>LCRM:W%#C +M%6?9I#H;-56R\E9<82"S("7(9(23B,IA"!-K)"SF8SX][SJYW"2%4?X2)6?82+6/41+F+51[B(51_A(E9] +1A(M:]>DJ]Q9_[Z\6^RH,```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu new file mode 100644 index 000000000000..bb8e69831df8 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-1x1-512-vtoc8.vhdf.gz +M'XL(".S%'50``VEM9RTQ>#$M-3$R+79T;V,X+G9H9&8N;W5T`*V4RVZ#,!!% +M]_F**W67!?)S"-NJS:Y2I?Y`()BHB[92U447_OC:L4FP<1ZJ,(,%&N9XKCT, +M8V$`BE`+D/:F!+2$4I#D'#VZ*4*PZX"C#MG,81=<]@J&W:U +MCL!-$L>O`S=@#9@H`@.N.4Q40U#V7R\<$W0+5)#M'X1 +MZOWS)+^'Y\/Z_>,PXD14-2[L6NJID^8J*96[=7UT_'5'G)QO$DUWKU-@"IPG +MPF-VN[18/$Z=Q)H!G3ZF.5KRDCB*M>=QFF51_R]ECZ.%2\75WNH/`$S(R-T& +"```` +` +end diff --git a/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu new file mode 100644 index 000000000000..2cc570c86059 --- /dev/null +++ b/usr.bin/mkimg/tests/img-1x1-512-vtoc8.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-1x1-512-vtoc8.vmdk.gz +M'XL(".W%'50``VEM9RTQ>#$M-3$R+79T;V,X+G9M9&LN;W5T`*U<76_DQA%\ +M]Z\8G%\."2"PEM\/!R2.;"`(#!@^(WDU/V,A]MU!)P0QL#\^'')J5)3$&\)J +M965R;KMKIWM6):6ZL%FV?3E7]*XH7#&ZLG(9W/)/V\-E^>-B>5P:/G']Q^WW +M_[SAU]N;F^M7&QA\EJ0@4SA9[%[G>O/DBW"7+V7MGE@>ER1<[K/Z9XD![G+P +MQ"%2F%N^O6IT=_(W`N`KD=7/E"38?%?FEW?_HJ-,_O+_=[6(ZW:EV= +MNZH/2U>5ZSIW]65]+G/U$C0O@%^[V[O/_W&WT^?A_N[3P\>POXL_VR6XJ'Q\ +M-7B$I;"Z\C?^"0_7>HAJ?[SY^>`>6>_%G6^2N +M:/UV?'SV^-@M_(MDKH)_#7?]V]]OWX5W;G;SJ;LGG,]:-K*\]E*'XE:5\]_/ +M'^ONI@\/'G$.7W%W_FQ#<\KUM0M_4Q:N;MVZG=)C7Y:GQU#RVKOA?NH>II]^ +M_S2]>_/;QP^Q=_YL?FKN^NO=PR]WP_NE +MS,_3FYNO'>$JW[OE`)NPKZWJ):4Z/-EEV]=O__>PU.O&<+)WA%LWL1:QO'9Y +M<67ML98#7(_BXO+"WRW_M&QXJ:2`#W+7CQ]N?OS7\B/NF_7^A[_^2+AFR5HB +MEPTN*4M!NYK*K?[RZ=O27=]_Z][X(G_Z95K?@81KMQ\S'[R=`];EQ=^$KFWP +MGL0*_\1ZLNZV>^C<-]WGZ>;KV]MOXLEVOMAB?2Q;FSQ*M4'[]_?:SJ5QVTEO +M![T>Q3CV-]W8?7J8[OWQQJ/H?8O&4*D_UN+Q&/>O4Z\G-?MWC+N^R_IX^_$6[8WL;+/OQ;HET37D?H5-/7FI!=]?'KJVXGP-6J;)')^VCW^J0&Y/X;CWP*,S#6KD$6Y@SOJ71EZQ\A:LQI9M#NXH]Y5H7>, +M[#5KD,5XJM@Z](Z1LV;Y"_^40G;BS[*J";UC9*Y9A2S*'=Q1[]K0.T;6FM7( +MHMW!'?6N"[UC9*]9@RS&4\7VH7>,G#7+7T@0D/MCN"'TCI&Y9A6R*'=P1[T; +M0^\866M6(XMV!W?4NRGTCI&]9@VR&$\5.X?>,7+6+'\II'=%"J[.0N\8F6M6 +M(8MR!W?0NYI\Q\A:LQI9M#NX@][5Y#M&]IHUR&(\52SYCI&S9OE+*;TKDW#D +M.T;FFE7(HMS!'?6.?,?(6K,:6;0[N*/>D>\8V6O6((OQ5+'D.T;.FN4OE?2N +M2L*1[QB9:U8ABW('=]0[\ATC:\UJ9-'NX(YZ1[YC9*]9@RS&4\62[Q@Y:Y:_ +M\(\@R/TQ'/F.D;EF%;(H=W!'O2/?,;+6K$86[0[NJ'?D.T;VFC7(8CQ5+/F. +MD;-F^0L%&L0A;E#NZ@=PWYCI&U9C6R:'=P![UKR'>,[#5K +MD,5XJECR'2-GS?*75GK7)N'(=XS,-:N01;F#.^H=^8Z1M68ULFAW<$>](]\Q +MLM>L01;CJ6+)=XR<-0[1LZ:Y2_4'R'WQW#D.T;FFE7(HMS!'?6.?,?(6K,: +M6;0[N*/>D>\8V6O6((OQ5+'D.T;.FN4O@_1N2,&U6>@=(W/-*F11[N`.>M>2 +M[QA9:U8CBW8'=]"[EGS'R%ZS!EF,IXHEWS%RUBQ_&:5W8Q*.?,?(7+,*690[ +MN*/>D>\866M6(XMV!W?4._(=(WO-&F0QGBJ6?,?(6;/\99+>34DX\ATC<\TJ +M9%'NX(YZ1[YC9*U9C2S:'=Q1[\AWC.PU:Y#%>*I8\ATC9\WREUEZ-R?AR'>, +MS#6KD$6Y@SOJ'?F.D;5F-;)H=W!'O2/?,;+7K$$6XZEBR7>,G#4KD^D9Y/X0 +MKLNVWL7(7+,*690[N(/>=8'O8F2M68TLVAW<0>^ZP'L01;CJ6(#W\7( +M6;-\RT2_0U+2Z@+?0?0[J'X'T>^0U.^ZP'<0_0ZJWT'T.R3UNR[P'42_@^IW +M$/WN1+&![R#Z'52_@^AW2$I:7>`[B'X'U>\@^AV2^ET7^`ZBWT'U.XA^AZ1^ +MUP6^@^AW4/T.HM^=*#;P'42_@^IW$/T.24FK"WP'T>^@^AU$OT-2O^L"WT'T +M.ZA^!]'OD-3ONL!W$/T.JM]!]+L3Q0:^@^AW4/T.HM\A*6GU6>B=Z'=0_0ZB +MWR&IW_7D.]'OH/H=1+]#4K_KR7>BWT'U.XA^=Z)8\IWH=U#]#J+?(2EI]>0[ +MT>^@^AU$OT-2O^O)=Z+?0?4[B'Z'I'[7D^]$OX/J=Q#][D2QY#O1[Z#Z'42_ +M0U+2ZLEWHM]!]3N(?H>D?M>3[T2_@^IW$/T.2?VN)]^)?@?5[R#ZW8EBR7>B +MWT'U.XA^AZ2DU9/O1+^#ZG<0_0Y)_:XGWXE^!]7O(/H=DOI=3[X3_0ZJWT'T +MNQ/%DN]$OX/J=Q#]#DE):\A"[T2_@^IW$/T.2?UN(-^)?@?5[R#Z'9+ZW4"^ +M$_T.JM]!]+L3Q9+O1+^#ZG<0_0Y)26L@WXE^!]7O(/H=DOK=0+X3_0ZJWT'T +M.R3UNX%\)_H=5+^#Z'\@^AV2DM9`OA/]#JK?0?0[)/6[@7PG +M^AU4OX/H=TCJ=P/Y3O0[J'X'T>].%$N^$_T.JM]!]#LD):V!?"?Z'52_@^AW +M2.IW`_E.]#NH?@?1[Y#4[P;RG>AW4/T.HM^=*)9\)_H=5+^#Z'=(2EIC%GHG +M^AU4OX/H=TCJ=R/Y3O0[J'X'T>^0U.]&\IWH=U#]#J+?G2B6?"?Z'52_@^AW +M2$I:(_E.]#NH?@?1[Y#4[T;RG>AW4/T.HM\AJ=^-Y#O1[Z#Z'42_.U$L^4[T +M.ZA^!]'OD)2T1O*=Z'=0_0ZBWR&IWXWD.]'OH/H=1+]#4K\;R7>BWT'U.XA^ +M=Z)8\IWH=U#]#J+?(2EIC>0[T>^@^AU$OT-2OQO)=Z+?0?4[B'Z'I'XWDN]$ +MOX/J=Q#][D2QY#O1[Z#Z73330>X%SFW?`6[*MMZ]:"E_X9]B[]R+NYN,_8%8 +M_8%QIK!5]<<`-SCK_<7Y-A^O\B\BSK?Y>)5_$7&^S<>K_(N(\VT^7N5?1)QO +MF_@7$>?;)OY%Q/FVB7\1<;YMXE]$G&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7T2< +M;YOX%Q'GVR;^1<3YMHE_$7&^;>)?1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE]$ +MG&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)? +M1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE\$Y]LV_D5POFWC7P3GVS;^17"^;>-? +M!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3GVS;^17"^;>-?!.?;-OY%<+YMXU\$ +MY]LV_D5POFWC7P3GVS;^17"^;>-?!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3G +MVS;^17"^;>-?!.?;-OY%<+YMXU\$Y]LV_D5POFWC7P3GVS;^17"^;>-?!.?; +M-OY%<+YMXU\$Y]LV_D5POFWC7T2<;S/R5?Y%Q/DV(U_E7T2<;S/R5?Y%Q/DV +M(U_E7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)?1)QOF_@7$>?;)OY%Q/FVB7\1 +M<;YMXE]$G&^;^!<1Y]LF_D7$^;:)?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_ +M$7&^;>)?1)QOF_@7$>?;)OY%Q/FVB7\1<;YMXE]$G&^;^!<1Y]LF_D7$^;:) +M?Q%QOFWB7T2<;YOX%Q'GVR;^1<3YMHE_$7&^;>)?!.?;-OY%3*;^14RF_D5, +MIOY%3*;^14RF_D5,IOY%3*;^14RF_D5,IOY%3*;^14RF_D5,IOY%3*;^14RF +M_D5,IOY%S%EFZ%_$;.I?Q&SJ7\1LZE_$;.I?Q&SJ7\1LZE_$;.I?Q&SJ7\1L +MZE_$;.I?Q&SJ7\1LZE_$;.I?Q&SJ7\1LZE^\9%EFZ%^\//LLX9-PSXO=_('% +MNK^BXF>ZEOZ30LOU4T/STOF//SX`_.Y^FKYY?UM^O]M?8;^_9I>'+P,VZTCS +M^?;:_#>ZQ7/UIN^S@\-+NPH_L$[CQ$:YYEO6E +M8M^^N+O)]*V"^2SY=4SN#]7`6[]6.QM4O_\O\=/7'^XV?]O>ZL4 +4`=#LO5?XSV'-OOH_FA1I)IY=```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu new file mode 100644 index 000000000000..13210f03aded --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-apm.raw.gz +M'XL("/[%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN6#-2, +M^JH4R/L%LWH;`CW.Z2,.S5RJ3R@Y2]]3UWVU$SB1ZW,]KAJKD]OS.P>T@":H +MQW"J+53KRD'=IJN/I]UI=]AO(HXL3C6N6?]'W7?=3:J3F6=+,V>[B$L9@/W9 +M(NJCW+M'YW$H9[P=A$T2D!6((!HK7+J:O8^`RV/;/J]?'CZ6Z]0_HLSZU`S_ +M1.*?_TE2_Y#J4[G]4S?]TQ6TGMC-BW\_OWX1H[[,_G$6_&/UQ'F]8%9E__%` +1"L!L"DDX8/$'F8$ZXZ<%```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu new file mode 100644 index 000000000000..03492316e6ac --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-apm.vhd.gz +M'XL("/_%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD+F]U=`"M5EUOVR`4 +M?<^ON-+>*BT"#-?=T]1JS=ND:M6>6\O!5:2UC9I(ZX-__+A\U#@&U\UP$,'" +M]W`X]P,8H+P',I&_"]MR_0M^^/.OVN'M;^Z=?.3#. +M8JNQ.=F+"J19I`;1T"*XI3'T`6;]Y>;Q8O?T&."$APL+2P0I0!D0.5D'V3L[ +M0MIW/9+BTQ$]R"F.*Y)9B>`F_J_W^CT[`B5+;=7#5 +ME)WJ?,[9I',EVO:N=*LNL+LWV7;<'7SSORLE]$S+'35Q7R5.>>J +J2W`%K[KH2U;6ROTMO>JB+UF%KKH$5_"J2W!%K[IH"^KJ'[J1;&,?#0`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu new file mode 100644 index 000000000000..e1b66268c980 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-apm.vhdf.gz +M'XL("/_%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FAD9BYO=70`K57);L(P +M$+WS%2/UAM3(\3*FIRXJW"JAHIXA(@F*5""B2.TA'U^OX"P@6MF,+$<3/]Z\ +M9T\(L0.`"Q`4B`KB@IGY_-P):*;OB1HD\:,96;#TVJ[+<$EG-*.Q!:0Z+0CP +MO+>/A8!I.]',W[J`%D[SXRE(H@/7@.(F?L]U_5D,P-%8Y5HXUF4W>CMQ"^H` +MV]Z"Y\=CGSUN[$`MO#)"!:<@&'`.-%?$AR@?ERHIDG +M[9\%Y`XP&D-TW1F9N^M:1.9[P"0$I&=[#>!ZORO6Q^HGO,'HNG-9#H?>3YG^ +M%J`$FID6D^MUP.]NNAE7VXV'\]W/_['R^F1QMTILESM3!AO(U9D=ZXN$'?44 +M3U:V"G?L5F9^#(OEIV*+$KBEZ:/UT$IHN*>V&1;.=+_PY?]Z:^$P\E%1'\K1 +)+TV"K"_2!P`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu new file mode 100644 index 000000000000..860e005e645a --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-apm.vmdk.gz.uu @@ -0,0 +1,83 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-apm.vmdk.gz +M'XL("/_%'50``VEM9RTV,W@R-34M-#`Y-BUA<&TN=FUD:RYO=70`K9Q;;^3& +M$87?_2L(^<4(D`'/\/ZP0.S(!H+`P,+K)(\.K[&0]4J0A"0+S(\/F^S3.I3$ +M;<*J]<@SM5-5TUU-E;1?'3!-US])DG=)GB?YD!1EDB*9_VI])&GV9,R/<\TW +M+G^]_O'O)_[YYG2Z?+4F@XN2$*2:3HS-YUQ.S_XPW?E+49LWYLVE2S4[3G/#KY/KFX=_)]?C0W]_>G\R]YEF#=6E>Z%>\.E:UR*,YV+FAOE85C=^>G09)_\GK,Z=K2].L7QV[EX4>5(UR;*/O][T'^9M/HQ7IZ\3IBM=[>8#K/VZUEW/(>7NR<[+OGS_O\=YO\G@3_:& +MZ99%+)N8/[LX)T7EGJ.6KVG!M?$9=?3_WGCS>?AOD;+7G'=,-:NWDY6>H7%=;T?%'A8^?:7:5/2YMS,]WH2K0N +MJO;?&'.N=1U/57!73.$>O@J7SZ=?QW:8EY5]%R+ +M]2C\PCZ?'L;>I\M2?X#3ICCKFI*L3++,KVC;0!]O[Y>EE=F5]N/L^<^RM_;C +M_,6/U.IW)ES36:^O3)_]/,LT+A>CV"1T/\72^>M/\]?[I_65;GVE>%8:58O1 +M;-+]K%&`YMMO*UH^>D4>Z)OTHA/?!K +M65G[VM$STZAC.'09CM?.WI. +M&N6>V"`@K_?3];YV],PT*A>CV*3;J]W@:T?/2J-J,9I-NKW:C;YV].PTJA=C +M.+39R=>.GI-&N:=<:I?'TE6IKQT],XW*Q2@VZ79J5['?T;/2J%J,9I-NIW85 +M^QT].XWJQ1@.;9;]CIZ31KFG0FI71-.QW]$STZADT:YIU)J5T;3L=_1,].H7(QBDVZO=NQW]*PT +MJA:CV:3;JQW['3T[C>K%&`YMEOV.GI-&N2?^$@1YO9^._8Z>F4;E8A2;='NU +M8[^C9Z51M1C-)MU>[=COZ-EI5"_&<&BS['?TG#3*/1'(0%[OIJM37SMZ9AJ5 +MBU%LTNW4KF:_HV>E4;48S2;=3NUJ]CMZ=AK5BS$G8:U8LQ'-HL^QT])XUR3_PG +M%.3U?CKV.WIF&I6+46S2[=6._8Z>E4;58C2;='NU8[^C9Z=1O1C#H;V?COV.GIE&Y6(4FW1[M6._HV>E4;48S2;=7NW8[^C9:50OQG!H +ML^QW])PTRCWU4KL^EJY)?>WHF6E4+D:Q2;=3NX;]CIZ51M5B-)MT.[5KV._H +MV6E4+\9P:+/L=_2<-,H]#5*[(9J._8Z>F4;E8A2;='NU8[^C9Z51M1C-)MU> +M[=COZ-EI5"_&<&BS['?TG#3*/8U2NS&:COV.GIE&Y6(4FW1[M6._HV>E4;48 +MS2;=7NW8[^C9:50OQG!HL^QW])PTRCU-4KLIFH[]CIZ91N5B%)MT>[5COZ-G +MI5&U&,TFW5[MV._HV6E4+\9P:+/L=_2<-"J5Z1GD]6ZZ-EUK%SPSC^$WT'Y'83?(8JT^M373O@= +ME-]!^!VB_*YGOQ-^!^5W$'Z'*+_KV>^$WT'Y'83?'=@L^YWP.RB_@_`[1)%6 +MSWXG_`[*[R#\#E%^U[/?";^#\CL(OT.4W_7L=\+OH/P.PN\.;);]3O@=E-]! +M^!VB2*MGOQ-^!^5W$'Z'*+_KV>^$WT'Y'83?(O8[X7=0?@?A=P7YAO\_$F_2+"?)N/-^D7$>;; +M?+Q)OX@PW^;C3?I%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB +M7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YM +MHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^ +M;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D5POFVC7P3G +MVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?; +M-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV +M^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z +M17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z183Y-CW?I%]$F&_3 +M\TWZ183Y-CW?I%]$F&_3\TWZ183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FV +MB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183Y +MMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$ +M^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI% +M<+YMHU_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1HJE_$:*I?Q&BJ7\1HJE_$:*I? +MQ&BJ7\1HJE_$:*I?Q&BJ7\1HJE_$E*:&^D5,IOI%3*;Z14RF^D5,IOI%3*;Z +M14RF^D5,IOI%3*;Z14RF^D5,IOI%3*;Z14RF^D5,IOI%3*;Z14RF^L5SFJ:& +M^L7SBWL)'TSWJ_?]:[&7TCX_4\NS3?/UI>;KV^Y7Z^[ +MO>KP(B[3A-B^<7G_XVOURY?[]>;+;4W=;4S7^_4>6-^W=W[FZ8O(W^EWNWYGS;KF\IW`Q<76_W+7WCS>/-[>??F&ZY7Z]@[^-Z_'5 +M_=;>O;HZXWLQY_G!L^6_$,X^X?9L$Z[/^MZ?>;X<1\G['1?N+KK%6!^JDT9/TFT?HENCYK[7%>?K%^ +M5994U2O7YE/]'OZ[7HAT%PLF#=('BW@&'^DE:>%"])HVN +M*]P,M9Z,/RYYA7LPNB:@GH'%*EA_K"=67[CE +&;;$%!0`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu new file mode 100644 index 000000000000..9e1039688b42 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vhd.gz.uu @@ -0,0 +1,17 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-bsd.vhd.gz +M'XL("`#&'50``VEM9RTV,W@R-34M-#`Y-BUB5LB`]_)6VQ"<*">WB/ +M.Q`1HGT`5`*J`E6"2JF=25"WD.4`IM,6;.K8?D*M/]Y+_7TX1?:I%RTL%MS* +M-R=[3$":23+`@B91.VI#[3#1S7:_/+SM'0XMSDTL%4B$U$#D8)Y!C?O^ZG4H +MX/I4+&;6?#H8D_H*TF?VEBA&ZNF.>A/Y[QFH"9AFM-U3!3E>NX(OV^>Q^.J) +M=/GC[M!X"><$\]/`QZT8+FG#T5%8\H*.(2F[;SF"NS._=8>3<^HH9\JQCDEG +MT\#)K/.>'8\SQ"7$"8B<934#GN,+G;[;H0STW)W1!T-W"\)E_OB8X?""N^#C +M7NVYS`9W(;RP>NNA.ATX&+O^SKARYQ+$W[DM#L,>!-B<+"8#S:AA/=U1/T;^ +MVP+1'E7!SCYT1U4HA=("@RDTP#*P0BQGD^VW6:BLPD`72<(%O$@2+N!%DG`! +>+Y*$"WB1)%S`BR3A@EXDE?F+(,3B!S97<3I\A^-+5O.X +M?#`B3JSAHL.RGL,=$IP,PCK19#RQJCA(U^_5!.X^/,<>IY:\"YE@;DHP&ZS> +M*G>QMG9@E]89N`,N@=E.)BCP5E_H_=N/W1`DW`7_8!QNB;B"ZO,$)U;"!8I[ +M0QPGRGT)5[)W''M7;5P,.;P9?[RY"*$WM\6);1N!:#I+.(%!:_R>%_BGG,X6 +MJ#K@9AFT7>\S$DP-QH'1^%TH,'LH;`H4]"3YZNO35=_7G[3"B.-M,YA<:"\D +MWA93@"CQ)^8=OQ/_[LZ7W?7C$G&Q5<4?*X-)UP&B1N%:&N[CZ?EAZ)T<)\F2 +M[''T,VU[(7"2O4.*4[=@G6M:(.\7V1#!9*M"G&8#J__6ML69C8]*.'S9+_P) +&SWLP!P`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu new file mode 100644 index 000000000000..3df9b01e40e9 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-bsd.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-bsd.vmdk.gz +M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUBB#F<^\,FCB,'"((`AFW8K^;<8B'V[D(K!%F`/S[3,WU:9T2- +M>V"5S%VREE7%[NIAB?[J@%FV_CA7=*XH7#&XLG(9W/Q/Z\UE^;,QWXKXQ/6? +M]__Z\<2?KTZGZQ=K,O@H"4&FZ<38O,[U].*'ZUN]O=6]Z?EN7]J]YGF#=65_Z!?\*G:WV*:G3YX'+XI]WU\>\/OXZG_XZ/GQX^O'\';O?L +MS[;(7='ZY7C_[/FV,?R+9*Z"?PUW_=L_[M^%*S<[?;P\,IV/FAK6+[S_/00MKS4KG\< +M+T_C#Y\_CN_N?OOP/M;.GZTO6;LD:I9"Y:[,?:JP-5^^TF?TE\UR:N[ZZ\/3 +M+P_]]_,V/XUWIR\=TU6^=O,!-F%=ZZ[GD&KW9.=E7[_YW].\7S>$DWU@NF41 +MRR;FUR[/KJQ]KOD`\[EV>>[RQN5+^GG!\TX*>"=W_?#^]-U/#E7>%.[[;__Z +M'=,U<[K9O;S#NOYX#% +M//L'H6IK>M_$"O_$_&;+9;;O+319ZG6U/[Z +M7LHY%VX]Z?6@EZ,8ANYT&2X?G\9'?[SQ*#I_M0YAI_Y8B^=CW+Y.O9S4Y*\8 +M=WWG[AZ&^4Q]VG^/'WYCNGZ]C.=U^$NB70)S_V"^>I;T8WB%]8KQQ^33C4^/ +MGT_]YU\?W@_S&\V]8[IAK=V\G/DTUT7%-;U<5'S9N79W>%[:G)OI1E^B=5%- +M>&/,N=9U/%M!S+=:C +M"`O[?/HT]B%=GH4#G#;%6=?D+^7Y2EY7M&V@3Q\>EZ55^9WVX_SE[[*W]N/B +MYE=J_0<3KNFLUU=E+WZ?Y1I7B%%N$OK?8MGZ,>#T[?/Z*K^^2CQKC6K$:#?I +M?IY3?+S=;N4OL8MX=AK5BS$[Z?C9P%ZYAI5B%%N +MTNW5K@RUHV>M48T8[2;=7NVJ4#MZ=AK5BS$[6[A-K1L].H7HSAT&:[4#MZ3AKE +M[]@@((_WT_6A=O3,-:H0H]RDVZO=$&I'SUJC&C':3;J]VHVA=O3L-*H78SBT +MV2G4CIZ31OF[0FI7I-+56:@=/7.-*L0H-^EV:E>SW]&SUJA&C':3;J=V-?L= +M/3N-ZL48#FV6_8Z>DT;YNU)J5R;3L=_1,]>H0HQRDVZO=NQW]*PUJA&CW:3; +MJQW['3T[C>K%&`YMEOV.GI-&^;M*:EDX:Y>\:J5V32M=DH7;TS#6J$*/< +MI-NI7<-^1\]:HQHQVDVZG=HU['?T[#2J%V,XM%GV.WI.&N7O6JE=FTS'?D?/ +M7*,*,N8:58A1;M+MU8[]CIZU1C5BM)MT>[5COZ-GIU&]&,.AS;+? +MT7/2*'_72^WZ5+HV"[6C9ZY1A1CE)MU.[5KV.WK6&M6(T6[2[=2N9;^C9Z=1 +MO1C#HG4;T8PZ'-LM_1<](H?S=*[<9D.O8[>N8:58A1;M+MU8[]CIZU1C5BM)MT +M>[5COZ-GIU&]&,.AS;+?T7/2*'\W2>VF9#KV.WKF&E6(46[2[=6._8Z>M48U +M8K2;='NU8[^C9Z=1O1C#H0Q[OI+ME:N^B9:U0A1KE)MU.[ +M2^AWT;/6J$:,=I-NIW:7T.^B9Z=1O1C#H\NH=]!^!V4WT'XW8'-AGX' +MX7=0?@?A=T@BK4OH=Q!^!^5W$'Z')+^[A'X'X7=0?@?A=TCRNTOH=Q!^!^5W +M$'YW8+.AWT'X'93?0?@=DDBKRT+MA-]!^1V$WR')[SKV.^%W4'X'X7=(\KN. +M_4[X'93?0?C=@QWPF_@_(["+\[L%GV.^%W4'X'X7=((JT^"[43?@?E +M=Q!^AR2_Z]GOA-]!^1V$WR')[WKV.^%W4'X'X7<'-LM^)_P.RN\@_`Y)I-6S +MWPF_@_(["+]#DM_U['?"[Z#\#L+OD.1W/?N=\#LHOX/PNP.;9;\3?@?E=Q!^ +MAR32ZMGOA-]!^1V$WR')[WKV.^%W4'X'X7=(\KN>_4[X'93?0?C=@PWPF_@_(["+]#DM\- +M['?"[Z#\#L+O#FR6_4[X'93?0?@=DDAK8+\3?@?E=Q!^AR2_&]COA-]!^1V$ +MWR')[P;V.^%W4'X'X7<'-LM^)_P.RN\@_`Y)I#6PWPF_@_(["+]#DM\-['?" +M[Z#\#L+OD.1W`_N=\#LHOX/PNP.;9;\3?@?E=U%,!WDLZ=SZ)Z0;L[5VKTK* +M7_FG6#OWZNI&8WT@%GU@G"FLN_IC"==TUNN+\VW>WJ1?1)QO\_8F_2+B?)NW +M-^D7$>?;O+U)OX@XWS;1+R+.MTWTBXCS;1/](N)\VT2_B#C?-M$O(LZW3?2+ +MB/-M$_TBXGS;1+^(.-\VT2\BSK=-](N(\VT3_2+B?-M$OX@XWS;1+R+.MTWT +MBXCS;1/](N)\VT2_B#C?-M$O(LZW3?2+B/-M$_TBXGS;1+^(.-\VT2\BSK=- +M](N(\VT3_2+B?-M$OX@XWS;1+R+.MTWTBXCS;1/](N)\VT2_",ZW;?2+X'S; +M1K\(SK=M](O@?-M&OPC.MVWTB^!\VT:_",ZW;?2+X'S;1K\(SK=M](O@?-M& +MOPC.MVWTB^!\VT:_",ZW;?2+X'S;1K\(SK=M](O@?-M&OPC.MVWTB^!\VT:_ +M",ZW;?2+X'S;1K\(SK=M](O@?-M&OPC.MVWTB^!\VT:_",ZW;?2+X'S;1K\( +MSK=M](O@?-M&OPC.MVWTB^!\VT:_",ZW;?2+X'S;1K^(.-^FYYOTBXCS;7J^ +M2;^(.-^FYYOTBXCS;7J^2;^(.-\VT2\BSK=-](N(\VT3_2+B?-M$OX@XWS;1 +M+R+.MTWTBXCS;1/](N)\VT2_B#C?-M$O(LZW3?2+B/-M$_TBXGS;1+^(.-\V +MT2\BSK=-](N(\VT3_2+B?-M$OX@XWS;1+R+.MTWTBXCS;1/](N)\VT2_B#C? +M-M$O(LZW3?2+B/-M$_TBXGS;1+^(.-\VT2\BSK=-](N(\VT3_2+B?-M$OPC. +MMVWTBQA-]8L83?6+&$WUBQA-]8L83?6+&$WUBQA-]8L83?6+&$WUBQA-]8L8 +M3?6+&$WUBQA-]8L83?6+&$WUBYBRS%"_B,E4OXC)5+^(R52_B,E4OXC)5+^( +MR52_B,E4OXC)5+^(R52_B,E4OXC)5+^(R52_B,E4OXC)5+^(R52_>,ZRS%"_ +M>+[Y+N&#Z6XWN^H#BV5]Z[>#WOZ]_\3UZ]/VOYAP^8+=LO9?=%I6KCD?7>%/ +MW_SXRH:+L]F&UW0W7Y[\,EWD7=->NK](.M_@)_'/SW;Q2KH_G^2; +MHHOE"W9W5Z=SBF.;-?[RY&+Y$EOUU7/V'<:#'WZ>?_'>B.?KGM?7WB[CO-GN +M[ZS/W6[7-U']^E`]C\V[=6>[;IO.-U$]S\T1)JKWU>WJ>N/#N/DJUH/O7)]D +G^\Y=TYUM&T&U=)9U^'_[]_X3UV]/V__6A,62\(O_`X=39,35MA'R;P%9+"+__24B%\`\`9'I+=PLV&=0#-<07.&S[TN1Y!;-.[HGN-K/&5>NJ<.7$%W,L.BL3ILL!CN_ +M1^,,L@-9@#"337'@)[[PU7<*92CF[HH^"-VU#E?Q\Y+@U(:[P'%CH2+Q9"'< +M>+TZ5-V`Y`9.]H*M\ ++0F1O]"SVO.4&```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu new file mode 100644 index 000000000000..c00d3897a737 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-ebr.vhd.gz +M'XL("`'&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FAD+F]U=`"ME\%NG#`0 +MAN_[%"/UE@,R@VW(92-%3<^1HK1G+X$HAS91MX<<>/AXL+W8@-EL,\`BK\;S +M^1_/V,A"N`M`5Z![T!UH1>U:@KZ&N@&P1O_@^"[]7QC:US]=^^_EO?#7L'.P +M4L1>J3OY8P72#E(#&AI$/U$;AH`IOMT]7[W\?@XX]+@PL-0@$92%R,4XC3BI +M(]*/VX?OZCZJ$<5JRN*FQ@GK9?M3X^&7HXRPY/\20PQ+E&G +MQ,PKDKDVJ5&P:SB]Y74)[FKG<^%*Q19&;=\"=`DU4MN639B'Q6-+Y?WX9OX> +MNYD^S)2*CI(QM\E\N.A+!4-GKT"2P*UP8:0K]VQ*J;E7? +MN&SW,>Z).]S^,J!28,P"^!CTML,/A.5P0'._V*>XFPE6N^B9*M#DE=1>W(]S>_0). +M;JFC/:%;,V2#5=*5=O9=7"4H>W2H8-_?,$8FS,XCPJ#$=;!YWMQ +M$.(>`/,F^[*@V\R>;K5>]33Z<3>P;9-`AVO,+K/`]%H,$].+-L`U%`J=U&]G +MARK$'7.;V]X'%`+J.@*^>OU8YG"4VHHY`U(GQF5!M]_@YH&J3QA1`A<@)"AV +MJX;OA[=$?!6AN0QV.'8-YQ5V&93"[0)[U.'Y).^,) +MHE."16-%WF11IN%]89R!:J`%$#7(&`:.\85)OVVL!D/F7M`/8G-KBROQ>AK@ +MV!5S`>/Z0A7$$X7PBO>J6+LF'(M!)]%P6 +M=,\;W!R0#\!L'E3#W28+D"U(#5+8>9PO5?['7%JG"P/AD;D*F_NT?WF< +M:U?$3E+(>W2Z.$?#D?=V(8Z/QFK=ET`Z=?2!!,E297&"S';]-[8.)S.GBKEW +*5W]/U6F<$`D````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu new file mode 100644 index 000000000000..92bef3108c99 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-ebr.vmdk.gz.uu @@ -0,0 +1,84 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-ebr.vmdk.gz +M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUE8G(N=FUD:RYO=70`K5S1;N3& +M$7SW5PSDMSPL6,LEN7PX.W'.`8(@@!$[]FO(Y3`68M\==$*0`_3QX9!3HR)% +M'FFK=:L#^]A=V]U#M735!679].'3D]?3&`(41*"3.'$F+W/TVGQ0;CSYZ)F-X;7>1[L*%P+D$Y&9PQ4I-F\5^+KL_?!&;%_++0P[#\9:U +MJW)7MM%T93':N:O.X[W,58-3/P!^Z=[>?_R/>^L_WA[N/SR^C_F=P]D.SIW@#`45I7A(MP(<'6`*+W+.Y_#-H__A +MTP?_YN[7]^]2[\+9AI;5(]!U;%3NBCQ`Q=)"^XJ`&!Z;\=3;)#VD_?_N]QJ-=U\63O"3Y;G+KRX?X8>$ATHN"$[NZ?V[TS]^`X)#B%#0;.:BJG^8OE8NJ?OOW5WH<@??O;C$TBX>OHR"\[3.6`TS^$B=FV" +M#T/L$FZ,)^O>-H^-^Z;YZ$]?OGW[33K9)A1[&5]#:CZ@E!-T>+['=@Z-FTYZ +M.NCQ*+JN/35=\^'1/X3C34?1AJ>UBY6&8[T\'^/\?:KQI/KPQ+BG-^[NOAO. +M-,#^V[__E7"WZ3$>\@B/1#T&YN%B>'I&>!_?87IBPC$%./_X\.ET^_3+_;MN +M^$)S;PC73;T;TAE.7QW(5\ +M>!7A%;OP].GTLV^Z(2UW=RZ*NW04_?(HM$6++DP'/?1B.HJ8V*?31W^+<'D6 +M#["?-6?**3S*PY,\930?H(_O'\;4ROQ.YW&^_%[VVGE\>?$MM?J=@!.<=7YE +MMO?]C*]\!N@$+'O.KPSY7<2ST*A2C&H&-_PT'8:Y<7H#\%=8HOX`PKD>FPJC5QO)#BWZ%T1>T?/0J-*,:H9 +MW%;ORM@[>M8:U8C1KF:W++:*O:-GIU%>C/X0W#7VCC^`0:['WM'(L[6?\I:] +MJV/OZ%EH5"E&-8/;ZET3>T?/6J,:,=K5[);%MK%W].PTRHO1'X*[Q=YQK$"N +MQ][1R/7&9N^ZV#MZ%AI5BE'-X+9ZYV/OZ%EK5"-&NYK=LM@^]HZ>G49Y,?HC +M<%46>W>1WO%Z[!V-7&]L]:[BO*-GH5&E&-4,;J-W%><=/6N-:L1H5[-;%LMY +M1\].H[P8_2$XSKM">L?KL74?/6J,:,=K5 +M[);%\7KL'8U<;VSVCO..GH5&E6)4,[BMWG'>T;/6 +MJ$:,=C6[9;&<=_3L-,J+T1^"X[SCCTZ0Z[%W-'*]L=D[SCMZ%AI5BE'-X+9Z +MQWE'SUJC&C':U>R6Q7+>T;/3*"]&?P3NFL7>7:5WO!Y[1R/7&UN]NW+>T;/0 +MJ%*,:@:WT;LKYQT]:XUJQ&A7LUL6RWE'STZCO!C](3C.NUIZQ^NQ=S1RO;'9 +M.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7LEL5RWM&STR@O1G\(CO..__&"7(^] +MHY'KC<=[1L]"H4HQJ!K?5.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^D-PG'=D +M+2'78^]HY'ICLW><=_0L-*H4HYK!;?6.\XZ>M48U8K2KV2V+Y;RC9Z=17HS^ +M"%R=Q=[=I'>\'GM'(]<;6[VK.>_H66A4*48U@]OH7A8:58I1S>"V>L=Y1\]:HQHQ +MVM7LEL5RWM&STR@O1G\(CO/.2^]X/?:.1JXW-GO'>4?/0J-*,:H9W%;O.._H +M66M4(T:[FMVR6,X[>G8:Y<7H#\%QWO72.UZ/O:.1ZXW-WG'>T;/0J%*,:@:W +MU3O..WK6&M6(T:YFMRR6\XZ>G49Y,?HC<$TV]2[MW"#7H7?)R/7&5N^:..^2 +M9Z%1I1C5#&ZC=TV<=\FSUJA&C'8UNV6Q<=XESTZCO!C](;@X[R#\'92_@_!W +MV.7OFCCO(/P=E+^#\'?8Y>^:..\@_!V4OX/P=RO9+8N-\P["WT'Y.PA_=P`N +MSCL(?P?E[R#\'7;YNR;..PA_!^7O(/P==OF[)LX["'\'Y>\@_-U*=LMBX[R# +M\'=0_@["WQV`B_,.PM]!^3L(?X==_JZ)\P["WT'Y.PA_AUW^KHGS#L+?0?D[ +M"'^WDMVRV#CO(/P=E+^#\'?[<&T6>R?\'92_@_!WV.7O6LX[X>^@_!V$O\,N +M?]=RW@E_!^7O(/S=2G;+8CGOA+^#\G<0_NX`'.>=\'=0_@["WV&7OVLY[X2_ +M@_)W$/X.N_Q=RWDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^' +M7?ZNY;P3_@[*WT'X.^SR=RWGG?!W4/X.PM^M9+^PR]^UG'?"WT'Y.PA_MY+=LEC..^'OH/P= +MA+_;A[MEL7?"WT'Y.PA_AUW^[L9Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_MY+= +MLEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_AUW^[L9Y)_P= +ME+^#\']NG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?" +MWT'Y.PA_AUW^[L9Y)_P=E+^#\'_ZSCOA+^#\G<0_FXENV6QG'?"WT'Y.PA_=P". +M\T[X.RA_!^'OL,O?=9QWPM]!^3L(?X==_J[CO!/^#LK?0?B[E>R6Q7+>"7\' +MY>\@_-T!.,X[X>^@_!V$O\,N?]=QW@E_!^7O(/P==OF[CO-.^#LH?P?A[U:R +M6Q;+>2?\'92_@_!W!^`X[X2_@_)W$/X.N_Q=QWDG_!V4OX/P=]CE[SK..^'O +MH/P=A+];R6Y9+.>=\'=0_@["W^W#^6SJ79+@0:Y'&2.-7&\\C4T;/MWPF;EG +MN#CO5A5]*_^4>N?6LWNAQ3\&][+826Z(46Z8-A%3N;\/<((SED/B&KN^#WA$ +M#HFT+N?K57)(I'4Y7Z^20R*MR_EZE1P2:5UN(H=$6I>;R"&1UN4F;R"&1UN4F;R"&1UN4F;R"&1 +MUN4F;R"&1UN4F; +MR"&1UN4F$-Y5#PIO*(>%-Y9#P +MIG)(>%,Y)+RI'!+>5`X);RJ'A#>50\*;RB'A3>60\*9R2/199BB'1&\JAT1O +M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J +MAT1O*H=$;RJ'/&=99BB'/&>F7S7^ +M[V+Z5;(O_]Z^\?3-:?Z'@-?Q<2ZJ\%MQB])=ST=[I..%6O\F[:OV741I^<< +MODT$]H[_*3O/`=/YNN?\ZI=IG&?E?B8_][+<\"U2?]>LGL=LJFZ4Z^9PXZ"2 +M\YP=X4[WOGJ9WU52W;V`262JW42MW2JMW:@3]FC-2=#U\?A@2(C1KIP$)(Q_UR]_#C +M(F4X`*,AJ\@U'>B?Q?+L=W>[@:;JVX#^]ZF$%5!X8,`U/B@U/>,3SAQ.?9BAFO/6=K7-O+Z7US<VLL(>^M^[#3@KEUG%/"MSJ#-T%:HV@7M< +MX7+FG6G&1 +M2+VH9?I)M7^I;M +I.KTU^C>&>/QE.,8A3KCM(>YN;99QB!..=8@;_W]*RMT?5F[7A(@+```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu new file mode 100644 index 000000000000..0dfa2d8094ba --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vhd.gz.uu @@ -0,0 +1,22 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-gpt.vhd.gz +M'XL("`+&'50``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FAD+F]U=`"MF#MOW#`, +M@/?[%2RZI:ACR9+L6UHT:`)T2U];A_@A!QEZ?5R&#/[Q%67Y(5MRX81W@LZ& +MS,\D15$\I6G_`5`9J!:4!B7Q.A>@CI`7`&;0-6Y[YFZAJW^==/WX\)2X3W?H +M82R=2_GB*,\S$.8E.?`27Z(:O(9NP"2OK^\O'G[>#SCN<,.+A0+!01J(6+U' +MI:-V2+JY^OK1(N\F[;*U=I-4_].VD+6S)[)!NSO;OY\;*XR4>1Y;#JF$5$S- +MN_$&)F,7OI/I0FJF9LBI,V-#.+4EM0=W<7!ST8>*"8S<],9U#'*.UR9L!C^L +MF@F5I_/O\N]9+_3CD5!1HWYL-9;%S>4N5/CPL--`8#AOF0N6\KC$!4+E1=Y3 +MOMPPN\8))G#<#;?F^]Z;4##73[%TP^?QR8CJ5Z)^9FVE9:"/#W17B?\=@56U +M#SAXT,>-!EVRGNMW??,);C]\^8:P'Y.Y-89+PZ&HH3Y"6RVT +M6Z^T[=Q2\S[Z>!LT-HOB+L,X7&QMLX$+M3A.;$FYK6R'L3+UI8JY5*:ARJ`M +MH6PBN'<+''5>UCA<*[<(7`[O0Y +M.?6PM\F?-TX_S5Q$A%I\(.8];?-R$3,WGQ)VQ%SP<=1Y61?H/4GFO:,+EE"+ +M#T2]5_;>"SL)O1=:NN.NEB2O?%Q%ZSUF=PVS/DS^7O?Q@>XV\;\]D+MMB&Q? +MXRZ1DFDH')!,0^'6+Z&&3&].YMY95FY2B#(,X@@S#.((,PSB2#,,`@DS#.(( +M,PSB"#,,XD@SC*(MA)0KA+("-,,_+I4?-?&2IBN2N+82BY=-&(12> +M#,I"2/VO$&IUS-B1LS"6L!!2U(60]\S367P9T]\<05D#B@`$W."?E>(TQ +M8.ULE/E58;$S09=SCR/+1DF$&^-5*RL[8AP)N*-<>QE0*>BZ,^"W8WS>O"/N^R.7,.4<.[0##'FR_BH[] +MO]R`)Q`W;N!R5L;)K56AABX1JVBZJHU7"0.]`-M!-Q9P +M;UZA8U,NI#A1.WLM9D]5R]Y^+I:_DD8?9RK>MP<];(JQ37U\T>\U/#]8=[?Y\?RX[I@:1[`,H96"U"9>U0L3L0 +M5[$[$%>Q.Q!7M3L06+$[$%>Q.Q!7L3L05[4['-#0>D,<<5A[H@7#H!'0IU53 +M'L=32WZ'P&X2N89OC?Z-(9Y_&*;B$$?]F]F6#Z25X;KN<#"U*Y%.KR) +M'O$\BN_J[NGZ^297IW+O;[]\\,C');K,:TJOLN?B +M%#81/D?WZ(_O8K'R)-98<,JI7"SYD3BRA8PX7RKQQ2]]M@%7NU3<7X/=/VC0 +&,#.S#0`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu new file mode 100644 index 000000000000..829240355e69 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-gpt.vmdk.gz.uu @@ -0,0 +1,88 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-gpt.vmdk.gz +M'XL("`/&'50``VEM9RTV,W@R-34M-#`Y-BUG<'0N=FUD:RYO=70`K5Q=C]S& +M$7SWKYB<'QPDR(*U_%H^*(B=LP,C"*#(3O*2ARR_XD-L23D=C`C8'Q\..357 +MO+LY4KX^\;3;VN[:Z9YEFXWCB +M"Y<_7__E[P?^_/IPN'RV@,%'20@RA1-C]3Z7PX,?PAV?BUJ],!W'3;C<1[6/ +M`@/<,?%"$JZ87CP^%<+5G>>7>_]$X%P$7^S5, +MVULUKLY=U0;35>5LYZX^SJ]EKIZO+][%]9W]'L[ +M.1>5]Z\ZCS`E5E?^B7_!PS4>HAIN\I#\6M +M*N=_'Q_SZH:W=QYQ##]Q=7YO0W'*^;T+_Z0L7-VX>3FEQSY.+_UP +MOAN^__A^>'7UT[NWL79^;WW)FAGH-!'SQWA*E^[:0-/85U+UE-(E=S9:=F7K_]W-^7K^K"S-X2;%S$G +M,;UW>71E[;&F#9RWXNCRPC^;_FE:\)1)`>_D+N_>'M[\8SK%?;&^>_WE&\*= +MIJC)6[K]V53_+['X;Y$TBX9CG-O/.R#YC-HW\2 +MJK;`^R96^!?FG777Y[NS^^K\83A\?GW]5=S9LT^VF(]I:8-'J19H__F>RSD5 +M;MGI9:/GK>C[]G#NS^_OAEN_O7$K6E^B/F3JM[6XW\;U^]3S3HW^$^,NK]S5 +M33_MJ8?]]_#N)\)UR\=X6H?_2#1S8.Z?3)^>&7X([[!\8OPV>;CA[O;CH?OX +MX\W;?CK1W"O"]4OMIN7D65A47-/#1<6WG6IWE=TO;<(FW.!+M"SJ%$Z,"6M9 +MQWT5_">F]$>HPN7CX8?AW$_+/+JGU+P1< +MX*S75V4/KF>YQA5BE"M`?Q7+IM\_3+^O[]=7^?55XEEKU$F,9@7WKPGB_>-T +M*_\1.XMGJU&=&/V>ZE6^M0WB.3ZL'K]J0)ZGX?A=@)ZY1A5BE"NX5.W*4#MZ +MUAIU$J-9P:5J5X7:T;/5J$Z,?E>R=:@=/4>-\@_\*H5LQ]>RZA1J1\]R;:@=/4>-\@]L$)#G:;@N +MU(Z>N4858I0KN%3M^E`[>M8:=1*C6<&E:C>$VM&SU:A.C'Y7LF.H'3U'C?(/ +MA=2NV(*KLU`[>N8:58A1KN`2M:O9[^A9:]1)C&8%EZA=S7Y'SU:C.C'Z7M8:=1*C6<&E:L=^1\]6 +MHSHQ^EW)LM_1<]0H_\`O09#G:3CV.WKF&E6(4:[@4K5COZ-GK5$G,9H57*IV +M['?T;#6J$Z/?E2S['3U'C?(/)&0@SY-PIRS4CIZY1A5BE"NX1.U.['?TK#7J +M)$:S@DO4[L1^1\]6HSHQ^EW)LM_1<]0H_]!([9I-./8[>N8:58A1KN!2M6._ +MHV>M42-\@_\+Q3D>1J._8Z>N4858I0K +MN%3MV._H66O428QF!9>J'?L=/5N-ZL3H=R7+?D?/4:/\`_E'R/,T'/L=/7.- +M*L0H5W"IVK'?T;/6J),8S0HN53OV.WJV&M6)T>]*EOV.GJ-&^8=.:M=MP359 +MJ!T]QW]*PUZB1&LX)+U*YAOZ-GJU&=&/VN9-GOZ#EJE'_H +MI7;])AS['3USC2K$*%=PJ=JQW]&SUJB3&,T*+E4[]CMZMAK5B='O2I;]CIZC +M1OF'06HW;,*QW]$SUZA"C'(%EZH=^QT]:XTZB=&LX%*U8[^C9ZM1G1C]KF39 +M[^@Y:I1_&*5VXR8<^QT]K8:U8G1 +M[TJ6_8Z>HT9E,CV#/$_"G;.E=M$SUZA"C'(%EZC=.?2[Z%EKU$F,9@67J-TY +M]+OHV6I4)T:_*]G0[Z+GJ%&^9,+?89/2.H=^!^'OH/P=A+_#)G]W#OT.PM]! +M^3L(?X=-_NX<^AV$OX/R=Q#^;D>RH=]!^#LH?P?A[[!):9U#OX/P=U#^#L+? +M89._.X=^!^'OH/P=A+_#)G]W#OT.PM]!^3L(?[\@ +M_-V.9-GOA+^#\G<0_@Z;E%;+?B?\'92_@_!WV.3O6O8[X>^@_!V$O\,F?]>R +MWPE_!^7O(/S=CF39[X2_@_)W$/X.FY16RWXG_!V4OX/P=]CD[UKV.^'OH/P= +MA+_#)G_7LM\)?P?E[R#\W8YDV>^$OX/R=Q#^#IN45LM^)_P=E+^#\'?8Y.]: +M]COA[Z#\'82_PR9_U[+?"7\'Y>\@_-V.9-GOA+^#\G<0_@Z;E%:7A=H)?P?E +M[R#\'3;YNX[]3O@[*'\'X>^PR=]U['?"WT'Y.PA_MR-9]COA[Z#\'82_PR:E +MU;'?"7\'Y>\@_!TV^;N._4[X.RA_!^'OL,G?=>QWPM]!^3L(?[^@ +M_!V$O\,FI=6QWPE_!^7O(/P=-OF[COU.^#LH?P?A[[#)WW7L=\+?0?D["'^W +M(UGV.^'OH/P=A+_#)J75L=\)?P?E[R#\'3;YNX[]3O@[*'\'X>^PR=]U['?" +MWT'Y.PA_MR-9]COA[Z#\'82_PR:EU6>A=L+?0?D["'^'3?ZN9[\3_@[*WT'X +M.VSR=SW[G?!W4/X.PM_M2);]3O@[*'\'X>^P26GU['?"WT'Y.PA_ATW^KF>_ +M$_X.RM]!^#ML\G<]^YWP=U#^#L+?[4B6_4[X.RA_!^'OL$EI]>QWPM]!^3L( +M?X=-_JYGOQ/^#LK?0?@[;/)W/?N=\'=0_@["W^U(EOU.^#LH?P?A[[!):?7L +M=\+?0?D["'^'3?ZN9[\3_@[*WT'X.VSR=SW[G?!W4/X.PM_M2);]3O@[*'\7 +MQ720YP+GEM\`-V1+[9Z4E#_Q3[%V[LG5#=;ZP''<"Y@_G:[?XY@NLF>7\>GK +MPZQ?C#./I>J_#'"!,ZX?XOQ=RG0?]ZGZ2L3Y.X\7Z2L1Y^\\7J2O1)R_\WB1 +MOA)Q_FZBKT2?O)OI*Q/F[ +MB;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2O#NL_$1#MIP%RA6LX)ES`GQN+ +MUFL8W#B&8U'.W6<8[V+]1,*_/@A<;UR__?N['&7ISN='@'_C^N;]+4I_/^:B +MF6_.RSOSED6$FW,O.UW?U]]\ZUY_^>9[#_;/^W3GVSMWN2?;BMJCK%>'=+I_ +M>O/X["CFVSM/U3_63R:;)^&^>.ID*^;;.X_],W!/'6FXXKFH3[T3>#'?WEFC +M5'WK\L&UN1O/[MPGX'[_`*XR_N3-=YYM*U=W_O[!)5PWW^RYKSPM[4[3:;*< +M$T=W[+T2H88[^CLR'RYO_WIXNX#][O#?WX;U+7>>Q=-'^H54]8KY+N^G5+IU +MHF&OV[S`Y=;5\]]7VM*L>DWXL#QUI%](5N^\5"]Q59NJ]]2I.\'QJO:K-5QK +M6[UROFHLPI/'?Z=?N+P^K/\L@$4`-%MAX6\I:'=V>#C#L\/#&9X='L[T[/"` +MAF>'AS,\.SR)&MX$?=PIA?QPM^],_OL +)_ZT-&`6T90`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu new file mode 100644 index 000000000000..7daee291631c --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-mbr.raw.gz +M'XL("`/&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N<."$AHZ))*E6Z_I>W,Y9*GR,/7Q*0Q)1^-!!B$9/CI;VR0DAI`I4&Z +MA7G=,=Q$W(?B5(PT]7<,:"7T?0(4""19\VO'@C$U5`;, +M&:S^5N'SY_&AD'`J5\"$TWNX23!5T!+NRG`E5=],4>P4KSN^9KB&QH2KMM3A +M34PIW;:U)U;>9DJ,^7\>7+]9#XY1).Y_T(+N//@A6(N])Y +9W3'\BK@3L`K`;#?H?SXIBQ>7_'@>Y08````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu new file mode 100644 index 000000000000..7b3c619133af --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-mbr.vhd.gz +M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD+F]U=`"METUOXR`0 +MAN_Y%2/MK0<+CP'32RI5FSU7JMJ>L6M'/>RVVNPA!__X,@9L\%>:+;9C$<$\ +MO,,,8\&8O0!D`;(%V8`4U"XYR%LH%8#I=`_V[]S]A:Y^_]/4_][.F;NZG87E +M++2*S"^!FDA)0TR3RE=K0>4SVXW"\>?M]]#AT.#\QE\`1A('PV3R*#>J( +M].O^\>=473%7-UK9>=H6BC88483JLNPNQ'%C9<;3(Z'EO4S_1'^BCA`7J1-L +M8A7(7%K4P-DEG-RRN@9WLW.QL*EB$J,T;P8RAQ*I;=+&K\/L,:ER/GWHOZ=F +MH@]74D4&P9CV\75WT:4*^L%.`2>!6^Y"3SE-<0NI\JW5D[$==PVS"$SX#NS= +MCU=O1$&H3^9L8\W7@[&J3Y,^L[>87GBO=W3W67P/P*JZ#JB851CC!H>K>G!8 +MB]$CNU?=^M4Y%,UB0/IMNP_6KWI-'-^JO0XH!&@]`SYY??6FC.OU*94XOJI/ +M&%%2.1<2%'Y5X6'_*KU2#OZO^BF-EW!><%CM8]Q=@"ML]HV4H#A%>1>V +M`]S>_CR.;ZFCFM`L=:PZ*Q(GBU83NS#.D#>0%\"4Z\,8.,071GVWZ[ZT=&(;RP>ONYNCIQ,*KISOCBSB5(O',M#M,6 +M`MU7%I.!9M3\O=[1/63Q;8'H/D7)OFWHBFDRA=P!DRDTP":Q0IWV^R&=PD0' +J!<(E/"@0+N%!@7`)#PJ$2WA0(%S"@P+ADAX4I#D",K;[!%1JM8A=#@`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu new file mode 100644 index 000000000000..8cbe4047435a --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-mbr.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-mbr.vhdf.gz +M'XL("`3&'50``VEM9RTV,W@R-34M-#`Y-BUM8G(N=FAD9BYO=70`K96[;L,@ +M%(;W/,61NF6PN)LLB10UG2M5;6?7P5&&MDN'#G[X@O&%8WQ)*NQC"POX_)\+ +M0(B_``0#4DR\YSOJ8X;O>K/=-#3Z<1]0$ZBJ")A9H,>5%F<'6"MDV[#&*W#" +M[6.MI,!-V_8&==97 +MF\3YU4W!R!R$!*E`LUL5OI_>1@H]CJ9RV./8&JX3["MH"G<(<-Q7WT"AP:RP +M[L)V@-O[I\.))74V$L1,=;XJ`J4`:4=.U<@-I!KD,@PY54 +ME]]?IORY_H89=CC:'T6QN?F,N]6B3D]?3&`(41*"3.'$F+W/TVGQ0;CSYZ)F-X;7>1[L*%P+D$Y&9PQ4I-F\5^+KL_?!&;%_++0P[#\9:U +MJW)7MM%T93':N:O.X[W,58-3/P!^Z=[>?_R/>^L_WA[N/SR^C_F=P]D.SIW@#`45I7A(MP(<'6`*+W+.Y_#-H__A +MTP?_YN[7]^]2[\+9AI;5(]!U;%3NBCQ`Q=)"^XJ`&!Z;\=3;)#VD_?_N]QJ-=U\63O"3Y;G+KRX?X8>$ATHN"$[NZ?V[TS]^`X)#B%#0;.:BJG^8OE8NJ?OOW5WH<@??O;C$TBX>OHR"\[3.6`TS^$B=FV" +M#T/L$FZ,)^O>-H^-^Z;YZ$]?OGW[33K9)A1[&5]#:CZ@E!-T>+['=@Z-FTYZ +M.NCQ*+JN/35=\^'1/X3C34?1AJ>UBY6&8[T\'^/\?:KQI/KPQ+BG-^[NOAO. +M-,#^V[__E7"WZ3$>\@B/1#T&YN%B>'I&>!_?87IBPC$%./_X\.ET^_3+_;MN +M^$)S;PC73;T;TAE.7QW(5\ +M>!7A%;OP].GTLV^Z(2UW=RZ*NW04_?(HM$6++DP'/?1B.HJ8V*?31W^+<'D6 +M#["?-6?**3S*PY,\930?H(_O'\;4ROQ.YW&^_%[VVGE\>?$MM?J=@!.<=7YE +MMO?]C*]\!N@$+'O.KPSY7<2ST*A2C&H&-_PT'8:Y<7H#\%=8HOX`PKD>FPJC5QO)#BWZ%T1>T?/0J-*,:H9 +MW%;ORM@[>M8:U8C1KF:W++:*O:-GIU%>C/X0W#7VCC^`0:['WM'(L[6?\I:] +MJV/OZ%EH5"E&-8/;ZET3>T?/6J,:,=K5[);%MK%W].PTRHO1'X*[Q=YQK$"N +MQ][1R/7&9N^ZV#MZ%AI5BE'-X+9ZYV/OZ%EK5"-&NYK=LM@^]HZ>G49Y,?HC +M<%46>W>1WO%Z[!V-7&]L]:[BO*-GH5&E&-4,;J-W%><=/6N-:L1H5[-;%LMY +M1\].H[P8_2$XSKM">L?KL74?/6J,:,=K5 +M[);%\7KL'8U<;VSVCO..GH5&E6)4,[BMWG'>T;/6 +MJ$:,=C6[9;&<=_3L-,J+T1^"X[SCCTZ0Z[%W-'*]L=D[SCMZ%AI5BE'-X+9Z +MQWE'SUJC&C':U>R6Q7+>T;/3*"]&?P3NFL7>7:5WO!Y[1R/7&UN]NW+>T;/0 +MJ%*,:@:WT;LKYQT]:XUJQ&A7LUL6RWE'STZCO!C](3C.NUIZQ^NQ=S1RO;'9 +M.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7LEL5RWM&STR@O1G\(CO..__&"7(^] +MHY'KC<=[1L]"H4HQJ!K?5.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^D-PG'=D +M+2'78^]HY'ICLW><=_0L-*H4HYK!;?6.\XZ>M48U8K2KV2V+Y;RC9Z=17HS^ +M"%R=Q=[=I'>\'GM'(]<;6[VK.>_H66A4*48U@]OH7A8:58I1S>"V>L=Y1\]:HQHQ +MVM7LEL5RWM&STR@O1G\(CO/.2^]X/?:.1JXW-GO'>4?/0J-*,:H9W%;O.._H +M66M4(T:[FMVR6,X[>G8:Y<7H#\%QWO72.UZ/O:.1ZXW-WG'>T;/0J%*,:@:W +MU3O..WK6&M6(T:YFMRR6\XZ>G49Y,?HC<$TV]2[MW"#7H7?)R/7&5N^:..^2 +M9Z%1I1C5#&ZC=TV<=\FSUJA&C'8UNV6Q<=XESTZCO!C](;@X[R#\'92_@_!W +MV.7OFCCO(/P=E+^#\'?8Y>^:..\@_!V4OX/P=RO9+8N-\P["WT'Y.PA_=P`N +MSCL(?P?E[R#\'7;YNR;..PA_!^7O(/P==OF[)LX["'\'Y>\@_-U*=LMBX[R# +M\'=0_@["WQV`B_,.PM]!^3L(?X==_JZ)\P["WT'Y.PA_AUW^KHGS#L+?0?D[ +M"'^WDMVRV#CO(/P=E+^#\'?[<&T6>R?\'92_@_!WV.7O6LX[X>^@_!V$O\,N +M?]=RW@E_!^7O(/S=2G;+8CGOA+^#\G<0_NX`'.>=\'=0_@["WV&7OVLY[X2_ +M@_)W$/X.N_Q=RWDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^' +M7?ZNY;P3_@[*WT'X.^SR=RWGG?!W4/X.PM^M9+^PR]^UG'?"WT'Y.PA_MY+=LEC..^'OH/P= +MA+_;A[MEL7?"WT'Y.PA_AUW^[L9Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_MY+= +MLEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?"WT'Y.PA_AUW^[L9Y)_P= +ME+^#\']NG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>]NG'?" +MWT'Y.PA_AUW^[L9Y)_P=E+^#\'_ZSCOA+^#\G<0_FXENV6QG'?"WT'Y.PA_=P". +M\T[X.RA_!^'OL,O?=9QWPM]!^3L(?X==_J[CO!/^#LK?0?B[E>R6Q7+>"7\' +MY>\@_-T!.,X[X>^@_!V$O\,N?]=QW@E_!^7O(/P==OF[CO-.^#LH?P?A[U:R +M6Q;+>2?\'92_@_!W!^`X[X2_@_)W$/X.N_Q=QWDG_!V4OX/P=]CE[SK..^'O +MH/P=A+];R6Y9+.>=\'=0_@["W^W#^6SJ79+@0:Y'&2.-7&\\C4T;/MWPF;EG +MN#CO5A5]*_^4>N?6LWNAQ3\&][+826Z(46Z8-A%3N;\/<((SED/B&KN^#WA$ +M#HFT+N?K57)(I'4Y7Z^20R*MR_EZE1P2:5UN(H=$6I>;R"&1UN4F;R"&1UN4F;R"&1UN4F;R"&1 +MUN4F;R"&1UN4F; +MR"&1UN4F$-Y5#PIO*(>%-Y9#P +MIG)(>%,Y)+RI'!+>5`X);RJ'A#>50\*;RB'A3>60\*9R2/199BB'1&\JAT1O +M*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\J +MAT1O*H=$;RJ'/&=99BB'/&>F/KF +M-/^3`-'^-L#A0>C[%X`L^(+P*`\.PZLIXL7PRGLI^`:7^]6"OPY_?742N,ZX +M?^A_&V!1N*9Y`?A/YG?^;!J_/;_*&Y_O=7Q@BBK\FMVB=-?ST0Q_^O;'1883 +MG)E^=H+;_?I(+&B_!?>UP.73T_>,HK\)7)\[O1:XKZ9/PET^EYTNJ(X5:_RK +MNZ_9=1&GYQR^[P0ZD/_+.\\!T_FZY_SJEVF<9^5^)C_WLMSP/5=_>:V>QVQ, +M;Y3KYG!A4.EYSHYPIWM?O;]]X^NXT_S,!7B*@6039%_\'RJ'TQAO8``` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu new file mode 100644 index 000000000000..78699409562f --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-pc98.raw.gz +M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G)A=RYO=70`K93-CH0@ +M#,?O/D7/>S"EPHH7)YED[W.9W;-K]"E\^`7!E8KXD0!(,(5?_FVAB*X!2`+L +M=N:T87J6O$_%1S'3Q'@/J!1T,?!M@#..K+Y&0B_!K#8#QG$=S#"5F[;@A#'& +M('\J:=C!>7=EYO@1'@JYK[`>,BO4LT)5@U2@/D'3584_7]\[*=&8+24.1V>X +M17`UIG"/`%>Y:[921'"J%U`-_B= +M&ZOK,R=#;%_&Q9=K(?SE.ASE+03-7%G,#;15/)K3ANE5\NZ`T@.S1=!6/L3B +)#]P1(I+G!@`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu new file mode 100644 index 000000000000..858287753cad --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-pc98.vhd.gz +M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9"YO=70`K9=-;^,@ +M$(;O^14C[:T'"X\!DTLK5=N>*U7MGHG7KGKH;M7LH0?_^#(&DL%?2;;$#L(" +M'M[Y`(00_@>@*]`=Z!:THGHM06^A-@"N,;PXE&7XA+[Y^Z=M_KU^%N'7;SRL +M%'Q4.IS&8P7235(#6II$_Z8Z]!%3_+A[N7I]>XDX#+@XL=0@$92#R,D\1AS4 +M$>G^]O'G6%TU57<?I.J@ZUJ/BZHKBAN.D&^7ZTZNADX/,^"8?20/')>J4 +M&(UB,N>\I]-Q,E2<$X2*#3B8 +MGWKOB`*N3Y=BQ>?+P5C49TF?6UO"SI3+#?UMD3X'X*Z[#*@4V"GP*1K=;J:!:R[[_CVV;V']I5(9AWDW`COL+"X#:1>?E,L-_4.1 +M/AZ(X3#*=KIA.#VR*90!F$VA#.='1H6V64VV2[-0!X69K@J$RWA5(%S&JP+A +?,EX5")?QJD"XC%<%PF6]*FAW"11B\P51KS:'7PX````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu new file mode 100644 index 000000000000..bfbd1f1b6745 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-pc98.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-pc98.vhdf.gz +M'XL("`7&'50``VEM9RTV,W@R-34M-#`Y-BUP8SDX+G9H9&8N;W5T`*V5/6^# +M,!"&]_R*D[IEB/R-61(I:CI7JMK.E)HH0]NE0P=^?'T8@@]#DE;&!AD=?GCO +MSCXS%BX`)8!5,\]E0[O?T-:NUJN.QIN_`;6&*@4^>V"'$ZBO5%`K\*-)AZ89 +M.S&TF\DUX+@WIJ!^UJ)A!M>[JS+'3["+0OZNL'"9%=I.H2Y`:=`&K+A5X>OA +M928EEF5+2<"):[A!L&R6<+L()\,R&RD\FE5SD*Y_B<<1;AON`:F,@1Q]X(^2-VM$%?0[WF$$U?< +M!8I[0UR43Y+"*]';INKJS,G@TYUQX\Y%"-VY`2?R%H*RJRQ^!6(53Y[+AO9Q +M0UL`JAZ8+8*V/]V,!-.`<6`TC@L%IH3"QD!!5U);?WVZ^OOT$V<8<7QRYL0= +MYPN)N\44("K\B7G'<:3O[G!=<=GSCI/H[6*<.COK7%<"^=C)"S',EBK$:3:9]=_W;Y3=6&39/IR+FM.)7W\ZG6Y?3&#P41*"1.'$F#W/[;3X(MSY"]QY>#4#X!?NK>/'__CWG8?KT^/'Y[?A_S._FP'YZSP +M_L75(PR%E86_\#<\7.4ABLZEK4OA;[O;TU\??^E._^V>/CZ^?_<&+/?LSS9+ +M75;Y=+Q_\O*8&?Y)$E?`/X>[_>5O;]^$5VYR^E`_$7&='*/?1YNMZ'DL7?7IZY^[G[X +M]*%[\_#K^W>Q=_YL?@R-BIU>>JA0FF^?;E']"^;\=3<[9?'YY\?K]\/ +M97[L'DY?.L(5OG?#`5Y"7E/50TBQ>;)#VK=O_O<\U.O:<+*/A!N3&(L8GCL_ +MN[ST6,,!ID/OTM2E%Y>.\$/"0R49O).[O7]W^NXGAR*]9.[[;__\'>$N`]S@ +M.20XA`P%S6K*I_KSY9=Y[.`:-Y]A>A:Q.\ +M'V*9OS&>K'M;/]?NZ_IC=_KR[=NOX\G6OMAL?`RI=1ZEF*#]ZWMLY]"XZ:2G +M@QZ/HFV;4]W6'YZ[)W^\\2@:_VIM0Z7^6+.78YP_3SF>5.]?,>[VQCT\ML.9 +M>MA_=^]_)=QU>AD/>?B71#4&IOYB>/6,\%UXAND5XX_)PW7/3Y].UT^_/+YK +MAS>:>T.X=NK=D,YPFE-2,:=E4O%IA]X]X"6U`9MPG6_1E-0EO#$&K"F/ERZD +MPR/WC]"%VZ?3SUW=#FFYAW.>/\2CZ)='H2U:=&$ZZ*$7TU&$Q#Z=/G;7`)7@E3QG-!^CS^Z9W<_4LO?"3C!6>=7 +M)'L_S_A(9X!.P)*7_`J?7R:>N4858I0SN.&WB=.WP_>_AN\/`N=?8A?QK#2J +M%J,YTKW"_[RXBF>K49T8_2&X++2(OZ!`KL>FTDCU1H1SB][EH7?TS#6J$*.< +MP6WUK@B]HV>E4;48S6IVRV++T#MZMAK5B=$?@KN$WO$7,,CUV#L::;+V6]ZR +M=U7H'3USC2K$*&=P6[VK0^_H66E4+4:SFMVRV";TCIZM1G5B](?@KJ%W'"N0 +MZ[%W-%*]L=F[-O2.GKE&%6*4,[BMWG6A=_2L-*H6HUG-;EEL'WI'SU:C.C'Z +M(W!E$GJ72>]X/?:.1JHWMGI7H0HQR!K?1NY+SCIZ51M5B-*O9+8OE +MO*-GJU&=&/TA.,Z[7'K'Z[%W-%*]L=D[SCMZYAI5B%'.X+9ZQWE'STJC:C&: +MU>R6Q7+>T;/5J$Z,_A`/UV#L:J=[8[!WG'3USC2K$*&=P6[WCO*-G +MI5&U&,UJ=LMB.>_HV6I4)T9_"([SCK\Z0:['WM%(]<9F[SCOZ)EK5"%&.8/; +MZAWG'3TKC:K%:%:S6Q;+>4?/5J,Z,?HC<)/UV#L:J=[8ZMV%\XZ> +MN4858I0SN(W>73COZ%EI5"U&LYK=LEC..WJV&M6)T1^"X[RKI'>\'GM'(]4; +MF[WCO*-GKE&%&.4,;JMWG'?TK#2J%J-9S6Y9+.<=/5N-ZL3H#\%QWO$_7I#K +ML74?/2J-J,9K5[);%<=/7.-*L0H9W!;O>.\HV>E4;48S6IVRV(Y[^C9:E0G +M1G\$KDI"[Z[2.UZ/O:.1ZHVMWE6<=_3,-:H0HYS!;?2NXKRC9Z51M1C-:G;+ +M8CGOZ-EJ5"=&?PB.\ZZ5WO&:K';L77L'M^P=YQT]#WVCD:J-S9[QWE'SURC"C'* +M&=Q6[SCOZ%EI5"U&LYK=LEC..WJV&M6)T1^!JY.I=W'G!KGVO8M&JC>V>E>' +M>1<]_J\.\@_!W4/X.PM]AE[^KP[R#\'=0_@["WZUDMRPV +MS#L(?P?E[R#\W0&X,.\@_!V4OX/P=]CE[^HP[R#\'92_@_!WV.7OZC#O(/P= +ME+^#\'^PR]\UG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^# +M\'?8Y>\:SCOA[Z#\'82_PRY_UW#>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`< +MYYWP=U#^#L+?89>_:SCOA+^#\G<0_@Z[_%W#>2?\'92_@_!W*]DMB^6\$_X. +MRM]!^+M]N&L2>B?\'92_@_!WV.7OKIQWPM]!^3L(?X==_N[*>2?\'92_@_!W +M*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X==_N[*>2?\'92_@_!WV.7OKIQW +MPM]!^3L(?[>2W;)8SCOA[Z#\'82_.P#'>2?\'92_@_!WV.7OKIQWPM]!^3L( +M?X==_N[*>2?\'92_@_!W*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X==_N[* +M>2?\'92_@_!WV.7OKIQWPM]!^3L(?[>2W;)8SCOA[Z#\'82_VX=KD]`[X>^@ +M_!V$O\,N?]=RW@E_!^7O(/P==OF[EO-.^#LH?P?A[U:R6Q;+>2?\'92_@_!W +M!^`X[X2_@_)W$/X.N_Q=RWDG_!V4OX/P=]CE[UK..^'OH/P=A+];R6Y9+.>= +M\'=0_@["WQV`X[P3_@[*WT'X.^SR=RWGG?!W4/X.PM]AE[]K.>^$OX/R=Q#^ +M;B6[9;&<=\+?0?D["']W`([S3O@[*'\'X>^PR]^UG'?"WT'Y.PA_AUW^KN6\ +M$_X.RM]!^+N5[);%;R"$1 +MU^4F;R"$1U^4F;R"$1U^4F;R"$1U^4F_[U] +MX_;U:?XG`J+_;8!Y[NI[P'^&@K/QTX2KS%VSM;KZ_N6Q5_`$9RS7S#+C_A7) +M9Q/Y[1F6G7&&ES'#O/0?M)L7[G(^FN%/W_RXR'"",SN2"6[W'1)YT'X+[H\" +METXOLQ<4_2SP*US*::S7`O?5]$VX['/9Z8KJ6+'&']Y]22Z+.#UG_Y/'$X+\ +M?]YY#AC/U[WD5]VG<9Z5^YG\W'VY_J>N?GRMGL=L4&^4Z^9P_J>NGN?L"'>Z +M]]5]=E?CP\#RG7'PG>M!YN_<">YL.PBJ<;),NH_[O[=OW+X]S?],@%D`-.M@ +/YC^:)/GB_P?]NZ=Q8``` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu new file mode 100644 index 000000000000..941ae5b49fac --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-vtoc8.raw.gz +M'XL("`;&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YR87T`AIYC_-%\-8 +M"$#6:#CJZG(E1R4@)00'A']I^);DPAU/QAS^OKGX*:_AB@`C7YSWCZK%@BN3 +M<,7'"%03':T#%5@+QK/`@&NCJGV*6YLOX+J][`99XJ)=GJ@XHCXS';+3Z3NN'R#%5+5J +M]BN',[NN"MFM.-VA]WM"L,,RCJ\.\>JJ-%I=@97OZC)YN>!^R^D)P'X$[C4A +.-4K5C!5GC7NA2P,%```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu new file mode 100644 index 000000000000..7c4a413cb062 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-vtoc8.vhd.gz +M'XL("`;&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&0N;W5T`*V6S6[; +M,`S'[WD*`KOU8,B4+-NG`NO6VX`!>X')MEP4P]:AW:&'//Q(6XXE?ZU9F0B. +M#(D__2E1#)4:/P!6@^W!>K`%]TL#MH:R`J#!T'!XYN$5SNW3+]_^>7S-PN=\ +M&F&YBJU2<[9'#886*0$=+V([[L-YPF0?/C_]!]]$,':O+LML89\B*YG.ST(\RIY:\)`,Q +M+E%7J(55I'1K4R-GMW#VR.H:W,TIG,48*A08)3T5V!Q*Y#Z%S;0/JT:A\OKR +MVSV_^(4^W`D5>]&7K\;:?758KZV +M&@$T];K-_;M_]IXN+NHOB3ZW$RS_?1RN2NS^<=DJ4#4GL=WCZ(:]Z*HYRA.N@\>+_`?8]PK?!A-"MW_1#_:DB_5[O;3.[J>?)XKRBS[^"B +MO'R[Q+7)58L;PFR_H0XVU7477-."T:G5H;-W6S@O&BI-_U9=A^BM7;N.Y/W#^FJ7?$6B"0C&7"2BKT`:@F$)+ +M1:2HPK*K4?24JZ!0J&YFG&#=S#C!NIEQ@G4SXP3K9L8)ULV,$ZV;"4BQ=_H+ +(%O'FLVP-```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu new file mode 100644 index 000000000000..d5ecd33a2377 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-4096-vtoc8.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-63x255-4096-vtoc8.vhdf.gz +M'XL("`?&'50``VEM9RTV,W@R-34M-#`Y-BUV=&]C."YV:&1F+F]U=`"ME+UN +MPR`4A?<\Q9&Z98C,C[$]1>I/MDJ5^@*U#409VDI5APY^^&*P8R#832-CA(C@ +M?)Q++C?+7`.X0$$A\KYSBIR!#%M=7 +M/I.]R=[KJ:FEYI`"M.X/$;*?>_[NGH[;T_MQQ-$AJO%@4Z//I3E^$F48[L$4 +MYM@=BR_)5[DW:'PR'3X:__;V/HZ?@S4%2#?6YMB#'\%"*OLL+L\BUO5C`)550B)<-1L/DZCS?/_@"N^E+5Y@5_55FXVK\HPT5A +MA*MV7MB%TS"[:R4X75_X!LHI?$)P;Q-0L8$[7>EIM]DOG>Y/7\7A^9>K.IS! +MW][F7+1UT0PQ+)K3$M=%6RVOE47KDV8/^+JXO?OT[^+6?1KO[SX^?(CGJ\*] +M]BEO!R\7C_W=VO[N8_[O[3W8?W;P3M +M5N'>:EWH.1PGY)=/UR8(7Z0L&@E?HWC\YF^W;^*36]Y\[.\!%ZK\0?S7]GTP +M;M,4X>/R6D[GWC\$Q#G^2:<+]S8.Y[1\;0V?G+1HS\5RG%/`KOS+4VQYF=UX +M[_H']]/GC^[-J]\^O$^S"_HV%H8WRD@AL=FN6O%XZ]W +M#[_]\FY_":,#M_`[MXKK5K7]+LWEE_[,=O__O@^RVF>&?O`+<< +M8FG"?^U359S:@%7[\?DJ?Q]KWVP5_LH?V'>B$I**QP_O;W[\IQ^T^.C=#W_] +M$7"=A_.9_H"^Q#>TZ>FT]G]Z_E@6C^^^+5Z%)G_ZQ2U/(.#.X3%>D]?[($M8 +MA4_BU%;X0&(:7ECN;'';/_3%U_TG=_/Z]O;K=&?[T*PNES^:"RC-"AV>[V6< +M?G#KG5YO]'(KIFFXZ:?^XX.[#[!>_POK$A-L4X-S#_>>; +M\?.O=^\G_T8KW@!N6F?GCU/7\5#I3,\/E;ZLG]VK^NEH'AMP+HQH/507WQ@> +M:SW'TQ3\LQ*>F#2%Q\\WO[A^\L1K`ET([B>^T+VVW*W+?'ZX!OKY^O,;X=<@KOW!/E-ES7 +M4M!M`'_P(#_[CX^;\\DIO'//E-ESU4#!F#G?"A?>N1-E.JZ:GS4J6;CPSA7* +MK+BJID`OX,)/*:7_>$MPE3-E]EPU4#`>:79Y5";* +M=%PUEYL?([,_-DI3Q=DAL^*JF@*]@+LRNZ:.LT-FPU4M!=T&;F]V&F>'S)ZK +M!@K&0\V>XNR0Z;AJ+K<_)M=9N";.#ID55]44Z`7J@8+Q2+,M^`Z9CJMF"L+59.'`=\BLN*JF0"_@KLRN +M!=\AL^&JEH)N`[ZX:*!@/-0N^0Z;CJKG<_(!;=EDX\!TR*ZZJ +M*=`+N&NS`]\AL^&JEH)N`[JP8*QB/-=N`[9#JNFBD(5Y^% +M`]\AL^*JF@*]@+LRNPY\A\R&JUH*N@W^0V;%534%>@%W;7;@.V0V7-52T&W@]F8'OD-FSU4#!>.A9L%WR'1< +M-9?;?\./63CP'3(KKJHIT`NX:[,#WR&SX:J6@FX#MS<[\!TR>ZX:*!@/-0N^ +M0Z;CJIF"<$U9./`=,BNNJBG0"[AKLP/?(;/AJI:";@.W,[MS&6>'S)ZK!@K& +M(\V>P7?(=%PU4Q`NEX4#WR&SXJJ:`KV`NS*[,_@.F0U7M11T&[B]V8'OD-ES +MU4#!>*A9\!TR'5?-%(1KSL*![Y!9<55-@5[`79L=^`Z9#5>U%'0;N+W9@>^0 +MV7/50,%XJ%GP'3(=5\WE1J=,F[Y]N,AW*;/BJIH"O8"[-KO(=RFSX:J6@FX# +MMS>[R'J@8+Q4+.1[U*FXZIYNQF5K*1UCGPGI-\)ZW="^IUD];MSY#LA +M_4Y8OQ/2[R2KW_5EG!WI=\+ZG9!^EV^VCWPGI-\)ZW="^IUD):T^\IV0?B>L +MWPGI=Y+5[_K(=T+ZG;!^)Z3?25:_ZR/?">EWPOJ=D'YWH-G(=T+ZG;!^)Z3? +M25;2ZB/?">EWPOJ=D'XG6?VNCWPGI-\)ZW="^IUD];L^\IV0?B>LWPGI=P>: +MC7PGI-\)ZW>;;4M6TNK!=Z3?">MW0OJ=9/6['GQ'^IVP?B>DWTE6O^O!=Z3? +M">MW0OK=@6;!=Z3?">MW0OJ=9"6M'GQ'^IVP?B>DWTE6O^O!=Z3?">MW0OJ= +M9/6[H8RS(_U.6+\3TN_RS0[@.]+OA/4[(?U.LI+6`+XC_4Y8OQ/2[R2KWPW@ +M.]+OA/4[(?U.LOK=`+XC_4Y8OQ/2[PXT"[XC_4Y8OQ/2[R0K:0W@.]+OA/4[ +M(?U.LOK=`+XC_4Y8OQ/2[R2KWPW@.]+OA/4[(?WN0+/@.]+OA/4[WBA+5M(: +MP'>DWPGK=T+ZG63UNP%\1_J=L'XGI-])5K\;P'>DWPGK=T+ZW8%FP7>DWPGK +M=T+ZG60EK0%\1_J=L'XGI-])5K\;P'>DWPGK=T+ZG63UN[&,LR/]3EB_$]+O +M\LV.X#O2[X3U.R']3K*2U@B^(_U.6+\3TN\DJ]^-X#O2[X3U.R']3K+ZW0B^ +M(_U.6+\3TN\.-`N^(_U.6+\3TN\D*VF-X#O2[X3U.R']3K+ZW0B^(_U.6+\3 +MTN\DJ]^-X#O2[X3U.R'][D"SX#O2[X3U._:&2E;2&L%WI-\)ZW="^IUD];L1 +M?$?ZG;!^)Z3?25:_&\%WI-\)ZW="^MV!9L%WI-\)ZW="^IUD):T1?$?ZG;!^ +M)Z3?25:_&\%WI-\)ZW="^IUD];NIC+,C_4Y8OQ/2[_+-3N`[TN^$]3LA_4ZR +MDM8$OB/]3EB_$]+O)*O?3>`[TN^$]3LA_4ZR^MT$OB/]3EB_$]+O#C0+OB/] +M3EB_$]+O)"MI3>`[TN^$]3LA_4ZR^MT$OB/]3EB_$]+O)*O?3>`[TN^$]3LA +M_>Y`L^`[TN^$]3LA_:XJK\,53W"1[RHJ>:JJ*=`MG(R:FM;Y)G9-3>M\$[NFIG6^B5U3TSK?Q*ZI:9UO8M?4M,XWL6MJ +M6N>;V#4UK?--[)J:UODF=DU-ZWP3NZ:F=;Z)75/3.M_$KJEIG6]BU]2TSC>Q +M:VI:YYO8-36M\TWLFIK6^29V34WK?!.[IJ9UOHE=4],ZW\2NJ6F=;V+7U+3. +M-[%K:EKGF]@U-:WS3>R:FM;Y)G9-3>M\$[NFIG6^B5U3LR:BG6^C5U3LR:BG6^C5U3LR:BG6^C5U3LR:BG6^C5U3TSH?F2^R:VI:YR/S +M179-3>M\9+[(KJEIG8_,%]DU-:WS3>R:FM;Y)G9-3>M\$[NFIG6^B5U3TSK? +MQ*ZI:9UO8M?4M,XWL6MJ6N>;V#4UK?--[)J:UODF=DU-ZWP3NZ:F=;Z)75/3 +M.M_$KJEIG6]BU]2TSC>Q:VI:YYO8-36M\TWLFIK6^29V34WK?!.[IJ9UOHE= +M4],ZW\2NJ6F=;V+7U+3.-[%K:EKGF]@U-:WS3>R:FM;Y)G9-3>M\$[NFIG6^ +MB5U3L6AG9-=:9V376F=DUU +MIG9-=:9V376F=DUUIG9-=:9V376F=DUUIG9-=:9V376F=DUUIG9-=:9V376F +M=DUUIG9-GIDR\#=LM2M-I]6+KR_%1USL)]Z7PK7&_5[@HW +M'(5;-S>3*YQ[!OMZ#DR>XOSR'>VKW +M^;NM*I[JKYRNN'JZ*<$-8_C5V,>G]\TU.&?ZJ,A\%&[JB\$_)U+,XSY<]<5# +H_/^/2K\`KOZ`R__OO^"_9VS_6P$U`IJ=4/U[HRR_^A][EZ;PS5\````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu new file mode 100644 index 000000000000..b47d4c617b0d --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-apm.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-63x255-512-apm.raw.gz +M'XL("/7%'50``VEM9RTV,W@R-34M-3$R+6%P;2YR87]/"5(HG(/PDN:+T(BV4_QK-K +MQGP`)"$%F$T64G`PPN4^2)B7M]+&71G#%![&V8VNZ[AR$*:X]T#ARI*!FE%? +ME0)YOV#6KT.@QSE]Q*&92_4!)6?I6W;=9SN!$[D^U^.JL3JY.[]S0`MH@EJ$ +M4^V@6E<.ZK9=?3SM3_OOPS;BR.)4XYKU?]1]U=VD.IEYMC1SMA27,@#[LT74 +M1[EWC\[C4,YX.PB;)"`K$$$T5KAT-7L?`5?'MGW:/#^\KS:I?T29]:D9_HG$ +M/_^3I/XAU:=R^Z=N^JN*\7C#KLO]X(`5@ +/-H4D'+#X`^%)]I"G!0`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu new file mode 100644 index 000000000000..68c383866a79 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-512-apm.vhd.gz +M'XL("/;%'50``VEM9RTV,W@R-34M-3$R+6%P;2YV:&0N;W5T`*U66VO;,!1^ +MSZ\XT+="@Z['W=/86/,V*"M[;HTCE\#:AB:P/OC'5T>76HYES\WD"$5&/I\^ +M?>8?`)2`+:`!U#2N%.`7J*X![&1HPO4\O$+7O#R;YKA[6X>G6WDPSE*K +MH3G9"PG*+E*!J&D1W-(8N@BSOKAYO-P]/48X$>#BP@I!"=`61(W60?;!CI`V +MW^]^.,B'GIT2*<9B=6"VM=!PJ06,;-E&'4;.A\G;8 +MUZ\'<\)/3(0*?O#CHSDYO5T10D7$CP,#1>$\MUUP*,=3N$RH_)=Z.+1386!% +M8#I."+?]H7H]%*3\D+,9S:>=,Z:_->&;WX1##MU1SWAW;/U +M:VC:9HC:YJ*B?^'#B>[V9S9<&N*G.(4Q17)#,;R$W[?]_H_)P(E2V_5P%BDJM0US.[JG>9]GIPKXU"WT; +MDT8$P*%O(?(SI6//.'<@"4\GI.[/(+&UQ#7-V?<1X.;5&'L*7?W>W*7Z&566 +M'V<+]!.)?CY)4OW2VL*G#O'S^GJ\PY5UV" +I*WC5Q5"R)JW\W]*K+H:25>BJ2W`%K[H$5_2JBZZ@KMX!;=,CGA\-```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu new file mode 100644 index 000000000000..6096dacbb0a9 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-apm.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-512-apm.vhdf.gz +M'XL("/;%'50``VEM9RTV,W@R-34M-3$R+6%P;2YV:&1F+F]U=`"M54UKPD`0 +MO?LK!GH3&I+=R<2>^D'U5I!*SQI,(H&JP0KM(3^^^ZF[211;=AV6#9-]OGEO +M=Q+'>@!@"BF#6$1L@JOY_-P):*?OD1AQ9$<[TF#)M5V7X:+.:$=C#T!$Q>0G>U5@.O]KEP?ZQ_W!I/ISE4U''(_X_); +M0!FP7+680JX=?G?3S;C>;BR<[7[VCX77)XN[59)?[DP8K"!79W:\+Q)UU!,\ +M>>45;MBMU/SH%HNG8LL*4-.TX3UX"0GWY)NAX53W=-W;3Y?.;Y]="N+IV>7MP+R1=$A(EFW3%*WO:W>R75O>'KWSQW/HRMX;Y +M>,LFJ;*D[+R9E,5B9TEU7MY+DVIVFN:$7R?7-P__3J['A_[^YN[QUJ_O[,YV +M=LY+YU_V+L.\L:IT+]P;+EWC4I1CD@U)!O=V;C>/K/>/]P<_OI';C= +MLSO;/$ORQBW'^:=/CXWA/B1-2KC/2"Y__LOU.W_EIJ>[]I[I7-2\D/FSYWUH +MWK),W/?+Q[*Z\=.CRSCYK[`Z=[:^.,7RV;E[4>1)U23+<@J7^SR_/?@M+[7K +M[\?V67#[> +M//YZTW^8M_DP7IV^3IBN=+6;#[#VZUIW/8>4NR<[+_OR_?\>Y_TF@S_9&Z9; +M%K%L8O[LXIP4E&FJ^>HV7->X!PR;VBSIV+=?_'\LDPN'[Y/KMPF?_YU7*Y`IFO6'S/GO)X# +M%O/L7OBJK>E=$\O=&\O))M?M8YM\USZ,IZ^OK[\+)]NZS>;+8U[:Z+*4:VIW +M?2_EG`NWGO1ZT,M1#$-W:H?V[G&\=\<;CJ)S)1K\3MVQYD_'N/V<:CFIR5TQ +MR>5= +M?S[UGS_>?!KF'[3D'=,-:^WFY62I7U18T_-%A8^=:W>5/BUMSLUTHRO1NJC: +M_V#,N=9U/%7!73&%>_@J7#Z??AW;85Y6M!S+=:C +M\`O[?'H8>Y\N2_T!3IOBK&M*LC+),K^B;0-]O+U?EE9F5]J/L^>_R][:C_,7 +MOU*KWYEP36>]OC)]]OLLT[A)9:50M1K-) +M]\\YQ=W+[9;N$FO%L].H7HSA2/5*U]I&\9R>5X]_:D!>[Z?CWP+TS#0J%Z/8 +MI-NK7>%K1\]*HVHQFDVZO=J5OG;T[#2J%V,XM-G*UXZ>DT:Y)_XIA?3`GV5E +M[6M'STRCC&&0YOM?.WH.6F4 +M>V*#@+S>3]?[VM$STZAC.'0 +M9B=?.WI.&N6>CV*3;J5W%?D?/2J-J,9I-NIW:5>QW +M].PTJA=C.+19]CMZ3AKEG@JI71%-QWY'STRCDX:Y9Y*J5T93<=^1\],HW(QBDVZO=JQW]&STJA: +MC&:3;J]V['?T[#2J%V,XM%GV.WI.&N6>^$<0Y/5^.O8[>F8:E8M1;-+MU8[] +MCIZ51M5B-)MT>[5COZ-GIU&]&,.AS;+?T7/2*/=$(`-YO9NN3GWMZ)EI5"Y& +ML4FW4[N:_8Z>E4;58C2;=#NUJ]GOZ-EI5"_&<&BS['?TG#3*/352NR::COV. +MGIE&Y6(4FW1[M6._HV>E4;48S2;=7NW8[^C9:50OQG!HL^QW])PTRCWQ_T)! +M7N^G8[^C9Z91N1C%)MU>[=COZ%EI5"U<FW5SOV.WIV&M6+,1S:+/L=/2>- +MG4;U8@R'-LM^1\])H]S3*+4;H^G8[^B9:50N1K%)MU<[]CMZ5AI5B]%L +MTNW5COV.GIU&]6(,AS;+?D?/2:/E8: +M58O1;-+MU8[]CIZ=1O5B#(05[OIFO3M7;!,].H7(QBDVZG +M=JWO=\&STJA:C&:3;J=VK>]WP;/3J%Z,X=!F?;\+GI-&N9()OT,4:;6^WT'X +M'93?0?@=HORN]?T.PN^@_`["[Q#E=ZWO=Q!^!^5W$'YW8+.^WT'X'93?0?@= +MHDBK]?T.PN^@_`["[Q#E=ZWO=Q!^!^5W$'Z'*+]K?;^#\#LHOX/PNP.;]?T. +MPN^@_`["[Q!%6JWO=Q!^!^5W$'Z'*+]K?;^#\#LHOX/P.T3Y7>O['83?0?D= +MA-\=V*SO=Q!^!^5W$'Z'*-+J4E\[X7=0?@?A=XCRNX[]3O@=E-]!^!VB_*YC +MOQ-^!^5W$'YW8+/L=\+OH/P.PN\015H=^YWP.RB_@_`[1/E=QWXG_`[*[R#\ +M#E%^U['?";^#\CL(OSNP6?8[X7=0?@?A=X@BK8[]3O@=E-]!^!VB_*YCOQ-^ +M!^5W$'Z'*+_KV.^$WT'Y'83?'=@L^YWP.RB_@_`[1)%6QWXG_`[*[R#\#E%^ +MU['?";^#\CL(OT.4WW7L=\+OH/P.PN\.;);]3O@=E-]!^!VB2*M/?>V$WT'Y +M'83?(O8[X7=0?@?A=XCRNY[]3O@=E-]!^-V!S;+?";^#\CL(OT,4:?7L +M=\+OH/P.PN\0Y7<]^YWP.RB_@_`[1/E=SWXG_`[*[R#\[L!FV>^$WT'Y'83? +M(8JT>O8[X7=0?@?A=XCRNY[]3O@=E-]!^!VB_*YGOQ-^!^5W$'YW8+/L=\+O +MH/P.PN\015H]^YWP.RB_@_`[1/E=SWXG_`[*[R#\#E%^U[/?";^#\CL(OSNP +M6?8[X7=0?@?A=X@BK2'UM1-^!^5W$'Z'*+\;V.^$WT'Y'83?(^$WT'Y71#305Y+NF3]]NG&=*W=JY+R +M5_XIU"YY=76CL3X0BSXPS!367?V^A&LZZ_6%^38?;](O(LRW^7B3?A%AOLW' +MF_2+"/-M/MZD7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI% +MA/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z +M183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF +M^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?!.?;-OI%<+YM +MHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC +M7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-? +M!.?;-OI%<+YMHU\$Y]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU\$ +MY]LV^D5POFVC7P3GVS;Z17"^;:-?!.?;-OI%<+YMHU]$F&_3\TWZ183Y-CW? +MI%]$F&_3\TWZ183Y-CW?I%]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH +M%Q'FVR;Z183YMHE^$6&^;:)?1)AOF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^; +MZ!<1YMLF^D6$^;:)?A%AOFVB7T28;YOH%Q'FVR;Z183YMHE^$6&^;:)?1)AO +MF^@7$>;;)OI%A/FVB7X18;YMHE]$F&^;Z!<1YMLF^D6$^;:)?A%AOFVB7P3G +MVS;Z18RF^D6,IOI%C*;Z18RF^D6,IOI%C*;Z18RF^D6,IOI%C*;Z18RF^D6, +MIOI%C*;Z18RF^D6,IOI%C*;Z14QI:JA?Q&2J7\1DJE_$9*I?Q&2J7\1DJE_$ +M9*I?Q&2J7\1DJE_$9*I?Q&2J7\1DJE_$9*I?Q&2J7\1DJE_$9*I?/*=I:JA? +M/+^XE_#!="\WN^H#\V5]>>'N7:KW^EWO:OR%A-__Y-)\\VQ]N?GZEOOUNMNK +M#B_B,DV([1N7]S^^5K]\N5]OOMS6U-W&=+U?[X'U?7MW]W%\)=V+>S'_WNVN +MZ;*7JRLF?Z/?Y?Z=.>^6RWL*%Q-7]\M=>_]X\WAS^^D7IEONUSOXV[@>7]UO +M[=VKJS.^%W.>'SQ;$I&S3[@]VX3KL[[W9YXOQU'R?L>%NXMNL=Q1]SS,"R_< +M>T7V,N$/]^/XW8?K/_[MAP]:OSPW7E]YH'XJA5M_2+1^B:[/6GN]R?#XF:X6+`:LCA +MK@BGO')`EEP@KTZ`ZN<#_D:X9GHC3N]%YRO!^RU%-EE3JG:QMW;EA_L,H@>A +M@-M9)RGPUU]8XKND84B2[DY\D*;;!EQ-[07"R8-T@>+>`8?Z25IX4+TFC:XK +MW`RUGHP_)S=`Z.1..%GV(I#CS>+_0&^5[GF%>S"Z)J">@<4J6'^L)U9?N.5M +%L04%```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu new file mode 100644 index 000000000000..2e7c6573ef52 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhd.gz.uu @@ -0,0 +1,17 @@ +# $FreeBSD$ +begin 644 img-63x255-512-bsd.vhd.gz +M'XL("/?%'50``VEM9RTV,W@R-34M-3$R+6)S9"YV:&0N;W5T`*V7/6_#(!"& +M]_R*D[IEL/`98W=IHJCI7*E2.[O$CC+T0TV'#/[QY6R(#W\E;;$)PH)[>(\[ +M$!&B?0!4`JH"58)*J9U)4+>0Y0"FTQ9LZMA^0JT_WDO]?3A%]JD7+2P6W,HW +M)WM,0)I),L"")E$[:D/M,-'-=K\\O.T=#BW.32P52(340.1@GER7#-5U5NT\505)Q48D7%T4K3A.&BLSGHJ"2C8R7?$^O`Z.\]2EHF?%9(XM +M*G-V#*?FK'Z#6RYL+-I4,8F1F5J`BB%#:INT<>LP*"953L?/XNM8]O3A1*HH +M%HQ^GYQV%VVJH!ML%4@2..2*O]:/>7;2=LPBR!2UX&-^_[J=2C@ +M^E0L9M9\.AB3^@K29_:6*$;JZ8YZ$_GO&:@)F&:TW5,%.5Z[@B_;Y['XZHET +M^>/NT'@)YP3ST\#'K1@N:XPN=OMNA#/3 +M[;G,!G5<'./G1'52B%T@*#*33`,K!"+&>3[;=9J*S"0!=)P@6\2!(NX$62<`$O +=DH0+>)$D7,"+).&"7B25^8L@Q.('-E=QRWT,```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu new file mode 100644 index 000000000000..c102a9fd6bc6 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-63x255-512-bsd.vhdf.gz +M'XL("/?%'50``VEM9RTV,W@R-34M-3$R+6)S9"YV:&1F+F]U=`"ME#M/PS`0 +M@/?\BI/8.D1^QUUH55%F)"280W"J#L#"P.`?CR^)&U^>",5VHEAW]^4>]C'6 +M#@`E@)43[WF!/^5T^FR7-32!0%V`TJ`-V*#.^D4V1.!?SR]Y.GR'XTM6\[A\ +M,").K.&BP[*>PQT2G`S".M%D/+&J.$C7[]4$[CX\QQZGEKP+F6!N2C`;K-XJ +M=[&V=F"7UAFX`RZ!V4XF*/!67^C]VX_=$"3U=M7`PYO!E_O+D(H3>WQ8EM&X%H.DLX@4%K_)X7^*>RAL"A3T)/GJZ]-5W]>?M,*(XVTSF%QH+R3> +M%E.`*/$GYAV_$__NSI?=]>,2<;%5Q1\K@TG7`:)&X5H:[N/I^6'HG1PGR9+L +MS`'```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu new file mode 100644 index 000000000000..79b142eba461 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-bsd.vmdk.gz.uu @@ -0,0 +1,81 @@ +# $FreeBSD$ +begin 644 img-63x255-512-bsd.vmdk.gz +M'XL("/?%'50``VEM9RTV,W@R-34M-3$R+6)S9"YV;61K+F]U=`"MG%MO(\<1 +MA=_]*QKR6QZ(.9S[PR:.(P<(@@"&;=BOYMQB(?;N0BL$68`_/M,S?5IG1(U[ +M8)7,7;*65<7NZF&)_NJ`6;;^.%=TKBA<,;BR8-U97_H%_PJ=K?8IJ=/G@/_L^;8Q_(MDKH)_#7?]VS_NWX4K-SM]O#PRG8^:%S*_]KP/S5M5 +MSO^YO2VK&]\_^8Q3^(FK\V<;BE,NKUWX!V7AZM8MRRE][O/\]!"VO-2N?QPO +M3^,/GS^.[^Y^^_`^ULZ?K2]9NR1JED+EKLQ]JK`U7[[29_27S7)J[OKKP],O +M#_WW\S8_C7>G+QW35;YV\P$V85WKKN>0:O=DYV5?O_G?T[Q?-X23?6"Z91'+ +M)N;7+L^NK'VN^0#SN79Y[O+&Y4OZ><'S3@IX)W?]\/[TW4\.5=X4[OMO__H= +MTS5SNMES7N`<,F]HLZ=RW7_Y\K)TU^^_<7=^DS_\,BY7(-.UZ]O,.Z_G@,4\ +M^P>A:FMZW\0*_\1RLN[^\G1Q7U\^C: +MRCD7;CWI]:"7HQB&[G09+A^?QD=_O/$H.G^U#F&G_EB+YV/?N'H;Y3'W:?X\??F.Z?KV,YW7X2Z)=`G/_8+YZEO1C>(7UBO''Y-.-3X^? +M3_WG7Q_>#_,;S;UCNF&MW;R<^3371<4UO5Q4?-FY=G=X7MJA0.<-L59U^0OY?E*7E>T;:!/'QZ7I57YG?;C_.7OLK?VX^+F +M5VK]!Q.NZ:S75V4O?I_E&E>(46X2^M]BV?HQX/3M\_HJO[Y*/&N-:L1H-^E^ +MGE-\O-UNY2^QBWAV&M6+,1RI7N5_7XSB.;VL'C]J0![OI^-G`7KF&E6(46[2 +M[=6N#+6C9ZU1C1CM)MU>[:I0.WIV&M6+,1S:;!UJ1\])H_P=/THA._"QK&I" +M[>B9:U0A1KE)MU>[-M2.GK5&-6*TFW1[M;N$VM&STZA>C.'09KM0.WI.&N7O +MV"`@C_?3]:%V],PUJA"CW*3;J]T0:D?/6J,:,=I-NKW:C:%V].PTJA=C.+39 +M*=2.GI-&^;M":E>DTM59J!T]DT;YNTIJ5R73L=_1,]>H0HQRDVZO=NQW]*PUJA&C +MW:3;JQW['3T[C>K%&`YMEOV.GI-&^3M^"((\WD_'?D?/7*,*,DX:Y>]:J5V;3,=^1\]< +MHPHQRDVZO=JQW]&SUJA&C':3;J]V['?T[#2J%V,XM%GV.WI.&N7O^+]0D,?[ +MZ=COZ)EK5"%&N4FW5SOV.WK6&M6(T6[2[=6._8Z>G4;U8@R'-LM^1\])H_P= +M^2/D\7XZ]CMZYAI5B%%NTNW5COV.GK5&-6*TFW1[M6._HV>G4;T8PZ'-LM_1 +M<](H?]=+[?I4NC8+M:-GKE&%&.4FW4[M6O8[>M8:U8C1;M+MU*YEOZ-GIU&] +M&,.AS;+?T7/2*'\W2.V&9#KV.WKF&E6(46[2[=6._8Z>M48U8K2;='NU8[^C +M9Z=1O1C#HG4;T8PZ'-LM_1<](H?S=)[:9D.O8[>N8:58A1;M+MU8[]CIZU1C5B +MM)MT>[5COZ-GIU&]&,.AS;+?T7/2J$RF9Y#'N^DNV5J[Z)EK5"%&N4FW4[M+ +MZ'?1L]:H1HQVDVZG=I?0[Z)GIU&]&,.AS89^%STGC?(E$WZ')-*ZA'X'X7=0 +M?@?A=TCRNTOH=Q!^!^5W$'Z')+^[A'X'X7=0?@?A=P^$WT'Y'83?(8FT.O8[X7=0?@?A=TCRNX[]3O@= +ME-]!^!V2_*YCOQ-^!^5W$'YW8+/L=\+OH/P.PN^01%H=^YWP.RB_@_`[)/E= +MQWXG_`[*[R#\#DE^U['?";^#\CL(OSNP6?8[X7=0?@?A=T@BK3X+M1-^!^5W +M$'Z')+_KV>^$WT'Y'83?(O8[X7=0?@?A=P^$WT'Y'83?(O8[X7=0?@?A=TCRNY[]3O@=E-]!^-V!S;+?";^# +M\CL(OT,2:?7L=\+OH/P.PN^0Y'<]^YWP.RB_@_`[)/E=SWXG_`[*[R#\[L!F +MV>^$WT'Y'83?(8FTABS43O@=E-]!^!V2_&Y@OQ-^!^5W$'Z')+\;V.^$WT'Y +M'83?'=@L^YWP.RB_@_`[))'6P'XG_`[*[R#\#DE^-[#?";^#\CL(OT.2WPWL +M=\+OH/P.PN\.;);]3O@=E-]!^!V22&M@OQ-^!^5W$'Z')+\;V.^$WT'Y'83? +M(2SIW/HGI!NSM7:O2LI? +M^:=8._?JZD9C?2`6?6"<*:R[^F,)UW36ZXOS;=[>I%]$G&_S]B;](N)\F[KY) +MOX@XWZ;GF_2+B/-M>KY)OX@XWS;1+R+.MTWTBXCS;1/](N)\VT2_B#C?-M$O +M(LZW3?2+B/-M$_TBXGS;1+^(.-\VT2\BSK=-](N(\VT3_2+B?-M$OX@XWS;1 +M+R+.MTWTBXCS;1/](N)\VT2_B#C?-M$O(LZW3?2+B/-M$_TBXGS;1+^(.-\V +MT2\BSK=-](N(\VT3_2+B?-M$OX@XWS;1+R+.MTWTBXCS;1/](N)\VT2_",ZW +M;?2+&$WUBQA-]8L83?6+&$WUBQA-]8L83?6+&$WUBQA-]8L83?6+&$WUBQA- +M]8L83?6+&$WUBQA-]8L83?6+F++,4+^(R52_B,E4OXC)5+^(R52_B,E4OXC) +M5+^(R52_B,E4OXC)5+^(R52_B,E4OXC)5+^(R52_B,E4OXC)5+]XSK+,4+]X +MOODNX8/I;C>[Z@.+97WKMX/>_KW_Q/7KT_:_F'#Y@MVR]E]T6E:N.1]=X4_? +M_/C*AHNSV8;7=#=?GOPR7>1=TUZZOT@ZW^`G\=Q\%W,/EX_/=O%*NC^?Y)NB +MB^4+=G=7IW.*8YLU_O+D8OD26_75<_8=QH,??IY_\=Z(Y^N>U]?>+N.\V>[O +MK,_=;MIZX\.X^2K6@^]/>BGG%N3[&'MXQ-6V$?)O`5DL(O_])2(7P#P!D=RX8A +M_VE#=LA&FGS^#>S[*-#C6KR%!W!8/6UP%#W!M1**+JJO<4M-<:_4[O;_`;4& +M:P/@;=:G$H>CZIRY5"!L9%TV#.><]QEHQH31%90:]!&,VJOP<;E'XFN$3.6P +MQZDMW"S89U`,UQ!XVL\95ZZIPY<07`GOO#5=PIE*.;NBCX(W;4.5_'SDN#4AKO`<6.A(O%D(=QX +MO3I4UR8.AOS]&3M_KH/PG^MQ*FTA.(V5!3,03X7KLF&XYKQ[8#D!D[V@JWQ" +*9&_T+/:\Y08````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu new file mode 100644 index 000000000000..b0e08ed34bc3 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-512-ebr.vhd.gz +M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65BP<[!2 +MQ%ZI._EC!=(.4@,:&D0_41N&@"F^W3U?O?Q^#CCTN#"PU"`1E(7(Q3B-.*DC +MTH_;A^]S==52W>3EQNE[J/JH1Q6K*XJ;&">ME^U/CX9>CC+#D_Q)##$N4:?$ +MS"N2N3:I4;!K.+WE=0GN:N=SX4K%%D9MWP)T"352VY9-F(?%8TOE_?AF_AZ[ +MF3[,E(J.DC&WR7RXZ$L%0V>O0)+`K7!AI!SGN)52^=+LZ=1/^H:=!*&"`,-P6Z7T"C@6C:MK.E88& +M/ZOPU]W/E?PV)K,=7!ZPP^$Y7!`<[_8I[B;"5:[Z)DJT.25U%[&;V]DMU+7,R#O.5\+\?VBMD.B@0CO&@0#C& +A@P+A&`\*A&,\*!".\:!`.-:#@K9'0"%V'P.\AOE=#@`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu new file mode 100644 index 000000000000..b865e864372f --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-512-ebr.vhdf.gz +M'XL("/C%'50``VEM9RTV,W@R-34M-3$R+65BW$0 +MXAX`\R;[LJ#;S)YNM5[U-/IQ-[!MDT"':\PNL\#T6@P3TXLVP#44"IW4;V>' +M*L0=9%&FX7UAG(%JH`40-<@8!H[QA4F_;:P&0^9>T`]B5,/=)@N0+4@-4MAYR4%NH50AD.%,ZIKO+]W\G'_#"%L<':^B +MN-O]K+"G19;`:OL3>;3S0+^'PVE]_CQYG"]5_L=<6J<+`^&1N0J;^[1_>9QK +M5\1.4LA[=+HX1\.1]W8ACH_&:MV70#IU]($$R5)E<8+,=OTWM@XG,Z>*N7=7 +)?T_5:9P0"0`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu new file mode 100644 index 000000000000..869f19ca438f --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-ebr.vmdk.gz.uu @@ -0,0 +1,84 @@ +# $FreeBSD$ +begin 644 img-63x255-512-ebr.vmdk.gz +M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+65B +M::MUJP/[V%W;W4.U=-4%9=GTX=RE=9>+NW2N*%T&-_S3]')9_FP,KTNZ\?2W +MMW__\<2//YY.3U],8`A1$H),X<28O<_3:?%!N//GHF8WAM=Y%RX/4>V+P`AW +MWKBQ"3?TPYW70IA=,][NPH7`N03D9G#%2DV;Q7XNNS]\$9L7\LM##L/QEK6K +MVT71E,=JYJ\[CO'NX_/+Z/^9W#V0[.ES+X +ME[>`,!16E>$BW`AP=8`HO>W=[\,VC_^'3 +M!__F[M?W[U+OPMF&EM4CT'5L5.Z*/$#%TD+[BH`8'IOQU-S3+_>//]_?OA_* +M_.CO3E\ZPI6A=\,!7F->4]5#2+EYLD/:3]_^[W&HUW7Q9.\)-R8Q%C&\=W%V +M116PA@/,A][ENAR!]^]N,32+AZ^C(+SM,Y8#3/X2)V;8(/ +M0^P2;HPGZ]XVCXW[IOGH3U^^??M-.MDF%'L97T-J/J"4$W1XOL=V#HV;3GHZ +MZ/$HNJX]-5WSX=$_A.--1]&&I[6+E89CO3P?X_Q]JO&D^O#$N*D9X']]A>F+",04X__CPZ73[],O]NV[X +M0G-O"-=-O1O2&4YS2BKEM$PJO>W0NSL\IS9@$\Z'%DU)7>,7QH`UY?'$5N_#TZ?2S;[HA+7=W+HJ[=!3]\BBT18LN3`<]]&(ZBIC8I]-'?XMP>18/ +ML)\U9\HI/,K#DSQE-!^@C^\?QM3*_$[G<;[\7O;:>7QY\2VU^IV`$YQU?F6V +M]_V,KWP&Z`0L>\ZO#/E=Q+/0J%*,:@8W_#1Q^F[X_-?P^4'@PB-V%<]:HQHQ +MVB/=*\/WBYMX=AKEQ>@/P5UBB_@#"N1Z;"J-7&\D.+?H71%[1\]"HTHQJAG< +M5N_*V#MZUAK5B-&N9KG45Z,_A#<-?:./X!!KL?>T\7KL'8U<;VSUKN*\HV>A4:48U0QNHW<5YQT]:XUJQ&A7LUL6RWE' +MSTZCO!C](3C.NT)ZQ^NQ=S1RO;'9.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7L +MEL5RWM&STR@O1G\(CO.NE-[Q>NP=C5QO;/:.\XZ>A4:58E0SN*W><=[1L]:H +M1HQV-;MEL9QW].PTRHO1'X+CO../3I#KL74?/6J,:,=K5[);%\'GM'(]<;6[V[S6Q;+>4?/3J.\&/TA.,Z[6GK'Z[%W-'*]L=D[ +MSCMZ%AI5BE'-X+9ZQWE'SUJC&C':U>R6Q7+>T;/3*"]&?PB.\X[_\8)N-S=YQWM&ST*A2C&H&M]4[SCMZUAK5B-&N9K3'Z0W"<=V0M +M(==C[VCD>F.S=YQW]"PTJA2CFL%M]8[SCIZU1C5BM*O9+8OEO*-GIU%>C/X( +M7)W%WMVD=[P>>TR6Q7+> +MT;/3*"]&?PB.\ZZ3WO&:K';J7?<";MD[SCMZ%AI5BE'-X+9ZQWE'SUJC&C': +MU>R6Q7+>T;/3*"]&?PB.\\Y+[W@]]HY&KC\=Y1\]"HTHQJAG<5N\X[^A9 +M:U0C1KN:W;)8SCMZ=AKEQ>@/P7'>]=([7H^]HY'KC<=[1L]"H4HQJ!K?5 +M.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^B-P33;U+NW<(->A=\G(]<96[YHX[Y)G +MH5&E&-4,;J-W39QWR;/6J$:,=C6[9;%QWB7/3J.\&/TAN#CO(/P=E+^#\'?8 +MY>^:..\@_!V4OX/P=]CE[YHX[R#\'92_@_!W*]DMBXWS#L+?0?D["']W`"[. +M.PA_!^7O(/P==OF[)LX["'\'Y>\@_!UV^;LFSCL(?P?E[R#\W4IVRV+CO(/P +M=U#^#L+?'8"+\P["WT'Y.PA_AUW^KHGS#L+?0?D["'^'7?ZNB?,.PM]!^3L( +M?[>2W;+8..\@_!V4OX/P=_MP;19[)_P=E+^#\'?8Y>]:SCOA[Z#\'82_PRY_ +MUW+>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`_:SGOA+^# +M\G<0_@Z[_%W+>2?\'92_@_!W*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X== +M_J[EO!/^#LK?0?@[[/)W+>>=\'=0_@["WZUDMRR6\T[X.RA_!^'O#L!QW@E_ +M!^7O(/P==OF[EO-.^#LH?P?A[[#+W[6<=\+?0?D["'^WDMVR6,X[X>^@_!V$ +MO]N'NV6Q=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE[VZ<=\+?0?D["'^WDMVR +M6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+?0?D["'^'7?[NQGDG_!V4 +MOX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE +M[VZ<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+? +M0?D["'^'7?[NQGDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[?;@NB[T3_@[*WT'X +M.^SR=QWGG?!W4/X.PM]AE[_K..^$OX/R=Q#^;B6[9;&<=\+?0?D["']W`([S +M3O@[*'\'X>^PR]]UG'?"WT'Y.PA_AUW^KN.\$_X.RM]!^+N5[);%"7\'Y>\@_!UV^;N.\T[X.RA_!^'O5K); +M%LMY)_P=E+^#\'<'X#COA+^#\G<0_@Z[_%W'>2?\'92_@_!WV.7O.LX[X>^@ +M_!V$OUO);EDLYYWP=U#^#L+?[X +M..]6%7TK_Y1ZY]:S>Z'%/P;WLMA);HA1;I@V$5.YOP]P@C.60^(:N[X/>$0. +MB;0NY^M5;R"&1UN4F;R"&1UN4F/??N]\LAD=;E]'R5'!)I74[/5\DAD=;E]'R5'!)I76XBAT1:EYO((9'6 +MY29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1 +MUN4F;R"&1UN4F$-Y5#PIO*(>%-Y9#PIG)(]%EF*(=$;RJ'1&\J +MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ' +M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\(+V-P/V_6;W+@A/WN`P +MO)HB7@ROO!>X&USN5_/[.OSUE<)UUN7VOPVP*%S3O`#\)_,[?S:-WYY?-?[O +M8OI5LB__WK[Q],UI_H>`U_%Q+JKP6W&+TEW/1S/\Z=L?%QE.<&9RUPEN]W%. +MI&6_!?>UP.73T_>,HK^X6Y\[O1:XKZ9/PET^EYWNDXX5:_R;MJ_9=1&GYQR^ +M303VCO\I.\\!T_FZY_SJEVF<9^5^)C_WLMSP+5)_UZR>QVRJ;I3KYG#CH)+S +MG!WA3O>^>IG=S?@PL/S*./B5&T#F7[D3W-EV$-3C9)E$&B__WK[Q]-UI_F<" +5O$1`LPY>PN\1R;[X/U4+_GL>8``` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu new file mode 100644 index 000000000000..2a259cb9f7d3 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.raw.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-512-gpt.raw.gz +M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+6=P="YR87.*>+8T+K=IG%GSBCWTO[.-."OG7G[JY2UX#:Z!MB)QGS.< +M8^X\@^;:0=F`.X!5T'3XT#I0*L079.('2*AO"W('I0)=([`_OHACA-V(K^LQ +M/J/&CLAMVD!5S^BUCL"@_D@7YKB"NWH>JV?9JK<;FR6W:0-9O2I6+U\D4C)] +MJEI22,+5S-5S:`[Z"/_O\SMMZ/=B?D6@&8%L$8;FD)F/ +M;YX>F;'Q`E`%J!Y4!TKB?2E`[:"L`,RB&]S.N7N$0?\Z=/IA_YBY:S@;P7(V +MEPK%49X7(,Q'2N`U?D2U>`^#A\E>7]Z=[W_>>3CNX/R'A0+!01H0L?J.8D=V +MB'1U\?6CA;R=V!5K=I/4^-?W4/2S-PK/[M;.[^?*"B-EWL=1`I/`Q#2"AV!A +M4G9A.\D64C.:,:/.E(W!J2VI4^#.SYPOQE`Q@5&:V9@NAY+CO0D;;X?5,*'R +M>/^[_GO?+?CQ1*BH([]\M5:DU>4N5+A_V3$0&,Y;ZH)%>5C"14+E1=93H9SW +MKC&""1SWP*WZH?4F*)CS4SG;L'G:&4E^-?(SN<7JR)Q>&"ZR\'<$;)K3`+T% +M0[BCPHU&^]DZTG631F.03(8M-AS"9O9K6F+_-OUI@%)"7:\`;SP_;=TA;<'; +M86"8XB!RD*;X3>%L=9=ZSN_RZA-NQ0PR5;=O%^S6F794 +M=Q]+-LW'Z.-]5-DB"?S_"ZF6+)2JYE*5A(J# +MTM#62;@?`1QU7>YPN5%0:MS"90[:[N6M@CPW_$R:5!:$`S=^-QN[V84;!!P. +MG[/#"/8V^_/&\>MR%Q&QD5Y(6:_C6Q&!I)Y0%T(XZKK<56@]26:]G0N6V$@O +M)*U7C]:+&PE)Q5+WN*MEV:L0KJ&U7F[;1Y,?IGZOY_3"<)V%OQ&0NVV(;%_C +MKI"2,10.D(RA4**=%9AO*-T)K#<\XRE&^$9A]^P5F&BC="SSW+ +:0#C"LPR$(SS+0#CB4,&^Y>P?_R=O5``3```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu new file mode 100644 index 000000000000..b9a9b8a1a58c --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vhdf.gz.uu @@ -0,0 +1,19 @@ +# $FreeBSD$ +begin 644 img-63x255-512-gpt.vhdf.gz +M'XL("/G%'50``VEM9RTV,W@R-34M-3$R+6=P="YV:&1F+F]U=`"METUOU#`0 +MAN_[*P9Q*R+8CNUD3XB*5N)6/GKCT'S8U4JP"(D#A_QX9NRDL;-VH,B)%7DU +M\9-YQS.9+&/^`)`"6)>XY@W3=16?T^'JX&B\?QX0GT\N;(`5`CUN0",3=(\Q +M8.T\&'>K_&(<-5OG#E>M!ZL"W!BNVHR\(<15'K?(M<\#*@5==P&\7_P3;CL4 +M2`WR"`+O9R`Y*`%*/N&<=C6$_MW,?S +M5Q-N'$'EQIYG-Q;Y7/HW_;6XQ2+5[7AJE9! +M*T`/,'99W+<(IPMGGB1SKZ$90!M0'`9+DU$#Y^@?EDGK(`($[OL1&@ZB)^!T +M_EB=/>QU]?/5[)_DQE!3OU%+L2XNG3T6HJ>*A:]XYPLJ9$W +M9*/7^>BE@T1.I4H7<7/4JA\X;IKHI/#Y0SL)B'RMJA +M8'40KF!U$*Y@=1"N:'40L&!U$*Y@=1"N8'40KFAU(-"P#$7NO?:>+IS3`%FSCA=INX-5FQR[$16[")$ZYH$]?SY[?& +MKS-77UK1O)'TL=:T(5"L.>.`PX^S&7Z=?H?1(QSW&9$/5Z?OCPM.S*J6!U-&8Q8C1%[(U;'/;CKVU"L?!)K+*!R)M<1_8@,R40FG$N5\.;_W5N/*YTJ^-?@\`>4./-P +$LPT````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu new file mode 100644 index 000000000000..ea3a546f8163 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-gpt.vmdk.gz.uu @@ -0,0 +1,88 @@ +# $FreeBSD$ +begin 644 img-63x255-512-gpt.vmdk.gz +M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6=P="YV;61K+F]U=`"M7%UOW-81 +M?<^ON%4>$K3H@F?Y_6"@294`01'`C=WFI0]=?C5"'=F5A:(&]L>7E[SGZE!: +MBG0T"NW=,6?.WIE+SBIG#I@D\X]S6>.RS&6=RPN7P(W_-!\N21^,\3A6/''^ +MR_6/?S_PY^O#X?S%#`8?)2%(%$Z,Q>><#X]^"'=\+FIQ8CR.FW"ICVJ>!`:X +MX\J)5;AL/'F\%,+5G:;3G7\C<"X"N05IW.)*T>G803\TEW??/RWN^X_MGW[X"TSWZO3@6AO^0Q!7PG^'.?_[A^E6X>\0A_,35^;T-QVFY>0>^SB>[D+*4^W:N_YTW[_] +M]*%_=?7K^]M8.[^WOF3U!%1-A4I=GGJHD)HO7^X1_64S[9H[O[NY_^6F?3.F +M^;&_.GSI"%?XVHT;6(5US5F/(<7JSH[+/G_WO_LQ7]>%G;TAW+2(*8GQL_.C +MRTN/-6[@M!5'EV;^W?A/XX+'3#)X)W=^?WOXZ>?Q%O?%>O/ZFY\(5XU1H^>X +MP#%D3&B14S[GGS^^+-WYS7?NRB?Y]I=^N@()5\^WF7>>]P&3>?1O0M5F>-_$ +M,G]BVEEW?;H_N6]/'_O#E]?7W\:=/?EDL^D8E]9[E&*&]M?W5,ZQ<=FKP5XP[OW)7-]VXIQ[V +M7_W[7PG7SI?QN`Y_2=138.K?C%?/!-^'3YBO&+]-'JZ_O_MT:#^]N[GMQAO- +MO2)<-]=N7$Z:A$7%-3U>5/S8L797RG>H5O;;UX#H^KQU\U(._7X?B[`#U3CP0:D?/0:/\2R:UR[;@ +MRB34CIZI1F5BY`NXE=J5['?T+#6J$J->P*W4KF2_HV>C4:T8W:YDV>_H.6B4 +M?\FE=ODF'/L=/5.-RL3(%W!KM6._HV>I4948]0)NK7;L=_1L-*H5H]N5+/L= +M/0>-\B^%U*[8A&._HV>J49D8^0)NK7;L=_0L-:H2HU[`K=6._8Z>C4:U8G2[ +MDF6_H^>@4?Z%OP1!WJ_#L=_1,]6H3(Q\`;=6._8[>I8:58E1+^#6:L=^1\]& +MHUHQNEW)LM_1<]`H_T)"!O)^%:Y*0NWHF6I4)D:^@%NI7<5^1\]2HRHQZ@7< +M2NTJ]CMZ-AK5BM'M2I;]CIZ#1OF76FI7;\*QW]$SU:A,C'P!MU8[]CMZEAI5 +MB5$OX-9JQWY'ST:C6C&Z7J49D8^0)NK7;L +M=_0L-:H2HU[`K=6._8Z>C4:U8G2[DF6_H^>@4?Z%_"/D_3H<^QT]4XW*Q,@7 +M<&NU8[^C9ZE1E1CU`FZM=NQW]&PTJA6CVY4L^QT]!XWR+ZW4KMV"JY-0.WJF +M&I6)D2_@5FI7L]_1L]2H2HQZ`;=2NYK]CIZ-1K5B=+N29;^CYZ!1_J63VG6; +M<.QW]$PU*A,C7\"MU8[]CIZE1E5BU`NXM=JQW]&ST:A6C&Y7LNQW]!PTRK_T +M4KM^$X[]CIZI1F5BY`NXM=JQW]&SU*A*C'H!MU8[]CMZ-AK5BM'M2I;]CIZ# +M1OF706HW;,*QW]$SU:A,C'P!MU8[]CMZEAI5B5$OX-9JQWY'ST:C6C&Z70]ZMPIV2N7?1,-2H3(U_`K=3N%/I=]"PUJA*C7L"MU.X4^EWT +M;#2J%:/;E6SH=]%ST"A?,N'OL$EIG4*_@_!W4/X.PM]AD[\[A7X'X>^@_!V$ +MO\,F?W<*_0["WT'Y.PA_MR/9T.\@_!V4OX/P=]BDM$ZAWT'X.RA_!^'OL,G? +MG4*_@_!W4/X.PM]AD[\[A7X'X>^@_!V$O]N1;.AW$/X.RM]!^#ML4EJGT.\@ +M_!V4OX/P=]CD[TZAWT'X.RA_!^'OL,G?G4*_@_!W4/X.PM_M2#;T.PA_!^7O +M(/P=-BFM)@FU$_X.RM]!^#ML\G<-^YWP=U#^#L+?89._:]COA+^#\G<0_FY' +MLNQWPM]!^3L(?X=-2JMAOQ/^#LK?0?@[;/)W#?N=\'=0_@["WV&3OVO8[X2_ +M@_)W$/YN1[+L=\+?0?D["'^'34JK8;\3_@[*WT'X.VSR=PW[G?!W4/X.PM]A +MD[]KV.^$OX/R=Q#^;D>R['?"WT'Y.PA_ATU*JV&_$_X.RM]!^#ML\G<-^YWP +M=U#^#L+?89._:]COA+^#\G<0_FY'LNQWPM]!^3L(?X=-2JM-0NV$OX/R=Q#^ +M#IO\7^@_!V$O]N1+/N=\'=0_@[" +MWV&3TFK9[X2_@_)W$/X.F_Q=RWXG_!V4OX/P=]CD[UKV.^'OH/P=A+_;D2S[ +MG?!W4/X.PM]AD])JV>^$OX/R=Q#^#IO\7]V),M^)_P=E+^#\'?8I+0Z]COA[Z#\'82_PR9_U['?"7\' +MY>\@_!TV^;N._4[X.RA_!^'O=B3+?B?\'92_@_!WV*2T.O8[X>^@_!V$O\,F +M?]>QWPE_!^7O(/P=-OF[COU.^#LH?P?A[W8DRWXG_!V4OX/P=]BDM#KV.^'O +MH/P=A+_#)G_7L=\)?P?E[R#\'3;YNX[]3O@[*'\'X>]V),M^)_P=E+^+8CK( +M>X%S\Y\`UR=S[2Y*RB_\4ZR=N[BZWEH?.`Q[`=/+Z?H]CNDB>789G[\^3/K% +M./.8J_[;`&?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2?O)OI*Q/F[B;X2=;P3[FFRLS[P +M"%-]Y?'X[#(^?WW95+_YZ:I/_UX_V/6>O6] +M&X9PS,JYAPSC4ZPO)/SU0>`ZX_KMW]_YR'-W.CT!_!O7-^UOEOOG,6?U]'!> +M/IDWSR+ZOJ^^_X']_J;G]YZL'\\I#L]WGEH7=VYOO00R]7AF73?/KT[ +MLNGQSF/UC^7%9--5N*\NW6S9]'CGH7L&[M*Q#I<]%_6Y3P+/IL<[:Y2J;UV5 +MN^KHG]_;/7[R[`/0NP5<87SE34^>;0I7MO[YP3E<.SWLN2L\+>VJ\3:9[XFC +M.W9>B5#"'?T3F0_GV[\>;F>P/Q[^\X>POOG)L[A\K)]8JUYV?.Z*\(O:2-LG5JMWFJNW\JTV+NK2K3O"\5OM=TNXQKAZDRI_ +M%IX\_7O]Q/GU8?G?#)@%0+,59OZ1@G9WAX%,[PX/:'AW>#C# +MN\/#&=X='L[T[LC\`R/MOL0]G+_VNK'FM7^&?[Z\:M:_CL?U_?QF6MA7BW0G +MSG'UJ_^9+_'+F]$;?HE[N&>_Q(=^/=GP\RA9PR]Q#V?Z)9[YIW=TQW$3.$XT%H%91?69#"( +ML5W]U`B&^W^?2FW=$7!SF\/MCP&-`><2X'W2IS=E'-=7=YGS:\>",354!LP9 +MK/Y6X?/G\:&0<"I7P(33>[A),%70$N[*<"55WTQ1[!2O.[YFN(;&A*NVU.%- +MR&[)L1JLR5LL%GM\CN<95`>J!&F#3\?`=WYAUG=)9>@HW`U]D(;K/*Z.]RN& +MTSOA0HSS'Q7/9Y3"G=MK4G5MYF2HSY?QY![E!@`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu new file mode 100644 index 000000000000..53ce05482727 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-512-mbr.vhd.gz +M'XL("/K%'50``VEM9RTV,W@R-34M-3$R+6UBJVIZQ:T<][+;:["$'__@R!FSP5YHMMF,1P3R\ +MPPQCP9B]`&0!L@79@!34+CG(6R@5@.ET#_;OW/V%KG[_T]3_WLZ9N[J=A>4L +MM(K-R1X+X&:2$E#3)/*5VM!Y3/;C<+QY^WWT.'0X/S&7P!&$@?#9/(H-ZHCT +MZ_[QYU1=,56]3/]$?Z*.$!>I$VQB +M%S<[&PJ6(2HS1O!C*'$JEMTL:OP^PQJ7(^?>B_IV:B +M#U=210;!F/;Q=7?1I0KZP4X!)X%;[D)/.4UQ"ZGRK=63L1UW#;,(3/@.[-V/ +M5V]$0:A/YFQCS=>#L:I/DSZSMYA>>*]W=/=9?`_`JKH.J)A5&.,&AZMZ<%B+ +MT2.[5]WZU3D4S6)`^FV[#]:O>DT+5A.[,,Z0-Y`7P)3KPQ@XQ!=&?;=S&1BYNZ$/ +MYNYJPI7Q^#S`X05W(<95[KOK1T8AO+!Z^[FZ.G$PJNG.^.+.)4B\@^1B*:3*%W`&3*33`)K%"G?;[(9W"1`<% +IPB4\*!`NX4&!<`D/"H1+>%`@7,*#`N&2'A2D.0(RMOL$5&JUB%T.```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu new file mode 100644 index 000000000000..719185543b99 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-512-mbr.vhdf.gz +M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB[; +MQ/G53<'('(0$J4"S6Q6^G]Y&"CV.IG+8X]@:KA/L*V@*=PAPW%??0*'!K+#N +MPG:`V_NGPXDE=382Q$QUS#HKTQ:+MC>>%^89J`'*@>BVCV%@GU\8].UB&0RY +MNZ`/8G<+A\OQ>!K@V(J[@'%NHPKSB5*X$KU]K*Y,G`PZ7ADWKEP'P2O7XUC: +MC6#7["RV`NVH^#W?43]G^/9`T0*315"W9YOBH"I0!I1T[5R`VD&N0R##E527 +MWU^F_+G^AAEV.-H?1;&Y^8R[U:)R8(7[B3J[=J#OX7397C\O':[;JKH?"^6" +M+BU$1.YJ[.[3\>5QK(['0=(H>G0X.'O'4?0.(4[TSAK3;(%T,/2!.B:W*H>3 +79#3KO[GU.)6X5.RYN_D#OC2Q.1`)```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu new file mode 100644 index 000000000000..0c79f4371098 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-mbr.vmdk.gz.uu @@ -0,0 +1,84 @@ +# $FreeBSD$ +begin 644 img-63x255-512-mbr.vmdk.gz +M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+6UB +M::MUJP/[V%W;W4.U=-4%9=GTX=RE=9>+NW2N*%T&-_S3]')9_FP,KTNZ\?2W +MMW__\<2//YY.3U],8`A1$H),X<28O<_3:?%!N//GHF8WAM=Y%RX/4>V+P`AW +MWKBQ"3?TPYW70IA=,][NPH7`N03D9G#%2DV;Q7XNNS]\$9L7\LM##L/QEK6K +MVT71E,=JYJ\[CO'NX_/+Z/^9W#V0[.ES+X +ME[>`,!16E>$BW`AP=8`HO>W=[\,VC_^'3 +M!__F[M?W[U+OPMF&EM4CT'5L5.Z*/$#%TD+[BH`8'IOQU-S3+_>//]_?OA_* +M_.CO3E\ZPI6A=\,!7F->4]5#2+EYLD/:3]_^[W&HUW7Q9.\)-R8Q%C&\=W%V +M116PA@/,A][ENAR!]^]N,32+AZ^C(+SM,Y8#3/X2)V;8(/ +M0^P2;HPGZ]XVCXW[IOGH3U^^??M-.MDF%'L97T-J/J"4$W1XOL=V#HV;3GHZ +MZ/$HNJX]-5WSX=$_A.--1]&&I[6+E89CO3P?X_Q]JO&D^O#$N*D9X']]A>F+",04X__CPZ73[],O]NV[X +M0G-O"-=-O1O2&4YS2BKEM$PJO>W0NSL\IS9@$\Z'%DU)7>,7QH`UY?'$5N_#TZ?2S;[HA+7=W+HJ[=!3]\BBT18LN3`<]]&(ZBIC8I]-'?XMP>18/ +ML)\U9\HI/,K#DSQE-!^@C^\?QM3*_$[G<;[\7O;:>7QY\2VU^IV`$YQU?F6V +M]_V,KWP&Z`0L>\ZO#/E=Q+/0J%*,:@8W_#1Q^F[X_-?P^4'@PB-V%<]:HQHQ +MVB/=*\/WBYMX=AKEQ>@/P5UBB_@#"N1Z;"J-7&\D.+?H71%[1\]"HTHQJAG< +M5N_*V#MZUAK5B-&N9KG45Z,_A#<-?:./X!!KL?>T\7KL'8U<;VSUKN*\HV>A4:48U0QNHW<5YQT]:XUJQ&A7LUL6RWE' +MSTZCO!C](3C.NT)ZQ^NQ=S1RO;'9.\X[>A8:58I1S>"V>L=Y1\]:HQHQVM7L +MEL5RWM&STR@O1G\(CO.NE-[Q>NP=C5QO;/:.\XZ>A4:58E0SN*W><=[1L]:H +M1HQV-;MEL9QW].PTRHO1'X+CO../3I#KL74?/6J,:,=K5[);%\'GM'(]<;6[V[S6Q;+>4?/3J.\&/TA.,Z[6GK'Z[%W-'*]L=D[ +MSCMZ%AI5BE'-X+9ZQWE'SUJC&C':U>R6Q7+>T;/3*"]&?PB.\X[_\8)N-S=YQWM&ST*A2C&H&M]4[SCMZUAK5B-&N9K3'Z0W"<=V0M +M(==C[VCD>F.S=YQW]"PTJA2CFL%M]8[SCIZU1C5BM*O9+8OEO*-GIU%>C/X( +M7)W%WMVD=[P>>TR6Q7+> +MT;/3*"]&?PB.\ZZ3WO&:K';J7?<";MD[SCMZ%AI5BE'-X+9ZQWE'SUJC&C': +MU>R6Q7+>T;/3*"]&?PB.\\Y+[W@]]HY&KC\=Y1\]"HTHQJAG<5N\X[^A9 +M:U0C1KN:W;)8SCMZ=AKEQ>@/P7'>]=([7H^]HY'KC<=[1L]"H4HQJ!K?5 +M.\X[>M8:U8C1KF:W+);SCIZ=1GDQ^B-P33;U+NW<(->A=\G(]<96[YHX[Y)G +MH5&E&-4,;J-W39QWR;/6J$:,=C6[9;%QWB7/3J.\&/TAN#CO(/P=E+^#\'?8 +MY>^:..\@_!V4OX/P=]CE[YHX[R#\'92_@_!W*]DMBXWS#L+?0?D["']W`"[. +M.PA_!^7O(/P==OF[)LX["'\'Y>\@_!UV^;LFSCL(?P?E[R#\W4IVRV+CO(/P +M=U#^#L+?'8"+\P["WT'Y.PA_AUW^KHGS#L+?0?D["'^'7?ZNB?,.PM]!^3L( +M?[>2W;+8..\@_!V4OX/P=_MP;19[)_P=E+^#\'?8Y>]:SCOA[Z#\'82_PRY_ +MUW+>"7\'Y>\@_-U*=LMB.>^$OX/R=Q#^[@`_:SGOA+^# +M\G<0_@Z[_%W+>2?\'92_@_!W*]DMB^6\$_X.RM]!^+L#<)QWPM]!^3L(?X== +M_J[EO!/^#LK?0?@[[/)W+>>=\'=0_@["WZUDMRR6\T[X.RA_!^'O#L!QW@E_ +M!^7O(/P==OF[EO-.^#LH?P?A[[#+W[6<=\+?0?D["'^WDMVR6,X[X>^@_!V$ +MO]N'NV6Q=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE[VZ<=\+?0?D["'^WDMVR +M6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+?0?D["'^'7?[NQGDG_!V4 +MOX/P=RO9+8OEO!/^#LK?0?B[`W"<=\+?0?D["'^'7?[NQGDG_!V4OX/P=]CE +M[VZ<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P=]CE[VZ<=\+? +M0?D["'^'7?[NQGDG_!V4OX/P=RO9+8OEO!/^#LK?0?B[?;@NB[T3_@[*WT'X +M.^SR=QWGG?!W4/X.PM]AE[_K..^$OX/R=Q#^;B6[9;&<=\+?0?D["']W`([S +M3O@[*'\'X>^PR]]UG'?"WT'Y.PA_AUW^KN.\$_X.RM]!^+N5[);%"7\'Y>\@_!UV^;N.\T[X.RA_!^'O5K); +M%LMY)_P=E+^#\'<'X#COA+^#\G<0_@Z[_%W'>2?\'92_@_!WV.7O.LX[X>^@ +M_!V$OUO);EDLYYWP=U#^#L+?[X +M..]6%7TK_Y1ZY]:S>Z'%/P;WLMA);HA1;I@V$5.YOP]P@C.60^(:N[X/>$0. +MB;0NY^M5;R"&1UN4F;R"&1UN4F/??N]\LAD=;E]'R5'!)I74[/5\DAD=;E]'R5'!)I76XBAT1:EYO((9'6 +MY29R2*1UN8D<$FE=;B*'1%J7F\@AD=;E)G)(I'6YB1P2:5UN(H=$6I>;R"&1 +MUN4F;R"&1UN4F$-Y5#PIO*(>%-Y9#PIG)(]%EF*(=$;RJ'1&\J +MAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ'1&\JAT1O*H=$;RJ' +M1&\JAT1O*H<\9UEF*(<\9Z9RR//+7TU\#.YEL9/<\#*6._WNTI=_;]]X^N8T +M_Y,`T?XVP.%!Z/L7@"SX@O`H#P[#JRGBQ?#*>RGX!I?[U8*_#G]]=1*XSKA_ +MZ'\;8%&XIGD!^$_F=_YL&K\]O\H;G^]U?&"**OR:W:)TU_/1#'_Z]L=%AA.< +MF7YV@MO]^D@L:+\%][7`Y=/3]XRBOPERW/`]5W]YK9[';$QO +ME.OF<&%0Z7G.CG"G>U^]S.YF?!A8?F4<_,H-(/.OW`GN;#L(ZG&R3*J/EW]O +=WWCZ[C3_,P%>(J!9!R_A%Y-D7_P?*H?3&&]@```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu new file mode 100644 index 000000000000..1a19b11af56c --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.raw.gz.uu @@ -0,0 +1,12 @@ +# $FreeBSD$ +begin 644 img-63x255-512-pc98.raw.gz +M'XL("/O%'50``VEM9RTV,W@R-34M-3$R+7!C.3@NI:\3\5',=/$>`^H%'0Q\&V`,XZLOD9"+\&L-@/&<1W,,)6;MN"$,<8@ +M?RIIV,%Y=V7F^!$>"KFOL!XR*]2S0E6#5*`^0=-5A3]?WSLIT9@M)0Y'9[A% +M<#6F<(\`5[EKME)$<*H74`W^)UP'N-9]"TX>J3.1P&'/D'16Y;TLVG1^+LPS +MB`%$!:B]C3CP/[^PZFMB&<3V>B=>N>NANU>RA!__X,@:2P5])ML0.P@(> +MWOD`A!#^!Z`KT!WH%K2B>BU!;Z$V`*XQO#B49?B$OOG[IVW^O7X6X==O/*P4 +M?%0ZG,9C!=)-4@-:FD3_ICKT$5/\N'NY>GU[B3@,N#BQU"`1E(/(R3Q&'-01 +MZ?[V\>=87355=QSEY^DZJ#K6H^+JBN*&XZ0;Y?K3JZ&3@\SX)A])`\N^(`JY/EV+%Y\O!6-1G29];6\+.E,L-_6V1/@?@KKL,J!38*?`I&MR0OJV$ +M1L[YG1MYUNIH%K+OO^/;9O8?VE4AERLT)K-",RA4-6WH2H/!"8FQ +MV4+B<7@*%P7S_3[%W3!.^K93&9B8NZ(/IN9:PM5I_Y+A\(2YD.)V +MX>2-/9,0GO#>]51=DSD8N_'*.'/E$B1=N1Z'>3<".^PL+@-I%Y^4RPW]0Y$^ +M'HCA,,IVNF$X/;(IE`&83:$,YT=&A;993;9+LU`'A9FN"H3+>%4@7,:K`N$R +>7A4(E_&J0+B,5P7"9;TJ:'<)%&+S!5&O-H=?#@`` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu new file mode 100644 index 000000000000..dce8fa35c6b5 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-pc98.vhdf.gz.uu @@ -0,0 +1,15 @@ +# $FreeBSD$ +begin 644 img-63x255-512-pc98.vhdf.gz +M'XL("/S%'50``VEM9RTV,W@R-34M-3$R+7!C.3@N=FAD9BYO=70`K94];X,P +M$(;W_(J3NF6(_(U9$BEJ.E>JVLZ4FBA#VZ5#!WY\?1B"#T.25L8&&1U^>._. +M/C,6+@`E@%4SSV5#N]_0UJ[6JX[&F[\!M88J!3Y[8(<3J*]44"OPHTF'IAD[ +M,;2;R37@N#>FH'[6HF$&U[NK,L=/L(M"_JZP<)D5VDZA+D!IT`:LN%7AZ^%E +M)B6694M)P(EKN$&P;)9PNP@GPS(;*3R:57.0KG^)QQ%N&^X!IRZI\Y%@;LZP +MZ*S.NUBL;W1>G&?@#K@$9GN;H,!S?F'45Z8R!''W@CY(W:T05]#O>8035]P% +MBGM#7)1/DL(KT=NFZNK,R>#3G7'CSD4(W;D!)_(6@K*K+'X%8A5/GLN&]G%# +M6P"J'I@M@K8_W8P$TX!Q8#2."P6FA,+&0$%74EM_?;KZ^_039QAQ?'+FQ!WG +M"XF[Q10@*OR)><=QI._N<%R?/HX#;BA5PX^5P:!K#U&)NY:Z^[!_NI^JDVF0 +M+(D>1YUQV?..D^CM8IPZ.^M<5P+YV,D+,'0T[-%;FD +M2/OZM">PQ>[:[I[=OE-U89-D^G(N:UR6N:QU>>$2N.&?IH=+TA=C>&3QQNWO +M;__QXXE??SJ=;E],8/!1$H)$X<28/<_MM/@BW/ES4;,;P^.\"Y?ZJ.8N,,"= +M-VYLP@W]<.>U$&97C[=;?R%P+@*Y&5R^4M-FL9_+[@]?A.;Y_%*?PW"\1>7* +MU!5-,%V1CW;JRO-X+W'EX-0/@%^ZMX\?_^/>=A^O3X\?GM^'_,[^;`?GK/#^ +MQ=4C#(65A;_P-SQ_?L$?OP%;/S9QN:DX_/G?F+/'-EY<9T2Q=]>GKG[N?OCT +MH7OS\.O[=[%W_FQ]RZH1Z#(V*G5YZJ%":;Y]N4?T+YOQU-SME\?GGQ^OWP]E +M?NP>3E\ZPA6^=\,!7D)>4]5#2+%YLD/:MV_^]SS4Z]IPLH^$&Y,8BQB>.S^[ +MO/18PP&F0^_2U*47EX[P0\)#)1F\D[N]?W?Z[B>'(KUD[OMO__P=X2X#W.`Y +M)#B$#`7-:LJG^O/ER]+=OO_&/?@B?_BY&U^!A*NFMYEWGLX!HWGV%Z%K$[P? +M8IF_,9ZL>UL_U^[K^F-W^O+MVZ_CR=:^V&Q\#*EU'J68H/WK>VSGT+CII*># +M'H^B;9M3W=8?GKLG?[SQ*!K_:FU#I?Y8LY=CG#]/.9Y4[U\Q[O;&/3RVPYEZ +MV']W[W\EW'5Z&0]Y^)=$-0:F_F)X]8SP77B&Z17CC\G#=<]/GT[73[\\OFN' +M-YI[0[AVZMV0SG":4U(QIV52\6F'WCW@);4!FW"=;]&4U"6\,0:L*8^7+J3# +M(_>/T(7;I]//7=T.:;F'A+5IT83KHH1?3483$/IT^=M<`ER;A +M`/M9"5/&9PN?Y:]=AYG=S]2R]\).,%9YUS_/^$AG@$[`DI?\"I]?)IZY1A5BE#.XX;>)T[?#][^&[P\"YU]B%_&L-*H6 +MHSG2O<+_O+B*9ZM1G1C](;@LM(B_H$"NQZ;22/5&A'.+WN6A=_3,-:H0HYS! +M;?6N"+VC9Z51M1C-:G;+8LO0.WJV&M6)T1^"NX3>\1@=/7.-*L0H9W!;O:M#[^A9:50M1K.:W;+8)O2.GJU&=6+TA^"NH7<<*Y#K +ML7N4858I0SN*W>=:%W]*PTJA:C6D?/5J,Z,?HC +M<&42>I=)[W@]]HY&JC>V>E=RWM$SUZA"C'(&M]&[DO..GI5&U6(TJ]DMB^6\ +MHV>K49T8_2$XSKM<>L?KL74?/2J-J,9K5 +M[);%<=/7.-*L0H9W!;O>.\HV>E +M4;48S6IVRV(Y[^C9:E0G1G\(CO..OSI!KL?>T4CUQF;O.._HF6M4(48Y@]OJ +M'><=/2N-JL5H5K-;%LMY1\]6HSHQ^B-PER3T[B*]X_78.QJIWMCJW87SCIZY +M1A5BE#.XC=Y=.._H66E4+4:SFMVR6,X[>K8:U8G1'X+CO*ND=[P>>T.\HV>N4848Y0QNJW><=_2L-*H6HUG-;EDLYQT]6XWJQ.@/P7'>\3]>D.NQ +M=S12O;'9.\X[>N8:58A1SN"V>L=Y1\]*HVHQFM7LEL5RWM&SU:A.C/X0'.<= +M64O(]=@[&JG>V.P=YQT]59QW],PUJA"CG,%M]*[BO*-GI5&U&,UJ=LMB +M.>_HV6I4)T9_"([SKI7>\9JL=NQ=>P>W[!WG'3USC2K$*&=P6[WCO*-GI5&U +M&,UJ=LMB.>_HV6I4)T9_"([SKI/>\7KL'8U4;VSVCO..GKE&%6*4,[BMWG'> +MT;/2J%J,9C6[9;&<=_1L-:H3HS\$QWG72^]X/?:.1JHW-GO'>4?/7*,*,K8:U8G1'X&KDZEW<><&N?:]BT:J-[9Z5X=Y +M%SUSC2K$*&=P&[VKP[R+GI5&U6(TJ]DMBPWS+GJV&M6)T1^""_,.PM]!^3L( +M?X==_JX.\P["WT'Y.PA_AUW^K@[S#L+?0?D["'^WDMVRV##O(/P=E+^#\'<' +MX,*\@_!W4/X.PM]AE[^KP[R#\'=0_@["WV&7OZO#O(/P=U#^#L+?K62W+#;, +M.PA_!^7O(/S=`;@P[R#\'92_@_!WV.7OZC#O(/P=E+^#\'?8Y>_J,.\@_!V4 +MOX/P=RO9+8L-\P["WT'Y.PA_MP_7)*%WPM]!^3L(?X==_J[AO!/^#LK?0?@[ +M[/)W#>>=\'=0_@["WZUDMRR6\T[X.RA_!^'O#L!QW@E_!^7O(/P==OF[AO-. +M^#LH?P?A[[#+WS6<=\+?0?D["'^WDMVR6,X[X>^@_!V$OSL`QWDG_!V4OX/P +M=]CE[QK..^'OH/P=A+_#+G_7<-X)?P?E[R#\W4IVRV(Y[X2_@_)W$/[N`!SG +MG?!W4/X.PM]AE[]K..^$OX/R=Q#^#KO\7<-Y)_P=E+^#\'^NG'?"WT'Y.PA_AUW^[LIY)_P=E+^#\'^NG'?" +MWT'Y.PA_MY+=LEC..^'OH/P=A+\[`,=Y)_P=E+^#\'?8Y>^NG'?"WT'Y.PA_ +MAUW^[LIY)_P=E+^#\'^NG'?"WT'Y.PA_MY+=LEC..^'OH/P=A+_;AVN3T#OA[Z#\ +M'82_PRY_UW+>"7\'Y>\@_!UV^;N6\T[X.RA_!^'O5K);%LMY)_P=E+^#\'<' +MX#COA+^#\G<0_@Z[_%W+>2?\'92_@_!WV.7O6LX[X>^@_!V$OUO);EDLYYWP +M=U#^#L+?'8#CO!/^#LK?0?@[[/)W+>>=\'=0_@["WV&7OVLY[X2_@_)W$/YN +M);MEL9QWPM]!^3L(?W<`CO-.^#LH?P?A[[#+W[6<=\+?0?D["'^'7?ZNY;P3 +M_@[*WT'XNY7LEL5RW@E_!^7O(/S=/ER73+V+$CS(]2ACI)'JC=O8M.';#=^) +M>X$+\VY5T;?R3[%W;CV[.RW^,;C[8B>Y(4:Y8=Q$3.7^/L`)SE@.B4OH^C[@ +M$3DDXKJ;R"$1U^4F;R"$1 +MU^4F;R"$1U^4F;R"$1U^4FF17W:=QGI7[F?SQVQ0;Y3KYG#^IZZ>Y^P(=[KW +MU7UV5^/#P/*=+_!_V[IW%@```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu new file mode 100644 index 000000000000..c949873459fc --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.raw.gz.uu @@ -0,0 +1,11 @@ +# $FreeBSD$ +begin 644 img-63x255-512-vtoc8.raw.gz +M'XL("/W%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G)A=RYO=70`K9)!;L,@ +M$$7W/L5?=V$Q@&V\JI16V56JU`O4-G"`K#E\2'!"C+'C1![0"&GF/\T7PU@( +M0-9H..KJ$?VGXEN3"'4_&'/Z^N?@IK^&*`"-?G/>/JL6"*Y-P +MQ<<(5!,=K0,56`O&L\"`:Z.J?8I;FR_@NKWL!ER_%5?[K*$-C$EP_P^X8>?/ +MH)E=`PH/\89=NMD5L=G:2Q9V"4<1]YGBHEV>J#BB/C,=LM/I.ZX?(,54M6KV +M*XT*PPS*.KP[QZJHT6EV!E>_J,GFYX'[+Z0G`?@3N-2$U +-2M6,%6>->Z%+`P4````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu new file mode 100644 index 000000000000..523a1ae8f369 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhd.gz.uu @@ -0,0 +1,18 @@ +# $FreeBSD$ +begin 644 img-63x255-512-vtoc8.vhd.gz +M'XL("/W%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9"YO=70`K9;-;MLP +M#,?O>0H"N_5@R)0LVZ<"Z];;@`%[@HA56D=&M3(V>WOQMI]=S&$"DZ3@P**Y>;071@H/Y:X5:B\<_=L:F?238I? +MQAFT.ZK8=]?.NX?3IE$CU:H\.HQL\%>M<*@.K(YP.^XZ=I=N*P4()Y5BOK8: +M`33UNLW]NW_VGBXNZB^)/K<3+/]]'*Y*[/YQV2I0-2>QW>-P]6Q5O__N.B?E +M[HAKWHJCG*$ZZ#QXO\!]CW"M\&$T*W?]$/]J2+]7N]M,[NIY\GBO*+/OX**\ +M?+O$M5YV'Z*U=NX[D_:S;`T````` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu new file mode 100644 index 000000000000..d8c4d3d6bf31 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vhdf.gz.uu @@ -0,0 +1,14 @@ +# $FreeBSD$ +begin 644 img-63x255-512-vtoc8.vhdf.gz +M'XL("/[%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G9H9&8N;W5T`*V4O6[# +M(!2%]SS%D;IEB,R/L3U%ZD^V2I7Z`K4-1!G:2E6'#G[X8K!C(-A-(V.$B.!\ +MG$LN-\M<`[A`02'ROG.*G(%S,`HP,Y,P6Z*.[O"EU/WK(V7/.]NZC8,1LWBY +M?U#-+G2[J'6;[0`L`QU9!I;(*F0T"72X:E)5?^*6_#ECMO3^W'$T2&J\6!3H\^E.7X291CNP13F +MV!V++\E7N3=H?#(=/AK_]O8^CI^#-05(-];FV(,?P4(J^RPNSR+5S6_#XL3* +.J6)R;_,+FZ-::BX'```` +` +end diff --git a/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu new file mode 100644 index 000000000000..d9340d12bc61 --- /dev/null +++ b/usr.bin/mkimg/tests/img-63x255-512-vtoc8.vmdk.gz.uu @@ -0,0 +1,83 @@ +# $FreeBSD$ +begin 644 img-63x255-512-vtoc8.vmdk.gz +M'XL("/[%'50``VEM9RTV,W@R-34M-3$R+79T;V,X+G9M9&LN;W5T`*U<76_= +MQA%]SZ\@[#X412%PR+DD[X-1-U$"%$6`(`[:U_!CV0A-;$,6BAK0C^\NN6=U +MJ'OI9:-QJ$#C.W.T,^0]DL\A5E_13X:TPO +M//[]]OM_W-"?QZ]6,`E55"(EPU&P^3J/-\_^`*[Z4M7F!7]56;C:ORC#16&$ +MJW9>V(73,+MK)3A=7_@&RBE\0G!O$U"Q@3M=Z6FWV2^=[D]?Q>'YEZLZG,'? +MWN9N39@_XNKB]^_3OXM9]&N_O/CY\B.>KPKWU +MR=J$_&8,"+ZQM@F?A!<"W#E`-*ZHIZ*6\'+Q>/_=W:_NYC_N_M/=A_=O!.U6 +MX=YJ7>@Y'"?DET_7)@A?I"P:"5^C>/SF;[=OXI-;WGSL[P$7JOQ!_-?V?3!N +MTQ3AX_):3N?>/P3$.?Y)IPOW-@[GM'QM#9^/[LVKWSZ\3[,+]S:,[+P`=67_LQV__^^#[+:9X9^\`MQQB +M:<)_[5-5G-J`5?OQ^2I_'VO?;!7^RA_8=Z(2DHK'#^]O?ORG'[3XZ-T/?_T1 +M<)V'\YG^@+[$-[3IZ;3V?WK^6!:/[[XM7H4F?_K%+4\@X,[A,5Z3U_L@2UB% +M3^+45OA`8AI>6.YL<=L_],77_2=W\_KV]NMT9_O0K"Z7/YH+*,T*'9[O99Q^ +M<.N=7F_T'4W^7L:8/_E/OP&N'%]C/TYPB-Q7@KK\(E_>A9X%[_"^L2$VQ3@W,/]YYOQ +M\Z]W[R?_1BO>`&Y:9^>/4]?Q4.E,SP^5OJR?W:OZZ6@>&W`NC&@]5!??&!YK +M/_N'[RQRI>5:?3JW0KYN>W@D?T;`KKC?:S6&]%/-CG +MFT]NC'!U&6_@O!G.>J:B;IY&L"70AP_WR]$:WS/Q]E+^5@OOJ6V#,C? +ME^8#WWXTG$\(3MK?>;X5[N)[[0O;;@V<#NS6QZ5,V7V7#50,!YI=GE4)LIT +M7#67FQ\CLS\V2E/%V2&SXJJ:`KV`NS*[IHZS0V;#52T%W09N;W8:9X?,GJL& +M"L9#S9[B[)#IN&HNMS\FUUFX)LX.F157U13H!=RUV;5Q=LALN*JEH-O`['S(JK:@KT`N[:[,!WR&RXJJ6@ +MV\#MS0Y\A\R>JP8*QD/-@N^0Z;AJIB!^0V7!5 +M2T&W@=N975O&V2&SYZJ!@O%(LRWX#IF.JV8*PM5DXZX:*!@/-0N^0Z;CJIF"<+59./`=,BNNJBG0"[AK +MLP/?(;/AJI:";@.W-SOP'3)[KAHH&`\U"[Y#IN.JN=S\@%MV63CP'3(KKJHI +MT`NX:[,#WR&SX:J6@FX#MS<[\!TR>ZX:*!@/-0N^0Z;CJIF"<)VS<.`[9%9< +M55.@%W#79@>^0V;#52T%W09N9W9=&6>'S)ZK!@K&(\UVX#MD.JZ:*0A7GX4# +MWR&SXJJ:`KV`NS*[#GR'S(:K6@JZ#=S>[,!WR.RY:J!@/-0L^`Z9CJOF#V9@>^0V;/50,%XZ%FP7?(=%PU +ME]M_PX]9./`=,BNNJBG0"[AKLP/?(;/AJI:";@.W-SOP'3)[KAHH&`\U"[Y# +MIN.JF8)P35DX\!TR*ZZJ*=`+N&NS`]\AL^&JEH)N`[U%'0;N+W9@>^0V7/5 +M0,%XJ%GP'3(=5\T4A&O.PH'OD%EQ54V!7L!=FQWX#ID-5[44=!NXO=F![Y#9 +M<]5`P7BH6?`=,AU7S>5&ITR;OGVXR'DWPGK=T+ZG63UNW/D.R'] +M3EB_$]+O)*O?]66<'>EWPOJ=D'Z7;[:/?">DWPGK=T+ZG60EK3[RG9!^)ZS? +M">EWDM7O^LAW0OJ=L'XGI-])5K_K(]\)Z7?"^IV0?G>@VDWPGK=T+ZG63UNS[RG9!^)ZS?">EW!YJ- +M?">DWPGK=YMM2U;2ZL%WI-\)ZW="^IUD];L>?$?ZG;!^)Z3?25:_Z\%WI-\) +MZW="^MV!9L%WI-\)ZW="^IUD):T>?$?ZG;!^)Z3?25:_Z\%WI-\)ZW="^IUD +M];NAC+,C_4Y8OQ/2[_+-#N`[TN^$]3LA_4ZRDM8`OB/]3EB_$]+O)*O?#>`[ +MTN^$]3LA_4ZR^MT`OB/]3EB_$]+O#C0+OB/]3EB_$]+O)"MI#>`[TN^$]3LA +M_4ZR^MT`OB/]3EB_$]+O)*O?#>`[TN^$]3LA_>Y`L^`[TN^$]3O>*$M6TAK` +M=Z3?">MW0OJ=9/6[`7Q'^IVP?B>DWTE6OQO`=Z3?">MW0OK=@6;!=Z3?">MW +M0OJ=9"6M`7Q'^IVP?B>DWTE6OQO`=Z3?">MW0OJ=9/6[L8RS(_U.6+\3TN_R +MS8[@.]+OA/4[(?U.LI+6"+XC_4Y8OQ/2[R2KWXW@.]+OA/4[(?U.LOK="+XC +M_4Y8OQ/2[PXT"[XC_4Y8OQ/2[R0K:8W@.]+OA/4[(?U.LOK="+XC_4Y8OQ/2 +M[R2KWXW@.]+OA/4[(?WN0+/@.]+OA/4[]H9*5M(:P7>DWPGK=T+ZG63UNQ%\ +M1_J=L'XGI-])5K\;P7>DWPGK=T+ZW8%FP7>DWPGK=T+ZG60EK1%\1_J=L'XG +MI-])5K\;P7>DWPGK=T+ZG63UNZF,LR/]3EB_$]+O\LU.X#O2[X3U.R']3K*2 +MU@2^(_U.6+\3TN\DJ]]-X#O2[X3U.R']3K+ZW02^(_U.6+\3TN\.-`N^(_U. +M6+\3TN\D*VE-X#O2[X3U.R']3K+ZW02^(_U.6+\3TN\DJ]]-X#O2[X3U.R'] +M[D"SX#O2[X3U.R']KBJOPQ5/<)'O*BIYJJHIT"V5 +MOTJS*ZXW.WZI:A_N3&G,:GS0HJ)_SE;=<\!PQ#_XCS^F\]6+*:TB +MN/K8^?XLEQVMF5VS[HSMFIK6^;A>9-?4M,[']2*[IJ9U/JX7 +MV34UK?--[)J:UODF=DU-ZWP3NZ:F=;Z)75/3.M_$KJEIG6]BU]2TSC>Q:VI: +MYYO8-36M\TWLFIK6^29V34WK?!.[IJ9UOHE=4],ZW\2NJ6F=;V+7U+3.-[%K +M:EKGF]@U-:WS3>R:FM;Y)G9-3>M\$[NFIG6^B5U3TSK?Q*ZI:9UO8M?4M,XW +ML6MJ6N>;V#4UK?--[)J:UODF=DU-ZWP3NZ:F=;Z)75.QSK>Q:RK6^39V3<4Z +MW\:NJ5CGV]@U%>M\&[NF8IUO8]=4K/-M[)J*=;Z-75.QSK>Q:RK6^39V3<4Z +MW\:NJ5CGV]@U%>M\&[NF8IUO8]=4K/-M[)J*=;Z-75.QSK>Q:RK6^39V3<4Z +MW\:NJ5CGV]@U%>M\&[NF8IUO8]=4K/-M[)J*=;Z-75.QSK>Q:RK6^39V3<4Z +MW\:NJ5CGV]@U%>M\&[NF8IUO8]=4K/-M[)J*=;Z-75/3.A^9+[)K:EKG(_-% +M=DU-ZWQDOLBNJ6F=C\P7V34UK?--[)J:UODF=DU-ZWP3NZ:F=;Z)75/3.M_$ +MKJEIG6]BU]2TSC>Q:VI:YYO8-36M\TWLFIK6^29V34WK?!.[IJ9UOHE=4],Z +MW\2NJ6F=;V+7U+3.-[%K:EKGF]@U-:WS3>R:FM;Y)G9-3>M\$[NFIG6^B5U3 +MTSK?Q*ZI:9UO8M?4M,XWL6MJ6N>;V#4UK?--[)J:UODF=DU-ZWP3NZ:F=;Z) +M75.QSK>Q:RK6^39V39U,[9HZF=HU=3*U:^ID:M=45Y:&=DUUIG9-=:9V376F +M=DUUIG9-=:9V376F=DUUIG9-=:9V376F=DUUIG9-=:9V376F=DUUIG9-=:9V +M376F=DV=R]+0KJFSJ5U39U.[ILZF=DV=3>V:.IO:-74VM6OJ;&K7U-G4KJFS +MJ5U39U.[ILZF=DV=C>V:71E>U@:_L?<4?@_L:?F=L'7X[9]U^/W6UP"_NW?N +MZW>W5?T]GZ^[^$W6+SY?MZF3+P-VRU*TVGU8NO+\5'7.PGWI?"M<;]7N"C<< +MA5LW-Y,KG'L&]S/!63\LV2X#0O;]9ZWH.3)[B_/(=[:O?Y +MNZTJGNJOG*ZX>KHIP0UC^-78QZ?WS34X9_JHR'P4;NJ+P3\G4LSC/ESUQ4/\ +G_X]*OP"N_H#+_^^_X+]G;/];`34"FIU0_7NC++_Z'WN7IO#-7P`` +` +end diff --git a/usr.bin/mkimg/tests/mkimg.sh b/usr.bin/mkimg/tests/mkimg.sh new file mode 100755 index 000000000000..7c2221c03a52 --- /dev/null +++ b/usr.bin/mkimg/tests/mkimg.sh @@ -0,0 +1,141 @@ +# $FreeBSD$ + +mkimg_blksz_list="512 4096" +mkimg_format_list="raw vhd vhdf vmdk" +mkimg_geom_list="1x1 63x255" +mkimg_scheme_list="apm bsd ebr gpt mbr pc98 vtoc8" + +bootcode() +{ + case $1 in + bsd|pc98) echo 8192 ;; + gpt|mbr) echo 512 ;; + *) echo 0 ;; + esac + return 0 +} + +mkcontents() +{ + local byte count name + + byte=$1 + count=$2 + + name=_tmp-$byte-$count.bin + jot -b $byte $(($count/2)) > $name + echo $name + return 0 +} + +makeimage() +{ + local blksz bootarg bootsz format geom nhds nsecs partarg pfx scheme + + format=$1 + scheme=$2 + blksz=$3 + geom=$4 + pfx=$5 + shift 5 + + nsecs=${geom%x*} + nhds=${geom#*x} + + bootsz=`bootcode $scheme` + if test $bootsz -gt 0; then + bootarg="-b `mkcontents B $bootsz`" + else + bootarg="" + fi + + partarg="" + for P in $*; do + partarg="$partarg -p $P" + done + if test -z "$partarg"; then + local swap ufs + swap="-p freebsd-swap::128K" + ufs="-p freebsd-ufs:=`mkcontents P 4194304`" + partarg="$ufs $swap" + fi + + imagename=$pfx-$geom-$blksz-$scheme.$format + + mkimg -y -f $format -o $imagename -s $scheme -P $blksz -H $nhds -T $nsecs \ + $bootarg $partarg + echo $imagename + return 0 +} + +mkimg_test() +{ + local blksz format geom scheme + + geom=$1 + blksz=$2 + scheme=$3 + format=$4 + + case $scheme in + ebr|mbr|pc98) + bsd=`makeimage raw bsd $blksz $geom _tmp` + partinfo="freebsd:=$bsd" + ;; + *) + partinfo="" + ;; + esac + image=`makeimage $format $scheme $blksz $geom img $partinfo` + result=$image.out + hexdump -C $image > $result + baseline=`atf_get_srcdir`/$image + if test "x$mkimg_update_baseline" = "xyes"; then + echo '# $FreeBSD$' > $image.gz.uu + gzip -c $result | uuencode $image.gz >> $image.gz.uu + rm $image $result _tmp-* + else + atf_check -s exit:0 cmp -s $baseline $result + fi + return 0 +} + +atf_test_case rebase +rebase_body() +{ + local nm + + mkimg_update_baseline=yes + for nm in $mkimg_tests; do + ${nm}_body + done + return 0 +} + +atf_init_test_cases() +{ + local B F G S nm nr + + nr=1 + for G in $mkimg_geom_list; do + for B in $mkimg_blksz_list; do + for S in $mkimg_scheme_list; do + for F in $mkimg_format_list; do + nm="test_$nr" + # nm="$G_$B_$S_$F" + atf_test_case $nm + eval "${nm}_body() { mkimg_test $G $B $S $F; }" + mkimg_tests="${mkimg_tests} ${nm}" + atf_add_test_case $nm + nr=$((nr+1)) + done + done + done + done + + # XXX hack to make updating the baseline easier + if test "${__RUNNING_INSIDE_ATF_RUN}" != "internal-yes-value"; then + atf_add_test_case rebase + fi +} + -- cgit v1.3 From 1ed3631a02ef1d3ab8375f924a14f310d983aa7b Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Mon, 22 Sep 2014 09:54:48 +0000 Subject: Register /usr/tests/lib/libproc to fix build. Missed in r271937, reviewed in D710. --- etc/mtree/BSD.tests.dist | 2 ++ 1 file changed, 2 insertions(+) (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 527e611d014b..beec7a3e06bb 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -89,6 +89,8 @@ .. libnv .. + libproc + .. libutil .. .. -- cgit v1.3 From 0fc950b70ae234f3242515b271897a12aa3f7179 Mon Sep 17 00:00:00 2001 From: Stefan Eßer Date: Mon, 22 Sep 2014 11:54:13 +0000 Subject: The new naming scheme for keymap files for use with vt(4) introduced a collision for "no" as a country code with "NO" meaning "do not load any keymap" (which also has been the default value in etc/defaults/rc.conf for a long time). The result of this collision is, that "kbdcontrol -l no" will load the Norwegian keymap, while "keymap=no" in rc.conf was interpreted as the lower case spelling of "NO" meaning "no keyboard" (and "no.kbd" was not loaded). Fix this by matching only the upper-case spelling "NO" in rc.d/syscons when deciding whether to load a keymap file. This will lead to "no.kbd" being loaded, if the until now valid (but non-default) spelling "no" was used in an individual rc.conf file to mean "no keyboard". But all alternatives I could think of introduce a larger violation of POLA ... Reported by: Gyrd Thane Lange (gyrd-se at thanelange.no) MFC after: 3 days --- etc/rc.d/syscons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/syscons b/etc/rc.d/syscons index 0dc41ad5f0b8..a60ac4c7318d 100755 --- a/etc/rc.d/syscons +++ b/etc/rc.d/syscons @@ -167,7 +167,7 @@ syscons_configure_keyboard() # keymap # case ${keymap} in - [Nn][Oo] | '') + NO | '') ;; *) sc_init -- cgit v1.3 From 8302963dc2e556e676136ad3b78eaa2a3280588a Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Tue, 23 Sep 2014 18:38:06 +0000 Subject: Remove settings for pkg_* scripts which are no longer present. MFC after: 1 week --- etc/defaults/periodic.conf | 8 -------- 1 file changed, 8 deletions(-) (limited to 'etc') diff --git a/etc/defaults/periodic.conf b/etc/defaults/periodic.conf index 8520fc5bbf35..bbf97d9a36b2 100644 --- a/etc/defaults/periodic.conf +++ b/etc/defaults/periodic.conf @@ -75,10 +75,6 @@ daily_backup_passwd_enable="YES" # Backup passwd & group # 210.backup-aliases daily_backup_aliases_enable="YES" # Backup mail aliases -# 220.backup-pkgdb -daily_backup_pkgdb_enable="YES" # Backup /var/db/pkg -daily_backup_pkgdb_dir="/var/backups" - # 300.calendar daily_calendar_enable="NO" # Run calendar -a @@ -257,10 +253,6 @@ security_status_passwdless_period="daily" security_status_logincheck_enable="YES" security_status_logincheck_period="daily" -# 460.chkportsum -security_status_chkportsum_enable="NO" # Check ports w/ wrong checksum -security_status_chkportsum_period="daily" - # 500.ipfwdenied security_status_ipfwdenied_enable="YES" security_status_ipfwdenied_period="daily" -- cgit v1.3 From d8eaf8b5dfb3fa583668dbad8b3fa8d5e109ad71 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 23 Sep 2014 22:07:08 +0000 Subject: Don't install /etc/rc.d/keyserv unless MK_OPENSSL == yes Sponsored by: EMC / Isilon Storage Division --- etc/rc.d/Makefile | 5 ++++- tools/build/mk/OptionalObsoleteFiles.inc | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 186c9743d665..12c87db584cd 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -72,7 +72,6 @@ FILES= DAEMON \ jail \ kadmind \ kdc \ - keyserv \ kfd \ kld \ kldxref \ @@ -186,6 +185,10 @@ _nscd= nscd _opensm= opensm .endif +.if ${MK_OPENSSL} != "no" +FILES+= keyserv +.endif + .if ${MK_OPENSSH} != "no" _sshd= sshd .endif diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 67b132c1d621..a12775b8b083 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -3510,9 +3510,9 @@ OLD_FILES+=usr/libexec/ssh-pkcs11-helper OLD_FILES+=usr/sbin/sshd .endif -#.if ${MK_OPENSSL} == no -# to be filled in -#.endif +.if ${MK_OPENSSL} == no +OLD_FILES+=etc/rc.d/keyserv +.endif .if ${MK_PC_SYSINSTALL} == no # backend-partmanager -- cgit v1.3 From 89d65d77e6adc3f90544e6c908a8040b552f765a Mon Sep 17 00:00:00 2001 From: Warren Block Date: Thu, 25 Sep 2014 21:57:35 +0000 Subject: Revised to better point to release notes and errata, security advisories, and be more specific about the -questions list. MFC after: 3 days --- etc/motd | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'etc') diff --git a/etc/motd b/etc/motd index e616d517e0a5..e70e98d025c9 100644 --- a/etc/motd +++ b/etc/motd @@ -1,12 +1,13 @@ FreeBSD ?.?.? (UNKNOWN) -Welcome to FreeBSD! Handy technical support resources: +Welcome to FreeBSD! -Security advisories and errata: https://www.FreeBSD.org/releases/ -Handbook: https://www.FreeBSD.org/handbook/ -FAQ: https://www.FreeBSD.org/faq/ -Mailing list: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/ -Forums: https://forums.FreeBSD.org/ +Release Notes, Errata: https://www.FreeBSD.org/releases/ +Security Advisories: https://www.FreeBSD.org/security/ +FreeBSD Handbook: https://www.FreeBSD.org/handbook/ +FreeBSD FAQ: https://www.FreeBSD.org/faq/ +Questions List: https://lists.FreeBSD.org/mailman/listinfo/freebsd-questions/ +FreeBSD Forums: https://forums.FreeBSD.org/ Documents installed with the system are in the /usr/local/share/doc/freebsd/ directory, or can be installed later with: pkg install en-freebsd-doc @@ -14,7 +15,6 @@ For other languages, replace "en" with a language code like de or fr. Show the version of FreeBSD installed: uname -a Please include that output and any error messages when posting questions. - Introduction to manual pages: man man FreeBSD directory layout: man hier -- cgit v1.3 From 371b7a54c3b254841c7007581bf04b887b1db5ff Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Sun, 28 Sep 2014 12:41:48 +0000 Subject: Regenerate usb.conf MFC after: 3 days --- etc/devd/usb.conf | 128 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 115 insertions(+), 13 deletions(-) (limited to 'etc') diff --git a/etc/devd/usb.conf b/etc/devd/usb.conf index c8d252abe387..7828a8561cfe 100644 --- a/etc/devd/usb.conf +++ b/etc/devd/usb.conf @@ -65,7 +65,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x03f0"; - match "product" "(0x2016|0x2116|0x2216|0x3016|0x3116)"; + match "product" "(0x2016|0x2116|0x2216)"; + action "kldload -n uipaq"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x241d|0x251d)"; + action "kldload -n u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x03f0"; + match "product" "(0x3016|0x3116)"; action "kldload -n uipaq"; }; @@ -129,7 +145,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0403"; - match "product" "(0x6001|0x6004|0x6006|0x6006|0x6010|0x6011|0x6014|0x6015|0x8372|0x9378|0x9379|0x937a|0x937c|0x9868|0x9e90|0x9f80|0xa6d0|0xabb8|0xb810|0xb811|0xb812|0xbaf8|0xbbe2|0xbca0|0xbca1|0xbca2|0xbca4|0xbcd8|0xbcd9|0xbcda|0xbdc8|0xbfd8|0xbfd9|0xbfda|0xbfdb|0xbfdc|0xc7d0|0xc850|0xc991|0xcaa0|0xcc48|0xcc49|0xcc4a|0xd010|0xd011|0xd012|0xd013|0xd014|0xd015|0xd016|0xd017|0xd070|0xd071|0xd388|0xd389|0xd38a|0xd38b|0xd38c|0xd38d|0xd38e|0xd38f|0xd578|0xd678|0xd738|0xd780|0xdaf8|0xdaf9|0xdafa|0xdafb|0xdafc|0xdafd|0xdafe|0xdaff|0xdc00|0xdc01|0xdd20|0xdf28|0xdf30|0xdf31|0xdf32|0xdf33|0xdf35|0xe000|0xe001|0xe002|0xe004|0xe006|0xe008|0xe009|0xe00a|0xe050|0xe0e8|0xe0e9|0xe0ea|0xe0eb|0xe0ec|0xe0ed|0xe0ee|0xe0ef|0xe0f0|0xe0f1|0xe0f2|0xe0f3|0xe0f4|0xe0f5|0xe0f6|0xe0f7|0xe40b|0xe520|0xe548|0xe6c8|0xe700|0xe729|0xe808|0xe809|0xe80a|0xe80b|0xe80c|0xe80d|0xe80e|0xe80f|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xe88d|0xe88e|0xe88f|0xea90|0xebe0|0xec88|0xec89|0xed22|0xed71|0xed72|0xed73|0xed74|0xee18|0xeee8|0xeee9|0xeeea|0xeeeb|0xeeec|0xeeed|0xeeee|0xeeef|0xef50|0xef51|0xf068|0xf069|0xf06a|0xf06b|0xf06c|0xf06d|0xf06e|0xf06f|0xf070|0xf0c0|0xf0c8|0xf208|0xf2d0|0xf3c0|0xf3c1|0xf3c2|0xf448|0xf449|0xf44a|0xf44b|0xf44c|0xf460|0xf608|0xf60b|0xf680|0xf850|0xf857|0xf9d0|0xf9d1|0xf9d2|0xf9d3|0xf9d4|0xf9d5|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfa05|0xfa06|0xfa10|0xfa33|0xfa88|0xfad0|0xfaf0|0xfb58|0xfb59|0xfb5a|0xfb5b|0xfb5c|0xfb5d|0xfb5e|0xfb5f|0xfb80|0xfb99|0xfbfa|0xfc08|0xfc09|0xfc0a|0xfc0b|0xfc0c|0xfc0d|0xfc0e|0xfc0f|0xfc60|0xfc70|0xfc71|0xfc72|0xfc73|0xfc82|0xfd60|0xfe38|0xff00|0xff18|0xff1c|0xff1d|0xff20|0xff38|0xff39|0xff3a|0xff3b|0xff3c|0xff3d|0xff3e|0xff3f|0xffa8)"; + match "product" "(0x6001|0x6004|0x6006|0x6006|0x6010|0x6011|0x6014|0x6015|0x8372|0x9378|0x9379|0x937a|0x937c|0x9868|0x9e90|0x9f80|0xa6d0|0xa6d1|0xabb8|0xb810|0xb811|0xb812|0xbaf8|0xbbe2|0xbca0|0xbca1|0xbca2|0xbca4|0xbcd8|0xbcd9|0xbcda|0xbdc8|0xbfd8|0xbfd9|0xbfda|0xbfdb|0xbfdc|0xc7d0|0xc850|0xc991|0xcaa0|0xcc48|0xcc49|0xcc4a|0xd010|0xd011|0xd012|0xd013|0xd014|0xd015|0xd016|0xd017|0xd070|0xd071|0xd388|0xd389|0xd38a|0xd38b|0xd38c|0xd38d|0xd38e|0xd38f|0xd578|0xd678|0xd738|0xd780|0xdaf8|0xdaf9|0xdafa|0xdafb|0xdafc|0xdafd|0xdafe|0xdaff|0xdc00|0xdc01|0xdd20|0xdf28|0xdf30|0xdf31|0xdf32|0xdf33|0xdf35|0xe000|0xe001|0xe002|0xe004|0xe006|0xe008|0xe009|0xe00a|0xe050|0xe0e8|0xe0e9|0xe0ea|0xe0eb|0xe0ec|0xe0ed|0xe0ee|0xe0ef|0xe0f0|0xe0f1|0xe0f2|0xe0f3|0xe0f4|0xe0f5|0xe0f6|0xe0f7|0xe40b|0xe520|0xe548|0xe6c8|0xe700|0xe729|0xe808|0xe809|0xe80a|0xe80b|0xe80c|0xe80d|0xe80e|0xe80f|0xe888|0xe889|0xe88a|0xe88b|0xe88c|0xe88d|0xe88e|0xe88f|0xea90|0xebe0|0xec88|0xec89|0xed22|0xed71|0xed72|0xed73|0xed74|0xee18|0xeee8|0xeee9|0xeeea|0xeeeb|0xeeec|0xeeed|0xeeee|0xeeef|0xef50|0xef51|0xf068|0xf069|0xf06a|0xf06b|0xf06c|0xf06d|0xf06e|0xf06f|0xf070|0xf0c0|0xf0c8|0xf208|0xf2d0|0xf3c0|0xf3c1|0xf3c2|0xf448|0xf449|0xf44a|0xf44b|0xf44c|0xf460|0xf608|0xf60b|0xf680|0xf850|0xf857|0xf9d0|0xf9d1|0xf9d2|0xf9d3|0xf9d4|0xf9d5|0xfa00|0xfa01|0xfa02|0xfa03|0xfa04|0xfa05|0xfa06|0xfa10|0xfa33|0xfa88|0xfad0|0xfaf0|0xfb58|0xfb59|0xfb5a|0xfb5b|0xfb5c|0xfb5d|0xfb5e|0xfb5f|0xfb80|0xfb99|0xfbfa|0xfc08|0xfc09|0xfc0a|0xfc0b|0xfc0c|0xfc0d|0xfc0e|0xfc0f|0xfc60|0xfc70|0xfc71|0xfc72|0xfc73|0xfc82|0xfd60|0xfe38|0xff00|0xff18|0xff1c|0xff1d|0xff20|0xff38|0xff39|0xff3a|0xff3b|0xff3c|0xff3d|0xff3e|0xff3f|0xffa8)"; action "kldload -n uftdi"; }; @@ -1057,7 +1073,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0586"; - match "product" "(0x3416|0x341a)"; + match "product" "(0x3416|0x341a|0x341e)"; action "kldload -n if_run"; }; @@ -1097,7 +1113,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x05ac"; - match "product" "(0x020d|0x020e|0x020f|0x0215|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c)"; + match "product" "(0x020d|0x020e|0x020f|0x0210|0x0214|0x0215|0x0216|0x0217|0x0218|0x0219|0x021a|0x021b|0x021c)"; action "kldload -n atp"; }; @@ -2353,7 +2369,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0b05"; - match "product" "(0x17b5|0x17cb)"; + match "product" "0x17b5"; + action "kldload -n ng_ubt"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "0x17ba"; + action "kldload -n if_urtwn"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0b05"; + match "product" "0x17cb"; action "kldload -n ng_ubt"; }; @@ -2481,7 +2513,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0bda"; - match "product" "(0x018a|0x317f)"; + match "product" "(0x0179|0x018a|0x317f)"; action "kldload -n if_urtwn"; }; @@ -2513,7 +2545,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x0bda"; - match "product" "(0x8176|0x8176|0x8177|0x8178|0x817a|0x817b|0x817c|0x817d|0x817e)"; + match "product" "(0x8176|0x8176|0x8177|0x8178|0x8179|0x817a|0x817b|0x817c|0x817d|0x817e)"; action "kldload -n if_urtwn"; }; @@ -2925,6 +2957,14 @@ nomatch 32 { action "kldload -n if_urtwn"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x0df6"; + match "product" "0x0072"; + action "kldload -n if_axge"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -3577,7 +3617,23 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x12d1"; - match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1464|0x1465|0x14ac|0x14c9|0x14d1|0x14fe|0x1505|0x1506|0x1520|0x1521|0x1803|0x1c05|0x1c0b)"; + match "product" "(0x1001|0x1003|0x1004|0x1401|0x1402|0x1403|0x1404|0x1405|0x1406|0x1407|0x1408|0x1409|0x140a|0x140b|0x140c|0x140d|0x140e|0x140f|0x1410|0x1411|0x1412|0x1413|0x1414|0x1415|0x1416|0x1417|0x1418|0x1419|0x141a|0x141b|0x141c|0x141d|0x141e|0x141f|0x1420|0x1421|0x1422|0x1423|0x1424|0x1425|0x1426|0x1427|0x1428|0x1429|0x142a|0x142b|0x142c|0x142d|0x142e|0x142f|0x1430|0x1431|0x1432|0x1433|0x1434|0x1435|0x1436|0x1437|0x1438|0x1439|0x143a|0x143b|0x143c|0x143d|0x143e|0x143f|0x1446|0x1464|0x1465|0x14ac|0x14c9|0x14d1|0x14fe|0x1505|0x1506|0x1520|0x1521)"; + action "kldload -n u3g"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "product" "0x155b"; + action "kldload -n if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "product" "(0x1803|0x1c05|0x1c0b)"; action "kldload -n u3g"; }; @@ -3753,7 +3809,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x1410"; - match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5020|0x5041|0x5100|0x6000|0x6002|0x7042)"; + match "product" "(0x1100|0x1110|0x1120|0x1130|0x1400|0x1410|0x1420|0x1430|0x1450|0x2100|0x2110|0x2120|0x2130|0x2400|0x2410|0x2420|0x4100|0x4400|0x5010|0x5020|0x5041|0x5100|0x6000|0x6002|0x7001|0x7031|0x7042)"; action "kldload -n u3g"; }; @@ -4553,7 +4609,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x1cf1"; - match "product" "(0x0001|0x0004)"; + match "product" "(0x0001|0x0004|0x0022)"; action "kldload -n uftdi"; }; @@ -4565,6 +4621,14 @@ nomatch 32 { action "kldload -n u3g"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x1d34"; + match "product" "0x0004"; + action "kldload -n uled"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -4633,7 +4697,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x2001"; - match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d)"; + match "product" "(0x3307|0x3308|0x3309|0x330a|0x330d|0x330f)"; action "kldload -n if_urtwn"; }; @@ -4665,7 +4729,7 @@ nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; match "vendor" "0x2001"; - match "product" "(0x3c09|0x3c0a|0x3c15|0x3c1a|0x3c1b|0x3c1f)"; + match "product" "(0x3c09|0x3c0a|0x3c15|0x3c1a|0x3c1b|0x3c1f|0x3c20)"; action "kldload -n if_run"; }; @@ -4685,6 +4749,14 @@ nomatch 32 { action "kldload -n if_aue"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x2001"; + match "product" "0x4a00"; + action "kldload -n if_axge"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5229,6 +5301,36 @@ nomatch 32 { action "kldload -n ng_ubt"; }; +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "intclass" "0xff"; + match "intsubclass" "0x02"; + match "intprotocol" "0x16"; + action "kldload -n if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "intclass" "0xff"; + match "intsubclass" "0x02"; + match "intprotocol" "0x46"; + action "kldload -n if_cdce"; +}; + +nomatch 32 { + match "bus" "uhub[0-9]+"; + match "mode" "host"; + match "vendor" "0x12d1"; + match "intclass" "0xff"; + match "intsubclass" "0x02"; + match "intprotocol" "0x76"; + action "kldload -n if_cdce"; +}; + nomatch 32 { match "bus" "uhub[0-9]+"; match "mode" "host"; @@ -5399,5 +5501,5 @@ nomatch 32 { action "kldload -n umass"; }; -# 2621 USB entries processed +# 2643 USB entries processed -- cgit v1.3 From 4a387a583beac520f018308bc077cb5a960309b9 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 2 Oct 2014 01:16:30 +0000 Subject: Resurrect set_rcvar() as a function to define a rc.conf variable. It defines a variable and its default value in load_rc_config() just after rc.conf is loaded. "rcvar" command shows the current and the default values. This is an attempt to solve a problem that rc.d scripts from third-party software do not have entries in /etc/defaults/rc.conf. The fact that load_rc_config() reads rc.conf only once and /etc/rc invokes the function before running rc.d scripts made developers confused for a long time because load_rc_config() just before run_rc_command() in each rc.d script overrides variables only when the script is directly invoked, not from /etc/rc. Variables defined in set_rcvar are always set in load_rc_config() after loading rc.conf. An rc.d script can now be written in a self-contained manner regarding the related variables as follows: --- name=foo rcvar=foo_enable set_rcvar foo_enable YES "Enable $name" set_rcvar foo_flags "-s" "Flags to $name" ... load_rc_config $name run_rc_command "$@" --- --- etc/rc.subr | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'etc') diff --git a/etc/rc.subr b/etc/rc.subr index 97b631f82d92..4b3fddf5d929 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -68,6 +68,39 @@ list_vars() done; } } +# set_rcvar [var] [defval] [desc] +# +# Echo or define a rc.conf(5) variable name. Global variable +# $rcvars is used. +# +# If no argument is specified, echo "${name}_enable". +# +# If only a var is specified, echo "${var}_enable". +# +# If var and defval are specified, the ${var} is defined as +# rc.conf(5) variable and the default value is ${defvar}. An +# optional argument $desc can also be specified to add a +# description for that. +# +set_rcvar() +{ + local _var + + case $# in + 0) echo ${name}_enable ;; + 1) echo ${1}_enable ;; + *) + debug "set_rcvar: \$$1=$2 is added" \ + " as a rc.conf(5) variable." + _var=$1 + rcvars="${rcvars# } $_var" + eval ${_var}_defval=\"$2\" + shift 2 + eval ${_var}_desc=\"$*\" + ;; + esac +} + # set_rcvar_obsolete oldvar [newvar] [msg] # Define obsolete variable. # Global variable $rcvars_obsolete is used. @@ -76,7 +109,7 @@ set_rcvar_obsolete() { local _var _var=$1 - debug "rcvar_obsolete: \$$1(old) -> \$$2(new) is defined" + debug "set_rcvar_obsolete: \$$1(old) -> \$$2(new) is defined" rcvars_obsolete="${rcvars_obsolete# } $1" eval ${1}_newvar=\"$2\" @@ -1091,8 +1124,8 @@ $command $rc_flags $command_args" echo "" fi echo "#" - # Get unique vars in $rcvar - for _v in $rcvar; do + # Get unique vars in $rcvar $rcvars + for _v in $rcvar $rcvars; do case $v in $_v\ *|\ *$_v|*\ $_v\ *) ;; *) v="${v# } $_v" ;; @@ -1238,7 +1271,7 @@ run_rc_script() unset name command command_args command_interpreter \ extra_commands pidfile procname \ - rcvar rcvars_obsolete required_dirs required_files \ + rcvar rcvars rcvars_obsolete required_dirs required_files \ required_vars eval unset ${_arg}_cmd ${_arg}_precmd ${_arg}_postcmd @@ -1306,7 +1339,7 @@ load_rc_config() done # Set defaults if defined. - for _var in $rcvar; do + for _var in $rcvar $rcvars; do eval _defval=\$${_var}_defval if [ -n "$_defval" ]; then eval : \${$_var:=\$${_var}_defval} -- cgit v1.3 From a85f6c30437e1e248729023716b64aac1b4cd259 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 2 Oct 2014 19:53:37 +0000 Subject: - Add a test for bug 191427 where pw(8) will go into an infinite loop Reviewed by: will MFC after: 1 month --- etc/mtree/BSD.tests.dist | 2 ++ usr.sbin/pw/Makefile | 6 ++++++ usr.sbin/pw/tests/Makefile | 10 ++++++++++ usr.sbin/pw/tests/group | 3 +++ usr.sbin/pw/tests/helper_functions.shin | 15 +++++++++++++++ usr.sbin/pw/tests/master.passwd | 4 ++++ usr.sbin/pw/tests/pw_delete.sh | 24 ++++++++++++++++++++++++ 7 files changed, 64 insertions(+) create mode 100644 usr.sbin/pw/tests/Makefile create mode 100644 usr.sbin/pw/tests/group create mode 100755 usr.sbin/pw/tests/helper_functions.shin create mode 100644 usr.sbin/pw/tests/master.passwd create mode 100755 usr.sbin/pw/tests/pw_delete.sh (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index beec7a3e06bb..3a9d0e001db4 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -287,6 +287,8 @@ .. newsyslog .. + pw + .. sa .. .. diff --git a/usr.sbin/pw/Makefile b/usr.sbin/pw/Makefile index eae0b879aa5b..8c5acf901d1c 100644 --- a/usr.sbin/pw/Makefile +++ b/usr.sbin/pw/Makefile @@ -11,4 +11,10 @@ WARNS?= 2 DPADD= ${LIBCRYPT} ${LIBUTIL} LDADD= -lcrypt -lutil +.include + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile new file mode 100644 index 000000000000..577ea9323919 --- /dev/null +++ b/usr.sbin/pw/tests/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/usr.sbin/pw + +ATF_TESTS_SH= pw_delete + +FILES= group helper_functions.shin master.passwd +FILESDIR= ${TESTSDIR} + +.include diff --git a/usr.sbin/pw/tests/group b/usr.sbin/pw/tests/group new file mode 100644 index 000000000000..620c588faa38 --- /dev/null +++ b/usr.sbin/pw/tests/group @@ -0,0 +1,3 @@ +# $FreeBSD$ +# +wheel:*:0:root diff --git a/usr.sbin/pw/tests/helper_functions.shin b/usr.sbin/pw/tests/helper_functions.shin new file mode 100755 index 000000000000..f87b1e7d9436 --- /dev/null +++ b/usr.sbin/pw/tests/helper_functions.shin @@ -0,0 +1,15 @@ +# $FreeBSD$ + +# Workdir to run tests in +TESTDIR=$(atf_get_srcdir) + +# Populate the files pw needs to use into $HOME/etc +populate_etc_skel() { + cp ${TESTDIR}/master.passwd ${HOME} || \ + atf_fail "Populating master.passwd in ${HOME}" + cp ${TESTDIR}/group ${HOME} || atf_fail "Populating group in ${HOME}" + + # Generate the passwd file + pwd_mkdb -p -d ${HOME} ${HOME}/master.passwd || \ + atf_fail "generate passwd from master.passwd" +} diff --git a/usr.sbin/pw/tests/master.passwd b/usr.sbin/pw/tests/master.passwd new file mode 100644 index 000000000000..f7dc837dabca --- /dev/null +++ b/usr.sbin/pw/tests/master.passwd @@ -0,0 +1,4 @@ +# $FreeBSD$ +# +root:*:0:0::0:0:Charlie &:/root:/bin/csh +toor:*:0:0::0:0:Bourne-again Superuser:/root: diff --git a/usr.sbin/pw/tests/pw_delete.sh b/usr.sbin/pw/tests/pw_delete.sh new file mode 100755 index 000000000000..06366294bd4b --- /dev/null +++ b/usr.sbin/pw/tests/pw_delete.sh @@ -0,0 +1,24 @@ +# $FreeBSD$ + +# Import helper functions +. $(atf_get_srcdir)/helper_functions.shin + +# Test that a user can be deleted when another user is part of this +# user's default group and does not go into an infinate loop. +# PR: 191427 +atf_test_case rmuser_seperate_group cleanup +rmuser_seperate_group_head() { + atf_set "timeout" "30" +} +rmuser_seperate_group_body() { + populate_etc_skel + pw -V ${HOME} useradd test || atf_fail "Creating test user" + pw -V ${HOME} groupmod test -M 'test,root' || \ + atf_fail "Modifying the group" + pw -V ${HOME} userdel test || atf_fail "delete the user" +} + + +atf_init_test_cases() { + atf_add_test_case rmuser_seperate_group +} -- cgit v1.3 From 56695221dd0c17cdfcb705a3fcaddaad0e07c872 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 00:32:33 +0000 Subject: Integrate usr.sbin/nmtree/tests from NetBSD into atf/kyua In collaboration with: pho Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.sbin/nmtree/Makefile | 6 +++++- usr.sbin/nmtree/tests/Makefile | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 usr.sbin/nmtree/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 3a9d0e001db4..9014223a8433 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -287,6 +287,8 @@ .. newsyslog .. + nmtree + .. pw .. sa diff --git a/usr.sbin/nmtree/Makefile b/usr.sbin/nmtree/Makefile index 8cba6f8691a8..5789ad8bfc29 100644 --- a/usr.sbin/nmtree/Makefile +++ b/usr.sbin/nmtree/Makefile @@ -1,6 +1,6 @@ # $FreeBSD$ -.include +.include .PATH: ${.CURDIR}/../../contrib/mtree @@ -24,4 +24,8 @@ LDADD+= ${LIBNETBSD} LINKS= ${BINDIR}/mtree ${BINDIR}/nmtree MLINKS= mtree.8 nmtree.8 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.sbin/nmtree/tests/Makefile b/usr.sbin/nmtree/tests/Makefile new file mode 100644 index 000000000000..1df81d0f0a44 --- /dev/null +++ b/usr.sbin/nmtree/tests/Makefile @@ -0,0 +1,32 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.sbin/mtree +.PATH: ${TESTSRC} + +TESTSDIR= ${TESTSBASE}/usr.sbin/nmtree + +ATF_TESTS_SH= nmtree_test +ATF_TESTS_SH_SRC_nmtree_test= t_mtree.sh + +FILESDIR= ${TESTSDIR} + +# NOTE: the output from FreeBSD's nmtree displays sha256digest instead of +# sha256; we need to mangle the specfiles to reflect this. +.for f in mtree_d_create.out netbsd6_d_create.out +CLEANFILES+= $f $f.tmp +FILES+= $f +$f: ${TESTSRC}/$f + sed -e 's/sha256/sha256digest/g' < ${.ALLSRC} > ${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} +.endfor + +FILES+= d_convert.in +FILES+= d_convert_C.out +FILES+= d_convert_C_S.out +FILES+= d_convert_D.out +FILES+= d_convert_D_S.out +FILES+= d_merge.in +FILES+= d_merge_C_M.out +FILES+= d_merge_C_M_S.out + +.include -- cgit v1.3 From d192d44ab4169a5dfa467fbe5a6b6d78df370b1d Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 00:37:58 +0000 Subject: Set the autoindent to 4 spaces with vim in BSD.tests.dist This will prevent vim users from accidentally checking in buggy mtree files (mixed tabs/spaces). MFC after: 2 weeks Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ 1 file changed, 2 insertions(+) (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 9014223a8433..bf3484de340a 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -296,3 +296,5 @@ .. .. .. + +# vim: set expandtab ts=4 sw=4: -- cgit v1.3 From 0be0d5f339ec4f82b38843515d74881f0beeccec Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 00:41:42 +0000 Subject: Integrate usr.sbin/basename/tests from NetBSD into atf/kyua In collaboration with: pho Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/basename/Makefile | 6 ++++++ usr.bin/basename/tests/Makefile | 12 ++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 usr.bin/basename/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index bf3484de340a..0042e9c7302b 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -143,6 +143,8 @@ usr.bin apply .. + basename + .. bmake archives fmt_44bsd diff --git a/usr.bin/basename/Makefile b/usr.bin/basename/Makefile index d647395c83d9..b392c3f378df 100644 --- a/usr.bin/basename/Makefile +++ b/usr.bin/basename/Makefile @@ -1,7 +1,13 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= basename MLINKS= basename.1 dirname.1 +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/basename/tests/Makefile b/usr.bin/basename/tests/Makefile new file mode 100644 index 000000000000..32dedabc5f4d --- /dev/null +++ b/usr.bin/basename/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/basename +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/basename +ATF_TESTS_SH= basename_test +ATF_TESTS_SH_SRC_basename_test= t_basename.sh + +.include -- cgit v1.3 From 0306a0a804523f943f01cf085675a0640a3f5eb0 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 00:50:33 +0000 Subject: Integrate usr.bin/cmp/tests from NetBSD into atf/kyua In collaboration with: sjg Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/cmp/Makefile | 6 ++++++ usr.bin/cmp/tests/Makefile | 12 ++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 usr.bin/cmp/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 0042e9c7302b..66367cc68b52 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -245,6 +245,8 @@ .. calendar .. + cmp + .. comm .. file2c diff --git a/usr.bin/cmp/Makefile b/usr.bin/cmp/Makefile index d93f54bc0fd5..5b9fdfc23a2a 100644 --- a/usr.bin/cmp/Makefile +++ b/usr.bin/cmp/Makefile @@ -1,7 +1,13 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= cmp SRCS= cmp.c link.c misc.c regular.c special.c +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/cmp/tests/Makefile b/usr.bin/cmp/tests/Makefile new file mode 100644 index 000000000000..1c054c6888f8 --- /dev/null +++ b/usr.bin/cmp/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/cmp +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/cmp +ATF_TESTS_SH= cmp_test +ATF_TESTS_SH_SRC_cmp_test= t_cmp.sh + +.include -- cgit v1.3 From 17313006a0db62a7fa55603a8316dd70698d3a0e Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 00:55:04 +0000 Subject: Integrate usr.bin/dirname/tests from NetBSD into atf/kyua In collaboration with: pho, sjg Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/dirname/Makefile | 6 ++++++ usr.bin/dirname/tests/Makefile | 12 ++++++++++++ 3 files changed, 20 insertions(+) create mode 100644 usr.bin/dirname/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 66367cc68b52..16e4b6033b69 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -249,6 +249,8 @@ .. comm .. + dirname + .. file2c .. join diff --git a/usr.bin/dirname/Makefile b/usr.bin/dirname/Makefile index fb0e660a5a95..be9193c63b50 100644 --- a/usr.bin/dirname/Makefile +++ b/usr.bin/dirname/Makefile @@ -1,7 +1,13 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= dirname MAN= +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/dirname/tests/Makefile b/usr.bin/dirname/tests/Makefile new file mode 100644 index 000000000000..5b84c57092fe --- /dev/null +++ b/usr.bin/dirname/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/dirname +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/dirname +ATF_TESTS_SH= dirname_test +ATF_TESTS_SH_SRC_dirname_test= t_dirname.sh + +.include -- cgit v1.3 From 6186fd1857626de0f7cb1a9e4dff19082f9ebb11 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 01:39:07 +0000 Subject: Integrate bin/sleep/tests from NetBSD into atf/kyua Sponsored by: EMC / Isilon Storage Division --- bin/sleep/Makefile | 6 ++++++ bin/sleep/tests/Makefile | 12 ++++++++++++ etc/mtree/BSD.tests.dist | 2 ++ 3 files changed, 20 insertions(+) create mode 100644 bin/sleep/tests/Makefile (limited to 'etc') diff --git a/bin/sleep/Makefile b/bin/sleep/Makefile index 4ff73308c45b..0ec3080476a5 100644 --- a/bin/sleep/Makefile +++ b/bin/sleep/Makefile @@ -1,6 +1,12 @@ # @(#)Makefile 8.1 (Berkeley) 5/31/93 # $FreeBSD$ +.include + PROG= sleep +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/bin/sleep/tests/Makefile b/bin/sleep/tests/Makefile new file mode 100644 index 000000000000..9b286e6ba967 --- /dev/null +++ b/bin/sleep/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/bin/sleep +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/bin/sleep +ATF_TESTS_SH= sleep_test +ATF_TESTS_SH_SRC_sleep_test= t_sleep.sh + +.include diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 16e4b6033b69..e91af3d325be 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -47,6 +47,8 @@ set-e .. .. + sleep + .. test .. .. -- cgit v1.3 From 48e0fbc3f95f23f5b9f1db9537ae357436ce3590 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 01:46:31 +0000 Subject: Integrate usr.bin/cut/tests from NetBSD into atf/kyua Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/cut/Makefile | 6 ++++++ usr.bin/cut/tests/Makefile | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 usr.bin/cut/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index e91af3d325be..6932551fd7ba 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -251,6 +251,8 @@ .. comm .. + cut + .. dirname .. file2c diff --git a/usr.bin/cut/Makefile b/usr.bin/cut/Makefile index 5be029a3d9d1..21c1a1c6354f 100644 --- a/usr.bin/cut/Makefile +++ b/usr.bin/cut/Makefile @@ -1,6 +1,12 @@ # From: @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +.include + PROG= cut +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/cut/tests/Makefile b/usr.bin/cut/tests/Makefile new file mode 100644 index 000000000000..b324a7804196 --- /dev/null +++ b/usr.bin/cut/tests/Makefile @@ -0,0 +1,21 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/cut +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/cut +ATF_TESTS_SH= cut_test +ATF_TESTS_SH_SRC_cut_test= t_cut.sh + +FILESDIR= ${TESTSDIR} +FILES= d_basic.out +FILES+= d_cut.in +FILES+= d_dflag.out +FILES+= d_dsflag.out +FILES+= d_latin1.in +FILES+= d_sflag.out +FILES+= d_utf8.in + +.include -- cgit v1.3 From 1e7075e0a47349d9417d16e5bcca4ef31d9ffced Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 01:53:23 +0000 Subject: Integrate usr.bin/grep/tests from NetBSD into atf/kyua Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/grep/Makefile | 4 ++++ usr.bin/grep/tests/Makefile | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 usr.bin/grep/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 6932551fd7ba..fd4921a590e2 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -257,6 +257,8 @@ .. file2c .. + grep + .. join .. jot diff --git a/usr.bin/grep/Makefile b/usr.bin/grep/Makefile index a4c614f2f499..32941fd4ba4a 100644 --- a/usr.bin/grep/Makefile +++ b/usr.bin/grep/Makefile @@ -85,4 +85,8 @@ DPADD+= ${LIBGNUREGEX} CFLAGS+= -DWITHOUT_NLS .endif +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/grep/tests/Makefile b/usr.bin/grep/tests/Makefile new file mode 100644 index 000000000000..59b948c98e5a --- /dev/null +++ b/usr.bin/grep/tests/Makefile @@ -0,0 +1,41 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/grep +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/grep + +ATF_TESTS_SH= grep_test +ATF_TESTS_SH_SRC_grep_test= t_grep.sh + +FILESDIR= ${TESTSDIR} +FILES= d_basic.out +FILES+= d_begin_end_a.out +FILES+= d_begin_end_b.out +FILES+= d_binary.out +FILES+= d_context2_a.out +FILES+= d_context2_b.out +FILES+= d_context2_c.out +FILES+= d_context_a.in +FILES+= d_context_a.out +FILES+= d_context_b.in +FILES+= d_context_b.out +FILES+= d_context_c.out +FILES+= d_context_d.out +FILES+= d_egrep.out +FILES+= d_file_exp.in +FILES+= d_file_exp.out +FILES+= d_ignore_case.out +FILES+= d_input +FILES+= d_invert.in +FILES+= d_invert.out +FILES+= d_recurse.out +FILES+= d_recurse_symlink.err +FILES+= d_recurse_symlink.out +FILES+= d_whole_line.out +FILES+= d_word_regexps.out +FILES+= d_zgrep.out + +.include -- cgit v1.3 From 9752f4a74f61bde8fd59b263e72d623247e27a05 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 02:07:34 +0000 Subject: Integrate usr.bin/diff/tests from NetBSD into atf/kyua at gnu/usr.bin/diff/tests Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ gnu/usr.bin/diff/Makefile | 6 ++++++ gnu/usr.bin/diff/tests/Makefile | 17 +++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 gnu/usr.bin/diff/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index fd4921a590e2..72b34ac0f8dc 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -70,6 +70,8 @@ lib .. usr.bin + diff + .. .. .. lib diff --git a/gnu/usr.bin/diff/Makefile b/gnu/usr.bin/diff/Makefile index c5c66dcce0ec..6b29df5c0e98 100644 --- a/gnu/usr.bin/diff/Makefile +++ b/gnu/usr.bin/diff/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + DIFFSRC=${.CURDIR}/../../../contrib/diff/src .PATH: ${DIFFSRC} \ ${.CURDIR}/../../../contrib/diff/lib \ @@ -27,4 +29,8 @@ SUBDIR+=doc DPADD= ${LIBGNUREGEX} LDADD= -lgnuregex +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/gnu/usr.bin/diff/tests/Makefile b/gnu/usr.bin/diff/tests/Makefile new file mode 100644 index 000000000000..aa1629d33f53 --- /dev/null +++ b/gnu/usr.bin/diff/tests/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../../contrib/netbsd-tests/usr.bin/diff +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/gnu/usr.bin/diff +ATF_TESTS_SH= diff_test +ATF_TESTS_SH_SED_diff_test= -e 's/t_diff/`basename $$0`/g' +ATF_TESTS_SH_SRC_diff_test= t_diff.sh + +FILESDIR= ${TESTSDIR} +FILES+= d_mallocv1.in +FILES+= d_mallocv2.in + +.include -- cgit v1.3 From cdfd89cea1d0df2e80c4c24938aa97a5e599c72d Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Thu, 9 Oct 2014 02:24:34 +0000 Subject: Integrate usr.bin/gzip/tests from NetBSD into atf/kyua Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ usr.bin/gzip/Makefile | 4 ++++ usr.bin/gzip/tests/Makefile | 12 ++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 usr.bin/gzip/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 72b34ac0f8dc..45c2d7c0eb07 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -261,6 +261,8 @@ .. grep .. + gzip + .. join .. jot diff --git a/usr.bin/gzip/Makefile b/usr.bin/gzip/Makefile index 73724358a560..a3722e7193a8 100644 --- a/usr.bin/gzip/Makefile +++ b/usr.bin/gzip/Makefile @@ -28,4 +28,8 @@ LINKS+= ${BINDIR}/gzip ${BINDIR}/gunzip \ ${BINDIR}/gzip ${BINDIR}/zcat \ ${BINDIR}/zdiff ${BINDIR}/zcmp +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/gzip/tests/Makefile b/usr.bin/gzip/tests/Makefile new file mode 100644 index 000000000000..155d739f17bd --- /dev/null +++ b/usr.bin/gzip/tests/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +TESTSRC= ${.CURDIR}/../../../contrib/netbsd-tests/usr.bin/gzip +.PATH: ${TESTSRC} + +.include + +TESTSDIR= ${TESTSBASE}/usr.bin/gzip +ATF_TESTS_SH= gzip_test +ATF_TESTS_SH_SRC_gzip_test= t_gzip.sh + +.include -- cgit v1.3 From 62f9ed9540b0bba293025eefca69734ff0f6d5a1 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Thu, 9 Oct 2014 13:58:19 +0000 Subject: Add example devd configuration file for USB printers. --- etc/devd/Makefile | 2 +- etc/devd/ulpt.conf | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 etc/devd/ulpt.conf (limited to 'etc') diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 82a5000ff8ae..6d1031ee598c 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -11,7 +11,7 @@ FILES+= asus.conf .endif .if ${MK_USB} != "no" -FILES+= uath.conf usb.conf +FILES+= uath.conf ulpt.conf usb.conf .endif .if ${MK_ZFS} != "no" diff --git a/etc/devd/ulpt.conf b/etc/devd/ulpt.conf new file mode 100644 index 000000000000..2082726cbf47 --- /dev/null +++ b/etc/devd/ulpt.conf @@ -0,0 +1,18 @@ +# +# $FreeBSD$ +# + +# +# Example devd configuration file for USB printers. +# Uncomment the notify rule below to enable. +# +# Generic USB printer devices +#notify 100 { +# match "system" "USB"; +# match "subsystem" "INTERFACE"; +# match "type" "ATTACH"; +# match "intclass" "0x07"; +# match "intsubclass" "0x01"; +# match "intprotocol" "(0x01|0x02|0x03)"; +# action "chown root:wheel /dev/$cdev"; +#}; -- cgit v1.3 From 37c7d4443c025122954a6c6447c88e21297c7a40 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sat, 11 Oct 2014 20:28:04 +0000 Subject: Rename s/network/netif/ and set netif_enable for namespace consistency. --- etc/defaults/rc.conf | 1 + etc/rc.d/netif | 31 ++++++++++++++++--------------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index b24e869cdd43..18989fafffb3 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -110,6 +110,7 @@ synchronous_dhclient="NO" # Start dhclient directly on configured # interfaces during startup. defaultroute_delay="30" # Time to wait for a default route on a DHCP interface. defaultroute_carrier_delay="5" # Time to wait for carrier while waiting for a default route. +netif_enable="YES" # Set to YES to initialize network interfaces netif_ipexpand_max="2048" # Maximum number of IP addrs in a range spec. wpa_supplicant_program="/usr/sbin/wpa_supplicant" wpa_supplicant_flags="-s" # Extra flags to pass to wpa_supplicant diff --git a/etc/rc.d/netif b/etc/rc.d/netif index 154f1ce704e2..dd0dde21bd23 100755 --- a/etc/rc.d/netif +++ b/etc/rc.d/netif @@ -33,9 +33,10 @@ . /etc/rc.subr . /etc/network.subr -name="network" -start_cmd="network_start" -stop_cmd="network_stop" +name="netif" +rcvar="${name}_enable" +start_cmd="netif_start" +stop_cmd="netif_stop" cloneup_cmd="clone_up" clonedown_cmd="clone_down" clear_cmd="doclear" @@ -47,7 +48,7 @@ cmdifn= set_rcvar_obsolete ipv6_enable ipv6_activate_all_interfaces set_rcvar_obsolete ipv6_prefer -network_start() +netif_start() { local _if @@ -71,7 +72,7 @@ network_start() ifnet_rename $cmdifn # Configure the interface(s). - network_common ifn_start $cmdifn + netif_common ifn_start $cmdifn if [ -f /etc/rc.d/ipfilter ] ; then # Resync ipfilter @@ -87,19 +88,19 @@ network_start() fi } -network_stop() +netif_stop() { _clone_down=1 - network_stop0 $* + netif_stop0 $* } doclear() { _clone_down= - network_stop0 $* + netif_stop0 $* } -network_stop0() +netif_stop0() { local _if @@ -108,7 +109,7 @@ network_stop0() cmdifn=$* # Deconfigure the interface(s) - network_common ifn_stop $cmdifn + netif_common ifn_stop $cmdifn # Destroy cloned interfaces if [ -n "$_clone_down" ]; then @@ -126,28 +127,28 @@ vnet_up() { cmdifn=$* - network_common ifn_vnetup $cmdifn + netif_common ifn_vnetup $cmdifn } vnet_down() { cmdifn=$* - network_common ifn_vnetdown $cmdifn + netif_common ifn_vnetdown $cmdifn } -# network_common routine +# netif_common routine # Common configuration subroutine for network interfaces. This # routine takes all the preparatory steps needed for configuriing # an interface and then calls $routine. -network_common() +netif_common() { local _cooked_list _tmp_list _fail _func _ok _str _cmdifn _func= if [ -z "$1" ]; then - err 1 "network_common(): No function name specified." + err 1 "netif_common(): No function name specified." else _func="$1" shift -- cgit v1.3 From 61a8e8491886d0acd492dc4cbca0690f07b132c6 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sat, 11 Oct 2014 23:49:27 +0000 Subject: Add ${name}_env and ${name}_prepend. ${name}_env is an argument list which will be passed to env(1). ${name}_prepend is simply prepended to the command line for $command. --- etc/rc.subr | 12 +++++++++++- share/man/man8/rc.subr.8 | 26 +++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'etc') diff --git a/etc/rc.subr b/etc/rc.subr index 4b3fddf5d929..387b909848ec 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -749,6 +749,8 @@ check_startmsgs() # NOTE: $flags from the parent environment # can be used to override this. # +# ${name}_env n Environment variables to run ${command} with. +# # ${name}_fib n Routing table number to run ${command} with. # # ${name}_nice n Nice level to run ${command} at. @@ -764,6 +766,8 @@ check_startmsgs() # to run the chrooted ${command} with. # Requires /usr to be mounted. # +# ${name}_prepend n Command added before ${command}. +# # ${rc_arg}_cmd n If set, use this as the method when invoked; # Otherwise, use default command (see below) # @@ -937,7 +941,8 @@ run_rc_command() eval _chdir=\$${name}_chdir _chroot=\$${name}_chroot \ _nice=\$${name}_nice _user=\$${name}_user \ _group=\$${name}_group _groups=\$${name}_groups \ - _fib=\$${name}_fib + _fib=\$${name}_fib _env=\$${name}_env \ + _prepend=\$${name}_prepend if [ -n "$_user" ]; then # unset $_user if running as that user if [ "$_user" = "$(eval $IDCMD)" ]; then @@ -1022,12 +1027,14 @@ run_rc_command() _doit="\ ${_nice:+nice -n $_nice }\ ${_fib:+setfib -F $_fib }\ +${_env:+env $_env }\ chroot ${_user:+-u $_user }${_group:+-g $_group }${_groups:+-G $_groups }\ $_chroot $command $rc_flags $command_args" else _doit="\ ${_chdir:+cd $_chdir && }\ ${_fib:+setfib -F $_fib }\ +${_env:+env $_env }\ $command $rc_flags $command_args" if [ -n "$_user" ]; then _doit="su -m $_user -c 'sh -c \"$_doit\"'" @@ -1038,6 +1045,9 @@ $command $rc_flags $command_args" fi _doit="nice -n $_nice $_doit" fi + if [ -n "$_prepend" ]; then + _doit="$_prepend $_doit" + fi fi # run the full command diff --git a/share/man/man8/rc.subr.8 b/share/man/man8/rc.subr.8 index 7c3b654229df..47457ead9046 100644 --- a/share/man/man8/rc.subr.8 +++ b/share/man/man8/rc.subr.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 23, 2012 +.Dd October 12, 2014 .Dt RC.SUBR 8 .Os .Sh NAME @@ -568,6 +568,22 @@ to before running Only supported after .Pa /usr is mounted. +.It Va ${name}_env +A list of environment variables to run +.Va command +with. +This will be passed as arguments to +.Xr env 1 +utility. +.It Va ${name}_fib +FIB +.Pa Routing Table +number to run +.Va command +with. +See +.Xr setfib 1 +for more details. .It Va ${name}_flags Arguments to call .Va command @@ -622,6 +638,14 @@ as. Comma separated list of supplementary groups to run the chrooted .Va command with. +.It Va ${name}_prepend +Commands to be prepended to +.Va command . +This is a generic version of +.Va ${name}_env , +.Va ${name}_fib , +or +.Va ${name}_nice . .It Ar argument Ns Va _cmd Shell commands which override the default method for .Ar argument . -- cgit v1.3 From 2869fca8b0f3fa55ca1b79c7446320d87dab6502 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sun, 12 Oct 2014 02:42:36 +0000 Subject: Add env and prepend to _rc_namevarlist. --- etc/rc.subr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.subr b/etc/rc.subr index 387b909848ec..6534f6858f65 100644 --- a/etc/rc.subr +++ b/etc/rc.subr @@ -2050,7 +2050,7 @@ check_kern_features() # check_namevarlist var # Return "0" if ${name}_var is reserved in rc.subr. -_rc_namevarlist="program chroot chdir flags fib nice user group groups" +_rc_namevarlist="program chroot chdir env flags fib nice user group groups prepend" check_namevarlist() { local _v -- cgit v1.3 From d49c6f029c3aeb62bcea97004159377efb72692c Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sun, 12 Oct 2014 19:12:48 +0000 Subject: Add an AC line monitor so power_profile can work Summary: Add a polling loop (1Hz) to monitor the battery and AC status, to notify devd like ACPI does for power monitoring. This allows /etc/rc.d/power_profile to work on PowerPC laptops Test Plan: Tested on a Titanium PowerBook, configuring economy_cpu_freq and performance_cpu_freq, disabling powerd. Reviewers: #powerpc, nwhitehorn Reviewed By: nwhitehorn Subscribers: rpaulo Differential Revision: https://reviews.freebsd.org/D937 --- etc/devd/apple.conf | 8 +++++++- sys/powerpc/powermac/pmu.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/devd/apple.conf b/etc/devd/apple.conf index 8518890a5d6d..7f066cdf5ad7 100644 --- a/etc/devd/apple.conf +++ b/etc/devd/apple.conf @@ -71,4 +71,10 @@ notify 0 { action "camcontrol eject cd0"; }; - +# Equivalent to the ACPI/ACAD notify +notify 10 { + match "system" "PMU"; + match "subsystem" "POWER"; + match "type" "ACLINE"; + action "/etc/rc.d/power_profile $notify"; +} diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c index 913845e59bc8..bb3147952d59 100644 --- a/sys/powerpc/powermac/pmu.c +++ b/sys/powerpc/powermac/pmu.c @@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -183,6 +184,9 @@ static int pmu_send(void *cookie, int cmd, int length, uint8_t *in_msg, static uint8_t pmu_read_reg(struct pmu_softc *sc, u_int offset); static void pmu_write_reg(struct pmu_softc *sc, u_int offset, uint8_t value); static int pmu_intr_state(struct pmu_softc *); +static void pmu_battquery_proc(void); +static void pmu_battery_notify(struct pmu_battstate *batt, + struct pmu_battstate *old); /* these values shows that number of data returned after 'send' cmd is sent */ static signed char pm_send_cmd_type[] = { @@ -256,6 +260,13 @@ static signed char pm_receive_cmd_type[] = { -1, -1, -1, -1, -1, -1, -1, -1, }; +static struct proc *pmubattproc; +static struct kproc_desc pmu_batt_kp = { + "pmu_batt", + pmu_battquery_proc, + &pmubattproc +}; + /* We only have one of each device, so globals are safe */ static device_t pmu = NULL; static device_t pmu_extint = NULL; @@ -420,6 +431,8 @@ pmu_attach(device_t dev) struct sysctl_oid *oid, *battroot; char battnum[2]; + /* Only start the battery monitor if we have a battery. */ + kproc_start(&pmu_batt_kp); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "acline", CTLTYPE_INT | CTLFLAG_RD, sc, 0, pmu_acline_state, "I", "AC Line Status"); @@ -914,6 +927,39 @@ pmu_query_battery(struct pmu_softc *sc, int batt, struct pmu_battstate *info) return (0); } +static void +pmu_battery_notify(struct pmu_battstate *batt, struct pmu_battstate *old) +{ + char notify_buf[16]; + int acline; + + acline = (batt->state & PMU_PWR_AC_PRESENT) ? 1 : 0; + if (acline != (old->state & PMU_PWR_AC_PRESENT)) { + snprintf(notify_buf, sizeof(notify_buf), + "notify=0x%02x", acline); + devctl_notify("PMU", "POWER", "ACLINE", notify_buf); + } +} + +static void +pmu_battquery_proc() +{ + struct pmu_softc *sc; + struct pmu_battstate batt; + struct pmu_battstate cur_batt; + int error; + + sc = device_get_softc(pmu); + + error = pmu_query_battery(sc, 0, &cur_batt); + while (1) { + error = pmu_query_battery(sc, 0, &batt); + pmu_battery_notify(&batt, &cur_batt); + cur_batt = batt; + pause("pmu_batt", hz); + } +} + static int pmu_acline_state(SYSCTL_HANDLER_ARGS) { -- cgit v1.3 From f96f5e21e0545d56ce0ea86cae6b59de3f3095f4 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sun, 12 Oct 2014 22:11:28 +0000 Subject: s/-/_/ in name. --- etc/rc.d/bgfsck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/bgfsck b/etc/rc.d/bgfsck index 101577ef90ec..d15744c90516 100755 --- a/etc/rc.d/bgfsck +++ b/etc/rc.d/bgfsck @@ -9,7 +9,7 @@ . /etc/rc.subr -name="background-fsck" +name="background_fsck" rcvar="background_fsck" start_cmd="bgfsck_start" stop_cmd=":" -- cgit v1.3 From f8080a9986c63fbc48df591d6b8d678103d7b0bf Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Thu, 16 Oct 2014 00:33:06 +0000 Subject: HYPERV isn't available on all architectures, but just on by default for i386/amd64. Rather, it only works on i386/amd64 and should only be built there. Rather than change the default based on which architecutre, do things more directly by only building it on i386/amd64 and having it always on. This is how we handle other options that are relevant only for a few architectures. --- etc/devd/Makefile | 7 +++---- libexec/Makefile | 7 ++----- libexec/Makefile.amd64 | 5 +++++ libexec/Makefile.i386 | 5 +++++ share/mk/src.opts.mk | 8 +------- 5 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 libexec/Makefile.amd64 create mode 100644 libexec/Makefile.i386 (limited to 'etc') diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 6d1031ee598c..27dfb92f1711 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -8,6 +8,9 @@ FILES+= apple.conf .if ${MACHINE} == "amd64" || ${MACHINE} == "i386" FILES+= asus.conf +.if ${MK_HYPERV} != "no" +FILES+= hyperv.conf +.endif .endif .if ${MK_USB} != "no" @@ -18,10 +21,6 @@ FILES+= uath.conf ulpt.conf usb.conf FILES+= zfs.conf .endif -.if ${MK_HYPERV} != "no" -FILES+= hyperv.conf -.endif - NO_OBJ= FILESDIR= /etc/devd FILESMODE= 644 diff --git a/libexec/Makefile b/libexec/Makefile index 74cc6d8fb27f..7d1c1f8ddae4 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -13,7 +13,6 @@ SUBDIR= ${_atf} \ fingerd \ ftpd \ getty \ - ${_hyperv} \ ${_mail.local} \ ${_mknetid} \ ${_pppoed} \ @@ -55,10 +54,6 @@ _dma= dma _dma-mbox-create= dma-mbox-create .endif -.if ${MK_HYPERV} != "no" -_hyperv= hyperv -.endif - .if ${MK_NIS} != "no" _mknetid= mknetid _ypxfr= ypxfr @@ -95,4 +90,6 @@ _atf= atf _tests= tests .endif +.include + .include diff --git a/libexec/Makefile.amd64 b/libexec/Makefile.amd64 new file mode 100644 index 000000000000..1092a29a2a33 --- /dev/null +++ b/libexec/Makefile.amd64 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +.if ${MK_HYPERV} != "no" +SUBDIR+= hyperv +.endif diff --git a/libexec/Makefile.i386 b/libexec/Makefile.i386 new file mode 100644 index 000000000000..1092a29a2a33 --- /dev/null +++ b/libexec/Makefile.i386 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +.if ${MK_HYPERV} != "no" +SUBDIR+= hyperv +.endif diff --git a/share/mk/src.opts.mk b/share/mk/src.opts.mk index a852d3d7cee2..91ed3c0f8f2d 100644 --- a/share/mk/src.opts.mk +++ b/share/mk/src.opts.mk @@ -90,6 +90,7 @@ __DEFAULT_YES_OPTIONS = \ GPL_DTC \ GROFF \ HTML \ + HYPERV \ ICONV \ INET \ INET6 \ @@ -211,13 +212,6 @@ __DEFAULT_NO_OPTIONS+=CLANG_IS_CC CLANG CLANG_BOOTSTRAP __DEFAULT_YES_OPTIONS+=GCC GCC_BOOTSTRAP GNUCXX .endif -# HyperV is only available for x86 and amd64. -.if ${__T} == "amd64" || ${__T} == "i386" -__DEFAULT_YES_OPTIONS+=HYPERV -.else -__DEFAULT_NO_OPTIONS+=HYPERV -.endif - .include # -- cgit v1.3 From 544d3b859e541b97cff24bb8ce5b9be199a79013 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Fri, 17 Oct 2014 00:31:51 +0000 Subject: Add support of "/{udp,tcp,proto}" suffix into $firewall_myservices, which interpreted the listed items as port numbers of TCP services. A service with no suffix still works and recognized as a TCP service for backward compatibility. It should be updated with /tcp suffix. PR: 194292 MFC after: 1 week --- etc/rc.firewall | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'etc') diff --git a/etc/rc.firewall b/etc/rc.firewall index d8a3f6ca5508..20652535cb6e 100644 --- a/etc/rc.firewall +++ b/etc/rc.firewall @@ -422,8 +422,8 @@ case ${firewall_type} in [Ww][Oo][Rr][Kk][Ss][Tt][Aa][Tt][Ii][Oo][Nn]) # Configuration: - # firewall_myservices: List of TCP ports on which this host - # offers services. + # firewall_myservices: List of ports/protocols on which this + # host offers services. # firewall_allowservices: List of IPv4 and/or IPv6 addresses # that have access to # $firewall_myservices. @@ -487,7 +487,24 @@ case ${firewall_type} in # for i in ${firewall_allowservices} ; do for j in ${firewall_myservices} ; do - ${fwcmd} add pass tcp from $i to me $j + case $j in + [0-9A-Za-z]*/[Pp][Rr][Oo][Tt][Oo]) + ${fwcmd} add pass ${j%/[Pp][Rr][Oo][Tt][Oo]} from $i to me + ;; + [0-9A-Za-z]*/[Tt][Cc][Pp]) + ${fwcmd} add pass tcp from $i to me ${j%/[Tt][Cc][Pp]} + ;; + [0-9A-Za-z]*/[Uu][Dd][Pp]) + ${fwcmd} add pass udp from $i to me ${j%/[Uu][Dd][Pp]} + ;; + *[0-9A-Za-z]) + echo "Consider using tcp/$j in firewall_myservices." > /dev/stderr + ${fwcmd} add pass tcp from $i to me $j + ;; + *) + echo "Invalid port in firewall_myservices: $j" > /dev/stderr + ;; + esac done done -- cgit v1.3 From 98d13b7d481e69e9eca57102b8c114065512d434 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Sun, 19 Oct 2014 20:46:59 +0000 Subject: - Honer MK_KERBEROS for Heimdal rc.d scripts. - Add rc.c/kerberos to OLD_FILES. --- ObsoleteFiles.inc | 2 ++ etc/rc.d/Makefile | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'etc') diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index debdbc62c2d4..3629bb843543 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -48,6 +48,8 @@ OLD_FILES+=etc/rc.d/hv_kvpd # 20140917: libnv was accidentally being installed to /usr/lib instead of /lib OLD_LIBS+=usr/lib/libnv.a OLD_LIBS+=usr/lib/libnv.so.0 +# 20140829: rc.d/kerberos removed +OLD_FILES+=etc/rc.d/kerberos # 20140814: libopie version bump OLD_LIBS+=usr/lib/libopie.so.7 OLD_LIBS+=usr/lib32/libopie.so.7 diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 12c87db584cd..2a3057f68db9 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -70,12 +70,12 @@ FILES= DAEMON \ iscsictl \ iscsid \ jail \ - kadmind \ - kdc \ - kfd \ + ${_kadmind} \ + ${_kdc} \ + ${_kfd} \ kld \ kldxref \ - kpasswdd \ + ${_kpasswdd} \ ldconfig \ local \ localpkg \ @@ -181,6 +181,13 @@ _casperd= casperd _nscd= nscd .endif +.if ${MK_KERBEROS} != "no" +_kadmind= kadmind +_kdc= kdc +_kfd= kfd +_kpasswdd= kpasswdd +.endif + .if ${MK_OFED} != "no" _opensm= opensm .endif -- cgit v1.3 From 7e67dfc9e15e86afe145f70d90fade3bd762c666 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Mon, 20 Oct 2014 04:14:35 +0000 Subject: Fix a typo. Spotted by: O. Hartmann --- etc/rc.firewall | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.firewall b/etc/rc.firewall index 20652535cb6e..ee578effa8b7 100644 --- a/etc/rc.firewall +++ b/etc/rc.firewall @@ -498,7 +498,8 @@ case ${firewall_type} in ${fwcmd} add pass udp from $i to me ${j%/[Uu][Dd][Pp]} ;; *[0-9A-Za-z]) - echo "Consider using tcp/$j in firewall_myservices." > /dev/stderr + echo "Consider using ${j}/tcp in firewall_myservices." \ + > /dev/stderr ${fwcmd} add pass tcp from $i to me $j ;; *) -- cgit v1.3 From d7790611c185ee3e0ea33efcded27447281785bb Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Thu, 23 Oct 2014 23:14:23 +0000 Subject: Hook libxo to the build. Sponsored by: Juniper Networks, Inc. --- etc/mtree/BSD.include.dist | 2 ++ lib/Makefile | 1 + lib/libxo/Makefile | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 lib/libxo/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist index 3462d7ed9b95..fd543870cd73 100644 --- a/etc/mtree/BSD.include.dist +++ b/etc/mtree/BSD.include.dist @@ -249,6 +249,8 @@ .. libmilter .. + libxo + .. lzma .. machine diff --git a/lib/Makefile b/lib/Makefile index b683a90f6ff9..b1f0de0dd908 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -106,6 +106,7 @@ SUBDIR= ${SUBDIR_ORDERED} \ ${_libvgl} \ ${_libvmmapi} \ libwrap \ + libxo \ liby \ ${_libypclnt} \ libz \ diff --git a/lib/libxo/Makefile b/lib/libxo/Makefile new file mode 100644 index 000000000000..644b71f4a9c6 --- /dev/null +++ b/lib/libxo/Makefile @@ -0,0 +1,36 @@ +# $FreeBSD$ + +LIBXO= ${.CURDIR:H:H}/contrib/libxo + +.PATH: ${LIBXO}/libxo + +LIB= xo +SHLIB_MAJOR=0 + +SRCS= libxo.c + +CFLAGS+=-I${LIBXO}/libxo + +INCS= xo.h +INCSDIR=${INCLUDEDIR}/libxo + +MAN+= libxo.3 +MAN+= xo_attr.3 \ + xo_create.3 \ + xo_emit.3 \ + xo_err.3 \ + xo_finish.3 \ + xo_flush.3 \ + xo_no_setlocale.3 \ + xo_open_container.3 \ + xo_open_list.3 \ + xo_parse_args.3 \ + xo_set_allocator.3 \ + xo_set_flags.3 \ + xo_set_info.3 \ + xo_set_options.3 \ + xo_set_style.3 \ + xo_set_writer.3 +MAN+= xo_format.5 + +.include -- cgit v1.3 From 1c1c418e5270ce6c17f3dbba9bfdac6da3689e85 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Tue, 28 Oct 2014 10:39:41 +0000 Subject: Add regression tests for the timeout(1) utility They are modeled over the regression tests that are provided for the GNU coreutils timeout(1) utility --- etc/mtree/BSD.tests.dist | 2 + usr.bin/timeout/Makefile | 6 ++ usr.bin/timeout/tests/Makefile | 7 ++ usr.bin/timeout/tests/timeout.sh | 215 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 230 insertions(+) create mode 100644 usr.bin/timeout/tests/Makefile create mode 100644 usr.bin/timeout/tests/timeout.sh (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 45c2d7c0eb07..93ca4df7dedb 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -281,6 +281,8 @@ regress.multitest.out .. .. + timeout + .. tr .. truncate diff --git a/usr.bin/timeout/Makefile b/usr.bin/timeout/Makefile index 46ca6e36e8a9..c1957aeadeeb 100644 --- a/usr.bin/timeout/Makefile +++ b/usr.bin/timeout/Makefile @@ -1,5 +1,11 @@ # $FreeBSD$ +.include + PROG= timeout +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + .include diff --git a/usr.bin/timeout/tests/Makefile b/usr.bin/timeout/tests/Makefile new file mode 100644 index 000000000000..6303718dd222 --- /dev/null +++ b/usr.bin/timeout/tests/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/usr.bin/timeout + +ATF_TESTS_SH= timeout + +.include diff --git a/usr.bin/timeout/tests/timeout.sh b/usr.bin/timeout/tests/timeout.sh new file mode 100644 index 000000000000..e04e6f93b0b7 --- /dev/null +++ b/usr.bin/timeout/tests/timeout.sh @@ -0,0 +1,215 @@ +# $FreeBSD$ + +atf_test_case nominal +nominal_head() +{ + atf_set "descr" "Basic tests on timeout(1) utility" +} + +nominal_body() +{ + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 5 true +} + +atf_test_case time_unit +time_unit_head() +{ + atf_set "descr" "Test parsing the default time unit" +} + +time_unit_body() +{ + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 1d true + + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 1h true + + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 1m true + + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 1s true +} + +atf_test_case no_timeout +no_timeout_head() +{ + atf_set "descr" "Test disabled timeout" +} + +no_timeout_body() +{ + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x timeout 0 true +} + +atf_test_case exit_numbers +exit_numbers_head() +{ + atf_set "descr" "Test exit numbers" +} + +exit_numbers_body() +{ + atf_check \ + -o empty \ + -e empty \ + -s exit:2 \ + -x timeout 5 sh -c \'exit 2\' + + atf_check \ + -o empty \ + -e empty \ + -s exit:124 \ + -x timeout .1 sleep 1 + + # With preserv status exit shoudl be 128 + TERM aka 143 + atf_check \ + -o empty \ + -e empty \ + -s exit:143 \ + -x timeout --preserve-status .1 sleep 10 + + atf_check \ + -o empty \ + -e empty \ + -s exit:124 \ + -x timeout -s1 -k1 .1 sleep 10 + + atf_check \ + -o empty \ + -e empty \ + -s exit:0 \ + -x sh -c 'trap "" CHLD; exec timeout 10 true' +} + +atf_test_case with_a_child +with_a_child_head() +{ + atf_set "descr" "When starting with a child (coreutils bug#9098)" +} + +with_a_child_body() +{ + out=$(sleep .1 & exec timeout .5 sh -c 'sleep 2; echo foo') + status=$? + test "$out" = "" && test $status = 124 || atf_fail + +} + +atf_test_case invalid_timeout +invalid_timeout_head() +{ + atf_set "descr" "Invalid timeout" +} + +invalid_timeout_body() +{ + atf_check \ + -o empty \ + -e inline:"timeout: invalid duration\n" \ + -s exit:125 \ + -x timeout invalid sleep 0 + + atf_check \ + -o empty \ + -e inline:"timeout: invalid duration\n" \ + -s exit:125 \ + -x timeout --kill-after=invalid 1 sleep 0 + + atf_check \ + -o empty \ + -e inline:"timeout: invalid duration\n" \ + -s exit:125 \ + -x timeout 42D sleep 0 + + atf_check \ + -o empty \ + -e inline:"timeout: invalid duration\n" \ + -s exit:125 \ + -x timeout 999999999999999999999999999999999999999999999999999999999999d sleep 0 + + atf_check \ + -o empty \ + -e inline:"timeout: invalid duration\n" \ + -s exit:125 \ + -x timeout 2.34e+5d sleep 0 +} + +atf_test_case invalid_signal +invalid_signal_head() +{ + atf_set "descr" "Invalid signal" +} + +invalid_signal_body() +{ + atf_check \ + -o empty \ + -e inline:"timeout: invalid signal\n" \ + -s exit:125 \ + -x timeout --signal=invalid 1 sleep 0 +} + +atf_test_case invalid_command +invalid_command_head() +{ + atf_set "descr" "Invalid command" +} + +invalid_command_body() +{ + atf_check \ + -o empty \ + -e inline:"timeout: exec(.): Permission denied\n" \ + -s exit:126 \ + -x timeout 10 . +} + +atf_test_case no_such_command +no_such_command_head() +{ + atf_set "descr" "No such command" +} + +no_such_command_body() +{ + atf_check \ + -o empty \ + -e inline:"timeout: exec(enoexists): No such file or directory\n" \ + -s exit:127 \ + -x timeout 10 enoexists +} + +atf_init_test_cases() +{ + atf_add_test_case nominal + atf_add_test_case time_unit + atf_add_test_case no_timeout + atf_add_test_case exit_numbers + atf_add_test_case with_a_child + atf_add_test_case invalid_timeout + atf_add_test_case invalid_signal + atf_add_test_case invalid_command + atf_add_test_case no_such_command +} -- cgit v1.3 From f2664bdf4ba2f9aeaa4f16eeb4f15119f8de9c7c Mon Sep 17 00:00:00 2001 From: Ed Maste Date: Tue, 28 Oct 2014 14:48:52 +0000 Subject: Add missing /usr/lib/debug directories Directories for /usr/lib{,32}/{i18n,private} were missing from the mtree file, which caused installworld to install the files that should be in the directory as the name of the directory. --- ObsoleteFiles.inc | 5 +++++ etc/mtree/BSD.debug.dist | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'etc') diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 3629bb843543..5ac579f984a3 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,11 @@ # xargs -n1 | sort | uniq -d; # done +# 20141028: debug files accidentally installed as directory name +OLD_FILES+=usr/lib/debug/usr/lib/i18n +OLD_FILES+=usr/lib/debug/usr/lib/private +OLD_FILES+=usr/lib/debug/usr/lib32/i18n +OLD_FILES+=usr/lib/debug/usr/lib32/private # 20141015: OpenSSL 1.0.1j import OLD_FILES+=usr/share/openssl/man/man3/CMS_sign_add1_signer.3.gz # 20140922: sleepq_calc_signal_retval.9 and sleepq_catch_signals.9 removed diff --git a/etc/mtree/BSD.debug.dist b/etc/mtree/BSD.debug.dist index ab75d0fbb781..7797a4c4173d 100644 --- a/etc/mtree/BSD.debug.dist +++ b/etc/mtree/BSD.debug.dist @@ -26,8 +26,16 @@ lib engines .. + i18n + .. + private + .. .. lib32 + i18n + .. + private + .. .. libexec bsdinstall -- cgit v1.3 From 10cb24248a6f13974e11c255c8014cfefe6420a7 Mon Sep 17 00:00:00 2001 From: Mark Murray Date: Thu, 30 Oct 2014 21:21:53 +0000 Subject: This is the much-discussed major upgrade to the random(4) device, known to you all as /dev/random. This code has had an extensive rewrite and a good series of reviews, both by the author and other parties. This means a lot of code has been simplified. Pluggable structures for high-rate entropy generators are available, and it is most definitely not the case that /dev/random can be driven by only a hardware souce any more. This has been designed out of the device. Hardware sources are stirred into the CSPRNG (Yarrow, Fortuna) like any other entropy source. Pluggable modules may be written by third parties for additional sources. The harvesting structures and consequently the locking have been simplified. Entropy harvesting is done in a more general way (the documentation for this will follow). There is some GREAT entropy to be had in the UMA allocator, but it is disabled for now as messing with that is likely to annoy many people. The venerable (but effective) Yarrow algorithm, which is no longer supported by its authors now has an alternative, Fortuna. For now, Yarrow is retained as the default algorithm, but this may be changed using a kernel option. It is intended to make Fortuna the default algorithm for 11.0. Interested parties are encouraged to read ISBN 978-0-470-47424-2 "Cryptography Engineering" By Ferguson, Schneier and Kohno for Fortuna's gory details. Heck, read it anyway. Many thanks to Arthur Mesh who did early grunt work, and who got caught in the crossfire rather more than he deserved to. My thanks also to folks who helped me thresh this out on whiteboards and in the odd "Hallway track", or otherwise. My Nomex pants are on. Let the feedback commence! Reviewed by: trasz,des(partial),imp(partial?),rwatson(partial?) Approved by: so(des) --- etc/defaults/rc.conf | 2 +- etc/rc.d/Makefile | 1 - etc/rc.d/geli | 2 +- etc/rc.d/initrandom | 61 --- etc/rc.d/postrandom | 2 +- etc/rc.d/random | 2 +- libexec/save-entropy/save-entropy.sh | 2 +- .../kld/random_adaptor/random_adaptor_example.c | 54 ++- sys/conf/NOTES | 6 +- sys/conf/files | 11 +- sys/conf/options | 1 - sys/dev/glxsb/glxsb.c | 2 +- sys/dev/random/build.sh | 24 + sys/dev/random/dummy_rng.c | 121 +++-- sys/dev/random/fortuna.c | 433 +++++++++++++++++ sys/dev/random/fortuna.h | 44 ++ sys/dev/random/harvest.c | 141 ------ sys/dev/random/hash.c | 21 +- sys/dev/random/hash.h | 2 +- sys/dev/random/ivy.c | 43 +- sys/dev/random/live_entropy_sources.c | 145 +++--- sys/dev/random/live_entropy_sources.h | 31 +- sys/dev/random/nehemiah.c | 37 +- sys/dev/random/random_adaptors.c | 486 ++++++++++++++----- sys/dev/random/random_adaptors.h | 61 +-- sys/dev/random/random_harvestq.c | 428 +++++++++-------- sys/dev/random/random_harvestq.h | 40 +- sys/dev/random/randomdev.c | 271 ++++++----- sys/dev/random/randomdev.h | 51 +- sys/dev/random/randomdev_soft.c | 250 +++------- sys/dev/random/randomdev_soft.h | 51 +- sys/dev/random/rwfile.c | 96 ---- sys/dev/random/rwfile.h | 39 -- sys/dev/random/uint128.h | 75 +++ sys/dev/random/unit_test.c | 257 ++++++++++ sys/dev/random/unit_test.h | 72 +++ sys/dev/random/yarrow.c | 523 +++++++++++++-------- sys/dev/random/yarrow.h | 11 +- sys/kern/init_main.c | 2 +- sys/kern/kern_intr.c | 25 +- sys/kern/subr_bus.c | 2 +- sys/modules/Makefile | 15 + sys/modules/padlock_rng/Makefile | 11 + sys/modules/random/Makefile | 10 +- sys/modules/rdrand_rng/Makefile | 11 + sys/net/if_ethersubr.c | 3 +- sys/net/if_tun.c | 3 +- sys/netgraph/ng_iface.c | 3 +- sys/sys/random.h | 29 +- sys/vm/uma_core.c | 35 ++ 50 files changed, 2492 insertions(+), 1556 deletions(-) delete mode 100755 etc/rc.d/initrandom create mode 100755 sys/dev/random/build.sh create mode 100644 sys/dev/random/fortuna.c create mode 100644 sys/dev/random/fortuna.h delete mode 100644 sys/dev/random/harvest.c delete mode 100644 sys/dev/random/rwfile.c delete mode 100644 sys/dev/random/rwfile.h create mode 100644 sys/dev/random/uint128.h create mode 100644 sys/dev/random/unit_test.c create mode 100644 sys/dev/random/unit_test.h create mode 100644 sys/modules/padlock_rng/Makefile create mode 100644 sys/modules/rdrand_rng/Makefile (limited to 'etc') diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 18989fafffb3..79799bf91654 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -645,7 +645,7 @@ update_motd="YES" # update version info in /etc/motd (or NO) entropy_file="/entropy" # Set to NO to disable caching entropy through reboots. # /var/db/entropy-file is preferred if / is not avail. entropy_dir="/var/db/entropy" # Set to NO to disable caching entropy via cron. -entropy_save_sz="2048" # Size of the entropy cache files. +entropy_save_sz="4096" # Size of the entropy cache files. entropy_save_num="8" # Number of entropy cache files to save. harvest_interrupt="YES" # Entropy device harvests interrupt randomness harvest_ethernet="YES" # Entropy device harvests ethernet randomness diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 2a3057f68db9..72b524709701 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -57,7 +57,6 @@ FILES= DAEMON \ hostid_save \ hostname \ inetd \ - initrandom \ ip6addrctl \ ipfilter \ ipfs \ diff --git a/etc/rc.d/geli b/etc/rc.d/geli index 8b867b37cbd0..4551f716613b 100755 --- a/etc/rc.d/geli +++ b/etc/rc.d/geli @@ -28,7 +28,7 @@ # # PROVIDE: disks -# REQUIRE: initrandom +# REQUIRE: random # KEYWORD: nojail . /etc/rc.subr diff --git a/etc/rc.d/initrandom b/etc/rc.d/initrandom deleted file mode 100755 index 907668b191c6..000000000000 --- a/etc/rc.d/initrandom +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: initrandom -# REQUIRE: dumpon ddb -# BEFORE: disks -# KEYWORD: nojail - -. /etc/rc.subr - -name="initrandom" -start_cmd="initrandom_start" -stop_cmd=":" - -initrandom_start() -{ - soft_random_generator=`sysctl kern.random 2>/dev/null` - - echo -n 'Entropy harvesting:' - - if [ \! -z "${soft_random_generator}" ] ; then - - if [ -w /dev/random ]; then - if checkyesno harvest_interrupt; then - ${SYSCTL} kern.random.sys.harvest.interrupt=1 >/dev/null - echo -n ' interrupts' - else - ${SYSCTL} kern.random.sys.harvest.interrupt=0 >/dev/null - fi - - if checkyesno harvest_ethernet; then - ${SYSCTL} kern.random.sys.harvest.ethernet=1 >/dev/null - echo -n ' ethernet' - else - ${SYSCTL} kern.random.sys.harvest.ethernet=0 >/dev/null - fi - - if checkyesno harvest_p_to_p; then - ${SYSCTL} kern.random.sys.harvest.point_to_point=1 >/dev/null - echo -n ' point_to_point' - else - ${SYSCTL} kern.random.sys.harvest.point_to_point=0 >/dev/null - fi - - if checkyesno harvest_swi; then - ${SYSCTL} kern.random.sys.harvest.swi=1 >/dev/null - echo -n ' swi' - else - ${SYSCTL} kern.random.sys.harvest.swi=0 >/dev/null - fi - fi - - fi - - echo '.' -} - -load_rc_config random -run_rc_command "$1" diff --git a/etc/rc.d/postrandom b/etc/rc.d/postrandom index 006d56342fe8..3a608307e37f 100755 --- a/etc/rc.d/postrandom +++ b/etc/rc.d/postrandom @@ -4,7 +4,7 @@ # # PROVIDE: postrandom -# REQUIRE: initrandom random FILESYSTEMS +# REQUIRE: random FILESYSTEMS # BEFORE: LOGIN # KEYWORD: nojail diff --git a/etc/rc.d/random b/etc/rc.d/random index 8499522986e0..c7da932939fe 100755 --- a/etc/rc.d/random +++ b/etc/rc.d/random @@ -4,7 +4,7 @@ # # PROVIDE: random -# REQUIRE: initrandom FILESYSTEMS +# REQUIRE: FILESYSTEMS # BEFORE: netif # KEYWORD: nojail shutdown diff --git a/libexec/save-entropy/save-entropy.sh b/libexec/save-entropy/save-entropy.sh index 880a988404d7..06319d56e67a 100755 --- a/libexec/save-entropy/save-entropy.sh +++ b/libexec/save-entropy/save-entropy.sh @@ -53,7 +53,7 @@ case ${entropy_dir} in ;; esac -entropy_save_sz=${entropy_save_sz:-2048} +entropy_save_sz=${entropy_save_sz:-4096} entropy_save_num=${entropy_save_num:-8} if [ ! -d "${entropy_dir}" ]; then diff --git a/share/examples/kld/random_adaptor/random_adaptor_example.c b/share/examples/kld/random_adaptor/random_adaptor_example.c index da588a87fe5d..34993c17b9da 100644 --- a/share/examples/kld/random_adaptor/random_adaptor_example.c +++ b/share/examples/kld/random_adaptor/random_adaptor_example.c @@ -35,17 +35,20 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#include +#include +#include -static int random_example_read(void *, int); +static void live_random_example_init(void); +static void live_random_example_deinit(void); +static u_int live_random_example_read(void *, u_int); -struct random_adaptor random_example = { - .ident = "Example RNG", - .source = RANDOM_PURE_BOGUS, /* Make sure this is in - * sys/random.h and is unique */ - .read = random_example_read, +struct random_adaptor live_random_example = { + .les_ident = "Example RNG", + .les_source = RANDOM_PURE_BOGUS, /* Make sure this is in + * sys/random.h and is unique */ + .les_read = live_random_example_read, }; /* @@ -58,8 +61,26 @@ getRandomNumber(void) return 4; /* chosen by fair dice roll, guaranteed to be random */ } -static int -random_example_read(void *buf, int c) +static void +live_random_example_init(void) +{ + + /* Do initialisation stuff here */ +} + +static void +live_random_example_deinit(void) +{ + + /* Do de-initialisation stuff here */ +} + +/* get bytes of random stuff into . You may presume + * that is a multiple of 2^n, with n>=3. A typical value + * is c=16. + */ +static u_int +live_random_example_read(void *buf, u_int c) { uint8_t *b; int count; @@ -69,22 +90,23 @@ random_example_read(void *buf, int c) for (count = 0; count < c; count++) b[count] = getRandomNumber(); - printf("returning %d bytes of pure randomness\n", c); + /* printf("returning %d bytes of pure randomness\n", c); */ return (c); } +/* ARGSUSED */ static int -random_example_modevent(module_t mod, int type, void *unused) +live_random_example_modevent(module_t mod __unused, int type, void *unused __unused) { int error = 0; switch (type) { case MOD_LOAD: - live_entropy_source_register(&random_example); + live_entropy_source_register(&live_random_example); break; case MOD_UNLOAD: - live_entropy_source_deregister(&random_example); + live_entropy_source_deregister(&live_random_example); break; case MOD_SHUTDOWN: @@ -98,4 +120,6 @@ random_example_modevent(module_t mod, int type, void *unused) return (error); } -LIVE_ENTROPY_SRC_MODULE(live_entropy_source_example, random_example_modevent, 1); +DEV_MODULE(live_random_example, live_random_example_modevent, NULL); +MODULE_VERSION(live_random_example, 1); +MODULE_DEPEND(live_random_example, randomdev, 1, 1, 1); diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 4eb25d54f793..513300c57334 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2993,10 +2993,10 @@ options BROOKTREE_ALLOC_PAGES=(217*4+1) options MAXFILES=999 # Random number generator -options RANDOM_YARROW # Yarrow RNG -##options RANDOM_FORTUNA # Fortuna RNG - not yet implemented +# Only ONE of the below two may be used; they are mutually exclusive. +options RANDOM_YARROW # Yarrow CSPRNG (Default) +#options RANDOM_FORTUNA # Fortuna CSPRNG options RANDOM_DEBUG # Debugging messages -options RANDOM_RWFILE # Read and write entropy cache # Module to enable execution of application via emulators like QEMU options IMAGACT_BINMISC diff --git a/sys/conf/files b/sys/conf/files index 3e89dbb18a97..7abcc6692ebf 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -2132,16 +2132,15 @@ rt2860.fw optional rt2860fw | ralfw \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rt2860.fw" -dev/random/harvest.c standard -dev/random/dummy_rng.c standard +dev/random/randomdev.c standard dev/random/random_adaptors.c standard -dev/random/live_entropy_sources.c optional random -dev/random/random_harvestq.c optional random -dev/random/randomdev.c optional random +dev/random/dummy_rng.c standard +dev/random/live_entropy_sources.c standard +dev/random/random_harvestq.c standard dev/random/randomdev_soft.c optional random dev/random/yarrow.c optional random +dev/random/fortuna.c optional random dev/random/hash.c optional random -dev/random/rwfile.c optional random dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rl/if_rl.c optional rl pci diff --git a/sys/conf/options b/sys/conf/options index f6ad35ac979c..ae0f852bfd6f 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -930,4 +930,3 @@ RCTL opt_global.h RANDOM_YARROW opt_random.h RANDOM_FORTUNA opt_random.h RANDOM_DEBUG opt_random.h -RANDOM_RWFILE opt_random.h diff --git a/sys/dev/glxsb/glxsb.c b/sys/dev/glxsb/glxsb.c index 646fe3fe7eae..9a467eda7a06 100644 --- a/sys/dev/glxsb/glxsb.c +++ b/sys/dev/glxsb/glxsb.c @@ -476,7 +476,7 @@ glxsb_rnd(void *v) if (status & SB_RNS_TRNG_VALID) { value = bus_read_4(sc->sc_sr, SB_RANDOM_NUM); /* feed with one uint32 */ - random_harvest(&value, 4, 32/2, RANDOM_PURE_GLXSB); + random_harvest(&value, sizeof(value), 32/2, RANDOM_PURE_GLXSB); } callout_reset(&sc->sc_rngco, sc->sc_rnghz, glxsb_rnd, sc); diff --git a/sys/dev/random/build.sh b/sys/dev/random/build.sh new file mode 100755 index 000000000000..e573dc1c724c --- /dev/null +++ b/sys/dev/random/build.sh @@ -0,0 +1,24 @@ +# $FreeBSD$ +# +# Basic script to build crude unit tests. +# +cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_YARROW \ + -I../.. -lstdthreads -Wall \ + unit_test.c \ + yarrow.c \ + hash.c \ + ../../crypto/rijndael/rijndael-api-fst.c \ + ../../crypto/rijndael/rijndael-alg-fst.c \ + ../../crypto/sha2/sha2.c \ + ../../crypto/sha2/sha256c.c \ + -o yunit_test +cc -g -O0 -pthread -DRANDOM_DEBUG -DRANDOM_FORTUNA \ + -I../.. -lstdthreads -Wall \ + unit_test.c \ + fortuna.c \ + hash.c \ + ../../crypto/rijndael/rijndael-api-fst.c \ + ../../crypto/rijndael/rijndael-alg-fst.c \ + ../../crypto/sha2/sha2.c \ + ../../crypto/sha2/sha256c.c \ + -o funit_test diff --git a/sys/dev/random/dummy_rng.c b/sys/dev/random/dummy_rng.c index 810a784a3b1f..a7ca4b3460db 100644 --- a/sys/dev/random/dummy_rng.c +++ b/sys/dev/random/dummy_rng.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 Arthur Mesh + * Copyright (c) 2013 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,98 +28,92 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_random.h" + #include +#include #include #include +#include #include -#include #include -#include +#include #include -#include -#include #include - -static struct mtx dummy_random_mtx; - -/* Used to fake out unused random calls in random_adaptor */ -static void -random_null_func(void) -{ -} +#include static int -dummy_random_poll(int events __unused, struct thread *td __unused) +dummy_random_zero(void) { return (0); } -static int -dummy_random_block(int flag) +static void +dummy_random(void) { - int error = 0; - - mtx_lock(&dummy_random_mtx); - - /* Blocking logic */ - while (!error) { - if (flag & O_NONBLOCK) - error = EWOULDBLOCK; - else { - printf("random: dummy device blocking on read.\n"); - error = msleep(&dummy_random_block, - &dummy_random_mtx, - PUSER | PCATCH, "block", 0); - } - } - mtx_unlock(&dummy_random_mtx); - - return (error); } +/* ARGSUSED */ static void dummy_random_init(void) { - mtx_init(&dummy_random_mtx, "sleep mtx for dummy_random", - NULL, MTX_DEF); -} - -static void -dummy_random_deinit(void) -{ +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif - mtx_destroy(&dummy_random_mtx); + randomdev_init_reader(dummy_random_read_phony); } -struct random_adaptor dummy_random = { - .ident = "Dummy entropy device that always blocks", - .init = dummy_random_init, - .deinit = dummy_random_deinit, - .block = dummy_random_block, - .poll = dummy_random_poll, - .read = (random_read_func_t *)random_null_func, - .reseed = (random_reseed_func_t *)random_null_func, - .seeded = 0, /* This device can never be seeded */ - .priority = 1, /* Bottom priority, so goes to last position */ -}; - -static int -dummy_random_modevent(module_t mod __unused, int type, void *unused __unused) +/* This is used only by the internal read_random(9) call, and then only + * if no entropy processor is loaded. + * + * Make a token effort to provide _some_ kind of output. No warranty of + * the quality of this output is made, mainly because its lousy. + * + * This is only used by the internal read_random(9) call when no other + * adaptor is active. + * + * It has external scope due to the way things work in + * randomdev_[de]init_reader() that the rest of the world doesn't need to + * know about. + * + * Caveat Emptor. + */ +u_int +dummy_random_read_phony(uint8_t *buf, u_int count) { + /* If no entropy device is loaded, don't spam the console with warnings */ + static int warned = 0; + u_long randval; + size_t size, i; + + if (!warned) { + log(LOG_WARNING, "random device not loaded/active; using insecure pseudo-random number generator\n"); + warned = 1; + } - switch (type) { - case MOD_LOAD: - random_adaptor_register("dummy", &dummy_random); - EVENTHANDLER_INVOKE(random_adaptor_attach, - &dummy_random); + /* srandom() is called in kern/init_main.c:proc0_post() */ - return (0); + /* Fill buf[] with random(9) output */ + for (i = 0; i < count; i += sizeof(randval)) { + randval = random(); + size = MIN(count - i, sizeof(randval)); + memcpy(buf + i, &randval, (size_t)size); } - return (EINVAL); + return (count); } -RANDOM_ADAPTOR_MODULE(dummy, dummy_random_modevent, 1); +struct random_adaptor randomdev_dummy = { + .ra_ident = "Dummy", + .ra_priority = 1, /* Bottom priority, so goes to last position */ + .ra_reseed = dummy_random, + .ra_seeded = (random_adaptor_seeded_func_t *)dummy_random_zero, + .ra_read = (random_adaptor_read_func_t *)dummy_random_zero, + .ra_write = (random_adaptor_write_func_t *)dummy_random_zero, + .ra_init = dummy_random_init, + .ra_deinit = dummy_random, +}; diff --git a/sys/dev/random/fortuna.c b/sys/dev/random/fortuna.c new file mode 100644 index 000000000000..46ec88d9d540 --- /dev/null +++ b/sys/dev/random/fortuna.c @@ -0,0 +1,433 @@ +/*- + * Copyright (c) 2013-2014 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHOR ``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 AUTHOR 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 +__FBSDID("$FreeBSD$"); + +#ifdef _KERNEL +#include "opt_random.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#else /* !_KERNEL */ +#include +#include +#include +#include +#include +#include +#include + +#include "unit_test.h" + +#include +#include + +#include +#include +#include +#endif /* _KERNEL */ + +#if !defined(RANDOM_YARROW) && !defined(RANDOM_FORTUNA) +#define RANDOM_YARROW +#elif defined(RANDOM_YARROW) && defined(RANDOM_FORTUNA) +#error "Must define either RANDOM_YARROW or RANDOM_FORTUNA" +#endif + +#if defined(RANDOM_FORTUNA) + +#define NPOOLS 32 +#define MINPOOLSIZE 64 +#define DEFPOOLSIZE 256 +#define MAXPOOLSIZE 65536 + +/* This algorithm (and code) presumes that KEYSIZE is twice as large as BLOCKSIZE */ +CTASSERT(BLOCKSIZE == sizeof(uint128_t)); +CTASSERT(KEYSIZE == 2*BLOCKSIZE); + +/* This is the beastie that needs protecting. It contains all of the + * state that we are excited about. + * Exactly one is instantiated. + */ +static struct fortuna_state { + /* P_i */ + struct pool { + u_int length; + struct randomdev_hash hash; + } pool[NPOOLS]; + + /* ReseedCnt */ + u_int reseedcount; + + /* C - 128 bits */ + union { + uint8_t byte[BLOCKSIZE]; + uint128_t whole; + } counter; + + /* K */ + struct randomdev_key key; + + /* Extras */ + u_int minpoolsize; + + /* Extras for the OS */ + +#ifdef _KERNEL + /* For use when 'pacing' the reseeds */ + sbintime_t lasttime; +#endif +} fortuna_state; + +/* The random_reseed_mtx mutex protects seeding and polling/blocking. */ +static mtx_t random_reseed_mtx; + +static struct fortuna_start_cache { + uint8_t junk[PAGE_SIZE]; + size_t length; + struct randomdev_hash hash; +} fortuna_start_cache; + +#ifdef _KERNEL +static struct sysctl_ctx_list random_clist; +RANDOM_CHECK_UINT(minpoolsize, MINPOOLSIZE, MAXPOOLSIZE); +#endif + +void +random_fortuna_init_alg(void) +{ + int i; +#ifdef _KERNEL + struct sysctl_oid *random_fortuna_o; +#endif + + memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk)); + fortuna_start_cache.length = 0U; + randomdev_hash_init(&fortuna_start_cache.hash); + + /* Set up a lock for the reseed process */ +#ifdef _KERNEL + mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF); +#else /* !_KERNEL */ + mtx_init(&random_reseed_mtx, mtx_plain); +#endif /* _KERNEL */ + +#ifdef _KERNEL + /* Fortuna parameters. Do not adjust these unless you have + * have a very good clue about what they do! + */ + random_fortuna_o = SYSCTL_ADD_NODE(&random_clist, + SYSCTL_STATIC_CHILDREN(_kern_random), + OID_AUTO, "fortuna", CTLFLAG_RW, 0, + "Fortuna Parameters"); + + SYSCTL_ADD_PROC(&random_clist, + SYSCTL_CHILDREN(random_fortuna_o), OID_AUTO, + "minpoolsize", CTLTYPE_UINT|CTLFLAG_RW, + &fortuna_state.minpoolsize, DEFPOOLSIZE, + random_check_uint_minpoolsize, "IU", + "Minimum pool size necessary to cause a reseed automatically"); + + fortuna_state.lasttime = 0U; +#endif + + fortuna_state.minpoolsize = DEFPOOLSIZE; + + /* F&S - InitializePRNG() */ + + /* F&S - P_i = \epsilon */ + for (i = 0; i < NPOOLS; i++) { + randomdev_hash_init(&fortuna_state.pool[i].hash); + fortuna_state.pool[i].length = 0U; + } + + /* F&S - ReseedCNT = 0 */ + fortuna_state.reseedcount = 0U; + + /* F&S - InitializeGenerator() */ + + /* F&S - C = 0 */ + uint128_clear(&fortuna_state.counter.whole); + + /* F&S - K = 0 */ + memset(&fortuna_state.key, 0, sizeof(fortuna_state.key)); +} + +void +random_fortuna_deinit_alg(void) +{ + + mtx_destroy(&random_reseed_mtx); + memset(&fortuna_state, 0, sizeof(fortuna_state)); +} + +/* F&S - AddRandomEvent() */ +/* Process a single stochastic event off the harvest queue */ +void +random_fortuna_process_event(struct harvest_event *event) +{ + u_int pl; + + /* We must be locked for all this as plenty of state gets messed with */ + mtx_lock(&random_reseed_mtx); + + /* Accumulate the event into the appropriate pool + * where each event carries the destination information + */ + /* F&S - P_i = P_i| */ + /* The hash_init and hash_finish are done in random_fortuna_read() below */ + pl = event->he_destination % NPOOLS; + randomdev_hash_iterate(&fortuna_state.pool[pl].hash, event, sizeof(*event)); + /* No point in counting above the outside maximum */ + fortuna_state.pool[pl].length += event->he_size; + fortuna_state.pool[pl].length = MIN(fortuna_state.pool[pl].length, MAXPOOLSIZE); + + /* Done with state-messing */ + mtx_unlock(&random_reseed_mtx); +} + +/* F&S - Reseed() */ +/* Reseed Mutex is held */ +static void +reseed(uint8_t *junk, u_int length) +{ + struct randomdev_hash context; + uint8_t hash[KEYSIZE], temp[KEYSIZE]; + + KASSERT(fortuna_state.minpoolsize > 0, ("random: Fortuna threshold = 0")); +#ifdef _KERNEL + mtx_assert(&random_reseed_mtx, MA_OWNED); +#endif + + /* F&S - temp = H(K|s) */ + randomdev_hash_init(&context); + randomdev_hash_iterate(&context, &fortuna_state.key, sizeof(fortuna_state.key)); + randomdev_hash_iterate(&context, junk, length); + randomdev_hash_finish(&context, temp); + + /* F&S - hash = H(temp) */ + randomdev_hash_init(&context); + randomdev_hash_iterate(&context, temp, KEYSIZE); + randomdev_hash_finish(&context, hash); + + /* F&S - K = hash */ + randomdev_encrypt_init(&fortuna_state.key, temp); + memset(temp, 0, sizeof(temp)); + memset(hash, 0, sizeof(hash)); + + /* Unblock the device if it was blocked due to being unseeded */ + if (uint128_is_zero(fortuna_state.counter.whole)) + random_adaptor_unblock(); + /* F&S - C = C + 1 */ + uint128_increment(&fortuna_state.counter.whole); +} + +/* F&S - GenerateBlocks() */ +/* Reseed Mutex is held, and buf points to a whole number of blocks. */ +static __inline void +random_fortuna_genblocks(uint8_t *buf, u_int blockcount) +{ + u_int i; + + for (i = 0u; i < blockcount; i++) { + /* F&S - r = r|E(K,C) */ + randomdev_encrypt(&fortuna_state.key, fortuna_state.counter.byte, buf, BLOCKSIZE); + buf += BLOCKSIZE; + + /* F&S - C = C + 1 */ + uint128_increment(&fortuna_state.counter.whole); + } +} + +/* F&S - PseudoRandomData() */ +/* Reseed Mutex is held, and buf points to a whole number of blocks. */ +static __inline void +random_fortuna_genrandom(uint8_t *buf, u_int bytecount) +{ + static uint8_t temp[BLOCKSIZE*(KEYSIZE/BLOCKSIZE)]; + u_int blockcount; + + /* F&S - assert(n < 2^20) */ + KASSERT((bytecount <= (1 << 20)), ("invalid single read request to fortuna of %d bytes", bytecount)); + + /* F&S - r = first-n-bytes(GenerateBlocks(ceil(n/16))) */ + blockcount = (bytecount + BLOCKSIZE - 1)/BLOCKSIZE; + random_fortuna_genblocks(buf, blockcount); + + /* F&S - K = GenerateBlocks(2) */ + random_fortuna_genblocks(temp, KEYSIZE/BLOCKSIZE); + randomdev_encrypt_init(&fortuna_state.key, temp); + memset(temp, 0, sizeof(temp)); +} + +/* F&S - RandomData() */ +/* Used to return processed entropy from the PRNG */ +/* The argument buf points to a whole number of blocks. */ +void +random_fortuna_read(uint8_t *buf, u_int bytecount) +{ +#ifdef _KERNEL + sbintime_t thistime; +#endif + struct randomdev_hash context; + uint8_t s[NPOOLS*KEYSIZE], temp[KEYSIZE]; + int i; + u_int seedlength; + + /* We must be locked for all this as plenty of state gets messed with */ + mtx_lock(&random_reseed_mtx); + + /* if buf == NULL and bytecount == 0 then this is the pre-read. */ + /* if buf == NULL and bytecount != 0 then this is the post-read; ignore. */ + if (buf == NULL) { + if (bytecount == 0) { + if (fortuna_state.pool[0].length >= fortuna_state.minpoolsize +#ifdef _KERNEL + /* F&S - Use 'getsbinuptime()' to prevent reseed-spamming. */ + && ((thistime = getsbinuptime()) - fortuna_state.lasttime > hz/10) +#endif + ) { +#ifdef _KERNEL + fortuna_state.lasttime = thistime; +#endif + + seedlength = 0U; + /* F&S - ReseedCNT = ReseedCNT + 1 */ + fortuna_state.reseedcount++; + /* s = \epsilon by default */ + for (i = 0; i < NPOOLS; i++) { + /* F&S - if Divides(ReseedCnt, 2^i) ... */ + if ((fortuna_state.reseedcount % (1 << i)) == 0U) { + seedlength += KEYSIZE; + /* F&S - temp = (P_i) */ + randomdev_hash_finish(&fortuna_state.pool[i].hash, temp); + /* F&S - P_i = \epsilon */ + randomdev_hash_init(&fortuna_state.pool[i].hash); + fortuna_state.pool[i].length = 0U; + /* F&S - s = s|H(temp) */ + randomdev_hash_init(&context); + randomdev_hash_iterate(&context, temp, KEYSIZE); + randomdev_hash_finish(&context, s + i*KEYSIZE); + } + else + break; + } +#ifdef RANDOM_DEBUG + printf("random: active reseed: reseedcount [%d] ", fortuna_state.reseedcount); + for (i = 0; i < NPOOLS; i++) + printf(" %d", fortuna_state.pool[i].length); + printf("\n"); +#endif + /* F&S */ + reseed(s, seedlength); + + /* Clean up */ + memset(s, 0, seedlength); + seedlength = 0U; + memset(temp, 0, sizeof(temp)); + memset(&context, 0, sizeof(context)); + } + } + } + /* if buf != NULL do a regular read. */ + else + random_fortuna_genrandom(buf, bytecount); + + mtx_unlock(&random_reseed_mtx); +} + +/* Internal function to hand external entropy to the PRNG */ +void +random_fortuna_write(uint8_t *buf, u_int count) +{ + uint8_t temp[KEYSIZE]; + int i; + uintmax_t timestamp; + + timestamp = get_cyclecount(); + randomdev_hash_iterate(&fortuna_start_cache.hash, ×tamp, sizeof(timestamp)); + randomdev_hash_iterate(&fortuna_start_cache.hash, buf, count); + timestamp = get_cyclecount(); + randomdev_hash_iterate(&fortuna_start_cache.hash, ×tamp, sizeof(timestamp)); + randomdev_hash_finish(&fortuna_start_cache.hash, temp); + for (i = 0; i < KEYSIZE; i++) + fortuna_start_cache.junk[(fortuna_start_cache.length + i)%PAGE_SIZE] ^= temp[i]; + fortuna_start_cache.length += KEYSIZE; + +#ifdef RANDOM_DEBUG + printf("random: %s - ", __func__); + for (i = 0; i < KEYSIZE; i++) + printf("%02X", temp[i]); + printf("\n"); +#endif + + memset(temp, 0, KEYSIZE); + + /* We must be locked for all this as plenty of state gets messed with */ + mtx_lock(&random_reseed_mtx); + + randomdev_hash_init(&fortuna_start_cache.hash); + + reseed(fortuna_start_cache.junk, MIN(PAGE_SIZE, fortuna_start_cache.length)); + memset(fortuna_start_cache.junk, 0, sizeof(fortuna_start_cache.junk)); + + mtx_unlock(&random_reseed_mtx); +} + +void +random_fortuna_reseed(void) +{ + + /* CWOT */ +} + +int +random_fortuna_seeded(void) +{ + + return (!uint128_is_zero(fortuna_state.counter.whole)); +} + +#endif /* RANDOM_FORTUNA */ diff --git a/sys/dev/random/fortuna.h b/sys/dev/random/fortuna.h new file mode 100644 index 000000000000..81fcac3f0b11 --- /dev/null +++ b/sys/dev/random/fortuna.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2013 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef SYS_DEV_RANDOM_FORTUNA_H_INCLUDED +#define SYS_DEV_RANDOM_FORTUNA_H_INCLUDED + +#ifdef _KERNEL +typedef struct mtx mtx_t; +#endif + +void random_fortuna_init_alg(void); +void random_fortuna_deinit_alg(void); +void random_fortuna_read(uint8_t *, u_int); +void random_fortuna_write(uint8_t *, u_int); +void random_fortuna_reseed(void); +int random_fortuna_seeded(void); +void random_fortuna_process_event(struct harvest_event *event); + +#endif diff --git a/sys/dev/random/harvest.c b/sys/dev/random/harvest.c deleted file mode 100644 index 9dbae8449b35..000000000000 --- a/sys/dev/random/harvest.c +++ /dev/null @@ -1,141 +0,0 @@ -/*- - * Copyright (c) 2000-2013 Mark R V Murray - * 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 - * in this position and unchanged. - * 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 AUTHOR ``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 AUTHOR 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -static int read_random_phony(void *, int); - -/* Structure holding the desired entropy sources */ -struct harvest_select harvest = { 1, 1, 1, 1 }; -static int warned = 0; - -/* hold the address of the routine which is actually called if - * the randomdev is loaded - */ -static void (*reap_func)(u_int64_t, const void *, u_int, u_int, - enum esource) = NULL; -static int (*read_func)(void *, int) = read_random_phony; - -/* Initialise the harvester at load time */ -void -randomdev_init_harvester(void (*reaper)(u_int64_t, const void *, u_int, - u_int, enum esource), int (*reader)(void *, int)) -{ - reap_func = reaper; - read_func = reader; -} - -/* Deinitialise the harvester at unload time */ -void -randomdev_deinit_harvester(void) -{ - reap_func = NULL; - read_func = read_random_phony; - warned = 0; -} - -/* Entropy harvesting routine. This is supposed to be fast; do - * not do anything slow in here! - * Implemented as in indirect call to allow non-inclusion of - * the entropy device. - * - * XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle - * counters are built in, but on older hardware it will do a real time clock - * read which can be quite expensive. - */ -void -random_harvest(const void *entropy, u_int count, u_int bits, enum esource origin) -{ - if (reap_func) - (*reap_func)(get_cyclecount(), entropy, count, bits, origin); -} - -/* Userland-visible version of read_random */ -int -read_random(void *buf, int count) -{ - return ((*read_func)(buf, count)); -} - -/* If the entropy device is not loaded, make a token effort to - * provide _some_ kind of randomness. This should only be used - * inside other RNG's, like arc4random(9). - */ -static int -read_random_phony(void *buf, int count) -{ - u_long randval; - int size, i; - - if (!warned) { - log(LOG_WARNING, "random device not loaded; using insecure entropy\n"); - warned = 1; - } - - /* srandom() is called in kern/init_main.c:proc0_post() */ - - /* Fill buf[] with random(9) output */ - for (i = 0; i < count; i+= (int)sizeof(u_long)) { - randval = random(); - size = MIN(count - i, sizeof(u_long)); - memcpy(&((char *)buf)[i], &randval, (size_t)size); - } - - return (count); -} - -/* Helper routine to enable kproc_exit() to work while the module is - * being (or has been) unloaded. - * This routine is in this file because it is always linked into the kernel, - * and will thus never be unloaded. This is critical for unloadable modules - * that have threads. - */ -void -random_set_wakeup_exit(void *control) -{ - wakeup(control); - kproc_exit(0); - /* NOTREACHED */ -} diff --git a/sys/dev/random/hash.c b/sys/dev/random/hash.c index cf0feaa66ef9..7deee8781917 100644 --- a/sys/dev/random/hash.c +++ b/sys/dev/random/hash.c @@ -28,18 +28,33 @@ #include __FBSDID("$FreeBSD$"); +#ifdef _KERNEL #include #include +#else /* !_KERNEL */ +#include +#include +#include +#include +#include +#include +#include +#include "unit_test.h" +#endif /* _KERNEL */ #include #include #include +/* This code presumes that KEYSIZE is twice as large as BLOCKSIZE */ +CTASSERT(KEYSIZE == 2*BLOCKSIZE); + /* Initialise the hash */ void randomdev_hash_init(struct randomdev_hash *context) { + SHA256_Init(&context->sha); } @@ -47,6 +62,7 @@ randomdev_hash_init(struct randomdev_hash *context) void randomdev_hash_iterate(struct randomdev_hash *context, void *data, size_t size) { + SHA256_Update(&context->sha, data, size); } @@ -56,6 +72,7 @@ randomdev_hash_iterate(struct randomdev_hash *context, void *data, size_t size) void randomdev_hash_finish(struct randomdev_hash *context, void *buf) { + SHA256_Final(buf, &context->sha); } @@ -66,6 +83,7 @@ randomdev_hash_finish(struct randomdev_hash *context, void *buf) void randomdev_encrypt_init(struct randomdev_key *context, void *data) { + rijndael_cipherInit(&context->cipher, MODE_CBC, NULL); rijndael_makeKey(&context->key, DIR_ENCRYPT, KEYSIZE*8, data); } @@ -75,7 +93,8 @@ randomdev_encrypt_init(struct randomdev_key *context, void *data) * a multiple of BLOCKSIZE. */ void -randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, unsigned length) +randomdev_encrypt(struct randomdev_key *context, void *d_in, void *d_out, u_int length) { + rijndael_blockEncrypt(&context->cipher, &context->key, d_in, length*8, d_out); } diff --git a/sys/dev/random/hash.h b/sys/dev/random/hash.h index 4e6a4a0db831..57c0c6dfd81c 100644 --- a/sys/dev/random/hash.h +++ b/sys/dev/random/hash.h @@ -45,6 +45,6 @@ void randomdev_hash_init(struct randomdev_hash *); void randomdev_hash_iterate(struct randomdev_hash *, void *, size_t); void randomdev_hash_finish(struct randomdev_hash *, void *); void randomdev_encrypt_init(struct randomdev_key *, void *); -void randomdev_encrypt(struct randomdev_key *context, void *, void *, unsigned); +void randomdev_encrypt(struct randomdev_key *context, void *, void *, u_int); #endif diff --git a/sys/dev/random/ivy.c b/sys/dev/random/ivy.c index 23fd542e5c1a..724e7aacf937 100644 --- a/sys/dev/random/ivy.c +++ b/sys/dev/random/ivy.c @@ -35,11 +35,11 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include -#include #include #include @@ -47,18 +47,17 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#include #define RETRY_COUNT 10 -static int random_ivy_read(void *, int); +static u_int random_ivy_read(void *, u_int); -static struct random_hardware_source random_ivy = { - .ident = "Hardware, Intel Secure Key RNG", - .source = RANDOM_PURE_RDRAND, - .read = random_ivy_read +static struct live_entropy_source random_ivy = { + .les_ident = "Intel Secure Key RNG", + .les_source = RANDOM_PURE_RDRAND, + .les_read = random_ivy_read }; static inline int @@ -86,15 +85,17 @@ ivy_rng_store(long *buf) #endif } -static int -random_ivy_read(void *buf, int c) +/* It is specifically allowed that buf is a multiple of sizeof(long) */ +static u_int +random_ivy_read(void *buf, u_int c) { long *b; - int count; + u_int count; - KASSERT(c % sizeof(long) == 0, ("partial read %d", c)); - for (b = buf, count = c; count > 0; count -= sizeof(long), b++) { - if (ivy_rng_store(b) == 0) + KASSERT(c % sizeof(*b) == 0, ("partial read %d", c)); + b = buf; + for (count = c; count > 0; count -= sizeof(*b)) { + if (ivy_rng_store(b++) == 0) break; } return (c - count); @@ -107,14 +108,10 @@ rdrand_modevent(module_t mod, int type, void *unused) switch (type) { case MOD_LOAD: - if (cpu_feature2 & CPUID2_RDRAND) + if (cpu_feature2 & CPUID2_RDRAND) { live_entropy_source_register(&random_ivy); - else -#ifndef KLD_MODULE - if (bootverbose) -#endif - printf("%s: RDRAND is not present\n", - random_ivy.ident); + printf("random: live provider: \"%s\"\n", random_ivy.les_ident); + } break; case MOD_UNLOAD: @@ -134,4 +131,6 @@ rdrand_modevent(module_t mod, int type, void *unused) return (error); } -LIVE_ENTROPY_SRC_MODULE(random_rdrand, rdrand_modevent, 1); +DEV_MODULE(rdrand, rdrand_modevent, NULL); +MODULE_VERSION(rdrand, 1); +MODULE_DEPEND(rdrand, random_adaptors, 1, 1, 1); diff --git a/sys/dev/random/live_entropy_sources.c b/sys/dev/random/live_entropy_sources.c index d406ebd20861..9899cb4f9299 100644 --- a/sys/dev/random/live_entropy_sources.c +++ b/sys/dev/random/live_entropy_sources.c @@ -28,13 +28,16 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_random.h" + #include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -49,89 +52,73 @@ __FBSDID("$FreeBSD$"); #include "live_entropy_sources.h" -LIST_HEAD(les_head, live_entropy_sources); -static struct les_head sources = LIST_HEAD_INITIALIZER(sources); - /* - * The live_lock protects the consistency of the "struct les_head sources" + * The les_lock protects the consistency of the "struct les_head les_sources" */ -static struct sx les_lock; /* need a sleepable lock */ +static struct sx les_lock; /* Need a sleepable lock for the sbuf/sysctl stuff. */ + +LIST_HEAD(les_head, live_entropy_sources); +static struct les_head les_sources = LIST_HEAD_INITIALIZER(les_sources); void -live_entropy_source_register(struct random_hardware_source *rsource) +live_entropy_source_register(struct live_entropy_source *rsource) { - struct live_entropy_sources *les; + struct live_entropy_sources *lles; KASSERT(rsource != NULL, ("invalid input to %s", __func__)); - les = malloc(sizeof(struct live_entropy_sources), M_ENTROPY, M_WAITOK); - les->rsource = rsource; + lles = malloc(sizeof(*lles), M_ENTROPY, M_WAITOK); + lles->lles_rsource = rsource; sx_xlock(&les_lock); - LIST_INSERT_HEAD(&sources, les, entries); + LIST_INSERT_HEAD(&les_sources, lles, lles_entries); sx_xunlock(&les_lock); } void -live_entropy_source_deregister(struct random_hardware_source *rsource) +live_entropy_source_deregister(struct live_entropy_source *rsource) { - struct live_entropy_sources *les = NULL; + struct live_entropy_sources *lles = NULL; KASSERT(rsource != NULL, ("invalid input to %s", __func__)); sx_xlock(&les_lock); - LIST_FOREACH(les, &sources, entries) - if (les->rsource == rsource) { - LIST_REMOVE(les, entries); + LIST_FOREACH(lles, &les_sources, lles_entries) + if (lles->lles_rsource == rsource) { + LIST_REMOVE(lles, lles_entries); break; } sx_xunlock(&les_lock); - if (les != NULL) - free(les, M_ENTROPY); + if (lles != NULL) + free(lles, M_ENTROPY); } static int live_entropy_source_handler(SYSCTL_HANDLER_ARGS) { - struct live_entropy_sources *les; + struct live_entropy_sources *lles; + struct sbuf sbuf; int error, count; - count = error = 0; - sx_slock(&les_lock); - if (LIST_EMPTY(&sources)) - error = SYSCTL_OUT(req, "", 0); - else { - LIST_FOREACH(les, &sources, entries) { - - error = SYSCTL_OUT(req, ",", count++ ? 1 : 0); - if (error) - break; + sbuf_new_for_sysctl(&sbuf, NULL, 64, req); - error = SYSCTL_OUT(req, les->rsource->ident, strlen(les->rsource->ident)); - if (error) - break; - } + count = 0; + LIST_FOREACH(lles, &les_sources, lles_entries) { + sbuf_cat(&sbuf, (count++ ? ",'" : "'")); + sbuf_cat(&sbuf, lles->lles_rsource->les_ident); + sbuf_cat(&sbuf, "'"); } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + sx_sunlock(&les_lock); return (error); } -static void -live_entropy_sources_init(void *unused) -{ - - SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources, - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, - NULL, 0, live_entropy_source_handler, "", - "List of Active Live Entropy Sources"); - - sx_init(&les_lock, "live_entropy_sources"); -} - /* * Run through all "live" sources reading entropy for the given * number of rounds, which should be a multiple of the number @@ -140,15 +127,18 @@ live_entropy_sources_init(void *unused) * * BEWARE!!! * This function runs inside the RNG thread! Don't do anything silly! - * Remember that we are NOT holding harvest_mtx on entry! + */ +/* XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle + * counters are built in, but on older hardware it will do a real time clock + * read which can be quite expensive. */ void -live_entropy_sources_feed(int rounds, event_proc_f entropy_processor) +live_entropy_sources_feed(void) { - static struct harvest event; - static uint8_t buf[HARVESTSIZE]; - struct live_entropy_sources *les; - int i, n; + static struct harvest_event event; + struct live_entropy_sources *lles; + int i, read_rate; + u_int n; sx_slock(&les_lock); @@ -156,25 +146,23 @@ live_entropy_sources_feed(int rounds, event_proc_f entropy_processor) * Walk over all of live entropy sources, and feed their output * to the system-wide RNG. */ - LIST_FOREACH(les, &sources, entries) { - - for (i = 0; i < rounds; i++) { - /* - * This should be quick, since it's a live entropy - * source. - */ - /* FIXME: Whine loudly if this didn't work. */ - n = les->rsource->read(buf, sizeof(buf)); - n = MIN(n, HARVESTSIZE); - - event.somecounter = get_cyclecount(); - event.size = n; - event.bits = (n*8)/2; - event.source = les->rsource->source; - memcpy(event.entropy, buf, n); + read_rate = random_adaptor_read_rate(); + LIST_FOREACH(lles, &les_sources, lles_entries) { + + for (i = 0; i < harvest_pool_count*read_rate; i++) { + /* This *must* be quick, since it's a live entropy source. */ + n = lles->lles_rsource->les_read(event.he_entropy, HARVESTSIZE); + KASSERT((n > 0 && n <= HARVESTSIZE), ("very bad return from les_read (= %d) in %s", n, __func__)); + memset(event.he_entropy + n, 0, HARVESTSIZE - n); + + event.he_somecounter = get_cyclecount(); + event.he_size = n; + event.he_bits = (n*8)/2; + event.he_source = lles->lles_rsource->les_source; + event.he_destination = harvest_destination[event.he_source]++; /* Do the actual entropy insertion */ - entropy_processor(&event); + harvest_process_event(&event); } } @@ -182,14 +170,21 @@ live_entropy_sources_feed(int rounds, event_proc_f entropy_processor) sx_sunlock(&les_lock); } -static void -live_entropy_sources_deinit(void *unused) +void +live_entropy_sources_init(void) { - sx_destroy(&les_lock); + SYSCTL_PROC(_kern_random, OID_AUTO, live_entropy_sources, + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, 0, live_entropy_source_handler, "", + "List of Active Live Entropy Sources"); + + sx_init(&les_lock, "live_entropy_sources"); } -SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, - live_entropy_sources_init, NULL); -SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, - live_entropy_sources_deinit, NULL); +void +live_entropy_sources_deinit(void) +{ + + sx_destroy(&les_lock); +} diff --git a/sys/dev/random/live_entropy_sources.h b/sys/dev/random/live_entropy_sources.h index 9a23070fa637..95e2e4bf5a2c 100644 --- a/sys/dev/random/live_entropy_sources.h +++ b/sys/dev/random/live_entropy_sources.h @@ -30,31 +30,30 @@ #ifndef SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED #define SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED +typedef u_int random_live_read_func_t(void *, u_int); + /* * Live entropy source is a source of entropy that can provide * specified or approximate amount of entropy immediately upon request or within * an acceptable amount of time. */ +struct live_entropy_source { + const char *les_ident; + enum random_entropy_source les_source; + random_live_read_func_t *les_read; +}; + struct live_entropy_sources { - LIST_ENTRY(live_entropy_sources) entries; /* list of providers */ - struct random_hardware_source *rsource; /* associated random adaptor */ + LIST_ENTRY(live_entropy_sources) lles_entries; /* list of providers */ + struct live_entropy_source *lles_rsource; /* associated random adaptor */ }; extern struct mtx live_mtx; -void live_entropy_source_register(struct random_hardware_source *); -void live_entropy_source_deregister(struct random_hardware_source *); -void live_entropy_sources_feed(int, event_proc_f); - -#define LIVE_ENTROPY_SRC_MODULE(name, modevent, ver) \ - static moduledata_t name##_mod = { \ - #name, \ - modevent, \ - 0 \ - }; \ - DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \ - SI_ORDER_SECOND); \ - MODULE_VERSION(name, ver); \ - MODULE_DEPEND(name, random, 1, 1, 1); +void live_entropy_sources_init(void); +void live_entropy_sources_deinit(void); +void live_entropy_source_register(struct live_entropy_source *); +void live_entropy_source_deregister(struct live_entropy_source *); +void live_entropy_sources_feed(void); #endif /* SYS_DEV_RANDOM_LIVE_ENTROPY_SOURCES_H_INCLUDED */ diff --git a/sys/dev/random/nehemiah.c b/sys/dev/random/nehemiah.c index b60689e2bc64..47402507c9e7 100644 --- a/sys/dev/random/nehemiah.c +++ b/sys/dev/random/nehemiah.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 2013 Mark R V Murray + * Copyright (c) 2013 David E. O'Brien * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,11 +31,11 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include -#include #include #include @@ -44,21 +45,20 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include #include +#include static void random_nehemiah_init(void); static void random_nehemiah_deinit(void); -static int random_nehemiah_read(void *, int); +static u_int random_nehemiah_read(void *, u_int); -static struct random_hardware_source random_nehemiah = { - .ident = "Hardware, VIA Nehemiah Padlock RNG", - .source = RANDOM_PURE_NEHEMIAH, - .read = random_nehemiah_read +static struct live_entropy_source random_nehemiah = { + .les_ident = "VIA Nehemiah Padlock RNG", + .les_source = RANDOM_PURE_NEHEMIAH, + .les_read = random_nehemiah_read }; -/* TODO: now that the Davies-Meyer hash is gone and we only use +/* XXX: FIX? Now that the Davies-Meyer hash is gone and we only use * the 'xstore' instruction, do we still need to preserve the * FPU state with fpu_kern_(enter|leave)() ? */ @@ -75,7 +75,7 @@ VIA_RNG_store(void *buf) #ifdef __GNUCLIKE_ASM __asm __volatile( "movl $0,%%edx\n\t" - ".byte 0x0f, 0xa7, 0xc0" /* xstore */ + "xstore" : "=a" (retval), "+d" (rate), "+D" (buf) : : "memory" @@ -100,8 +100,9 @@ random_nehemiah_deinit(void) fpu_kern_free_ctx(fpu_ctx_save); } -static int -random_nehemiah_read(void *buf, int c) +/* It is specifically allowed that buf is a multiple of sizeof(long) */ +static u_int +random_nehemiah_read(void *buf, u_int c) { uint8_t *b; size_t count, ret; @@ -131,13 +132,9 @@ nehemiah_modevent(module_t mod, int type, void *unused) case MOD_LOAD: if (via_feature_rng & VIA_HAS_RNG) { live_entropy_source_register(&random_nehemiah); + printf("random: live provider: \"%s\"\n", random_nehemiah.les_ident); random_nehemiah_init(); - } else -#ifndef KLD_MODULE - if (bootverbose) -#endif - printf("%s: VIA Padlock RNG not present\n", - random_nehemiah.ident); + } break; case MOD_UNLOAD: @@ -158,4 +155,6 @@ nehemiah_modevent(module_t mod, int type, void *unused) return (error); } -LIVE_ENTROPY_SRC_MODULE(nehemiah, nehemiah_modevent, 1); +DEV_MODULE(nehemiah, nehemiah_modevent, NULL); +MODULE_VERSION(nehemiah, 1); +MODULE_DEPEND(nehemiah, random_adaptors, 1, 1, 1); diff --git a/sys/dev/random/random_adaptors.c b/sys/dev/random/random_adaptors.c index aa6db7b74947..c58f929e5acf 100644 --- a/sys/dev/random/random_adaptors.c +++ b/sys/dev/random/random_adaptors.c @@ -1,7 +1,7 @@ /*- + * Copyright (c) 2013 Mark R V Murray * Copyright (c) 2013 Arthur Mesh * Copyright (c) 2013 David E. O'Brien - * Copyright (c) 2013 Mark R V Murray * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,195 +29,383 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_random.h" + #include +#include +#include #include #include #include #include #include +#include +#include +#include #include #include +#include #include #include #include +#include #include #include -#include #include +#include +/* The random_adaptors_lock protects random_adaptors_list and friends and random_adaptor. + * We need a sleepable lock for uiomove/block/poll/sbuf/sysctl. + */ +static struct sx random_adaptors_lock; LIST_HEAD(adaptors_head, random_adaptors); -static struct adaptors_head adaptors = LIST_HEAD_INITIALIZER(adaptors); -static struct sx adaptors_lock; /* need a sleepable lock */ - -/* List for the dynamic sysctls */ -static struct sysctl_ctx_list random_clist; +static struct adaptors_head random_adaptors_list = LIST_HEAD_INITIALIZER(random_adaptors_list); +static struct random_adaptor *random_adaptor = NULL; /* Currently active adaptor */ +/* End of data items requiring random_adaptors_lock protection */ -struct random_adaptor *random_adaptor; +/* The random_readrate_mtx mutex protects the read-rate estimator. + */ +static struct mtx random_read_rate_mtx; +static int random_adaptor_read_rate_cache; +/* End of data items requiring random_readrate_mtx mutex protection */ -MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures"); +static struct selinfo rsel; -int -random_adaptor_register(const char *name, struct random_adaptor *rsp) +/* Utility routine to change active adaptor when the random_adaptors_list + * gets modified. + * + * Walk a list of registered random(4) adaptors and pick either a requested + * one or the highest priority one, whichever comes first. Panic on failure + * as the fallback must always be the "dummy" adaptor. + */ +static void +random_adaptor_choose(void) { - struct random_adaptors *rpp; + char rngs[128], *token, *cp; + struct random_adaptors *rra, *rrai; + struct random_adaptor *random_adaptor_previous; + int primax; - KASSERT(name != NULL && rsp != NULL, ("invalid input to %s", __func__)); + /* We are going to be messing with random_adaptor. + * Exclusive lock is mandatory. + */ + sx_assert(&random_adaptors_lock, SA_XLOCKED); - rpp = malloc(sizeof(struct random_adaptors), M_ENTROPY, M_WAITOK); - rpp->name = name; - rpp->rsp = rsp; + random_adaptor_previous = random_adaptor; - sx_xlock(&adaptors_lock); - LIST_INSERT_HEAD(&adaptors, rpp, entries); - sx_xunlock(&adaptors_lock); + random_adaptor = NULL; + if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) { + cp = rngs; - return (0); + /* XXX: FIX!! (DES): + * - fetch tunable once, at boot + * - make sysctl r/w + * - when fetching tunable or processing a sysctl + * write, parse into list of strings so we don't + * have to do it here again and again + * - sysctl read should return a reconstructed string + */ + while ((token = strsep(&cp, ",")) != NULL) { + LIST_FOREACH(rra, &random_adaptors_list, rra_entries) + if (strcmp(rra->rra_name, token) == 0) { + random_adaptor = rra->rra_ra; + break; + } + if (random_adaptor != NULL) { + printf("random: selecting requested adaptor <%s>\n", + random_adaptor->ra_ident); + break; + } + else + printf("random: requested adaptor <%s> not available\n", + token); + } + } + + primax = 0; + if (random_adaptor == NULL) { + /* + * Fall back to the highest priority item on the available + * RNG list. + */ + LIST_FOREACH(rrai, &random_adaptors_list, rra_entries) { + if (rrai->rra_ra->ra_priority >= primax) { + random_adaptor = rrai->rra_ra; + primax = rrai->rra_ra->ra_priority; + } + } + if (random_adaptor != NULL) + printf("random: selecting highest priority adaptor <%s>\n", + random_adaptor->ra_ident); + } + + KASSERT(random_adaptor != NULL, ("adaptor not found")); + + /* If we are changing adaptors, deinit the old and init the new. */ + if (random_adaptor != random_adaptor_previous) { +#ifdef RANDOM_DEBUG + printf("random: %s - changing from %s to %s\n", __func__, + (random_adaptor_previous == NULL ? "NULL" : random_adaptor_previous->ra_ident), + random_adaptor->ra_ident); +#endif + if (random_adaptor_previous != NULL) + (random_adaptor_previous->ra_deinit)(); + (random_adaptor->ra_init)(); + } } -struct random_adaptor * -random_adaptor_get(const char *name) -{ - struct random_adaptors *rpp; - struct random_adaptor *rsp; - rsp = NULL; +/* XXX: FIX!! Make sure we are not inserting a duplicate */ +void +random_adaptor_register(const char *name, struct random_adaptor *ra) +{ + struct random_adaptors *rra; - sx_slock(&adaptors_lock); + KASSERT(name != NULL && ra != NULL, ("invalid input to %s", __func__)); - LIST_FOREACH(rpp, &adaptors, entries) - if (strcmp(rpp->name, name) == 0) - rsp = rpp->rsp; + rra = malloc(sizeof(*rra), M_ENTROPY, M_WAITOK); + rra->rra_name = name; + rra->rra_ra = ra; - sx_sunlock(&adaptors_lock); + sx_xlock(&random_adaptors_lock); + LIST_INSERT_HEAD(&random_adaptors_list, rra, rra_entries); + random_adaptor_choose(); + sx_xunlock(&random_adaptors_lock); - return (rsp); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); } -/* - * Walk a list of registered random(4) adaptors and pick the last non-selected - * one. - * - * If none are selected, use yarrow if available. - */ void -random_adaptor_choose(struct random_adaptor **adaptor) +random_adaptor_deregister(const char *name) { - char rngs[128], *token, *cp; - struct random_adaptors *rppi, *ramax; - unsigned primax; + struct random_adaptors *rra; - KASSERT(adaptor != NULL, ("pre-conditions failed")); + KASSERT(name != NULL, ("invalid input to %s", __func__)); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - *adaptor = NULL; - if (TUNABLE_STR_FETCH("kern.random.active_adaptor", rngs, sizeof(rngs))) { - cp = rngs; + sx_xlock(&random_adaptors_lock); + LIST_FOREACH(rra, &random_adaptors_list, rra_entries) + if (strcmp(rra->rra_name, name) == 0) { + LIST_REMOVE(rra, rra_entries); + break; + } + random_adaptor_choose(); + sx_xunlock(&random_adaptors_lock); - while ((token = strsep(&cp, ",")) != NULL) - if ((*adaptor = random_adaptor_get(token)) != NULL) - break; - else if (bootverbose) - printf("%s random adaptor is not available," - " skipping\n", token); + free(rra, M_ENTROPY); +} + +/* ARGSUSED */ +int +random_adaptor_read(struct cdev *dev __unused, struct uio *uio, int flags) +{ + void *random_buf; + int c, error; + ssize_t nbytes; + +#ifdef RANDOM_DEBUG_VERBOSE + printf("random: %s %ld\n", __func__, uio->uio_resid); +#endif + + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + + sx_slock(&random_adaptors_lock); + + /* Let the entropy source do any pre-read setup. */ + (random_adaptor->ra_read)(NULL, 0); + + /* (Un)Blocking logic */ + error = 0; + while (!random_adaptor->ra_seeded()) { + if (flags & O_NONBLOCK) { + error = EWOULDBLOCK; + break; + } + + /* Sleep instead of going into a spin-frenzy */ + tsleep(&random_adaptor, PUSER | PCATCH, "block", hz/10); + + /* keep tapping away at the pre-read until we seed/unblock. */ + (random_adaptor->ra_read)(NULL, 0); } - primax = 0U; - if (*adaptor == NULL) { - /* - * Fall back to the highest priority item on the available - * RNG list. - */ - sx_slock(&adaptors_lock); + mtx_lock(&random_read_rate_mtx); - ramax = NULL; - LIST_FOREACH(rppi, &adaptors, entries) { - if (rppi->rsp->priority >= primax) { - ramax = rppi; - primax = rppi->rsp->priority; - } + /* The read-rate stuff is a rough indication of the instantaneous read rate, + * used to increase the use of 'live' entropy sources when lots of reads are done. + */ + nbytes = (uio->uio_resid + 32 - 1)/32; /* Round up to units of 32 */ + random_adaptor_read_rate_cache += nbytes*32; + random_adaptor_read_rate_cache = MIN(random_adaptor_read_rate_cache, 32); + + mtx_unlock(&random_read_rate_mtx); + + if (!error) { + + /* The actual read */ + + random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); + + while (uio->uio_resid && !error) { + c = MIN(uio->uio_resid, PAGE_SIZE); + (random_adaptor->ra_read)(random_buf, c); + error = uiomove(random_buf, c, uio); } - if (ramax != NULL) - *adaptor = ramax->rsp; - sx_sunlock(&adaptors_lock); + /* Let the entropy source do any post-read cleanup. */ + (random_adaptor->ra_read)(NULL, 1); - if (bootverbose && *adaptor) - printf("Falling back to <%s> random adaptor\n", - (*adaptor)->ident); + free(random_buf, M_ENTROPY); } + + sx_sunlock(&random_adaptors_lock); + + return (error); } -static void -random_adaptors_deinit(void *unused) +int +random_adaptor_read_rate(void) { + int ret; - sx_destroy(&adaptors_lock); - sysctl_ctx_free(&random_clist); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + + mtx_lock(&random_read_rate_mtx); + + ret = random_adaptor_read_rate_cache; + random_adaptor_read_rate_cache = 1; + + mtx_unlock(&random_read_rate_mtx); + + return (ret); } -static int -random_sysctl_adaptors_handler(SYSCTL_HANDLER_ARGS) +/* ARGSUSED */ +int +random_adaptor_write(struct cdev *dev __unused, struct uio *uio, int flags __unused) { - struct random_adaptors *rpp; - int error, count; + int c, error = 0; + void *random_buf; - count = error = 0; +#ifdef RANDOM_DEBUG + printf("random: %s %zd\n", __func__, uio->uio_resid); +#endif - sx_slock(&adaptors_lock); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - if (LIST_EMPTY(&adaptors)) - error = SYSCTL_OUT(req, "", 0); - else { - LIST_FOREACH(rpp, &adaptors, entries) { + sx_slock(&random_adaptors_lock); - error = SYSCTL_OUT(req, ",", count++ ? 1 : 0); - if (error) - break; + random_buf = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); - error = SYSCTL_OUT(req, rpp->name, strlen(rpp->name)); - if (error) - break; - } + while (uio->uio_resid > 0) { + c = MIN(uio->uio_resid, PAGE_SIZE); + error = uiomove(random_buf, c, uio); + if (error) + break; + (random_adaptor->ra_write)(random_buf, c); + + /* Introduce an annoying delay to stop swamping */ + tsleep(&random_adaptor, PUSER | PCATCH, "block", hz/10); } - sx_sunlock(&adaptors_lock); + free(random_buf, M_ENTROPY); + + sx_sunlock(&random_adaptors_lock); return (error); } -static int -random_sysctl_active_adaptor_handler(SYSCTL_HANDLER_ARGS) +/* ARGSUSED */ +int +random_adaptor_poll(struct cdev *dev __unused, int events, struct thread *td __unused) { - struct random_adaptor *rsp; - struct random_adaptors *rpp; - const char *name; - int error; - name = NULL; - rsp = random_adaptor; +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif - if (rsp != NULL) { - sx_slock(&adaptors_lock); + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); - LIST_FOREACH(rpp, &adaptors, entries) - if (rpp->rsp == rsp) - name = rpp->name; + sx_slock(&random_adaptors_lock); - sx_sunlock(&adaptors_lock); + if (events & (POLLIN | POLLRDNORM)) { + if (random_adaptor->ra_seeded()) + events &= (POLLIN | POLLRDNORM); + else + selrecord(td, &rsel); } - if (rsp == NULL || name == NULL) - error = SYSCTL_OUT(req, "", 0); - else - error = SYSCTL_OUT(req, name, strlen(name)); + sx_sunlock(&random_adaptors_lock); + + return (events); +} + +/* This will be called by the entropy processor when it seeds itself and becomes secure */ +void +random_adaptor_unblock(void) +{ + + selwakeuppri(&rsel, PUSER); + wakeup(&random_adaptor); + printf("random: unblocking device.\n"); + + /* Do arc4random(9) a favour while we are about it. */ + (void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, ARC4_ENTR_HAVE); +} + +static int +random_sysctl_adaptors_handler(SYSCTL_HANDLER_ARGS) +{ + struct random_adaptors *rra; + struct sbuf sbuf; + int error, count; + + sx_slock(&random_adaptors_lock); + sbuf_new_for_sysctl(&sbuf, NULL, 64, req); + count = 0; + LIST_FOREACH(rra, &random_adaptors_list, rra_entries) + sbuf_printf(&sbuf, "%s%s(%d)", + (count++ ? "," : ""), rra->rra_name, rra->rra_ra->ra_priority); + + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + sx_sunlock(&random_adaptors_lock); return (error); } -static void -random_adaptors_init(void *unused) +static int +random_sysctl_active_adaptor_handler(SYSCTL_HANDLER_ARGS) +{ + struct random_adaptors *rra; + struct sbuf sbuf; + int error; + + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + + sx_slock(&random_adaptors_lock); + sbuf_new_for_sysctl(&sbuf, NULL, 16, req); + LIST_FOREACH(rra, &random_adaptors_list, rra_entries) + if (rra->rra_ra == random_adaptor) { + sbuf_cat(&sbuf, rra->rra_name); + break; + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + sx_sunlock(&random_adaptors_lock); + + return (error); +} + +void +random_adaptors_init(void) { +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif + SYSCTL_PROC(_kern_random, OID_AUTO, adaptors, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0, random_sysctl_adaptors_handler, "A", @@ -228,24 +416,74 @@ random_adaptors_init(void *unused) NULL, 0, random_sysctl_active_adaptor_handler, "A", "Active Random Number Generator Adaptor"); - sx_init(&adaptors_lock, "random_adaptors"); + sx_init(&random_adaptors_lock, "random_adaptors"); + + mtx_init(&random_read_rate_mtx, "read rate mutex", NULL, MTX_DEF); + + /* The dummy adaptor is not a module by itself, but part of the + * randomdev module. + */ + random_adaptor_register("dummy", &randomdev_dummy); + + live_entropy_sources_init(); } -SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator"); +void +random_adaptors_deinit(void) +{ + +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif + + live_entropy_sources_deinit(); -SYSINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, random_adaptors_init, - NULL); -SYSUNINIT(random_adaptors, SI_SUB_DRIVERS, SI_ORDER_FIRST, - random_adaptors_deinit, NULL); + /* Don't do this! Panic will surely follow! */ + /* random_adaptor_deregister("dummy"); */ + mtx_destroy(&random_read_rate_mtx); + + sx_destroy(&random_adaptors_lock); +} + +/* + * First seed. + * + * NB! NB! NB! + * NB! NB! NB! + * + * It turns out this is bloody dangerous. I was fiddling with code elsewhere + * and managed to get conditions where a safe (i.e. seeded) entropy device should + * not have been possible. This managed to hide that by unblocking the device anyway. + * As crap randomness is not directly distinguishable from good randomness, this + * could have gone unnoticed for quite a while. + * + * NB! NB! NB! + * NB! NB! NB! + * + * Very luckily, the probe-time entropy is very nearly good enough to cause a + * first seed all of the time, and the default settings for other entropy + * harvesting causes a proper, safe, first seed (unblock) in short order after that. + * + * That said, the below would be useful where folks are more concerned with + * a quick start than with extra paranoia in a low-entropy environment. + * + * markm - October 2013. + */ +#ifdef RANDOM_AUTOSEED +/* ARGSUSED */ static void -random_adaptors_reseed(void *unused) +random_adaptors_seed(void *unused __unused) { + + KASSERT(random_adaptor != NULL, ("No active random adaptor in %s", __func__)); + + sx_slock(&random_adaptors_lock); + random_adaptor->ra_reseed(); + sx_sunlock(&random_adaptors_lock); - (void)unused; - if (random_adaptor != NULL) - (*random_adaptor->reseed)(); arc4rand(NULL, 0, 1); } -SYSINIT(random_reseed, SI_SUB_INTRINSIC_POST, SI_ORDER_SECOND, +SYSINIT(random_seed, SI_SUB_INTRINSIC_POST, SI_ORDER_LAST, random_adaptors_reseed, NULL); +#endif /* RANDOM_AUTOSEED */ diff --git a/sys/dev/random/random_adaptors.h b/sys/dev/random/random_adaptors.h index 4765694a4526..08076cef9783 100644 --- a/sys/dev/random/random_adaptors.h +++ b/sys/dev/random/random_adaptors.h @@ -29,43 +29,46 @@ #ifndef SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED #define SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED -#include - MALLOC_DECLARE(M_ENTROPY); +typedef void random_adaptor_init_func_t(void); +typedef void random_adaptor_deinit_func_t(void); +typedef void random_adaptor_read_func_t(uint8_t *, u_int); +typedef void random_adaptor_write_func_t(uint8_t *, u_int); +typedef int random_adaptor_seeded_func_t(void); +typedef void random_adaptor_reseed_func_t(void); + +struct random_adaptor { + const char *ra_ident; + int ra_priority; + random_adaptor_init_func_t *ra_init; + random_adaptor_deinit_func_t *ra_deinit; + random_adaptor_read_func_t *ra_read; + random_adaptor_write_func_t *ra_write; + random_adaptor_reseed_func_t *ra_reseed; + random_adaptor_seeded_func_t *ra_seeded; +}; + struct random_adaptors { - LIST_ENTRY(random_adaptors) entries; /* list of providers */ - const char *name; /* name of random adaptor */ - struct random_adaptor *rsp; + LIST_ENTRY(random_adaptors) rra_entries; /* list of providers */ + const char *rra_name; /* name of random adaptor */ + struct random_adaptor *rra_ra; }; -struct random_adaptor *random_adaptor_get(const char *); -int random_adaptor_register(const char *, struct random_adaptor *); -void random_adaptor_choose(struct random_adaptor **); +/* Dummy "always-block" pseudo-device */ +extern struct random_adaptor randomdev_dummy; -extern struct random_adaptor *random_adaptor; +void random_adaptors_init(void); +void random_adaptors_deinit(void); -/* - * random_adaptor's should be registered prior to - * random module (SI_SUB_DRIVERS/SI_ORDER_MIDDLE) - */ -#define RANDOM_ADAPTOR_MODULE(name, modevent, ver) \ - static moduledata_t name##_mod = { \ - #name, \ - modevent, \ - 0 \ - }; \ - DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, \ - SI_ORDER_SECOND); \ - MODULE_VERSION(name, ver); \ - MODULE_DEPEND(name, random, 1, 1, 1); +void random_adaptor_register(const char *, struct random_adaptor *); +void random_adaptor_deregister(const char *); -typedef void (*random_adaptor_attach_hook)(void *, struct random_adaptor *); -EVENTHANDLER_DECLARE(random_adaptor_attach, random_adaptor_attach_hook); +int random_adaptor_read(struct cdev *, struct uio *, int); +int random_adaptor_write(struct cdev *, struct uio *, int); +int random_adaptor_poll(struct cdev *, int, struct thread *); -/* kern.random sysctls */ -#ifdef SYSCTL_DECL /* from sysctl.h */ -SYSCTL_DECL(_kern_random); -#endif /* SYSCTL_DECL */ +int random_adaptor_read_rate(void); +void random_adaptor_unblock(void); #endif /* SYS_DEV_RANDOM_RANDOM_ADAPTORS_H_INCLUDED */ diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c index b7b8381c8eb5..df6a853cd3e6 100644 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2013 Mark R V Murray + * Copyright (c) 2000-2014 Mark R V Murray * Copyright (c) 2013 Arthur Mesh * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. @@ -42,230 +42,293 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include +#include #include #include #include -#include #include -#include #include #include #include -#include -#define RANDOM_FIFO_MAX 1024 /* How many events to queue up */ +/* List for the dynamic sysctls */ +static struct sysctl_ctx_list random_clist; /* - * The harvest mutex protects the consistency of the entropy fifos and + * How many events to queue up. We create this many items in + * an 'empty' queue, then transfer them to the 'harvest' queue with + * supplied junk. When used, they are transferred back to the + * 'empty' queue. + */ +#define RANDOM_FIFO_MAX 1024 + +/* + * The harvest mutex protects the consistency of the entropy Fifos and * empty fifo and other associated structures. */ -struct mtx harvest_mtx; +static struct mtx harvest_mtx; -/* Lockable FIFO queue holding entropy buffers */ -struct entropyfifo { - int count; - STAILQ_HEAD(harvestlist, harvest) head; -}; +/* + * Lockable FIFO ring buffer holding entropy events + * If ring_in == ring_out, + * the buffer is empty. + * If (ring_in + 1) == ring_out (MOD RANDOM_FIFO_MAX), + * the buffer is full. + * + * The ring_in variable needs locking as there are multiple + * sources to the ring. Only the sources may change ring_in, + * but the consumer may examine it. + * + * The ring_out variable does not need locking as there is + * only one consumer. Only the consumer may change ring_out, + * but the sources may examine it. + */ +static struct entropyfifo { + struct harvest_event ring[RANDOM_FIFO_MAX]; + volatile u_int ring_in; + volatile u_int ring_out; +} entropyfifo; + +/* Round-robin destination cache. */ +u_int harvest_destination[ENTROPYSOURCE]; + +/* Function called to process one harvested stochastic event */ +void (*harvest_process_event)(struct harvest_event *); -/* Empty entropy buffers */ -static struct entropyfifo emptyfifo; +/* Allow the sysadmin to select the broad category of + * entropy types to harvest. + */ +static u_int harvest_source_mask = ((1U << RANDOM_ENVIRONMENTAL_END) - 1); -/* Harvested entropy */ -static struct entropyfifo harvestfifo; +/* Pool count is used by anything needing to know how many entropy + * pools are currently being maintained. + * This is of use to (e.g.) the live source feed where we need to give + * all the pools a top-up. + */ +int harvest_pool_count; /* <0 to end the kthread, 0 to let it run, 1 to flush the harvest queues */ -int random_kthread_control = 0; +static int random_kthread_control = 0; static struct proc *random_kthread_proc; -#ifdef RANDOM_RWFILE -static const char *entropy_files[] = { - "/entropy", - NULL -}; -#endif - -/* Deal with entropy cached externally if this is present. - * Lots of policy may eventually arrive in this function. - * Called after / is mounted. - */ static void -random_harvestq_cache(void *arg __unused) +random_kthread(void *arg __unused) { - uint8_t *keyfile, *data; - size_t size, i; -#ifdef RANDOM_RWFILE - const char **entropy_file; - uint8_t *zbuf; - int error; -#endif - - /* Get stuff that may have been preloaded by loader(8) */ - keyfile = preload_search_by_type("/boot/entropy"); - if (keyfile != NULL) { - data = preload_fetch_addr(keyfile); - size = preload_fetch_size(keyfile); - if (data != NULL && size != 0) { - for (i = 0; i < size; i += 16) - random_harvestq_internal(get_cyclecount(), data + i, 16, 16, RANDOM_CACHED); - printf("random: read %zu bytes from preloaded cache\n", size); - bzero(data, size); - } - else - printf("random: no preloaded entropy cache available\n"); - } + u_int maxloop, ring_out; -#ifdef RANDOM_RWFILE - /* Read and attempt to overwrite the entropy cache files. - * If the file exists, can be read and then overwritten, - * then use it. Ignore it otherwise, but print out what is - * going on. + /* + * Process until told to stop. + * + * Locking is not needed as this is the only place we modify ring_out, and + * we only examine ring_in without changing it. Both of these are volatile, + * and this is a unique thread. */ - data = malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); - zbuf = __DECONST(void *, zero_region); - for (entropy_file = entropy_files; *entropy_file; entropy_file++) { - error = randomdev_read_file(*entropy_file, data, PAGE_SIZE); - if (error == 0) { - printf("random: entropy cache '%s' provides %ld bytes\n", *entropy_file, (long)PAGE_SIZE); - error = randomdev_write_file(*entropy_file, zbuf, PAGE_SIZE); - if (error == 0) { - printf("random: entropy cache '%s' contents used and successfully overwritten\n", *entropy_file); - for (i = 0; i < PAGE_SIZE; i += 16) - random_harvestq_internal(get_cyclecount(), data + i, 16, 16, RANDOM_CACHED); - } - else - printf("random: entropy cache '%s' not overwritten and therefore not used; error = %d\n", *entropy_file, error); - } - else - printf("random: entropy cache '%s' not present or unreadable; error = %d\n", *entropy_file, error); - } - bzero(data, PAGE_SIZE); - free(data, M_ENTROPY); -#endif -} -EVENTHANDLER_DEFINE(mountroot, random_harvestq_cache, NULL, 0); + while (random_kthread_control >= 0) { -static void -random_kthread(void *arg) -{ - STAILQ_HEAD(, harvest) local_queue; - struct harvest *event = NULL; - int local_count; - event_proc_f entropy_processor = arg; + /* Deal with events, if any. Restrict the number we do in one go. */ + maxloop = RANDOM_FIFO_MAX; + while (entropyfifo.ring_out != entropyfifo.ring_in) { - STAILQ_INIT(&local_queue); - local_count = 0; + ring_out = (entropyfifo.ring_out + 1)%RANDOM_FIFO_MAX; + harvest_process_event(entropyfifo.ring + ring_out); + /* Modifying ring_out here ONLY. Sufficient for atomicity? */ + entropyfifo.ring_out = ring_out; - /* Process until told to stop */ - mtx_lock_spin(&harvest_mtx); - for (; random_kthread_control >= 0;) { - - /* - * Grab all the entropy events. - * Drain entropy source records into a thread-local - * queue for processing while not holding the mutex. - */ - STAILQ_CONCAT(&local_queue, &harvestfifo.head); - local_count += harvestfifo.count; - harvestfifo.count = 0; + /* The ring may be filled quickly so don't loop forever. */ + if (--maxloop) + break; - /* - * Deal with events, if any. - * Then transfer the used events back into the empty fifo. - */ - if (!STAILQ_EMPTY(&local_queue)) { - mtx_unlock_spin(&harvest_mtx); - STAILQ_FOREACH(event, &local_queue, next) - entropy_processor(event); - mtx_lock_spin(&harvest_mtx); - STAILQ_CONCAT(&emptyfifo.head, &local_queue); - emptyfifo.count += local_count; - local_count = 0; } - KASSERT(local_count == 0, ("random_kthread: local_count %d", - local_count)); - /* - * Do only one round of the hardware sources for now. - * Later we'll need to make it rate-adaptive. + * Give the fast hardware sources a go */ - mtx_unlock_spin(&harvest_mtx); - live_entropy_sources_feed(1, entropy_processor); - mtx_lock_spin(&harvest_mtx); + live_entropy_sources_feed(); /* * If a queue flush was commanded, it has now happened, * and we can mark this by resetting the command. + * A negative value, however, terminates the thread. */ if (random_kthread_control == 1) random_kthread_control = 0; - /* Work done, so don't belabour the issue */ - msleep_spin_sbt(&random_kthread_control, &harvest_mtx, - "-", SBT_1S/10, 0, C_PREL(1)); + /* Some work is done, so give the rest of the OS a chance. */ + tsleep_sbt(&random_kthread_control, 0, "-", SBT_1S/10, 0, C_PREL(1)); } - mtx_unlock_spin(&harvest_mtx); - random_set_wakeup_exit(&random_kthread_control); + randomdev_set_wakeup_exit(&random_kthread_control); /* NOTREACHED */ } void -random_harvestq_init(event_proc_f cb) +random_harvestq_flush(void) +{ + + /* Command a entropy queue flush and wait for it to finish */ + random_kthread_control = 1; + while (random_kthread_control) + pause("-", hz/10); +} + +/* ARGSUSED */ +RANDOM_CHECK_UINT(harvestmask, 0, ((1U << RANDOM_ENVIRONMENTAL_END) - 1)); + +/* ARGSUSED */ +static int +random_print_harvestmask(SYSCTL_HANDLER_ARGS) { + struct sbuf sbuf; int error, i; - struct harvest *np; - /* Initialise the harvest fifos */ + error = sysctl_wire_old_buffer(req, 0); + if (error == 0) { + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + for (i = RANDOM_ENVIRONMENTAL_END - 1; i >= 0; i--) + sbuf_cat(&sbuf, (harvest_source_mask & (1U << i)) ? "1" : "0"); + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); + } + + return (error); +} - /* Contains the currently unused event structs. */ - STAILQ_INIT(&emptyfifo.head); - for (i = 0; i < RANDOM_FIFO_MAX; i++) { - np = malloc(sizeof(struct harvest), M_ENTROPY, M_WAITOK); - STAILQ_INSERT_TAIL(&emptyfifo.head, np, next); +static const char *(random_source_descr[]) = { + "CACHED", + "ATTACH", + "KEYBOARD", + "MOUSE", + "NET_TUN", + "NET_ETHER", + "NET_NG", + "INTERRUPT", + "SWI", + "UMA_ALLOC", + "", /* "ENVIRONMENTAL_END" */ + "PURE_OCTEON", + "PURE_SAFE", + "PURE_GLXSB", + "PURE_UBSEC", + "PURE_HIFN", + "PURE_RDRAND", + "PURE_NEHEMIAH", + "PURE_RNDTEST", + /* "ENTROPYSOURCE" */ +}; + +/* ARGSUSED */ +static int +random_print_harvestmask_symbolic(SYSCTL_HANDLER_ARGS) +{ + struct sbuf sbuf; + int error, i; + + error = sysctl_wire_old_buffer(req, 0); + if (error == 0) { + sbuf_new_for_sysctl(&sbuf, NULL, 128, req); + for (i = RANDOM_ENVIRONMENTAL_END - 1; i >= 0; i--) { + sbuf_cat(&sbuf, (i == RANDOM_ENVIRONMENTAL_END - 1) ? "" : ","); + sbuf_cat(&sbuf, (harvest_source_mask & (1U << i)) ? random_source_descr[i] : ""); + } + error = sbuf_finish(&sbuf); + sbuf_delete(&sbuf); } - emptyfifo.count = RANDOM_FIFO_MAX; - /* Will contain the queued-up events. */ - STAILQ_INIT(&harvestfifo.head); - harvestfifo.count = 0; + return (error); +} +void +random_harvestq_init(void (*event_processor)(struct harvest_event *), int poolcount) +{ + uint8_t *keyfile, *data; + int error; + size_t size, j; + struct sysctl_oid *random_sys_o; + +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif + + random_sys_o = SYSCTL_ADD_NODE(&random_clist, + SYSCTL_STATIC_CHILDREN(_kern_random), + OID_AUTO, "harvest", CTLFLAG_RW, 0, + "Entropy Device Parameters"); + + SYSCTL_ADD_PROC(&random_clist, + SYSCTL_CHILDREN(random_sys_o), + OID_AUTO, "mask", CTLTYPE_UINT | CTLFLAG_RW, + &harvest_source_mask, ((1U << RANDOM_ENVIRONMENTAL_END) - 1), + random_check_uint_harvestmask, "IU", + "Entropy harvesting mask"); + + SYSCTL_ADD_PROC(&random_clist, + SYSCTL_CHILDREN(random_sys_o), + OID_AUTO, "mask_bin", CTLTYPE_STRING | CTLFLAG_RD, + NULL, 0, random_print_harvestmask, "A", "Entropy harvesting mask (printable)"); + + SYSCTL_ADD_PROC(&random_clist, + SYSCTL_CHILDREN(random_sys_o), + OID_AUTO, "mask_symbolic", CTLTYPE_STRING | CTLFLAG_RD, + NULL, 0, random_print_harvestmask_symbolic, "A", "Entropy harvesting mask (symbolic)"); + + /* Point to the correct event_processing function */ + harvest_process_event = event_processor; + + /* Store the pool count (used by live source feed) */ + harvest_pool_count = poolcount; + + /* Initialise the harvesting mutex and in/out indexes. */ mtx_init(&harvest_mtx, "entropy harvest mutex", NULL, MTX_SPIN); + entropyfifo.ring_in = entropyfifo.ring_out = 0U; /* Start the hash/reseed thread */ - error = kproc_create(random_kthread, cb, - &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); /* RANDOM_CSPRNG_NAME */ + error = kproc_create(random_kthread, NULL, + &random_kthread_proc, RFHIGHPID, 0, "rand_harvestq"); if (error != 0) panic("Cannot create entropy maintenance thread."); + + /* Get entropy that may have been preloaded by loader(8) + * and use it to pre-charge the entropy harvest queue. + */ + keyfile = preload_search_by_type("/boot/entropy"); + if (keyfile != NULL) { + data = preload_fetch_addr(keyfile); + size = preload_fetch_size(keyfile); + if (data != NULL && size != 0) { + for (j = 0; j < size; j += 16) + random_harvestq_internal(data + j, 16, 16, RANDOM_CACHED); + printf("random: read %zu bytes from preloaded cache\n", size); + bzero(data, size); + } + else + printf("random: no preloaded entropy cache\n"); + } + } void random_harvestq_deinit(void) { - struct harvest *np; - /* Destroy the harvest fifos */ - while (!STAILQ_EMPTY(&emptyfifo.head)) { - np = STAILQ_FIRST(&emptyfifo.head); - STAILQ_REMOVE_HEAD(&emptyfifo.head, next); - free(np, M_ENTROPY); - } - emptyfifo.count = 0; - while (!STAILQ_EMPTY(&harvestfifo.head)) { - np = STAILQ_FIRST(&harvestfifo.head); - STAILQ_REMOVE_HEAD(&harvestfifo.head, next); - free(np, M_ENTROPY); - } - harvestfifo.count = 0; +#ifdef RANDOM_DEBUG + printf("random: %s\n", __func__); +#endif + + /* + * Command the hash/reseed thread to end and wait for it to finish + */ + random_kthread_control = -1; + tsleep(&random_kthread_control, 0, "term", 0); mtx_destroy(&harvest_mtx); + + sysctl_ctx_free(&random_clist); } /* @@ -278,45 +341,42 @@ random_harvestq_deinit(void) * check a few lines below. This includes the "always-on" sources * like the Intel "rdrand" or the VIA Nehamiah "xstore" sources. */ +/* XXXRW: get_cyclecount() is cheap on most modern hardware, where cycle + * counters are built in, but on older hardware it will do a real time clock + * read which can be quite expensive. + */ void -random_harvestq_internal(u_int64_t somecounter, const void *entropy, - u_int count, u_int bits, enum esource origin) +random_harvestq_internal(const void *entropy, u_int count, u_int bits, + enum random_entropy_source origin) { - struct harvest *event; + struct harvest_event *event; + u_int ring_in; KASSERT(origin >= RANDOM_START && origin < ENTROPYSOURCE, ("random_harvest_internal: origin %d invalid\n", origin)); - /* Lockless read to avoid lock operations if fifo is full. */ - if (harvestfifo.count >= RANDOM_FIFO_MAX) + /* Mask out unwanted sources */ + if (!(harvest_source_mask & (1U << origin))) return; + /* Lock ring_in against multi-thread contention */ mtx_lock_spin(&harvest_mtx); - - /* - * On't overfill the harvest queue; this could steal all - * our memory. - */ - if (harvestfifo.count < RANDOM_FIFO_MAX) { - event = STAILQ_FIRST(&emptyfifo.head); - if (event != NULL) { - /* Add the harvested data to the fifo */ - STAILQ_REMOVE_HEAD(&emptyfifo.head, next); - emptyfifo.count--; - event->somecounter = somecounter; - event->size = count; - event->bits = bits; - event->source = origin; - - /* XXXX Come back and make this dynamic! */ - count = MIN(count, HARVESTSIZE); - memcpy(event->entropy, entropy, count); - - STAILQ_INSERT_TAIL(&harvestfifo.head, - event, next); - harvestfifo.count++; - } + ring_in = (entropyfifo.ring_in + 1)%RANDOM_FIFO_MAX; + if (ring_in != entropyfifo.ring_out) { + /* The ring is not full */ + event = entropyfifo.ring + ring_in; + + /* Stash the harvested stuff in the *event buffer */ + count = MIN(count, HARVESTSIZE); + event->he_somecounter = get_cyclecount(); + event->he_size = count; + event->he_bits = bits; + event->he_source = origin; + event->he_destination = harvest_destination[origin]++; + memcpy(event->he_entropy, entropy, count); + memset(event->he_entropy + count, 0, HARVESTSIZE - count); + + entropyfifo.ring_in = ring_in; } - mtx_unlock_spin(&harvest_mtx); } diff --git a/sys/dev/random/random_harvestq.h b/sys/dev/random/random_harvestq.h index a2ac3d1f91bc..ab09a3f05dbb 100644 --- a/sys/dev/random/random_harvestq.h +++ b/sys/dev/random/random_harvestq.h @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2013-2014 Mark R V Murray * Copyright (c) 2013 Arthur Mesh * All rights reserved. * @@ -29,14 +30,41 @@ #ifndef SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED #define SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED -typedef void (*event_proc_f)(struct harvest *event); +#define HARVESTSIZE 16 /* max size of each harvested entropy unit */ -void random_harvestq_init(event_proc_f); +/* These are used to queue harvested packets of entropy. The entropy + * buffer size is pretty arbitrary. + */ +struct harvest_event { + uintmax_t he_somecounter; /* fast counter for clock jitter */ + uint8_t he_entropy[HARVESTSIZE];/* some harvested entropy */ + u_int he_size; /* harvested entropy byte count */ + u_int he_bits; /* stats about the entropy */ + u_int he_destination; /* destination pool of this entropy */ + enum random_entropy_source he_source; /* origin of the entropy */ +}; + +void random_harvestq_init(void (*)(struct harvest_event *), int); void random_harvestq_deinit(void); -void random_harvestq_internal(u_int64_t, const void *, - u_int, u_int, enum esource); +void random_harvestq_internal(const void *, u_int, u_int, enum random_entropy_source); + +/* Pool count is used by anything needing to know how many entropy + * pools are currently being maintained. + * This is of use to (e.g.) the live source feed where we need to give + * all the pools a top-up. + */ +extern int harvest_pool_count; + +/* This is in randomdev.c as it needs to be permanently in the kernel */ +void randomdev_set_wakeup_exit(void *); + +/* Force all currently pending queue contents to clear, and kick the software processor */ +void random_harvestq_flush(void); + +/* Function called to process one harvested stochastic event */ +extern void (*harvest_process_event)(struct harvest_event *); -extern int random_kthread_control; -extern struct mtx harvest_mtx; +/* Round-robin destination cache. */ +extern u_int harvest_destination[ENTROPYSOURCE]; #endif /* SYS_DEV_RANDOM_RANDOM_HARVESTQ_H_INCLUDED */ diff --git a/sys/dev/random/randomdev.c b/sys/dev/random/randomdev.c index b76cb839a02c..bc41d511a8f1 100644 --- a/sys/dev/random/randomdev.c +++ b/sys/dev/random/randomdev.c @@ -26,9 +26,28 @@ * */ +/* + * NOTE NOTE NOTE + * + * This file is compiled into the kernel unconditionally. Any random(4) + * infrastructure that needs to be in the kernel by default goes here! + * + * Except ... + * + * The adaptor code all goes into random_adaptor.c, which is also compiled + * the kernel by default. The module in that file is initialised before + * this one. + * + * Other modules must be initialised after the above two, and are + * software random processors which plug into random_adaptor.c. + * + */ + #include __FBSDID("$FreeBSD$"); +#include "opt_random.h" + #include #include #include @@ -38,196 +57,196 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include -#include -#include -#include +#include #include #include -#include +#include +#include #include #include -#include -#include - #include -#include #include #include -#include #define RANDOM_MINOR 0 -static d_read_t random_read; -static d_write_t random_write; -static d_ioctl_t random_ioctl; -static d_poll_t random_poll; +static d_ioctl_t randomdev_ioctl; static struct cdevsw random_cdevsw = { - .d_version = D_VERSION, - .d_read = random_read, - .d_write = random_write, - .d_ioctl = random_ioctl, - .d_poll = random_poll, .d_name = "random", + .d_version = D_VERSION, + .d_read = random_adaptor_read, + .d_write = random_adaptor_write, + .d_poll = random_adaptor_poll, + .d_ioctl = randomdev_ioctl, }; /* For use with make_dev(9)/destroy_dev(9). */ static struct cdev *random_dev; +/* Set up the sysctl root node for the entropy device */ +SYSCTL_NODE(_kern, OID_AUTO, random, CTLFLAG_RW, 0, "Random Number Generator"); + +MALLOC_DEFINE(M_ENTROPY, "entropy", "Entropy harvesting buffers and data structures"); + /* ARGSUSED */ static int -random_read(struct cdev *dev __unused, struct uio *uio, int flag) +randomdev_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused, + int flags __unused, struct thread *td __unused) { - int c, error = 0; - void *random_buf; - - /* Blocking logic */ - if (!random_adaptor->seeded) - error = (*random_adaptor->block)(flag); - - /* The actual read */ - if (!error) { - - random_buf = (void *)malloc(PAGE_SIZE, M_ENTROPY, M_WAITOK); + int error = 0; - while (uio->uio_resid > 0 && !error) { - c = MIN(uio->uio_resid, PAGE_SIZE); - c = (*random_adaptor->read)(random_buf, c); - error = uiomove(random_buf, c, uio); - } - /* Finished reading; let the source know so it can do some - * optional housekeeping */ - (*random_adaptor->read)(NULL, 0); + switch (cmd) { + /* Really handled in upper layer */ + case FIOASYNC: + case FIONBIO: + break; - free(random_buf, M_ENTROPY); + default: + error = ENOTTY; } return (error); } -/* ARGSUSED */ -static int -random_write(struct cdev *dev __unused, struct uio *uio, int flag __unused) +/* Helper routine to enable kproc_exit() to work while the module is + * being (or has been) unloaded. + * This routine is in this file because it is always linked into the kernel, + * and will thus never be unloaded. This is critical for unloadable modules + * that have threads. + */ +void +randomdev_set_wakeup_exit(void *control) { - /* We used to allow this to insert userland entropy. - * We don't any more because (1) this so-called entropy - * is usually lousy and (b) its vaguely possible to - * mess with entropy harvesting by overdoing a write. - * Now we just ignore input like /dev/null does. - */ - uio->uio_resid = 0; - - return (0); + wakeup(control); + kproc_exit(0); + /* NOTREACHED */ } /* ARGSUSED */ static int -random_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t addr __unused, - int flags __unused, struct thread *td __unused) +randomdev_modevent(module_t mod __unused, int type, void *data __unused) { int error = 0; - switch (cmd) { - /* Really handled in upper layer */ - case FIOASYNC: - case FIONBIO: + switch (type) { + case MOD_LOAD: + printf("random: entropy device infrastructure driver\n"); + random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw, + RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0644, "random"); + make_dev_alias(random_dev, "urandom"); /* compatibility */ + random_adaptors_init(); break; + + case MOD_UNLOAD: + random_adaptors_deinit(); + destroy_dev(random_dev); + break; + + case MOD_SHUTDOWN: + break; + default: - error = ENOTTY; + error = EOPNOTSUPP; + break; + } + return (error); } -/* ARGSUSED */ -static int -random_poll(struct cdev *dev __unused, int events, struct thread *td) -{ - int revents = 0; +#define EARLY_2_DEV_MODULE(name, evh, arg) \ +static moduledata_t name##_mod = { \ + #name, \ + evh, \ + arg \ +}; \ +DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND) - if (events & (POLLIN | POLLRDNORM)) { - if (random_adaptor->seeded) - revents = events & (POLLIN | POLLRDNORM); - else - revents = (*random_adaptor->poll)(events, td); - } - return (revents); -} +EARLY_2_DEV_MODULE(randomdev, randomdev_modevent, NULL); +MODULE_VERSION(randomdev, 1); + +/* ================ + * Harvesting stubs + * ================ + */ +/* Internal stub/fake routine for when no entropy processor is loaded. + * If the entropy device is not loaded, don't act on harvesting calls + * and just return. + */ +/* ARGSUSED */ static void -random_initialize(void *p, struct random_adaptor *s) +random_harvest_phony(const void *entropy __unused, u_int count __unused, + u_int bits __unused, enum random_entropy_source origin __unused) { - static int random_inited = 0; - - if (random_inited) { - printf("random: <%s> already initialized\n", - random_adaptor->ident); - return; - } +} - random_adaptor = s; +/* Hold the address of the routine which is actually called */ +static void (*reap_func)(const void *, u_int, u_int, enum random_entropy_source) = random_harvest_phony; - (s->init)(); +/* Initialise the harvester when/if it is loaded */ +void +randomdev_init_harvester(void (*reaper)(const void *, u_int, u_int, enum random_entropy_source)) +{ - printf("random: <%s> initialized\n", s->ident); + reap_func = reaper; +} - /* Use an appropriately evil mode for those who are concerned - * with daemons */ - random_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &random_cdevsw, - RANDOM_MINOR, NULL, UID_ROOT, GID_WHEEL, 0666, "random"); - make_dev_alias(random_dev, "urandom"); /* compatibility */ +/* Deinitialise the harvester when/if it is unloaded */ +void +randomdev_deinit_harvester(void) +{ - /* mark random(4) as initialized, to avoid being called again */ - random_inited = 1; + reap_func = random_harvest_phony; } -/* ARGSUSED */ -static int -random_modevent(module_t mod __unused, int type, void *data __unused) +/* Entropy harvesting routine. + * Implemented as in indirect call to allow non-inclusion of + * the entropy device. + */ +void +random_harvest(const void *entropy, u_int count, u_int bits, enum random_entropy_source origin) { - static eventhandler_tag attach_tag = NULL; - int error = 0; - - switch (type) { - case MOD_LOAD: - random_adaptor_choose(&random_adaptor); - if (random_adaptor == NULL) { - printf("random: No random adaptor attached, " - "postponing initialization\n"); - attach_tag = EVENTHANDLER_REGISTER(random_adaptor_attach, - random_initialize, NULL, EVENTHANDLER_PRI_ANY); - } else - random_initialize(NULL, random_adaptor); + (*reap_func)(entropy, count, bits, origin); +} - break; +/* ================================ + * Internal reading stubs and fakes + * ================================ + */ - case MOD_UNLOAD: - if (random_adaptor != NULL) { - (*random_adaptor->deinit)(); - destroy_dev(random_dev); - } - /* Unregister the event handler */ - if (attach_tag != NULL) - EVENTHANDLER_DEREGISTER(random_adaptor_attach, - attach_tag); +/* Hold the address of the routine which is actually called */ +static u_int (*read_func)(uint8_t *, u_int) = dummy_random_read_phony; - break; +/* Initialise the reader when/if it is loaded */ +void +randomdev_init_reader(u_int (*reader)(uint8_t *, u_int)) +{ - case MOD_SHUTDOWN: - break; + read_func = reader; +} - default: - error = EOPNOTSUPP; - break; +/* Deinitialise the reader when/if it is unloaded */ +void +randomdev_deinit_reader(void) +{ - } - return (error); + read_func = dummy_random_read_phony; } -DEV_MODULE(random, random_modevent, NULL); -MODULE_VERSION(random, 1); +/* Kernel API version of read_random(). + * Implemented as in indirect call to allow non-inclusion of + * the entropy device. + */ +int +read_random(void *buf, int count) +{ + + return ((int)(*read_func)(buf, (u_int)count)); +} diff --git a/sys/dev/random/randomdev.h b/sys/dev/random/randomdev.h index b87789f0834f..4daf73588078 100644 --- a/sys/dev/random/randomdev.h +++ b/sys/dev/random/randomdev.h @@ -35,28 +35,33 @@ typedef void random_init_func_t(void); typedef void random_deinit_func_t(void); -typedef int random_block_func_t(int); -typedef int random_read_func_t(void *, int); -typedef int random_poll_func_t(int, struct thread *); -typedef void random_reseed_func_t(void); - -struct random_adaptor { - struct selinfo rsel; - const char *ident; - int seeded; - unsigned priority; - random_init_func_t *init; - random_deinit_func_t *deinit; - random_block_func_t *block; - random_read_func_t *read; - random_poll_func_t *poll; - random_reseed_func_t *reseed; -}; - -struct random_hardware_source { - const char *ident; - enum esource source; - random_read_func_t *read; -}; + +void randomdev_init_harvester(void (*)(const void *, u_int, u_int, enum random_entropy_source)); +void randomdev_init_reader(u_int (*)(uint8_t *, u_int)); +void randomdev_deinit_harvester(void); +void randomdev_deinit_reader(void); + +/* Stub/fake routines for when no entropy processor is loaded */ +extern u_int dummy_random_read_phony(uint8_t *, u_int); + +/* kern.random sysctls */ +#ifdef SYSCTL_DECL /* from sysctl.h */ +SYSCTL_DECL(_kern_random); + +/* If this was C++, the macro below would be a template */ +#define RANDOM_CHECK_UINT(name, min, max) \ +static int \ +random_check_uint_##name(SYSCTL_HANDLER_ARGS) \ +{ \ + if (oidp->oid_arg1 != NULL) { \ + if (*(u_int *)(oidp->oid_arg1) <= (min)) \ + *(u_int *)(oidp->oid_arg1) = (min); \ + else if (*(u_int *)(oidp->oid_arg1) > (max)) \ + *(u_int *)(oidp->oid_arg1) = (max); \ + } \ + return (sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, \ + req)); \ +} +#endif /* SYSCTL_DECL */ #endif diff --git a/sys/dev/random/randomdev_soft.c b/sys/dev/random/randomdev_soft.c index 0929704da896..61cdf356458b 100644 --- a/sys/dev/random/randomdev_soft.c +++ b/sys/dev/random/randomdev_soft.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2000-2013 Mark R V Murray + * Copyright (c) 2000-2014 Mark R V Murray * Copyright (c) 2004 Robert N. M. Watson * All rights reserved. * @@ -26,6 +26,16 @@ * */ +/* + * This is the loadable infrastructure base file for software CSPRNG + * drivers such as Yarrow or Fortuna. + * + * It is anticipated that one instance of this file will be used + * for _each_ invocation of a CSPRNG, but with different #defines + * set. See below. + * + */ + #include "opt_random.h" #if !defined(RANDOM_YARROW) && !defined(RANDOM_FORTUNA) @@ -33,15 +43,13 @@ #elif defined(RANDOM_YARROW) && defined(RANDOM_FORTUNA) #error "Must define either RANDOM_YARROW or RANDOM_FORTUNA" #endif -#if defined(RANDOM_FORTUNA) -#error "Fortuna is not yet implemented" -#endif #include __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -50,14 +58,9 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include -#include #include -#include -#include - #include #include #include @@ -69,111 +72,44 @@ __FBSDID("$FreeBSD$"); #include #endif - -static int randomdev_poll(int event, struct thread *td); -static int randomdev_block(int flag); -static void randomdev_flush_reseed(void); - +static struct random_adaptor random_soft_processor = { #if defined(RANDOM_YARROW) -static struct random_adaptor random_context = { - .ident = "Software, Yarrow", - .init = randomdev_init, - .deinit = randomdev_deinit, - .block = randomdev_block, - .read = random_yarrow_read, - .poll = randomdev_poll, - .reseed = randomdev_flush_reseed, - .seeded = 0, /* This will be seeded during entropy processing */ - .priority = 90, /* High priority, so top of the list. Fortuna may still win. */ -}; -#define RANDOM_MODULE_NAME yarrow #define RANDOM_CSPRNG_NAME "yarrow" + .ra_ident = "Yarrow", + .ra_priority = 90, /* High priority, so top of the list. Fortuna may still win. */ + .ra_read = random_yarrow_read, + .ra_write = random_yarrow_write, + .ra_reseed = random_yarrow_reseed, + .ra_seeded = random_yarrow_seeded, #endif - #if defined(RANDOM_FORTUNA) -static struct random_adaptor random_context = { - .ident = "Software, Fortuna", - .init = randomdev_init, - .deinit = randomdev_deinit, - .block = randomdev_block, - .read = random_fortuna_read, - .poll = randomdev_poll, - .reseed = randomdev_flush_reseed, - .seeded = 0, /* This will be excplicitly seeded at startup when secured */ - .priority = 100, /* High priority, so top of the list. Beat Yarrow. */ -}; -#define RANDOM_MODULE_NAME fortuna #define RANDOM_CSPRNG_NAME "fortuna" + .ra_ident = "Fortuna", + .ra_priority = 100, /* High priority, so top of the list. Beat Yarrow. */ + .ra_read = random_fortuna_read, + .ra_write = random_fortuna_write, + .ra_reseed = random_fortuna_reseed, + .ra_seeded = random_fortuna_seeded, #endif - -TUNABLE_INT("kern.random.sys.seeded", &random_context.seeded); - -/* List for the dynamic sysctls */ -static struct sysctl_ctx_list random_clist; - -/* ARGSUSED */ -static int -random_check_boolean(SYSCTL_HANDLER_ARGS) -{ - if (oidp->oid_arg1 != NULL && *(u_int *)(oidp->oid_arg1) != 0) - *(u_int *)(oidp->oid_arg1) = 1; - return (sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req)); -} + .ra_init = randomdev_init, + .ra_deinit = randomdev_deinit, +}; void randomdev_init(void) { - struct sysctl_oid *random_sys_o, *random_sys_harvest_o; #if defined(RANDOM_YARROW) - random_yarrow_init_alg(&random_clist); + random_yarrow_init_alg(); + random_harvestq_init(random_yarrow_process_event, 2); #endif #if defined(RANDOM_FORTUNA) - random_fortuna_init_alg(&random_clist); + random_fortuna_init_alg(); + random_harvestq_init(random_fortuna_process_event, 32); #endif - random_sys_o = SYSCTL_ADD_NODE(&random_clist, - SYSCTL_STATIC_CHILDREN(_kern_random), - OID_AUTO, "sys", CTLFLAG_RW, 0, - "Entropy Device Parameters"); - - SYSCTL_ADD_PROC(&random_clist, - SYSCTL_CHILDREN(random_sys_o), - OID_AUTO, "seeded", CTLTYPE_INT | CTLFLAG_RW, - &random_context.seeded, 0, random_check_boolean, "I", - "Seeded State"); - - random_sys_harvest_o = SYSCTL_ADD_NODE(&random_clist, - SYSCTL_CHILDREN(random_sys_o), - OID_AUTO, "harvest", CTLFLAG_RW, 0, - "Entropy Sources"); - - SYSCTL_ADD_PROC(&random_clist, - SYSCTL_CHILDREN(random_sys_harvest_o), - OID_AUTO, "ethernet", CTLTYPE_INT | CTLFLAG_RW, - &harvest.ethernet, 1, random_check_boolean, "I", - "Harvest NIC entropy"); - SYSCTL_ADD_PROC(&random_clist, - SYSCTL_CHILDREN(random_sys_harvest_o), - OID_AUTO, "point_to_point", CTLTYPE_INT | CTLFLAG_RW, - &harvest.point_to_point, 1, random_check_boolean, "I", - "Harvest serial net entropy"); - SYSCTL_ADD_PROC(&random_clist, - SYSCTL_CHILDREN(random_sys_harvest_o), - OID_AUTO, "interrupt", CTLTYPE_INT | CTLFLAG_RW, - &harvest.interrupt, 1, random_check_boolean, "I", - "Harvest IRQ entropy"); - SYSCTL_ADD_PROC(&random_clist, - SYSCTL_CHILDREN(random_sys_harvest_o), - OID_AUTO, "swi", CTLTYPE_INT | CTLFLAG_RW, - &harvest.swi, 1, random_check_boolean, "I", - "Harvest SWI entropy"); - - random_harvestq_init(random_process_event); - /* Register the randomness harvesting routine */ - randomdev_init_harvester(random_harvestq_internal, - random_context.read); + randomdev_init_harvester(random_harvestq_internal); } void @@ -182,118 +118,56 @@ randomdev_deinit(void) /* Deregister the randomness harvesting routine */ randomdev_deinit_harvester(); - /* - * Command the hash/reseed thread to end and wait for it to finish - */ - random_kthread_control = -1; - tsleep((void *)&random_kthread_control, 0, "term", 0); - #if defined(RANDOM_YARROW) random_yarrow_deinit_alg(); #endif #if defined(RANDOM_FORTUNA) random_fortuna_deinit_alg(); #endif - - sysctl_ctx_free(&random_clist); -} - -void -randomdev_unblock(void) -{ - if (!random_context.seeded) { - selwakeuppri(&random_context.rsel, PUSER); - wakeup(&random_context); - printf("random: unblocking device.\n"); - random_context.seeded = 1; - } - /* Do arc4random(9) a favour while we are about it. */ - (void)atomic_cmpset_int(&arc4rand_iniseed_state, ARC4_ENTR_NONE, - ARC4_ENTR_HAVE); } +/* ARGSUSED */ static int -randomdev_poll(int events, struct thread *td) +randomdev_soft_modevent(module_t mod __unused, int type, void *unused __unused) { - int revents = 0; - - mtx_lock(&random_reseed_mtx); + int error = 0; - if (random_context.seeded) - revents = events & (POLLIN | POLLRDNORM); - else - selrecord(td, &random_context.rsel); + switch (type) { + case MOD_LOAD: + printf("random: SOFT: %s init()\n", RANDOM_CSPRNG_NAME); + random_adaptor_register(RANDOM_CSPRNG_NAME, &random_soft_processor); + break; - mtx_unlock(&random_reseed_mtx); - return (revents); -} + case MOD_UNLOAD: + random_adaptor_deregister(RANDOM_CSPRNG_NAME); + break; -static int -randomdev_block(int flag) -{ - int error = 0; + case MOD_SHUTDOWN: + break; - mtx_lock(&random_reseed_mtx); + default: + error = EOPNOTSUPP; + break; - /* Blocking logic */ - while (!random_context.seeded && !error) { - if (flag & O_NONBLOCK) - error = EWOULDBLOCK; - else { - printf("random: blocking on read.\n"); - error = msleep(&random_context, - &random_reseed_mtx, - PUSER | PCATCH, "block", 0); - } } - mtx_unlock(&random_reseed_mtx); - return (error); } -/* Helper routine to perform explicit reseeds */ -static void -randomdev_flush_reseed(void) -{ - /* Command a entropy queue flush and wait for it to finish */ - random_kthread_control = 1; - while (random_kthread_control) - pause("-", hz / 10); +#define MID_DEV_MODULE(name, evh, arg) \ +static moduledata_t name##_mod = { \ + #name, \ + evh, \ + arg \ +}; \ +DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE) #if defined(RANDOM_YARROW) - /* This ultimately calls randomdev_unblock() */ - random_yarrow_reseed(); +MID_DEV_MODULE(yarrow, randomdev_soft_modevent, NULL); +MODULE_VERSION(yarrow, 1); +MODULE_DEPEND(yarrow, random_adaptors, 1, 1, 1); #endif #if defined(RANDOM_FORTUNA) - /* This ultimately calls randomdev_unblock() */ - random_fortuna_reseed(); +MID_DEV_MODULE(fortuna, randomdev_soft_modevent, NULL); +MODULE_VERSION(fortuna, 1); +MODULE_DEPEND(fortuna, random_adaptors, 1, 1, 1); #endif -} - -static int -randomdev_modevent(module_t mod __unused, int type, void *unused __unused) -{ - - switch (type) { - case MOD_LOAD: - random_adaptor_register(RANDOM_CSPRNG_NAME, &random_context); - /* - * For statically built kernels that contain both device - * random and options PADLOCK_RNG/RDRAND_RNG/etc.., - * this event handler will do nothing, since the random - * driver-specific handlers are loaded after these HW - * consumers, and hence hasn't yet registered for this event. - * - * In case where both the random driver and RNG's are built - * as seperate modules, random.ko is loaded prior to *_rng.ko's - * (by dependency). This event handler is there to delay - * creation of /dev/{u,}random and attachment of this *_rng.ko. - */ - EVENTHANDLER_INVOKE(random_adaptor_attach, &random_context); - return (0); - } - - return (EINVAL); -} - -RANDOM_ADAPTOR_MODULE(RANDOM_MODULE_NAME, randomdev_modevent, 1); diff --git a/sys/dev/random/randomdev_soft.h b/sys/dev/random/randomdev_soft.h index cbee779a7d05..e814de6f0891 100644 --- a/sys/dev/random/randomdev_soft.h +++ b/sys/dev/random/randomdev_soft.h @@ -29,58 +29,11 @@ #ifndef SYS_DEV_RANDOM_RANDOMDEV_SOFT_H_INCLUDED #define SYS_DEV_RANDOM_RANDOMDEV_SOFT_H_INCLUDED -/* This header contains only those definitions that are global - * and harvester-specific for the entropy processor +/* This header contains only those definitions that are + * specific to the entropy processor */ -/* #define ENTROPYSOURCE nn entropy sources (actually classes) - * This is properly defined in - * an enum in sys/random.h - */ - -/* The ring size _MUST_ be a power of 2 */ -#define HARVEST_RING_SIZE 1024 /* harvest ring buffer size */ -#define HARVEST_RING_MASK (HARVEST_RING_SIZE - 1) - -#define HARVESTSIZE 16 /* max size of each harvested entropy unit */ - -/* These are used to queue harvested packets of entropy. The entropy - * buffer size is pretty arbitrary. - */ -struct harvest { - uintmax_t somecounter; /* fast counter for clock jitter */ - uint8_t entropy[HARVESTSIZE]; /* the harvested entropy */ - u_int size, bits; /* stats about the entropy */ - enum esource source; /* origin of the entropy */ - STAILQ_ENTRY(harvest) next; /* next item on the list */ -}; - void randomdev_init(void); void randomdev_deinit(void); -void randomdev_init_harvester(void (*)(u_int64_t, const void *, u_int, - u_int, enum esource), int (*)(void *, int)); -void randomdev_deinit_harvester(void); - -void random_set_wakeup_exit(void *); -void random_process_event(struct harvest *event); -void randomdev_unblock(void); - -extern struct mtx random_reseed_mtx; - -/* If this was C++, the macro below would be a template */ -#define RANDOM_CHECK_UINT(name, min, max) \ -static int \ -random_check_uint_##name(SYSCTL_HANDLER_ARGS) \ -{ \ - if (oidp->oid_arg1 != NULL) { \ - if (*(u_int *)(oidp->oid_arg1) <= (min)) \ - *(u_int *)(oidp->oid_arg1) = (min); \ - else if (*(u_int *)(oidp->oid_arg1) > (max)) \ - *(u_int *)(oidp->oid_arg1) = (max); \ - } \ - return (sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, \ - req)); \ -} - #endif diff --git a/sys/dev/random/rwfile.c b/sys/dev/random/rwfile.c deleted file mode 100644 index 9b3895791690..000000000000 --- a/sys/dev/random/rwfile.c +++ /dev/null @@ -1,96 +0,0 @@ -/*- - * Copyright (c) 2013 Mark R V Murray - * 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 - * in this position and unchanged. - * 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 AUTHOR ``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 AUTHOR 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 -__FBSDID("$FreeBSD$"); - -#include "opt_random.h" - -#ifdef RANDOM_RWFILE - -#include -#include -#include -#include -#include -#include -#include - -#include - -int -randomdev_read_file(const char *filename, void *buf, size_t length) -{ - struct nameidata nd; - struct thread* td = curthread; - int error; - ssize_t resid; - int flags; - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); - flags = FREAD; - error = vn_open(&nd, &flags, 0, NULL); - if (error == 0) { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_vp->v_type != VREG) - error = ENOEXEC; - else - error = vn_rdwr(UIO_READ, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); - VOP_UNLOCK(nd.ni_vp, 0); - vn_close(nd.ni_vp, FREAD, td->td_ucred, td); - } - - return (error); -} - -int -randomdev_write_file(const char *filename, void *buf, size_t length) -{ - struct nameidata nd; - struct thread* td = curthread; - int error; - ssize_t resid; - int flags; - - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, filename, td); - flags = FWRITE | O_CREAT | O_TRUNC; - error = vn_open(&nd, &flags, 0, NULL); - if (error == 0) { - NDFREE(&nd, NDF_ONLY_PNBUF); - if (nd.ni_vp->v_type != VREG) - error = ENOEXEC; - else - error = vn_rdwr(UIO_WRITE, nd.ni_vp, buf, length, 0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid, td); - - VOP_UNLOCK(nd.ni_vp, 0); - vn_close(nd.ni_vp, FREAD, td->td_ucred, td); - } - - return (error); -} - -#endif diff --git a/sys/dev/random/rwfile.h b/sys/dev/random/rwfile.h deleted file mode 100644 index f14fd7b7e963..000000000000 --- a/sys/dev/random/rwfile.h +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * Copyright (c) 2013 Mark R V Murray - * 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 - * in this position and unchanged. - * 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 AUTHOR ``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 AUTHOR 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. - * - * $FreeBSD$ - */ - -#ifndef SYS_DEV_RANDOM_RWFILE_H_INCLUDED -#define SYS_DEV_RANDOM_RWFILE_H_INCLUDED - -#ifdef RANDOM_RWFILE - -int randomdev_read_file(const char *filename, void *buf, size_t); -int randomdev_write_file(const char *filename, void *buf, size_t); - -#endif - -#endif diff --git a/sys/dev/random/uint128.h b/sys/dev/random/uint128.h new file mode 100644 index 000000000000..b2cc1e0624b2 --- /dev/null +++ b/sys/dev/random/uint128.h @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2014 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef SYS_DEV_RANDOM_UINT128_H_INCLUDED +#define SYS_DEV_RANDOM_UINT128_H_INCLUDED + +/* This whole thing is a crock :-( + * + * Everyone knows you always need the __uint128_t types! + */ + +#ifdef __SIZEOF_INT128__ +typedef __uint128_t uint128_t; +#else +typedef uint64_t uint128_t[2]; +#endif + +static __inline void +uint128_clear(uint128_t *big_uint) +{ +#ifdef __SIZEOF_INT128__ + (*big_uint) = 0ULL; +#else + (*big_uint)[0] = (*big_uint)[1] = 0UL; +#endif +} + +static __inline void +uint128_increment(uint128_t *big_uint) +{ +#ifdef __SIZEOF_INT128__ + (*big_uint)++; +#else + (*big_uint)[0]++; + if ((*big_uint)[0] == 0UL) + (*big_uint)[1]++; +#endif +} + +static __inline int +uint128_is_zero(uint128_t big_uint) +{ +#ifdef __SIZEOF_INT128__ + return (big_uint == 0ULL); +#else + return (big_uint[0] == 0UL && big_uint[1] == 0UL); +#endif +} + +#endif /* SYS_DEV_RANDOM_UINT128_H_INCLUDED */ diff --git a/sys/dev/random/unit_test.c b/sys/dev/random/unit_test.c new file mode 100644 index 000000000000..32b3363e247b --- /dev/null +++ b/sys/dev/random/unit_test.c @@ -0,0 +1,257 @@ +/*- + * Copyright (c) 2000-2013 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + +/* + Build this by going: + +cc -g -O0 -pthread -DRANDOM_ -DRANDOM_DEBUG -I../.. -lstdthreads -Wall \ + unit_test.c \ + yarrow.c \ + fortuna.c \ + hash.c \ + ../../crypto/rijndael/rijndael-api-fst.c \ + ../../crypto/rijndael/rijndael-alg-fst.c \ + ../../crypto/sha2/sha2.c \ + -o unit_test +./unit_test + +Where is YARROW or FORTUNA. +*/ + +#include +#include +#include +#include +#include +#include + +#include "unit_test.h" + +#ifdef RANDOM_YARROW +#include "dev/random/yarrow.h" +#endif +#ifdef RANDOM_FORTUNA +#include "dev/random/fortuna.h" +#endif + +#define NUM_THREADS 3 + +static volatile int stopseeding = 0; + +void +random_adaptor_unblock(void) +{ + +#if 0 + if (mtx_trylock(&random_reseed_mtx) == thrd_busy) + printf("Mutex held. Good.\n"); + else { + printf("Mutex not held. PANIC!!\n"); + thrd_exit(0); + } +#endif + printf("random: unblocking device.\n"); +} + +static int +RunHarvester(void *arg __unused) +{ + int i, r; + struct harvest_event e; + + for (i = 0; ; i++) { + if (stopseeding) + break; + if (i % 1000 == 0) + printf("Harvest: %d\n", i); + r = random()%10; + e.he_somecounter = i; + *((uint64_t *)e.he_entropy) = random(); + e.he_size = 8; + e.he_bits = random()%4; + e.he_destination = i; + e.he_source = (i + 3)%7; + e.he_next = NULL; +#ifdef RANDOM_YARROW + random_yarrow_process_event(&e); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_process_event(&e); +#endif + usleep(r); + } + + printf("Thread #0 ends\n"); + + thrd_exit(0); + + return (0); +} + +static int +WriteCSPRNG(void *threadid) +{ + uint8_t *buf; + int i; + + printf("Thread #1 starts\n"); + + for (i = 0; ; i++) { + if (stopseeding) + break; + buf = malloc(4096); + if (i % 1000 == 0) + printf("Thread write 1 - %d\n", i); + if (buf != NULL) { +#ifdef RANDOM_YARROW + random_yarrow_write(buf, i); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_write(buf, i); +#endif + free(buf); + } + usleep(1000000); + } + + printf("Thread #1 ends\n"); + + thrd_exit(0); + + return (0); +} + +static int +ReadCSPRNG(void *threadid) +{ + size_t tid; + uint8_t *buf; + int i; + + tid = (size_t)threadid; + printf("Thread #%zd starts\n", tid); + +#ifdef RANDOM_YARROW + while (!random_yarrow_seeded()) +#endif +#ifdef RANDOM_FORTUNA + while (!random_fortuna_seeded()) +#endif + { +#ifdef RANDOM_YARROW + random_yarrow_read(NULL, 0); + random_yarrow_read(NULL, 1); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_read(NULL, 0); + random_fortuna_read(NULL, 1); +#endif + usleep(100); + } + + for (i = 0; i < 100000; i++) { + buf = malloc(i); + if (i % 1000 == 0) + printf("Thread read %zd - %d %p\n", tid, i, buf); + if (buf != NULL) { +#ifdef RANDOM_YARROW + random_yarrow_read(NULL, 0); + random_yarrow_read(buf, i); + random_yarrow_read(NULL, 1); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_read(NULL, 0); + random_fortuna_read(buf, i); + random_fortuna_read(NULL, 1); +#endif +#if 0 + { + int j; + + for (j = 0; j < i; j++) { + printf(" %02X", buf[j]); + if (j % 32 == 31 || j == i - 1) + printf("\n"); + } + } +#endif + free(buf); + } + usleep(100); + } + + printf("Thread #%zd ends\n", tid); + + thrd_exit(0); + + return (0); +} + +int +main(int argc, char *argv[]) +{ + thrd_t threads[NUM_THREADS]; + int rc; + long t; + +#ifdef RANDOM_YARROW + random_yarrow_init_alg(); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_init_alg(); +#endif + + for (t = 0; t < NUM_THREADS; t++) { + printf("In main: creating thread %ld\n", t); + rc = thrd_create(&threads[t], (t == 0 ? RunHarvester : (t == 1 ? WriteCSPRNG : ReadCSPRNG)), t); + if (rc != thrd_success) { + printf("ERROR; return code from thrd_create() is %d\n", rc); + exit(-1); + } + } + + for (t = 2; t < NUM_THREADS; t++) + thrd_join(threads[t], &rc); + + stopseeding = 1; + + thrd_join(threads[1], &rc); + thrd_join(threads[0], &rc); + +#ifdef RANDOM_YARROW + random_yarrow_deinit_alg(); +#endif +#ifdef RANDOM_FORTUNA + random_fortuna_deinit_alg(); +#endif + + /* Last thing that main() should do */ + thrd_exit(0); + + return (0); +} diff --git a/sys/dev/random/unit_test.h b/sys/dev/random/unit_test.h new file mode 100644 index 000000000000..9fc09318b0db --- /dev/null +++ b/sys/dev/random/unit_test.h @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2013 Mark R V Murray + * 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 + * in this position and unchanged. + * 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 AUTHOR ``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 AUTHOR 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. + * + * $FreeBSD$ + */ + + +#ifndef UNIT_TEST_H_INCLUDED +#define UNIT_TEST_H_INCLUDED + +void random_adaptor_unblock(void); + +static __inline uint64_t +get_cyclecount(void) +{ + + /* Shaddup! */ + return (4ULL); +} + +// #define PAGE_SIZE 4096 +#define HARVESTSIZE 16 + +enum random_entropy_source { + RANDOM_START = 0, + RANDOM_CACHED = 0, + ENTROPYSOURCE = 32 +}; + +struct harvest_event { + uintmax_t he_somecounter; /* fast counter for clock jitter */ + uint8_t he_entropy[HARVESTSIZE];/* some harvested entropy */ + u_int he_size; /* harvested entropy byte count */ + u_int he_bits; /* stats about the entropy */ + u_int he_destination; /* destination pool of this entropy */ + enum random_entropy_source he_source; /* origin of the entropy */ + void * he_next; /* next item on the list */ +}; + +struct sysctl_ctx_list; + +#define CTASSERT(x) _Static_assert(x, "compile-time assertion failed") +#define KASSERT(exp,msg) do { \ + if (!(exp)) { \ + printf msg; \ + exit(0); \ + } \ +} while (0) + +#endif /* UNIT_TEST_H_INCLUDED */ diff --git a/sys/dev/random/yarrow.c b/sys/dev/random/yarrow.c index 1cfa37372ed8..a8da20a93bf3 100644 --- a/sys/dev/random/yarrow.c +++ b/sys/dev/random/yarrow.c @@ -28,6 +28,7 @@ #include __FBSDID("$FreeBSD$"); +#ifdef _KERNEL #include "opt_random.h" #include @@ -39,197 +40,280 @@ __FBSDID("$FreeBSD$"); #include #include +#include + #include #include #include +#include #include -#include +#include +#include +#include +#else /* !_KERNEL */ +#include +#include +#include +#include +#include +#include +#include + +#include "unit_test.h" + +#include +#include + +#include +#include +#include #include +#endif /* _KERNEL */ + +#if !defined(RANDOM_YARROW) && !defined(RANDOM_FORTUNA) +#define RANDOM_YARROW +#elif defined(RANDOM_YARROW) && defined(RANDOM_FORTUNA) +#error "Must define either RANDOM_YARROW or RANDOM_FORTUNA" +#endif + +#if defined(RANDOM_YARROW) #define TIMEBIN 16 /* max value for Pt/t */ #define FAST 0 #define SLOW 1 +/* This algorithm (and code) presumes that KEYSIZE is twice as large as BLOCKSIZE */ +CTASSERT(BLOCKSIZE == sizeof(uint128_t)); +CTASSERT(KEYSIZE == 2*BLOCKSIZE); + /* This is the beastie that needs protecting. It contains all of the * state that we are excited about. * Exactly one is instantiated. */ -static struct random_state { +static struct yarrow_state { union { uint8_t byte[BLOCKSIZE]; - uint64_t qword[BLOCKSIZE/sizeof(uint64_t)]; - } counter; /* C */ - struct randomdev_key key; /* K */ - u_int gengateinterval; /* Pg */ - u_int bins; /* Pt/t */ - u_int outputblocks; /* count output blocks for gates */ - u_int slowoverthresh; /* slow pool overthreshhold reseed count */ + uint128_t whole; + } counter; /* C */ + struct randomdev_key key; /* K */ + u_int gengateinterval; /* Pg */ + u_int bins; /* Pt/t */ + u_int outputblocks; /* count output blocks for gates */ + u_int slowoverthresh; /* slow pool overthreshhold reseed count */ struct pool { struct source { u_int bits; /* estimated bits of entropy */ - } source[ENTROPYSOURCE]; - u_int thresh; /* pool reseed threshhold */ + } source[ENTROPYSOURCE];/* ... per source */ + u_int thresh; /* pool reseed threshhold */ struct randomdev_hash hash; /* accumulated entropy */ - } pool[2]; /* pool[0] is fast, pool[1] is slow */ - u_int which; /* toggle - sets the current insertion pool */ -} random_state; + } pool[2]; /* pool[0] is fast, pool[1] is slow */ + int seeded; + + struct start_cache { + uint8_t junk[KEYSIZE]; + struct randomdev_hash hash; + } start_cache; +} yarrow_state; +/* The random_reseed_mtx mutex protects seeding and polling/blocking. */ +static mtx_t random_reseed_mtx; + +#ifdef _KERNEL +static struct sysctl_ctx_list random_clist; RANDOM_CHECK_UINT(gengateinterval, 4, 64); RANDOM_CHECK_UINT(bins, 2, 16); RANDOM_CHECK_UINT(fastthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */ RANDOM_CHECK_UINT(slowthresh, (BLOCKSIZE*8)/4, (BLOCKSIZE*8)); /* Bit counts */ RANDOM_CHECK_UINT(slowoverthresh, 1, 5); +#else /* !_KERNEL */ +static u_int harvest_destination[ENTROPYSOURCE]; +#endif /* _KERNEL */ static void generator_gate(void); static void reseed(u_int); -/* The reseed thread mutex */ -struct mtx random_reseed_mtx; - -/* 128-bit C = 0 */ -/* Nothing to see here, folks, just an ugly mess. */ -static void -clear_counter(void) -{ - random_state.counter.qword[0] = 0UL; - random_state.counter.qword[1] = 0UL; -} - -/* 128-bit C = C + 1 */ -/* Nothing to see here, folks, just an ugly mess. */ -/* TODO: Make a Galois counter instead? */ -static void -increment_counter(void) -{ - random_state.counter.qword[0]++; - if (!random_state.counter.qword[0]) - random_state.counter.qword[1]++; -} - -/* Process a single stochastic event off the harvest queue */ void -random_process_event(struct harvest *event) +random_yarrow_init_alg(void) { - u_int pl, overthreshhold[2]; - struct source *source; - enum esource src; - -#if 0 - /* Do this better with DTrace */ - { - int i; - - printf("Harvest:%16jX ", event->somecounter); - for (i = 0; i < event->size; i++) - printf("%02X", event->entropy[i]); - for (; i < 16; i++) - printf(" "); - printf(" %2d %2d %02X\n", event->size, event->bits, event->source); - } -#endif - - /* Accumulate the event into the appropriate pool */ - pl = random_state.which; - source = &random_state.pool[pl].source[event->source]; - randomdev_hash_iterate(&random_state.pool[pl].hash, event, - sizeof(*event)); - source->bits += event->bits; - - /* Count the over-threshold sources in each pool */ - for (pl = 0; pl < 2; pl++) { - overthreshhold[pl] = 0; - for (src = RANDOM_START; src < ENTROPYSOURCE; src++) { - if (random_state.pool[pl].source[src].bits - > random_state.pool[pl].thresh) - overthreshhold[pl]++; - } - } - - /* if any fast source over threshhold, reseed */ - if (overthreshhold[FAST]) - reseed(FAST); + int i, j; +#ifdef _KERNEL + struct sysctl_oid *random_yarrow_o; +#endif /* _KERNEL */ - /* if enough slow sources are over threshhold, reseed */ - if (overthreshhold[SLOW] >= random_state.slowoverthresh) - reseed(SLOW); + memset(yarrow_state.start_cache.junk, 0, KEYSIZE); + randomdev_hash_init(&yarrow_state.start_cache.hash); - /* Invert the fast/slow pool selector bit */ - random_state.which = !random_state.which; -} + /* Set up the lock for the reseed/gate state */ +#ifdef _KERNEL + mtx_init(&random_reseed_mtx, "reseed mutex", NULL, MTX_DEF); +#else /* !_KERNEL */ + mtx_init(&random_reseed_mtx, mtx_plain); +#endif /* _KERNEL */ -void -random_yarrow_init_alg(struct sysctl_ctx_list *clist) -{ - int i; - struct sysctl_oid *random_yarrow_o; + /* Start unseeded, therefore blocked. */ + yarrow_state.seeded = 0; +#ifdef _KERNEL /* Yarrow parameters. Do not adjust these unless you have * have a very good clue about what they do! */ - random_yarrow_o = SYSCTL_ADD_NODE(clist, + random_yarrow_o = SYSCTL_ADD_NODE(&random_clist, SYSCTL_STATIC_CHILDREN(_kern_random), OID_AUTO, "yarrow", CTLFLAG_RW, 0, "Yarrow Parameters"); - SYSCTL_ADD_PROC(clist, + SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "gengateinterval", CTLTYPE_INT|CTLFLAG_RW, - &random_state.gengateinterval, 10, + &yarrow_state.gengateinterval, 10, random_check_uint_gengateinterval, "I", "Generation gate interval"); - SYSCTL_ADD_PROC(clist, + SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "bins", CTLTYPE_INT|CTLFLAG_RW, - &random_state.bins, 10, + &yarrow_state.bins, 10, random_check_uint_bins, "I", "Execution time tuner"); - SYSCTL_ADD_PROC(clist, + SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "fastthresh", CTLTYPE_INT|CTLFLAG_RW, - &random_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4, + &yarrow_state.pool[0].thresh, (3*(BLOCKSIZE*8))/4, random_check_uint_fastthresh, "I", "Fast reseed threshold"); - SYSCTL_ADD_PROC(clist, + SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "slowthresh", CTLTYPE_INT|CTLFLAG_RW, - &random_state.pool[1].thresh, (BLOCKSIZE*8), + &yarrow_state.pool[1].thresh, (BLOCKSIZE*8), random_check_uint_slowthresh, "I", "Slow reseed threshold"); - SYSCTL_ADD_PROC(clist, + SYSCTL_ADD_PROC(&random_clist, SYSCTL_CHILDREN(random_yarrow_o), OID_AUTO, "slowoverthresh", CTLTYPE_INT|CTLFLAG_RW, - &random_state.slowoverthresh, 2, + &yarrow_state.slowoverthresh, 2, random_check_uint_slowoverthresh, "I", "Slow over-threshold reseed"); +#endif /* _KERNEL */ - random_state.gengateinterval = 10; - random_state.bins = 10; - random_state.pool[0].thresh = (3*(BLOCKSIZE*8))/4; - random_state.pool[1].thresh = (BLOCKSIZE*8); - random_state.slowoverthresh = 2; - random_state.which = FAST; + yarrow_state.gengateinterval = 10; + yarrow_state.bins = 10; + yarrow_state.pool[FAST].thresh = (3*(BLOCKSIZE*8))/4; + yarrow_state.pool[SLOW].thresh = (BLOCKSIZE*8); + yarrow_state.slowoverthresh = 2; + + /* Ensure that the first time we read, we are gated. */ + yarrow_state.outputblocks = yarrow_state.gengateinterval; /* Initialise the fast and slow entropy pools */ - for (i = 0; i < 2; i++) - randomdev_hash_init(&random_state.pool[i].hash); + for (i = FAST; i <= SLOW; i++) { + randomdev_hash_init(&yarrow_state.pool[i].hash); + for (j = RANDOM_START; j < ENTROPYSOURCE; j++) + yarrow_state.pool[i].source[j].bits = 0U; + } /* Clear the counter */ - clear_counter(); - - /* Set up a lock for the reseed process */ - mtx_init(&random_reseed_mtx, "Yarrow reseed", NULL, MTX_DEF); + uint128_clear(&yarrow_state.counter.whole); } void random_yarrow_deinit_alg(void) { + mtx_destroy(&random_reseed_mtx); + memset(&yarrow_state, 0, sizeof(yarrow_state)); + +#ifdef _KERNEL + sysctl_ctx_free(&random_clist); +#endif +} + +static __inline void +random_yarrow_post_insert(void) +{ + u_int pl, overthreshhold[2]; + enum random_entropy_source src; + +#ifdef _KERNEL + mtx_assert(&random_reseed_mtx, MA_OWNED); +#endif + /* Count the over-threshold sources in each pool */ + for (pl = 0; pl < 2; pl++) { + overthreshhold[pl] = 0; + for (src = RANDOM_START; src < ENTROPYSOURCE; src++) { + if (yarrow_state.pool[pl].source[src].bits > yarrow_state.pool[pl].thresh) + overthreshhold[pl]++; + } + } + + /* If enough slow sources are over threshhold, then slow reseed + * else if any fast source over threshhold, then fast reseed. + */ + if (overthreshhold[SLOW] >= yarrow_state.slowoverthresh) + reseed(SLOW); + else if (overthreshhold[FAST] > 0 && yarrow_state.seeded) + reseed(FAST); +} + +/* Process a single stochastic event off the harvest queue */ +void +random_yarrow_process_event(struct harvest_event *event) +{ + u_int pl; + + mtx_lock(&random_reseed_mtx); + + /* Accumulate the event into the appropriate pool + * where each event carries the destination information. + * We lock against pool state modification which can happen + * during accumulation/reseeding and reading/regating + */ + pl = event->he_destination % 2; + randomdev_hash_iterate(&yarrow_state.pool[pl].hash, event, sizeof(*event)); + yarrow_state.pool[pl].source[event->he_source].bits += event->he_bits; + + random_yarrow_post_insert(); + + mtx_unlock(&random_reseed_mtx); +} + +/* Process a block of data suspected to be slightly stochastic */ +static void +random_yarrow_process_buffer(uint8_t *buf, u_int length) +{ + static struct harvest_event event; + u_int i, pl; + + /* Accumulate the data into the appropriate pools + * where each event carries the destination information. + * We lock against pool state modification which can happen + * during accumulation/reseeding and reading/regating + */ + memset(event.he_entropy + sizeof(uint32_t), 0, HARVESTSIZE - sizeof(uint32_t)); + for (i = 0; i < length/sizeof(uint32_t); i++) { + event.he_somecounter = get_cyclecount(); + event.he_bits = 0; /* Fake */ + event.he_source = RANDOM_CACHED; + event.he_destination = harvest_destination[RANDOM_CACHED]++; + event.he_size = sizeof(uint32_t); + *((uint32_t *)event.he_entropy) = *((uint32_t *)buf + i); + + /* Do the actual entropy insertion */ + pl = event.he_destination % 2; + randomdev_hash_iterate(&yarrow_state.pool[pl].hash, &event, sizeof(event)); +#ifdef DONT_DO_THIS_HERE + /* Don't do this here - do it in bulk at the end */ + yarrow_state.pool[pl].source[RANDOM_CACHED].bits += bits; +#endif + } + for (pl = FAST; pl <= SLOW; pl++) + yarrow_state.pool[pl].source[RANDOM_CACHED].bits += (length >> 4); + + random_yarrow_post_insert(); } static void @@ -239,45 +323,60 @@ reseed(u_int fastslow) * structures static. */ static uint8_t v[TIMEBIN][KEYSIZE]; /* v[i] */ + static uint8_t hash[KEYSIZE]; /* h' */ + static uint8_t temp[KEYSIZE]; static struct randomdev_hash context; - uint8_t hash[KEYSIZE]; /* h' */ - uint8_t temp[KEYSIZE]; u_int i; - enum esource j; + enum random_entropy_source j; -#if 0 - printf("Yarrow: %s reseed\n", fastslow == FAST ? "fast" : "slow"); -#endif + KASSERT(yarrow_state.pool[FAST].thresh > 0, ("random: Yarrow fast threshold = 0")); + KASSERT(yarrow_state.pool[SLOW].thresh > 0, ("random: Yarrow slow threshold = 0")); - /* The reseed task must not be jumped on */ - mtx_lock(&random_reseed_mtx); +#ifdef RANDOM_DEBUG +#ifdef RANDOM_DEBUG_VERBOSE + printf("random: %s %s\n", __func__, (fastslow == FAST ? "FAST" : "SLOW")); +#endif + if (!yarrow_state.seeded) { + printf("random: %s - fast - thresh %d,1 - ", __func__, yarrow_state.pool[FAST].thresh); + for (i = RANDOM_START; i < ENTROPYSOURCE; i++) + printf(" %d", yarrow_state.pool[FAST].source[i].bits); + printf("\n"); + printf("random: %s - slow - thresh %d,%d - ", __func__, yarrow_state.pool[SLOW].thresh, yarrow_state.slowoverthresh); + for (i = RANDOM_START; i < ENTROPYSOURCE; i++) + printf(" %d", yarrow_state.pool[SLOW].source[i].bits); + printf("\n"); + } +#endif +#ifdef _KERNEL + mtx_assert(&random_reseed_mtx, MA_OWNED); +#endif /* 1. Hash the accumulated entropy into v[0] */ randomdev_hash_init(&context); /* Feed the slow pool hash in if slow */ - if (fastslow == SLOW) - randomdev_hash_iterate(&context, - &random_state.pool[SLOW].hash, - sizeof(struct randomdev_hash)); - randomdev_hash_iterate(&context, - &random_state.pool[FAST].hash, sizeof(struct randomdev_hash)); + if (fastslow == SLOW) { + randomdev_hash_finish(&yarrow_state.pool[SLOW].hash, temp); + randomdev_hash_iterate(&context, temp, sizeof(temp)); + } + randomdev_hash_finish(&yarrow_state.pool[FAST].hash, temp); + randomdev_hash_iterate(&context, temp, sizeof(temp)); randomdev_hash_finish(&context, v[0]); /* 2. Compute hash values for all v. _Supposed_ to be computationally * intensive. */ - if (random_state.bins > TIMEBIN) - random_state.bins = TIMEBIN; - for (i = 1; i < random_state.bins; i++) { + if (yarrow_state.bins > TIMEBIN) + yarrow_state.bins = TIMEBIN; + for (i = 1; i < yarrow_state.bins; i++) { randomdev_hash_init(&context); /* v[i] #= h(v[i - 1]) */ randomdev_hash_iterate(&context, v[i - 1], KEYSIZE); /* v[i] #= h(v[0]) */ randomdev_hash_iterate(&context, v[0], KEYSIZE); /* v[i] #= h(i) */ - randomdev_hash_iterate(&context, &i, sizeof(u_int)); + randomdev_hash_iterate(&context, &i, sizeof(i)); /* Return the hashval */ randomdev_hash_finish(&context, v[i]); } @@ -287,98 +386,107 @@ reseed(u_int fastslow) */ randomdev_hash_init(&context); - randomdev_hash_iterate(&context, &random_state.key, KEYSIZE); - for (i = 1; i < random_state.bins; i++) - randomdev_hash_iterate(&context, &v[i], KEYSIZE); + randomdev_hash_iterate(&context, &yarrow_state.key, KEYSIZE); + for (i = 1; i < yarrow_state.bins; i++) + randomdev_hash_iterate(&context, v[i], KEYSIZE); randomdev_hash_finish(&context, temp); - randomdev_encrypt_init(&random_state.key, temp); + randomdev_encrypt_init(&yarrow_state.key, temp); /* 4. Recompute the counter */ - clear_counter(); - randomdev_encrypt(&random_state.key, random_state.counter.byte, temp, BLOCKSIZE); - memcpy(random_state.counter.byte, temp, BLOCKSIZE); + uint128_clear(&yarrow_state.counter.whole); + randomdev_encrypt(&yarrow_state.key, yarrow_state.counter.byte, temp, BLOCKSIZE); + memcpy(yarrow_state.counter.byte, temp, BLOCKSIZE); /* 5. Reset entropy estimate accumulators to zero */ for (i = 0; i <= fastslow; i++) for (j = RANDOM_START; j < ENTROPYSOURCE; j++) - random_state.pool[i].source[j].bits = 0; + yarrow_state.pool[i].source[j].bits = 0; /* 6. Wipe memory of intermediate values */ - memset((void *)v, 0, sizeof(v)); - memset((void *)temp, 0, sizeof(temp)); - memset((void *)hash, 0, sizeof(hash)); + memset(v, 0, sizeof(v)); + memset(temp, 0, sizeof(temp)); + memset(hash, 0, sizeof(hash)); + memset(&context, 0, sizeof(context)); +#ifdef RANDOM_RWFILE_WRITE_IS_OK /* Not defined so writes ain't gonna happen */ /* 7. Dump to seed file */ - /* XXX Not done here yet */ - /* Unblock the device if it was blocked due to being unseeded */ - randomdev_unblock(); + /* This pseudo-code is documentation. Please leave it alone. */ + seed_file = ""; + error = randomdev_write_file(seed_file, , PAGE_SIZE); + if (error == 0) + printf("random: entropy seed file '%s' successfully written\n", seed_file); +#endif - /* Release the reseed mutex */ - mtx_unlock(&random_reseed_mtx); + /* Unblock the device if it was blocked due to being unseeded */ + if (!yarrow_state.seeded) { + yarrow_state.seeded = 1; + random_adaptor_unblock(); + } } /* Internal function to return processed entropy from the PRNG */ -int -random_yarrow_read(void *buf, int count) +void +random_yarrow_read(uint8_t *buf, u_int bytecount) { - static int cur = 0; - static int gate = 1; - static uint8_t genval[KEYSIZE]; - size_t tomove; - int i; - int retval; + u_int blockcount, i; - /* Check for final read request */ - if (buf == NULL && count == 0) - return (0); + /* Check for initial/final read requests */ + if (buf == NULL) + return; /* The reseed task must not be jumped on */ mtx_lock(&random_reseed_mtx); - if (gate) { - generator_gate(); - random_state.outputblocks = 0; - gate = 0; - } - if (count > 0 && (size_t)count >= BLOCKSIZE) { - retval = 0; - for (i = 0; i < count; i += BLOCKSIZE) { - increment_counter(); - randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE); - tomove = MIN(count - i, BLOCKSIZE); - memcpy((char *)buf + i, genval, tomove); - if (++random_state.outputblocks >= random_state.gengateinterval) { - generator_gate(); - random_state.outputblocks = 0; - } - retval += (int)tomove; - cur = 0; + blockcount = (bytecount + BLOCKSIZE - 1)/BLOCKSIZE; + for (i = 0; i < blockcount; i++) { + if (yarrow_state.outputblocks++ >= yarrow_state.gengateinterval) { + generator_gate(); + yarrow_state.outputblocks = 0; } + uint128_increment(&yarrow_state.counter.whole); + randomdev_encrypt(&yarrow_state.key, yarrow_state.counter.byte, buf, BLOCKSIZE); + buf += BLOCKSIZE; } - else { - if (!cur) { - increment_counter(); - randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE); - memcpy(buf, genval, (size_t)count); - cur = BLOCKSIZE - count; - if (++random_state.outputblocks >= random_state.gengateinterval) { - generator_gate(); - random_state.outputblocks = 0; - } - retval = count; - } - else { - retval = MIN(cur, count); - memcpy(buf, &genval[BLOCKSIZE - cur], (size_t)retval); - cur -= retval; - } + + mtx_unlock(&random_reseed_mtx); +} + +/* Internal function to hand external entropy to the PRNG */ +void +random_yarrow_write(uint8_t *buf, u_int count) +{ + uintmax_t timestamp; + + /* We must be locked for all this as plenty of state gets messed with */ + mtx_lock(&random_reseed_mtx); + + timestamp = get_cyclecount(); + randomdev_hash_iterate(&yarrow_state.start_cache.hash, ×tamp, sizeof(timestamp)); + randomdev_hash_iterate(&yarrow_state.start_cache.hash, buf, count); + timestamp = get_cyclecount(); + randomdev_hash_iterate(&yarrow_state.start_cache.hash, ×tamp, sizeof(timestamp)); + randomdev_hash_finish(&yarrow_state.start_cache.hash, yarrow_state.start_cache.junk); + randomdev_hash_init(&yarrow_state.start_cache.hash); + +#ifdef RANDOM_DEBUG_VERBOSE + { + int i; + + printf("random: %s - ", __func__); + for (i = 0; i < KEYSIZE; i++) + printf("%02X", yarrow_state.start_cache.junk[i]); + printf("\n"); } +#endif + + random_yarrow_process_buffer(yarrow_state.start_cache.junk, KEYSIZE); + memset(yarrow_state.start_cache.junk, 0, KEYSIZE); + mtx_unlock(&random_reseed_mtx); - return (retval); } static void @@ -388,29 +496,26 @@ generator_gate(void) uint8_t temp[KEYSIZE]; for (i = 0; i < KEYSIZE; i += BLOCKSIZE) { - increment_counter(); - randomdev_encrypt(&random_state.key, random_state.counter.byte, temp + i, BLOCKSIZE); + uint128_increment(&yarrow_state.counter.whole); + randomdev_encrypt(&yarrow_state.key, yarrow_state.counter.byte, temp + i, BLOCKSIZE); } - randomdev_encrypt_init(&random_state.key, temp); - memset((void *)temp, 0, KEYSIZE); + randomdev_encrypt_init(&yarrow_state.key, temp); + memset(temp, 0, KEYSIZE); } -/* Helper routine to perform explicit reseeds */ void random_yarrow_reseed(void) { -#ifdef RANDOM_DEBUG - int i; - - printf("%s(): fast:", __func__); - for (i = RANDOM_START; i < ENTROPYSOURCE; ++i) - printf(" %d", random_state.pool[FAST].source[i].bits); - printf("\n"); - printf("%s(): slow:", __func__); - for (i = RANDOM_START; i < ENTROPYSOURCE; ++i) - printf(" %d", random_state.pool[SLOW].source[i].bits); - printf("\n"); -#endif + reseed(SLOW); } + +int +random_yarrow_seeded(void) +{ + + return (yarrow_state.seeded); +} + +#endif /* RANDOM_YARROW */ diff --git a/sys/dev/random/yarrow.h b/sys/dev/random/yarrow.h index f32313ee5773..9ba0b4e6e7c1 100644 --- a/sys/dev/random/yarrow.h +++ b/sys/dev/random/yarrow.h @@ -29,9 +29,16 @@ #ifndef SYS_DEV_RANDOM_YARROW_H_INCLUDED #define SYS_DEV_RANDOM_YARROW_H_INCLUDED -void random_yarrow_init_alg(struct sysctl_ctx_list *); +#ifdef _KERNEL +typedef struct mtx mtx_t; +#endif + +void random_yarrow_init_alg(void); void random_yarrow_deinit_alg(void); -int random_yarrow_read(void *, int); +void random_yarrow_read(uint8_t *, u_int); +void random_yarrow_write(uint8_t *, u_int); void random_yarrow_reseed(void); +int random_yarrow_seeded(void); +void random_yarrow_process_event(struct harvest_event *event); #endif diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 9faea009e68e..9246904f1cf5 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -853,4 +853,4 @@ kick_init(const void *udata __unused) sched_add(td, SRQ_BORING); thread_unlock(td); } -SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL); +SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_MIDDLE, kick_init, NULL); diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c index a8d9f1a29e63..7a5d93659913 100644 --- a/sys/kern/kern_intr.c +++ b/sys/kern/kern_intr.c @@ -885,13 +885,10 @@ intr_event_schedule_thread(struct intr_event *ie) * If any of the handlers for this ithread claim to be good * sources of entropy, then gather some. */ - if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) { - CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__, - p->p_pid, td->td_name); + if (ie->ie_flags & IE_ENTROPY) { entropy.event = (uintptr_t)ie; entropy.td = ctd; - random_harvest(&entropy, sizeof(entropy), 2, - RANDOM_INTERRUPT); + random_harvest(&entropy, sizeof(entropy), 2, RANDOM_INTERRUPT); } KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name)); @@ -1039,13 +1036,10 @@ intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it) * If any of the handlers for this ithread claim to be good * sources of entropy, then gather some. */ - if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) { - CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__, - p->p_pid, td->td_name); + if (ie->ie_flags & IE_ENTROPY) { entropy.event = (uintptr_t)ie; entropy.td = ctd; - random_harvest(&entropy, sizeof(entropy), 2, - RANDOM_INTERRUPT); + random_harvest(&entropy, sizeof(entropy), 2, RANDOM_INTERRUPT); } KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name)); @@ -1130,14 +1124,9 @@ swi_sched(void *cookie, int flags) CTR3(KTR_INTR, "swi_sched: %s %s need=%d", ie->ie_name, ih->ih_name, ih->ih_need); - if (harvest.swi) { - CTR2(KTR_INTR, "swi_sched: pid %d (%s) gathering entropy", - curproc->p_pid, curthread->td_name); - entropy.event = (uintptr_t)ih; - entropy.td = curthread; - random_harvest(&entropy, sizeof(entropy), 1, - RANDOM_SWI); - } + entropy.event = (uintptr_t)ih; + entropy.td = curthread; + random_harvest(&entropy, sizeof(entropy), 1, RANDOM_SWI); /* * Set ih_need for this handler so that if the ithread is already diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 31ad45ed9e9c..51d7ca69ac5b 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -2851,7 +2851,7 @@ device_attach(device_t dev) * need to be adjusted on other platforms. */ #ifdef RANDOM_DEBUG - printf("%s(): feeding %d bit(s) of entropy from %s%d\n", + printf("random: %s(): feeding %d bit(s) of entropy from %s%d\n", __func__, 4, dev->driver->name, dev->unit); #endif random_harvest(&attachtime, sizeof(attachtime), 4, RANDOM_ATTACH); diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 23e47539c1ff..fa956dfd3dd3 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -270,6 +270,7 @@ SUBDIR= \ ${_opensolaris} \ oce \ ${_padlock} \ + ${_padlock_rng} \ patm \ ${_pccard} \ ${_pcfclock} \ @@ -297,6 +298,7 @@ SUBDIR= \ ${_random} \ rc4 \ ${_rdma} \ + ${_rdrand_rng} \ re \ reiserfs \ rl \ @@ -583,6 +585,8 @@ _nvram= nvram _nxge= nxge .if ${MK_CRYPT} != "no" || defined(ALL_MODULES) _padlock= padlock +_padlock_rng= padlock_rng +_rdrand_rng= rdrand_rng .endif _s3= s3 _tpm= tpm @@ -602,6 +606,17 @@ _x86bios= x86bios _ixl= ixl _ixlv= ixlv _ntb= ntb +_nvd= nvd +_nvme= nvme +_nvram= nvram +_nxge= nxge +.if ${MK_CDDL} != "no" || defined(ALL_MODULES) +_opensolaris= opensolaris +.endif +.if ${MK_CRYPT} != "no" || defined(ALL_MODULES) +_padlock= padlock +.endif +_pccard= pccard _qlxge= qlxge _qlxgb= qlxgb _qlxgbe= qlxgbe diff --git a/sys/modules/padlock_rng/Makefile b/sys/modules/padlock_rng/Makefile new file mode 100644 index 000000000000..25bf24fe7189 --- /dev/null +++ b/sys/modules/padlock_rng/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/random + +KMOD= padlock_rng +SRCS= nehemiah.c +SRCS+= bus_if.h device_if.h + +CFLAGS+= -I${.CURDIR}/../.. + +.include diff --git a/sys/modules/random/Makefile b/sys/modules/random/Makefile index 6bf47f269f63..7d0370fa66c5 100644 --- a/sys/modules/random/Makefile +++ b/sys/modules/random/Makefile @@ -5,13 +5,9 @@ .PATH: ${.CURDIR}/../../crypto/sha2 KMOD= random -SRCS= randomdev.c -.if ${MACHINE} == "amd64" || ${MACHINE} == "i386" -SRCS+= nehemiah.c -SRCS+= ivy.c -.endif -SRCS+= randomdev_soft.c yarrow.c hash.c -SRCS+= random_harvestq.c live_entropy_sources.c rwfile.c +SRCS= randomdev_soft.c +SRCS+= yarrow.c hash.c +SRCS+= random_harvestq.c live_entropy_sources.c SRCS+= rijndael-alg-fst.c rijndael-api-fst.c sha2.c sha256c.c SRCS+= bus_if.h device_if.h vnode_if.h opt_cpu.h opt_random.h diff --git a/sys/modules/rdrand_rng/Makefile b/sys/modules/rdrand_rng/Makefile new file mode 100644 index 000000000000..9d5adc334145 --- /dev/null +++ b/sys/modules/rdrand_rng/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/random + +KMOD= rdrand_rng +SRCS= ivy.c +SRCS+= bus_if.h device_if.h + +CFLAGS+= -I${.CURDIR}/../.. + +.include diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 5f315ec02cb8..87e71b6fd78a 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -576,8 +576,7 @@ ether_input_internal(struct ifnet *ifp, struct mbuf *m) m->m_flags |= M_PROMISC; } - if (harvest.ethernet) - random_harvest(&(m->m_data), 12, 2, RANDOM_NET_ETHER); + random_harvest(&(m->m_data), 12, 2, RANDOM_NET_ETHER); ether_demux(ifp, m); CURVNET_RESTORE(); diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index 89af2882643d..bb9de4451f4c 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -906,8 +906,7 @@ tunwrite(struct cdev *dev, struct uio *uio, int flag) m_freem(m); return (EAFNOSUPPORT); } - if (harvest.point_to_point) - random_harvest(&(m->m_data), 12, 2, RANDOM_NET_TUN); + random_harvest(&(m->m_data), 12, 2, RANDOM_NET_TUN); if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); CURVNET_SET(ifp->if_vnet); diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c index 7326d3e42381..5aec8a3395b3 100644 --- a/sys/netgraph/ng_iface.c +++ b/sys/netgraph/ng_iface.c @@ -758,8 +758,7 @@ ng_iface_rcvdata(hook_p hook, item_p item) m_freem(m); return (EAFNOSUPPORT); } - if (harvest.point_to_point) - random_harvest(&(m->m_data), 12, 2, RANDOM_NET_NG); + random_harvest(&(m->m_data), 12, 2, RANDOM_NET_NG); M_SETFIB(m, ifp->if_fib); netisr_dispatch(isr, m); return (0); diff --git a/sys/sys/random.h b/sys/sys/random.h index 8bb262ab446a..271462576a66 100644 --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -34,12 +34,17 @@ int read_random(void *, int); /* - * Note: if you add or remove members of esource, remember to also update the - * KASSERT regarding what valid members are in random_harvest_internal(). + * Note: if you add or remove members of random_entropy_source, remember to also update the + * KASSERT regarding what valid members are in random_harvest_internal(), and remember the + * strings in the static array random_source_descr[] in random_harvestq.c. + * + * NOTE: complain loudly to markm@ or on the lists if this enum gets more than 32 + * distinct values (0-31)! ENTROPYSOURCE may be == 32, but not > 32. */ -enum esource { +enum random_entropy_source { RANDOM_START = 0, RANDOM_CACHED = 0, + /* Environmental sources */ RANDOM_ATTACH, RANDOM_KEYBOARD, RANDOM_MOUSE, @@ -48,6 +53,9 @@ enum esource { RANDOM_NET_NG, RANDOM_INTERRUPT, RANDOM_SWI, + RANDOM_UMA_ALLOC, + RANDOM_ENVIRONMENTAL_END, /* This one is wasted */ + /* High-quality HW RNGs from here on. */ RANDOM_PURE_OCTEON, RANDOM_PURE_SAFE, RANDOM_PURE_GLXSB, @@ -59,20 +67,7 @@ enum esource { RANDOM_PURE_VIRTIO, ENTROPYSOURCE }; -void random_harvest(const void *, u_int, u_int, enum esource); - -/* Allow the sysadmin to select the broad category of - * entropy types to harvest - */ -struct harvest_select { - int ethernet; - int point_to_point; - int interrupt; - int swi; - int namei; -}; - -extern struct harvest_select harvest; +void random_harvest(const void *, u_int, u_int, enum random_entropy_source); #endif /* _KERNEL */ diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 8527b091b311..50e66c058268 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2097,6 +2098,12 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) int lockfail; int cpu; +#if 0 + /* XXX: FIX!! Do not enable this in CURRENT!! MarkM */ + /* The entropy here is desirable, but the harvesting is expensive */ + random_harvest(&(zone->uz_name), sizeof(void *), 1, RANDOM_UMA_ALLOC); +#endif + /* This is the fast path allocation */ #ifdef UMA_DEBUG_ALLOC_1 printf("Allocating one item from %s(%p)\n", zone->uz_name, zone); @@ -2127,6 +2134,11 @@ uma_zalloc_arg(uma_zone_t zone, void *udata, int flags) zone->uz_fini(item, zone->uz_size); return (NULL); } +#if 0 + /* XXX: FIX!! Do not enable this in CURRENT!! MarkM */ + /* The entropy here is desirable, but the harvesting is expensive */ + random_harvest(&item, sizeof(void *), 1, RANDOM_UMA_ALLOC); +#endif return (item); } /* This is unfortunate but should not be fatal. */ @@ -2169,6 +2181,11 @@ zalloc_start: #endif if (flags & M_ZERO) uma_zero_item(item, zone); +#if 0 + /* XXX: FIX!! Do not enable this in CURRENT!! MarkM */ + /* The entropy here is desirable, but the harvesting is expensive */ + random_harvest(&item, sizeof(void *), 1, RANDOM_UMA_ALLOC); +#endif return (item); } @@ -2289,6 +2306,11 @@ zalloc_start: zalloc_item: item = zone_alloc_item(zone, udata, flags); +#if 0 + /* XXX: FIX!! Do not enable this in CURRENT!! MarkM */ + /* The entropy here is desirable, but the harvesting is expensive */ + random_harvest(&item, sizeof(void *), 1, RANDOM_UMA_ALLOC); +#endif return (item); } @@ -2636,6 +2658,19 @@ uma_zfree_arg(uma_zone_t zone, void *item, void *udata) int lockfail; int cpu; +#if 0 + /* XXX: FIX!! Do not enable this in CURRENT!! MarkM */ + /* The entropy here is desirable, but the harvesting is expensive */ + struct entropy { + const void *uz_name; + const void *item; + } entropy; + + entropy.uz_name = zone->uz_name; + entropy.item = item; + random_harvest(&entropy, sizeof(struct entropy), 2, RANDOM_UMA_ALLOC); +#endif + #ifdef UMA_DEBUG_ALLOC_1 printf("Freeing item %p to %s(%p)\n", item, zone->uz_name, zone); #endif -- cgit v1.3 From 202bbb3d748f48f3ecab17b8ce1fb44dfd953237 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Fri, 31 Oct 2014 22:20:27 +0000 Subject: rc.d/geli should not depend on random, as the attach functionality do not require additional entropy to function. It would create a circular dependency (not immediately obvious: geli provides 'disks' and requires 'random' as of r273872, 'random' requires 'FILESYSTEMS', 'FILESYSTEMS' requires 'root', 'root' requires 'swap', and finally 'swap' requires 'disk'). --- etc/rc.d/geli | 1 - 1 file changed, 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/geli b/etc/rc.d/geli index 4551f716613b..77fff39fdd4e 100755 --- a/etc/rc.d/geli +++ b/etc/rc.d/geli @@ -28,7 +28,6 @@ # # PROVIDE: disks -# REQUIRE: random # KEYWORD: nojail . /etc/rc.subr -- cgit v1.3 From 7bd12696d701b3237bedb7a5e9e4f00ca258683d Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Sun, 2 Nov 2014 00:11:25 +0000 Subject: add an rc.d script to automatically grow the specified FS... It has been tested on both MBR and GPT... It won't be enabled until you add growfs_enable="YES" and will only run on first boot.. --- etc/rc.d/Makefile | 1 + etc/rc.d/growfs | 98 +++++++++++++++++++++++++++++++++++++++++++++++++ share/man/man7/Makefile | 1 + share/man/man7/growfs.7 | 64 ++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100755 etc/rc.d/growfs create mode 100644 share/man/man7/growfs.7 (limited to 'etc') diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index 72b524709701..f42b207936e6 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -49,6 +49,7 @@ FILES= DAEMON \ geli \ geli2 \ gptboot \ + growfs \ gssd \ hastd \ ${_hcsecd} \ diff --git a/etc/rc.d/growfs b/etc/rc.d/growfs new file mode 100755 index 000000000000..db87d29322c4 --- /dev/null +++ b/etc/rc.d/growfs @@ -0,0 +1,98 @@ +#!/bin/sh +# +# Copyright 2014 John-Mark Gurney +# 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 AUTHOR 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 AUTHOR 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. +# +# $FreeBSD$ +# + +# PROVIDE: growfs +# BEFORE: sysctl +# KEYWORD: firstboot + +# This allows us to distribute a image +# and have it work on essentially any size drive. +# +# TODO: Figure out where this should really be ordered. +# I suspect it should go just after fsck but before mountcritlocal +# but it's hard to tell for sure because of the bug described +# below. +# + +. /etc/rc.subr + +name="growfs" +start_cmd="growfs_start" +stop_cmd=":" +rcvar="growfs_enable" + +growfs_start () +{ + echo "Growing root partition to fill device" + rootdev=$(df / | tail -n 1 | awk '{ sub("/dev/", "", $1); print $1 }') + if [ x"$rootdev" = x"${rootdev%/*}" ]; then + # raw device + rawdev="$rootdev" + else + rawdev=$(glabel status | awk '$1 == "'"$rootdev"'" { print $3 }') + if [ x"$rawdev" = x"" ]; then + echo "Can't figure out device for: $rootdev" + return + fi + fi + + sysctl -b kern.geom.conftxt | awk ' +{ + lvl=$1 + device[lvl] = $3 + type[lvl] = $2 + idx[lvl] = $7 + parttype[lvl] = $13 + if (dev == $3) { + for (i = 1; i <= lvl; i++) { + # resize + if (type[i] == "PART") { + pdev = device[i - 1] + cmd[i] = "gpart resize -i " idx[i] " " pdev + if (parttype[i] == "GPT") + cmd[i] = "gpart recover " pdev " ; " cmd[i] + } else if (type[i] == "LABEL") { + continue + } else { + print "unhandled type: " type[i] + exit 1 + } + } + for (i = 1; i <= lvl; i++) { + if (cmd[i]) + system(cmd[i]) + } + exit 0 + } +}' dev="$rawdev" + growfs -y /dev/"$rootdev" +} + +load_rc_config $name +run_rc_command "$1" diff --git a/share/man/man7/Makefile b/share/man/man7/Makefile index 78a4bbcae82a..65f30d7a3736 100644 --- a/share/man/man7/Makefile +++ b/share/man/man7/Makefile @@ -14,6 +14,7 @@ MAN= adding_user.7 \ environ.7 \ ffs.7 \ firewall.7 \ + growfs.7 \ hier.7 \ hostname.7 \ intro.7 \ diff --git a/share/man/man7/growfs.7 b/share/man/man7/growfs.7 new file mode 100644 index 000000000000..697305ea85df --- /dev/null +++ b/share/man/man7/growfs.7 @@ -0,0 +1,64 @@ +.\" Copyright 2014 John-Mark Gurney +.\" 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 AUTHOR 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd November 1, 2014 +.Dt GROWFS 7 +.Os +.Sh NAME +.Nm growfs +.Nd start up script to grow the root file-system. +.Sh DESCRIPTION +The following options in +.Pa /etc/rc.conf +control the behavior of +.Nm : +.Bl -tag -width ".Va growfs_enable" -offset indent +.It Va growfs_enable +.Pq Dq Li NO +If set to +.Dq Li YES , +the first time the machine boots, the root file-system will be automatically +expanded, if possible, to fill up all available space after it. +.El +.Pp +To expand the root file-system with-out rebooting, run the following command: +.Dl % /etc/rc.d/growfs onestart +.Sh IMPLEMENTATION NOTES +The script requires that +.Pa awk +be present and on the path. +This usually means that +.Pa /usr +should be mounted prior to running the script. +.Sh FILES +.Pa /etc/rc.conf +.Sh EXIT STATUS +.Ex -std +.Sh SEE ALSO +.Xr rc.conf 5 +.Sh AUTHORS +The man page and script were written by +.An John-Mark Gurney Aq Mt jmg@FreeBSD.org . -- cgit v1.3 From 7417198fcf8ee28079f8d31248f677dc0ad9b741 Mon Sep 17 00:00:00 2001 From: Dag-Erling Smørgrav Date: Sun, 2 Nov 2014 01:47:27 +0000 Subject: Get rid of the postrandom script. It was born in a time when the random script ran before filesystems were mounted, which is no longer the case. In random_start(), immediately delete each file that is fed into /dev/random, and recreate the default entropy file immediately after reading and deleting it. The logic used in random_stop() to determine which file to write to should probably be factored out and used here as well. --- ObsoleteFiles.inc | 2 ++ etc/rc.d/Makefile | 1 - etc/rc.d/adjkerntz | 2 +- etc/rc.d/postrandom | 41 ----------------------------------------- etc/rc.d/random | 51 ++++++++++++++++++++++++++++++++++----------------- 5 files changed, 37 insertions(+), 60 deletions(-) delete mode 100755 etc/rc.d/postrandom (limited to 'etc') diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 7c8f8987f505..c8072d446059 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,8 @@ # xargs -n1 | sort | uniq -d; # done +# 20141102: postrandom obsoleted by new /dev/random code +OLD_FILES+=etc/rc.d/postrandom # 20141031: initrandom obsoleted by new /dev/random code OLD_FILES+=etc/rc.d/initrandom # 20141028: debug files accidentally installed as directory name diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index f42b207936e6..bfa22bfcfd09 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -112,7 +112,6 @@ FILES= DAEMON \ pf \ pflog \ pfsync \ - postrandom \ powerd \ power_profile \ ppp \ diff --git a/etc/rc.d/adjkerntz b/etc/rc.d/adjkerntz index 03f615946e9f..18a822012059 100755 --- a/etc/rc.d/adjkerntz +++ b/etc/rc.d/adjkerntz @@ -4,7 +4,7 @@ # # PROVIDE: adjkerntz -# REQUIRE: FILESYSTEMS postrandom +# REQUIRE: FILESYSTEMS # BEFORE: netif # KEYWORD: nojail diff --git a/etc/rc.d/postrandom b/etc/rc.d/postrandom deleted file mode 100755 index 3a608307e37f..000000000000 --- a/etc/rc.d/postrandom +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/sh -# -# $FreeBSD$ -# - -# PROVIDE: postrandom -# REQUIRE: random FILESYSTEMS -# BEFORE: LOGIN -# KEYWORD: nojail - -. /etc/rc.subr - -name="postrandom" -start_cmd="${name}_start" -stop_cmd=":" - -# This will remove old ${entropy_file} and generate a new one. -# According to Bruce Schneier, this is strongly recommended in order -# to avoid using same ${entropy_file} across reboots. -# Reference: Chapter 10.6, Practical Cryptography, ISBN: 0-471-22357-3 - -postrandom_start() -{ - /etc/rc.d/random fastsaveseed - - case ${entropy_dir} in - [Nn][Oo]) - ;; - *) - entropy_dir=${entropy_dir:-/var/db/entropy} - if [ -d "${entropy_dir}" ]; then - if [ -w /dev/random ]; then - rm -f ${entropy_dir}/* - fi - fi - ;; - esac -} - -load_rc_config random -run_rc_command "$1" diff --git a/etc/rc.d/random b/etc/rc.d/random index c7da932939fe..2420a39f97ca 100755 --- a/etc/rc.d/random +++ b/etc/rc.d/random @@ -17,41 +17,58 @@ stop_cmd="random_stop" extra_commands="saveseed" saveseed_cmd="${name}_stop" +save_dev_random() +{ + for f ; do + if :>>"$f" ; then + debug "saving entropy to $f" + dd if=/dev/random of="$f" bs=4096 count=1 2>/dev/null + fi + done +} + feed_dev_random() { - if [ -f "${1}" -a -r "${1}" -a -s "${1}" ]; then - cat "${1}" | dd of=/dev/random bs=8k 2>/dev/null - fi + for f ; do + if [ -f "$f" -a -r "$f" -a -s "$f" ] ; then + if dd if="$f" of=/dev/random bs=4096 2>/dev/null ; then + debug "entropy read from $f" + rm -f "$f" + fi + fi + done } random_start() { + echo -n 'Feeding entropy:' + + if [ ! -w /dev/random ] ; then + warn "/dev/random is not writeable" + return 1 + fi + # Reseed /dev/random with previously stored entropy. - case ${entropy_dir} in + case ${entropy_dir:=/var/db/entropy} in [Nn][Oo]) ;; *) - entropy_dir=${entropy_dir:-/var/db/entropy} - if [ -d "${entropy_dir}" ]; then - if [ -w /dev/random ]; then - for seedfile in ${entropy_dir}/*; do - feed_dev_random "${seedfile}" - done - fi + if [ -d "${entropy_dir}" ] ; then + feed_dev_random "${entropy_dir}"/* fi ;; esac - case ${entropy_file} in + case ${entropy_file:=/entropy} in [Nn][Oo] | '') ;; *) - if [ -w /dev/random ]; then - feed_dev_random "${entropy_file}" - feed_dev_random /var/db/entropy-file - fi + feed_dev_random "${entropy_file}" /var/db/entropy-file + save_dev_random "${entropy_file}" ;; esac + + echo '.' } random_stop() @@ -59,7 +76,7 @@ random_stop() # Write some entropy so when the machine reboots /dev/random # can be reseeded # - case ${entropy_file} in + case ${entropy_file:=/entropy} in [Nn][Oo] | '') ;; *) -- cgit v1.3 From 4396281efd101df4aa695d03c2218ff0b6e5f30b Mon Sep 17 00:00:00 2001 From: Warren Block Date: Sun, 2 Nov 2014 19:25:31 +0000 Subject: Add the less-ambiguous freebsd-version command. Reviewed by: -stable MFC after: 3 days --- etc/motd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/motd b/etc/motd index e70e98d025c9..4dc41a744c31 100644 --- a/etc/motd +++ b/etc/motd @@ -13,7 +13,7 @@ Documents installed with the system are in the /usr/local/share/doc/freebsd/ directory, or can be installed later with: pkg install en-freebsd-doc For other languages, replace "en" with a language code like de or fr. -Show the version of FreeBSD installed: uname -a +Show the version of FreeBSD installed: freebsd-version ; uname -a Please include that output and any error messages when posting questions. Introduction to manual pages: man man FreeBSD directory layout: man hier -- cgit v1.3 From 3a361e0c330fe9d5ab506cc02ee3bcc3d2d474ce Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Mon, 3 Nov 2014 00:37:39 +0000 Subject: Do not try to create a /dev/log symlink in a jail. PR: 179828 --- etc/rc.d/syslogd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/syslogd b/etc/rc.d/syslogd index 2842b48fac9e..747b6f01c6e5 100755 --- a/etc/rc.d/syslogd +++ b/etc/rc.d/syslogd @@ -28,7 +28,7 @@ syslogd_precmd() # Transitional symlink for old binaries # - if [ ! -L /dev/log ]; then + if [ ! -L /dev/log ] && ! check_jail jailed; then ln -sf /var/run/log /dev/log fi rm -f /var/run/log -- cgit v1.3 From fa8093473b4828e734aecc5c7e00541fcabbe080 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Mon, 3 Nov 2014 07:18:42 +0000 Subject: Integrate pjdfstest test suite execution into kyua pjdfstest execution is opt-in and must be done as root due to some of the assumptions made by the test suite and lack of error checking in the non-root case A description of how to execute pjdfstest with kyua is provided in share/pjdfstest/README Phabric: D824 (an earlier prototype patch) MFC after: 1 month Relnotes: yes Sponsored by: EMC / Isilon Storage Division --- UPDATING | 5 ++++ etc/mtree/BSD.tests.dist | 34 ++++++++++++++++++++++++ share/doc/Makefile | 2 ++ share/doc/pjdfstest/Makefile | 8 ++++++ share/doc/pjdfstest/README | 36 +++++++++++++++++++++++++ tests/sys/Makefile | 6 ++++- tests/sys/pjdfstest/Makefile | 6 +++++ tests/sys/pjdfstest/pjdfstest/Makefile | 20 ++++++++++++++ tests/sys/pjdfstest/tests/Makefile | 39 ++++++++++++++++++++++++++++ tests/sys/pjdfstest/tests/chflags/Makefile | 18 +++++++++++++ tests/sys/pjdfstest/tests/chmod/Makefile | 17 ++++++++++++ tests/sys/pjdfstest/tests/chown/Makefile | 15 +++++++++++ tests/sys/pjdfstest/tests/conf | 15 +++++++++++ tests/sys/pjdfstest/tests/ftruncate/Makefile | 19 ++++++++++++++ tests/sys/pjdfstest/tests/granular/Makefile | 10 +++++++ tests/sys/pjdfstest/tests/link/Makefile | 22 ++++++++++++++++ tests/sys/pjdfstest/tests/mkdir/Makefile | 17 ++++++++++++ tests/sys/pjdfstest/tests/mkfifo/Makefile | 17 ++++++++++++ tests/sys/pjdfstest/tests/mknod/Makefile | 16 ++++++++++++ tests/sys/pjdfstest/tests/open/Makefile | 29 +++++++++++++++++++++ tests/sys/pjdfstest/tests/pjdfstest.test.mk | 14 ++++++++++ tests/sys/pjdfstest/tests/rename/Makefile | 26 +++++++++++++++++++ tests/sys/pjdfstest/tests/rmdir/Makefile | 20 ++++++++++++++ tests/sys/pjdfstest/tests/symlink/Makefile | 17 ++++++++++++ tests/sys/pjdfstest/tests/truncate/Makefile | 19 ++++++++++++++ tests/sys/pjdfstest/tests/unlink/Makefile | 18 +++++++++++++ tools/build/mk/OptionalObsoleteFiles.inc | 7 ++--- 27 files changed, 468 insertions(+), 4 deletions(-) create mode 100644 share/doc/pjdfstest/Makefile create mode 100644 share/doc/pjdfstest/README create mode 100644 tests/sys/pjdfstest/Makefile create mode 100644 tests/sys/pjdfstest/pjdfstest/Makefile create mode 100644 tests/sys/pjdfstest/tests/Makefile create mode 100644 tests/sys/pjdfstest/tests/chflags/Makefile create mode 100644 tests/sys/pjdfstest/tests/chmod/Makefile create mode 100644 tests/sys/pjdfstest/tests/chown/Makefile create mode 100644 tests/sys/pjdfstest/tests/conf create mode 100644 tests/sys/pjdfstest/tests/ftruncate/Makefile create mode 100644 tests/sys/pjdfstest/tests/granular/Makefile create mode 100644 tests/sys/pjdfstest/tests/link/Makefile create mode 100644 tests/sys/pjdfstest/tests/mkdir/Makefile create mode 100644 tests/sys/pjdfstest/tests/mkfifo/Makefile create mode 100644 tests/sys/pjdfstest/tests/mknod/Makefile create mode 100644 tests/sys/pjdfstest/tests/open/Makefile create mode 100644 tests/sys/pjdfstest/tests/pjdfstest.test.mk create mode 100644 tests/sys/pjdfstest/tests/rename/Makefile create mode 100644 tests/sys/pjdfstest/tests/rmdir/Makefile create mode 100644 tests/sys/pjdfstest/tests/symlink/Makefile create mode 100644 tests/sys/pjdfstest/tests/truncate/Makefile create mode 100644 tests/sys/pjdfstest/tests/unlink/Makefile (limited to 'etc') diff --git a/UPDATING b/UPDATING index 8fb2bd8645f4..a0af24560d27 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,11 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20141102: + pjdfstest has been integrated into kyua as an opt-in test suite. + Please see share/doc/pjdfstest/README for a more details on how to + execute it. + 20141009: gperf has been removed from the base system for architectures that use clang. Ports that require gperf will obtain it from the diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 93ca4df7dedb..9b3d0952fd65 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -17,6 +17,8 @@ doc atf .. + pjdfstest + .. .. .. tests @@ -143,6 +145,38 @@ .. netinet .. + pjdfstest + chflags + .. + chmod + .. + chown + .. + ftruncate + .. + granular + .. + link + .. + mkdir + .. + mkfifo + .. + mknod + .. + open + .. + rename + .. + rmdir + .. + symlink + .. + truncate + .. + unlink + .. + .. .. usr.bin apply diff --git a/share/doc/Makefile b/share/doc/Makefile index fda977f118e0..c752c51b33eb 100644 --- a/share/doc/Makefile +++ b/share/doc/Makefile @@ -7,10 +7,12 @@ SUBDIR= ${_IPv6} \ ${_atf} \ legal \ ${_llvm} \ + ${_pjdfstest} \ ${_roffdocs} .if ${MK_TESTS} != "no" _atf= atf +_pjdfstest= pjdfstest .endif .if ${MK_CLANG} != "no" diff --git a/share/doc/pjdfstest/Makefile b/share/doc/pjdfstest/Makefile new file mode 100644 index 000000000000..21d72f36e353 --- /dev/null +++ b/share/doc/pjdfstest/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +NO_OBJ= + +FILESDIR= ${SHAREDIR}/doc/pjdfstest +FILES= README + +.include diff --git a/share/doc/pjdfstest/README b/share/doc/pjdfstest/README new file mode 100644 index 000000000000..d09011789e42 --- /dev/null +++ b/share/doc/pjdfstest/README @@ -0,0 +1,36 @@ +pjdfstest test suite execution is integrated into kyua. This README describes +how to use pjdfstest in the default configuration (kyua work directory), and +with a specific filesystem path. + +Method 1. Executing with default configuration (kyua work directory) + + 1. Elevate privileges: + % su - + 2. cd to the tests directory: + % cd /usr/tests/sys/pjdfstest + 3. Run kyua: + % kyua test + + Executing the commands as shown above will run pjdfstest in the kyua work + directory. The kyua work directory defaults to a random generated path under + /tmp; please see TMPDIR in kyua(1) for more details on how the temporary path + is chosen with kyua. + +Method 2. Executing with a specific filesystem path (in this case /mnt) + + 1. Elevate privileges: + % su - + 2. cd to the tests directory: + % cd /usr/tests/sys/pjdfstest + 3. Run kyua: + % env PJDFSTEST_TEST_PATH=/mnt kyua test + + WARNING: the above method violates the test program isolation algorithm + described in kyua(1); as such, $PJDFSTEST_TEST_PATH must be cleaned up after + executing the testcases. + + It's highly recommended that $PJDFSTEST_TEST_PATH be pointed to a sandboxed + filesystem, e.g. a small UFS-formatted memory disk or ZFS dataset with + quotas enabled, so the filesystem can be easily destroyed after the test + execution is complete, and the testcases are properly bounded both in terms + of time and space. diff --git a/tests/sys/Makefile b/tests/sys/Makefile index 88b558ef31fd..b88af9eb48c0 100644 --- a/tests/sys/Makefile +++ b/tests/sys/Makefile @@ -4,9 +4,13 @@ .PATH: ${.CURDIR}/.. +TESTSDIR= ${TESTSBASE}/sys + TESTS_SUBDIRS+= kern TESTS_SUBDIRS+= netinet -TESTSDIR= ${TESTSBASE}/sys + +# Items not integrated into kyua runs by default +SUBDIR+= pjdfstest KYUAFILE= yes diff --git a/tests/sys/pjdfstest/Makefile b/tests/sys/pjdfstest/Makefile new file mode 100644 index 000000000000..7047811528c2 --- /dev/null +++ b/tests/sys/pjdfstest/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SUBDIR+= pjdfstest +SUBDIR+= tests + +.include diff --git a/tests/sys/pjdfstest/pjdfstest/Makefile b/tests/sys/pjdfstest/pjdfstest/Makefile new file mode 100644 index 000000000000..c0e82a41dc72 --- /dev/null +++ b/tests/sys/pjdfstest/pjdfstest/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +TOP= ${.CURDIR:H:H:H:H} + +.PATH: ${TOP}/contrib/pjdfstest + +BINDIR= ${TESTSBASE}/sys/pjdfstest +PROG= pjdfstest +MAN= + +CFLAGS= -D__OS_FreeBSD__ -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS +CFLAGS+= -DHAS_CHFLAGSAT -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL -DHAS_BINDAT +CFLAGS+= -DHAS_CONNECTAT + +# XXX: the upstream sources need some massaging with how it assigns ngroups in +# pjdfstest.c +NO_WERROR= +WARNS?= 6 + +.include diff --git a/tests/sys/pjdfstest/tests/Makefile b/tests/sys/pjdfstest/tests/Makefile new file mode 100644 index 000000000000..248b2095a6b7 --- /dev/null +++ b/tests/sys/pjdfstest/tests/Makefile @@ -0,0 +1,39 @@ +# $FreeBSD$ + +PJDFSTEST_SRCDIR= ${.CURDIR:H:H:H:H}/contrib/pjdfstest + +TESTSDIR= ${TESTSBASE}/sys/pjdfstest + +.PATH: ${.CURDIR} + +FILESDIR= ${TESTSDIR} +FILES= conf +FILES+= misc.sh +CLEANFILES+= misc.sh misc.sh.tmp + +misc.sh: ${PJDFSTEST_SRCDIR}/tests/misc.sh + sed -e '\,maindir=,s,maindir=.*,maindir=`dirname $$0`/../,' < ${.ALLSRC} > ${.TARGET}.tmp + mv ${.TARGET}.tmp ${.TARGET} + +afterinstall: install-tests-symlink +install-tests-symlink: .PHONY + rm -f ${DESTDIR}${TESTSDIR}/tests + ${INSTALL_SYMLINK} . ${DESTDIR}${TESTSDIR}/tests + +TESTS_SUBDIRS= chflags +TESTS_SUBDIRS+= chmod +TESTS_SUBDIRS+= chown +TESTS_SUBDIRS+= ftruncate +TESTS_SUBDIRS+= granular +TESTS_SUBDIRS+= link +TESTS_SUBDIRS+= mkdir +TESTS_SUBDIRS+= mkfifo +TESTS_SUBDIRS+= mknod +TESTS_SUBDIRS+= open +TESTS_SUBDIRS+= rename +TESTS_SUBDIRS+= rmdir +TESTS_SUBDIRS+= symlink +TESTS_SUBDIRS+= truncate +TESTS_SUBDIRS+= unlink + +.include diff --git a/tests/sys/pjdfstest/tests/chflags/Makefile b/tests/sys/pjdfstest/tests/chflags/Makefile new file mode 100644 index 000000000000..3b6a5265fdd4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/chflags/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/chmod/Makefile b/tests/sys/pjdfstest/tests/chmod/Makefile new file mode 100644 index 000000000000..cc0a3bbf1af4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/chmod/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/chown/Makefile b/tests/sys/pjdfstest/tests/chown/Makefile new file mode 100644 index 000000000000..665b6538d19e --- /dev/null +++ b/tests/sys/pjdfstest/tests/chown/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/conf b/tests/sys/pjdfstest/tests/conf new file mode 100644 index 000000000000..7a1168efea13 --- /dev/null +++ b/tests/sys/pjdfstest/tests/conf @@ -0,0 +1,15 @@ +#!/bin/sh +# +# $FreeBSD$ + +: ${PJDFSTEST_TEST_PATH=.} +if ! cd ${PJDFSTEST_TEST_PATH}/; then + echo 'Please set PJDFSTEST_TEST_PATH to a valid filesystem path' + echo 'Bail out!' + exit 1 +fi + +GREP=grep +mountpoint=$(df . | tail -1 | awk '{print $6}') +fs=$(mount -p | awk '$2 == "'$mountpoint'" { print toupper($3) }') +os=FreeBSD diff --git a/tests/sys/pjdfstest/tests/ftruncate/Makefile b/tests/sys/pjdfstest/tests/ftruncate/Makefile new file mode 100644 index 000000000000..da2ce584d3af --- /dev/null +++ b/tests/sys/pjdfstest/tests/ftruncate/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/granular/Makefile b/tests/sys/pjdfstest/tests/granular/Makefile new file mode 100644 index 000000000000..3f935e4e99ce --- /dev/null +++ b/tests/sys/pjdfstest/tests/granular/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/link/Makefile b/tests/sys/pjdfstest/tests/link/Makefile new file mode 100644 index 000000000000..14c7525689b0 --- /dev/null +++ b/tests/sys/pjdfstest/tests/link/Makefile @@ -0,0 +1,22 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 +TAP_TESTS_SH+= 15 +TAP_TESTS_SH+= 16 +TAP_TESTS_SH+= 17 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/mkdir/Makefile b/tests/sys/pjdfstest/tests/mkdir/Makefile new file mode 100644 index 000000000000..cc0a3bbf1af4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/mkdir/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/mkfifo/Makefile b/tests/sys/pjdfstest/tests/mkfifo/Makefile new file mode 100644 index 000000000000..cc0a3bbf1af4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/mkfifo/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/mknod/Makefile b/tests/sys/pjdfstest/tests/mknod/Makefile new file mode 100644 index 000000000000..1eaeaa09818e --- /dev/null +++ b/tests/sys/pjdfstest/tests/mknod/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/open/Makefile b/tests/sys/pjdfstest/tests/open/Makefile new file mode 100644 index 000000000000..bd2f7b5a985d --- /dev/null +++ b/tests/sys/pjdfstest/tests/open/Makefile @@ -0,0 +1,29 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 +TAP_TESTS_SH+= 15 +TAP_TESTS_SH+= 16 +TAP_TESTS_SH+= 17 +TAP_TESTS_SH+= 18 +TAP_TESTS_SH+= 19 +TAP_TESTS_SH+= 20 +TAP_TESTS_SH+= 21 +TAP_TESTS_SH+= 22 +TAP_TESTS_SH+= 23 +TAP_TESTS_SH+= 24 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/pjdfstest.test.mk b/tests/sys/pjdfstest/tests/pjdfstest.test.mk new file mode 100644 index 000000000000..3dc784f7eb63 --- /dev/null +++ b/tests/sys/pjdfstest/tests/pjdfstest.test.mk @@ -0,0 +1,14 @@ +# $FreeBSD$ + +PJDFSTEST_SRCDIR= ${.CURDIR:H:H:H:H:H}/contrib/pjdfstest + +.PATH: ${PJDFSTEST_SRCDIR}/tests/${.CURDIR:T} + +TESTSDIR?= ${TESTSBASE}/sys/pjdfstest/${.CURDIR:T} + +.for s in ${TAP_TESTS_SH} +TAP_TESTS_SH_SRC_$s= $s.t +TEST_METADATA.$s+= required_user="root" +.endfor + +.include diff --git a/tests/sys/pjdfstest/tests/rename/Makefile b/tests/sys/pjdfstest/tests/rename/Makefile new file mode 100644 index 000000000000..7eada047ef15 --- /dev/null +++ b/tests/sys/pjdfstest/tests/rename/Makefile @@ -0,0 +1,26 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 +TAP_TESTS_SH+= 15 +TAP_TESTS_SH+= 16 +TAP_TESTS_SH+= 17 +TAP_TESTS_SH+= 18 +TAP_TESTS_SH+= 19 +TAP_TESTS_SH+= 20 +TAP_TESTS_SH+= 21 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/rmdir/Makefile b/tests/sys/pjdfstest/tests/rmdir/Makefile new file mode 100644 index 000000000000..301e4e5c33d1 --- /dev/null +++ b/tests/sys/pjdfstest/tests/rmdir/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 +TAP_TESTS_SH+= 15 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/symlink/Makefile b/tests/sys/pjdfstest/tests/symlink/Makefile new file mode 100644 index 000000000000..cc0a3bbf1af4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/symlink/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/truncate/Makefile b/tests/sys/pjdfstest/tests/truncate/Makefile new file mode 100644 index 000000000000..da2ce584d3af --- /dev/null +++ b/tests/sys/pjdfstest/tests/truncate/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 +TAP_TESTS_SH+= 14 + +.include "../pjdfstest.test.mk" diff --git a/tests/sys/pjdfstest/tests/unlink/Makefile b/tests/sys/pjdfstest/tests/unlink/Makefile new file mode 100644 index 000000000000..3b6a5265fdd4 --- /dev/null +++ b/tests/sys/pjdfstest/tests/unlink/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +TAP_TESTS_SH= 00 +TAP_TESTS_SH+= 01 +TAP_TESTS_SH+= 02 +TAP_TESTS_SH+= 03 +TAP_TESTS_SH+= 04 +TAP_TESTS_SH+= 05 +TAP_TESTS_SH+= 06 +TAP_TESTS_SH+= 07 +TAP_TESTS_SH+= 08 +TAP_TESTS_SH+= 09 +TAP_TESTS_SH+= 10 +TAP_TESTS_SH+= 11 +TAP_TESTS_SH+= 12 +TAP_TESTS_SH+= 13 + +.include "../pjdfstest.test.mk" diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index 09c52cbc6962..d0b76ad77cb1 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -4068,9 +4068,10 @@ OLD_DIRS+=usr/share/sendmail/cf OLD_DIRS+=usr/share/sendmail .endif -#.if ${MK_SHAREDOCS} == no -# to be filled in -#.endif +.if ${MK_SHAREDOCS} == no +OLD_FILES+=usr/share/doc/pjdfstest/README +OLD_DIRS+=usr/share/doc/pjdfstest +.endif #.if ${MK_SYSCONS} == no # to be filled in -- cgit v1.3 From e4919241ae8042fd136f98ab592eefe9c931e8fe Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Mon, 3 Nov 2014 19:23:49 +0000 Subject: use tab instead of spaces like the rest of the file.. --- etc/rc.d/syscons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/rc.d/syscons b/etc/rc.d/syscons index a60ac4c7318d..67a9b91821ea 100755 --- a/etc/rc.d/syscons +++ b/etc/rc.d/syscons @@ -139,7 +139,7 @@ uk.*) echo uk;; us.iso.acc) echo us.acc;; us.pc-ctrl) echo us.ctrl;; us.iso) echo us;; - esac + esac } kbdcontrol_load_keymap() -- cgit v1.3 From 965f2b1b64805440af090e966e85e3fe64990362 Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Mon, 3 Nov 2014 21:03:54 +0000 Subject: switch from spaces to tabs to match style and awk... Pointed out by: brooks --- etc/rc.d/growfs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/growfs b/etc/rc.d/growfs index db87d29322c4..ec3633dc8f2a 100755 --- a/etc/rc.d/growfs +++ b/etc/rc.d/growfs @@ -49,20 +49,20 @@ rcvar="growfs_enable" growfs_start () { - echo "Growing root partition to fill device" - rootdev=$(df / | tail -n 1 | awk '{ sub("/dev/", "", $1); print $1 }') - if [ x"$rootdev" = x"${rootdev%/*}" ]; then - # raw device - rawdev="$rootdev" - else - rawdev=$(glabel status | awk '$1 == "'"$rootdev"'" { print $3 }') - if [ x"$rawdev" = x"" ]; then - echo "Can't figure out device for: $rootdev" - return + echo "Growing root partition to fill device" + rootdev=$(df / | tail -n 1 | awk '{ sub("/dev/", "", $1); print $1 }') + if [ x"$rootdev" = x"${rootdev%/*}" ]; then + # raw device + rawdev="$rootdev" + else + rawdev=$(glabel status | awk '$1 == "'"$rootdev"'" { print $3 }') + if [ x"$rawdev" = x"" ]; then + echo "Can't figure out device for: $rootdev" + return + fi fi - fi - sysctl -b kern.geom.conftxt | awk ' + sysctl -b kern.geom.conftxt | awk ' { lvl=$1 device[lvl] = $3 @@ -91,7 +91,7 @@ growfs_start () exit 0 } }' dev="$rawdev" - growfs -y /dev/"$rootdev" + growfs -y /dev/"$rootdev" } load_rc_config $name -- cgit v1.3 From 2f1217877e155a8a7de97e74eb7e82096a5ef316 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Tue, 4 Nov 2014 00:56:25 +0000 Subject: Add reachover Makefiles for contrib/netbsd-tests/lib/libc; this adds approximately 500 new testcases Various TODOs have been sprinkled around the Makefiles for items that even need to be ported (missing features), testcases have issues with building/linking, or issues at runtime. A variant of this code has been tested extensively on amd64 and i386 10-STABLE/11-CURRENT for several months without issue. It builds on other architectures, but the code will remain off until I have prove it works on virtual hardware or real hardware on other architectures In collaboration with: pho, Casey Peel Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 50 +++++++++++++++++++ lib/libc/Makefile | 2 + lib/libc/Makefile.amd64 | 6 +++ lib/libc/Makefile.i386 | 6 +++ lib/libc/tests/Makefile | 32 +++++++++++++ lib/libc/tests/Makefile.netbsd-tests | 7 +++ lib/libc/tests/c063/Makefile | 24 ++++++++++ lib/libc/tests/db/Makefile | 17 +++++++ lib/libc/tests/gen/Makefile | 58 ++++++++++++++++++++++ lib/libc/tests/gen/execve/Makefile | 15 ++++++ lib/libc/tests/gen/posix_spawn/Makefile | 34 +++++++++++++ lib/libc/tests/hash/Makefile | 31 ++++++++++++ lib/libc/tests/inet/Makefile | 11 +++++ lib/libc/tests/locale/Makefile | 22 +++++++++ lib/libc/tests/net/Makefile | 39 +++++++++++++++ lib/libc/tests/net/getaddrinfo/Makefile | 31 ++++++++++++ lib/libc/tests/regex/Makefile | 59 +++++++++++++++++++++++ lib/libc/tests/rpc/Makefile | 27 +++++++++++ lib/libc/tests/setjmp/Makefile | 13 +++++ lib/libc/tests/ssp/Makefile | 45 +++++++++++++++++ lib/libc/tests/stdio/Makefile | 17 +++++++ lib/libc/tests/stdlib/Makefile | 44 +++++++++++++++++ lib/libc/tests/string/Makefile | 33 +++++++++++++ lib/libc/tests/sys/Makefile | 85 +++++++++++++++++++++++++++++++++ lib/libc/tests/termios/Makefile | 11 +++++ lib/libc/tests/time/Makefile | 12 +++++ lib/libc/tests/tls/Makefile | 35 ++++++++++++++ lib/libc/tests/tls/dso/Makefile | 18 +++++++ lib/libc/tests/tls_dso/Makefile | 20 ++++++++ lib/libc/tests/ttyio/Makefile | 15 ++++++ 30 files changed, 819 insertions(+) create mode 100644 lib/libc/Makefile.amd64 create mode 100644 lib/libc/Makefile.i386 create mode 100644 lib/libc/tests/Makefile create mode 100644 lib/libc/tests/Makefile.netbsd-tests create mode 100644 lib/libc/tests/c063/Makefile create mode 100644 lib/libc/tests/db/Makefile create mode 100644 lib/libc/tests/gen/Makefile create mode 100644 lib/libc/tests/gen/execve/Makefile create mode 100644 lib/libc/tests/gen/posix_spawn/Makefile create mode 100644 lib/libc/tests/hash/Makefile create mode 100644 lib/libc/tests/inet/Makefile create mode 100644 lib/libc/tests/locale/Makefile create mode 100644 lib/libc/tests/net/Makefile create mode 100644 lib/libc/tests/net/getaddrinfo/Makefile create mode 100644 lib/libc/tests/regex/Makefile create mode 100644 lib/libc/tests/rpc/Makefile create mode 100644 lib/libc/tests/setjmp/Makefile create mode 100644 lib/libc/tests/ssp/Makefile create mode 100644 lib/libc/tests/stdio/Makefile create mode 100644 lib/libc/tests/stdlib/Makefile create mode 100644 lib/libc/tests/string/Makefile create mode 100644 lib/libc/tests/sys/Makefile create mode 100644 lib/libc/tests/termios/Makefile create mode 100644 lib/libc/tests/time/Makefile create mode 100644 lib/libc/tests/tls/Makefile create mode 100644 lib/libc/tests/tls/dso/Makefile create mode 100644 lib/libc/tests/tls_dso/Makefile create mode 100644 lib/libc/tests/ttyio/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 9b3d0952fd65..3c868b9352e2 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -89,6 +89,56 @@ test-programs .. .. + libc + c063 + .. + db + .. + gen + execve + .. + posix_spawn + .. + .. + hash + data + .. + .. + inet + .. + locale + .. + net + getaddrinfo + data + .. + .. + .. + regex + data + .. + .. + ssp + .. + stdio + .. + stdlib + .. + string + .. + sys + .. + time + .. + tls + dso + .. + .. + termios + .. + ttyio + .. + .. libcrypt .. libmp diff --git a/lib/libc/Makefile b/lib/libc/Makefile index ad3cc7415d7d..a535edfedf28 100644 --- a/lib/libc/Makefile +++ b/lib/libc/Makefile @@ -158,6 +158,8 @@ libkern.${LIBC_ARCH}:: ${KMSRCS} cp -fp ${.ALLSRC} ${DESTDIR}/sys/libkern/${LIBC_ARCH} .endif +.include + .include # Disable warnings in contributed sources. diff --git a/lib/libc/Makefile.amd64 b/lib/libc/Makefile.amd64 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/libc/Makefile.amd64 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/libc/Makefile.i386 b/lib/libc/Makefile.i386 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/libc/Makefile.i386 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/libc/tests/Makefile b/lib/libc/tests/Makefile new file mode 100644 index 000000000000..3036ce93f8ef --- /dev/null +++ b/lib/libc/tests/Makefile @@ -0,0 +1,32 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc + +SUBDIR= tls_dso + +TESTS_SUBDIRS= c063 +TESTS_SUBDIRS+= db +TESTS_SUBDIRS+= gen +TESTS_SUBDIRS+= hash +TESTS_SUBDIRS+= inet +TESTS_SUBDIRS+= net +TESTS_SUBDIRS+= regex +TESTS_SUBDIRS+= stdio +TESTS_SUBDIRS+= stdlib +TESTS_SUBDIRS+= string +TESTS_SUBDIRS+= sys +TESTS_SUBDIRS+= termios +TESTS_SUBDIRS+= tls +TESTS_SUBDIRS+= ttyio + +.if ${MK_LOCALES} != "no" +TESTS_SUBDIRS+= locale +.endif + +.if ${MK_SSP} != "no" +TESTS_SUBDIRS+= ssp +.endif + +.include diff --git a/lib/libc/tests/Makefile.netbsd-tests b/lib/libc/tests/Makefile.netbsd-tests new file mode 100644 index 000000000000..f364b1c1b486 --- /dev/null +++ b/lib/libc/tests/Makefile.netbsd-tests @@ -0,0 +1,7 @@ +# $FreeBSD$ + +OBJTOP?= ${.OBJDIR:H:H:H:H} +SRCTOP?= ${.CURDIR:H:H:H:H} +TESTSRC?= ${SRCTOP}/contrib/netbsd-tests/lib/libc/${.CURDIR:T} + +.include diff --git a/lib/libc/tests/c063/Makefile b/lib/libc/tests/c063/Makefile new file mode 100644 index 000000000000..b7431653fee2 --- /dev/null +++ b/lib/libc/tests/c063/Makefile @@ -0,0 +1,24 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/c063 + +#TODO: t_o_search, t_utimensat + +NETBSD_ATF_TESTS_C= t_faccessat +NETBSD_ATF_TESTS_C+= t_fchmodat +NETBSD_ATF_TESTS_C+= t_fchownat +NETBSD_ATF_TESTS_C+= t_fexecve +NETBSD_ATF_TESTS_C+= t_fstatat +NETBSD_ATF_TESTS_C+= t_linkat +NETBSD_ATF_TESTS_C+= t_mkdirat +NETBSD_ATF_TESTS_C+= t_mkfifoat +NETBSD_ATF_TESTS_C+= t_mknodat +NETBSD_ATF_TESTS_C+= t_openat +NETBSD_ATF_TESTS_C+= t_readlinkat +NETBSD_ATF_TESTS_C+= t_renameat +NETBSD_ATF_TESTS_C+= t_symlinkat +NETBSD_ATF_TESTS_C+= t_unlinkat + +CFLAGS+= -D_INCOMPLETE_XOPEN_C063 + +.include diff --git a/lib/libc/tests/db/Makefile b/lib/libc/tests/db/Makefile new file mode 100644 index 000000000000..323a9f07d4a6 --- /dev/null +++ b/lib/libc/tests/db/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/db + +BINDIR= ${TESTSDIR} + +PROGS= h_db + +FILESDIR= ${TESTSDIR} + +FILES= README + +NETBSD_ATF_TESTS_SH+= db_test + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/gen/Makefile b/lib/libc/tests/gen/Makefile new file mode 100644 index 000000000000..39e8838942a7 --- /dev/null +++ b/lib/libc/tests/gen/Makefile @@ -0,0 +1,58 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/gen + +# TODO: t_closefrom, t_cpuset, t_fmtcheck, t_randomid, t_sleep +# TODO: t_siginfo (fixes require further inspection) +# TODO: t_sethostname_test (consistently screws up the hostname) + +NETBSD_ATF_TESTS_C= alarm_test +NETBSD_ATF_TESTS_C+= assert_test +NETBSD_ATF_TESTS_C+= basedirname_test +NETBSD_ATF_TESTS_C+= dir_test +NETBSD_ATF_TESTS_C+= floatunditf_test +NETBSD_ATF_TESTS_C+= fnmatch_test +NETBSD_ATF_TESTS_C+= fpclassify_test +NETBSD_ATF_TESTS_C+= fpsetmask_test +NETBSD_ATF_TESTS_C+= fpsetround_test +NETBSD_ATF_TESTS_C+= ftok_test +NETBSD_ATF_TESTS_C+= getcwd_test +NETBSD_ATF_TESTS_C+= getgrent_test +NETBSD_ATF_TESTS_C+= glob_test +NETBSD_ATF_TESTS_C+= humanize_number_test +NETBSD_ATF_TESTS_C+= isnan_test +NETBSD_ATF_TESTS_C+= nice_test +NETBSD_ATF_TESTS_C+= pause_test +NETBSD_ATF_TESTS_C+= raise_test +NETBSD_ATF_TESTS_C+= realpath_test +NETBSD_ATF_TESTS_C+= setdomainname_test +NETBSD_ATF_TESTS_C+= sethostname_test +NETBSD_ATF_TESTS_C+= sleep_test +NETBSD_ATF_TESTS_C+= syslog_test +NETBSD_ATF_TESTS_C+= time_test +NETBSD_ATF_TESTS_C+= ttyname_test +NETBSD_ATF_TESTS_C+= vis_test + +.include "../Makefile.netbsd-tests" + +LDADD.humanize_number_test+= -lutil +DPADD.humanize_number_test+= ${LIBUTIL} + +LDADD.fpclassify_test+= -lm +DPADD.fpclassify_test+= ${LIBM} +LDADD.fpsetround_test+= -lm +DPADD.fpsetround_test+= ${LIBM} +LDADD.siginfo_test+= -lm +DPADD.siginfo_test+= ${LIBM} + +LDADD.nice_test+= -lpthread +DPADD.nice_test+= ${LIBPTHREAD} +LDADD.syslog_test+= -lpthread +DPADD.syslog_test+= ${LIBPTHREAD} + +TESTS_SUBDIRS= execve +TESTS_SUBDIRS+= posix_spawn + +.include diff --git a/lib/libc/tests/gen/execve/Makefile b/lib/libc/tests/gen/execve/Makefile new file mode 100644 index 000000000000..2106a1582358 --- /dev/null +++ b/lib/libc/tests/gen/execve/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/gen/${.CURDIR:T} + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/gen/execve + +NETBSD_ATF_TESTS_C= execve_test + +.include "../../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/gen/posix_spawn/Makefile b/lib/libc/tests/gen/posix_spawn/Makefile new file mode 100644 index 000000000000..a1c9b9e7cd1e --- /dev/null +++ b/lib/libc/tests/gen/posix_spawn/Makefile @@ -0,0 +1,34 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/gen/${.CURDIR:T} + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/gen/posix_spawn + +BINDIR= ${TESTSDIR} + +# TODO: t_spawnattr (fix from pho@ needs additional review) +NETBSD_ATF_TESTS_C= fileactions_test +NETBSD_ATF_TESTS_C+= spawn_test + +PROGS= h_fileactions +PROGS+= h_spawn +PROGS+= h_spawnattr + +SCRIPTS= h_nonexec +SCRIPTS+= h_zero + +.include "../../Makefile.netbsd-tests" + +h_zero: + dd if=/dev/zero of=h_zero bs=1k count=2 + chmod a+x h_zero + +CLEANFILES+= h_zero + +WARNS?=3 + +.include diff --git a/lib/libc/tests/hash/Makefile b/lib/libc/tests/hash/Makefile new file mode 100644 index 000000000000..df9d6d9b5c2d --- /dev/null +++ b/lib/libc/tests/hash/Makefile @@ -0,0 +1,31 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/hash + +NETBSD_ATF_TESTS_C= sha2_test + +NETBSD_ATF_TESTS_SH= hash_test + +BINDIR= ${TESTSDIR} + +PROGS+= h_hash + +FILESDIR= ${TESTSDIR}/data + +FILES+= data/md5test-in +FILES+= data/md5test-out +FILES+= data/sha1test-in +FILES+= data/sha1test-out +FILES+= data/sha1test2-out + +DPADD+= ${LIBMD} +LDADD+= -lmd +DPADD.sha2_test+= ${LIBCRYPTO} +LDADD.sha2_test+= -lcrypto + +CFLAGS.sha2_test+= -I${.CURDIR}/../../../../crypto/openssh/openbsd-compat +CFLAGS.sha2_test+= -I${.CURDIR}/../../../../crypto/openssh + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/inet/Makefile b/lib/libc/tests/inet/Makefile new file mode 100644 index 000000000000..a15b96ae35af --- /dev/null +++ b/lib/libc/tests/inet/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/inet + +NETBSD_ATF_TESTS_C= inet_network_test + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/locale/Makefile b/lib/libc/tests/locale/Makefile new file mode 100644 index 000000000000..e4dc553c46ae --- /dev/null +++ b/lib/libc/tests/locale/Makefile @@ -0,0 +1,22 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/locale + +NETBSD_ATF_TESTS_C= io_test +NETBSD_ATF_TESTS_C+= mbrtowc_test +NETBSD_ATF_TESTS_C+= mbstowcs_test +NETBSD_ATF_TESTS_C+= mbsnrtowcs_test +NETBSD_ATF_TESTS_C+= mbtowc_test +NETBSD_ATF_TESTS_C+= wcscspn_test +NETBSD_ATF_TESTS_C+= wcspbrk_test +NETBSD_ATF_TESTS_C+= wcsspn_test +NETBSD_ATF_TESTS_C+= wcstod_test +NETBSD_ATF_TESTS_C+= wctomb_test + +CFLAGS.t_wctomb.c+= -Wno-stack-protector + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/net/Makefile b/lib/libc/tests/net/Makefile new file mode 100644 index 000000000000..eb199f09b8d7 --- /dev/null +++ b/lib/libc/tests/net/Makefile @@ -0,0 +1,39 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/net + +BINDIR= ${TESTSDIR} + +NETBSD_ATF_TESTS_C= getprotoent_test +NETBSD_ATF_TESTS_C+= ether_aton_test + +SRCS.t_ether_aton= aton_ether_subr.c t_ether_aton.c + +aton_ether_subr.c: gen_ether_subr ${.CURDIR:H:H:H:H}/sys/net/if_ethersubr.c + ${HOST_SH} ${.ALLSRC} ${.TARGET} + +# TODO: hostent_test +NETBSD_ATF_TESTS_SH= nsdispatch_test +NETBSD_ATF_TESTS_SH+= protoent_test +NETBSD_ATF_TESTS_SH+= servent_test + +PROGS= h_nsd_recurse +PROGS+= h_protoent +PROGS+= h_servent +PROGS+= h_dns_server + +DPADD.h_nsd_recurse+= ${LIBPTHREAD} +LDADD.h_nsd_recurse+= -lpthread + +CLEANFILES+= aton_ether_subr.c + +.include "../Makefile.netbsd-tests" + +# TODO: the testcases needs to be ported to FreeBSD +#TESTS_SUBDIRS= getaddrinfo +FILES= hosts +FILES+= resolv.conf + +.include diff --git a/lib/libc/tests/net/getaddrinfo/Makefile b/lib/libc/tests/net/getaddrinfo/Makefile new file mode 100644 index 000000000000..a6b9eb197e99 --- /dev/null +++ b/lib/libc/tests/net/getaddrinfo/Makefile @@ -0,0 +1,31 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/net/${.CURDIR:T} + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/net/getaddrinfo + +BINDIR= ${TESTSDIR} + +.error "This testcase needs to be ported to FreeBSD (the output from getaddrinfo_test differs from NetBSD)" + +NETBSD_ATF_TESTS_SH= getaddrinfo_test + +PROGS= h_gai + +FILESDIR= ${TESTSDIR}/data + +FILES= basics_v4.exp basics_v4v6.exp +FILES+= no_host_v4.exp no_host_v4v6.exp +FILES+= no_serv_v4.exp no_serv_v4v6.exp +FILES+= sock_raw_v4.exp sock_raw_v4v6.exp +FILES+= spec_fam_v4.exp spec_fam_v4v6.exp +FILES+= scoped.exp +FILES+= unsup_fam.exp + +.include "../../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/regex/Makefile b/lib/libc/tests/regex/Makefile new file mode 100644 index 000000000000..37b3277e57c4 --- /dev/null +++ b/lib/libc/tests/regex/Makefile @@ -0,0 +1,59 @@ +# $FreeBSD$ + +.include + +BINDIR= ${TESTSDIR} + +TESTSDIR= ${TESTSBASE}/lib/libc/regex + +IMPLEMENTATION?= -DREGEX_SPENCER + +CFLAGS.h_regex+=-I${TESTSRC} -I${.CURDIR:H:H}/regex +PROGS+= h_regex +SRCS.h_regex= main.c split.c debug.c + +NETBSD_ATF_TESTS_SH= regex_test + +FILESDIR= ${TESTSDIR}/data +FILES+= README +FILES+= data/anchor.in +FILES+= data/backref.in +FILES+= data/basic.in +FILES+= data/bracket.in +FILES+= data/c_comments.in +FILES+= data/complex.in +FILES+= data/error.in +FILES+= data/meta.in +FILES+= data/nospec.in +FILES+= data/paren.in +FILES+= data/regress.in +FILES+= data/repet_bounded.in +FILES+= data/repet_multi.in +FILES+= data/repet_ordinary.in +FILES+= data/startend.in +FILES+= data/subexp.in +FILES+= data/subtle.in +FILES+= data/word_bound.in +FILES+= data/zero.in +#FILES+= data/att/README +FILES+= data/att/basic.dat +FILES+= data/att/categorization.dat +FILES+= data/att/forcedassoc.dat +FILES+= data/att/leftassoc.dat +FILES+= data/att/nullsubexpr.dat +FILES+= data/att/repetition.dat +FILES+= data/att/rightassoc.dat + +NETBSD_ATF_TESTS_C= exhaust_test +NETBSD_ATF_TESTS_C+= regex_att_test + +.for t in ${NETBSD_ATF_TESTS_C} +CFLAGS.$t+= -I${TESTSRC} ${IMPLEMENTATION} +.endfor + +.include "../Makefile.netbsd-tests" + +DPADD.regex_att_test+= ${LIBUTIL} +LDADD.regex_att_test+= -lutil + +.include diff --git a/lib/libc/tests/rpc/Makefile b/lib/libc/tests/rpc/Makefile new file mode 100644 index 000000000000..03802945cc68 --- /dev/null +++ b/lib/libc/tests/rpc/Makefile @@ -0,0 +1,27 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/rpc +SRCS.xdr_test= ${RPCSRC:.x=_xdr.c} t_xdr.c ${RPCSRC:.x=.h} + +NETBSD_ATF_TESTS_C= rpc_test +NETBSD_ATF_TESTS_C+= xdr_test + +RPCSRC= h_testbits.x +RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -L -C + +h_testbits.h: ${RPCSRC} + ${RPCGEN} -h -o ${.TARGET} ${.ALLSRC} + +h_testbits_xdr.c: ${RPCSRC} h_testbits.h + ${RPCGEN} ${.ALLSRC:M*.x} + +CLEANFILES+= ${RPCSRC:.x=.h} ${RPCSRC:.x=.c} h_testbits_xdr.c +CFLAGS+= -I${.OBJDIR} +DPSRCS+= h_testbits.h + +LDADD+= -lrpcsvc -lutil +DPADD+= ${LIBRPCSVC} ${LIBUTIL} + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/setjmp/Makefile b/lib/libc/tests/setjmp/Makefile new file mode 100644 index 000000000000..e4c7ae5144a6 --- /dev/null +++ b/lib/libc/tests/setjmp/Makefile @@ -0,0 +1,13 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/setjmp + +NETBSD_ATF_TESTS_C= t_setjmp +NETBSD_ATF_TESTS_C+= t_threadjmp + +DPADD.t_threadjmp+= ${LIBPTHREAD} +LDADD.t_threadjmp+= -lpthread + +WARNS?= 4 + +.include diff --git a/lib/libc/tests/ssp/Makefile b/lib/libc/tests/ssp/Makefile new file mode 100644 index 000000000000..cf767ce4bd0e --- /dev/null +++ b/lib/libc/tests/ssp/Makefile @@ -0,0 +1,45 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/ssp + +NO_WERROR= +WARNS?= 2 + +CFLAGS.h_raw+= -fstack-protector-all -Wstack-protector +.if ${COMPILER_TYPE} == "clang" +CFLAGS.h_raw+= -fsanitize=bounds +.elif ${COMPILER_TYPE} == "gcc" +CFLAGS.h_raw+= --param ssp-buffer-size=1 +DPADD+= ${LIBSSP} +LDADD+= -lssp +.endif + +NETBSD_ATF_TESTS_SH= ssp_test + +BINDIR= ${TESTSDIR} + +PROGS= h_fgets +PROGS+= h_gets +PROGS+= h_getcwd +PROGS+= h_memcpy +PROGS+= h_memmove +PROGS+= h_memset +PROGS+= h_raw +PROGS+= h_read +PROGS+= h_readlink +PROGS+= h_snprintf +PROGS+= h_sprintf +PROGS+= h_stpcpy +PROGS+= h_stpncpy +PROGS+= h_strcat +PROGS+= h_strcpy +PROGS+= h_strncat +PROGS+= h_strncpy +PROGS+= h_vsnprintf +PROGS+= h_vsprintf + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/stdio/Makefile b/lib/libc/tests/stdio/Makefile new file mode 100644 index 000000000000..3512dd954081 --- /dev/null +++ b/lib/libc/tests/stdio/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +TESTSDIR= ${TESTSBASE}/lib/libc/stdio + +NETBSD_ATF_TESTS_C= clearerr_test +NETBSD_ATF_TESTS_C+= fflush_test +NETBSD_ATF_TESTS_C+= fmemopen_test +NETBSD_ATF_TESTS_C+= fopen_test +NETBSD_ATF_TESTS_C+= fputc_test +NETBSD_ATF_TESTS_C+= mktemp_test +NETBSD_ATF_TESTS_C+= popen_test +NETBSD_ATF_TESTS_C+= printf_test +NETBSD_ATF_TESTS_C+= scanf_test + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/stdlib/Makefile b/lib/libc/tests/stdlib/Makefile new file mode 100644 index 000000000000..917160112f6a --- /dev/null +++ b/lib/libc/tests/stdlib/Makefile @@ -0,0 +1,44 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/stdlib + +# TODO: t_getenv_thread, t_mi_vector_hash +NETBSD_ATF_TESTS_C= abs_test +NETBSD_ATF_TESTS_C+= atoi_test +NETBSD_ATF_TESTS_C+= div_test +NETBSD_ATF_TESTS_C+= getenv_test +NETBSD_ATF_TESTS_C+= exit_test +NETBSD_ATF_TESTS_C+= hsearch_test +NETBSD_ATF_TESTS_C+= posix_memalign_test +NETBSD_ATF_TESTS_C+= random_test +NETBSD_ATF_TESTS_C+= strtod_test +NETBSD_ATF_TESTS_C+= strtol_test +NETBSD_ATF_TESTS_C+= system_test + +# TODO: need to come up with a correct explanation of what the patch pho does +# with h_atexit +#ATF_TESTS_SH= atexit_test +NETBSD_ATF_TESTS_SH= getopt_test + +.include "../Makefile.netbsd-tests" + +BINDIR= ${TESTSDIR} + +# TODO: see comment above +#PROGS+= h_atexit +PROGS+= h_getopt h_getopt_long + +.for t in h_getopt h_getopt_long +CFLAGS.$t+= -I${LIBNETBSD_SRCDIR} -I${SRCTOP}/contrib/netbsd-tests +LDFLAGS.$t+= -L${LIBNETBSD_OBJDIR} + +DPADD.$t+= ${LIBNETBSD} ${LIBUTIL} +LDADD.$t+= -lnetbsd -lutil +.endfor + +DPADD.strtod_test+= ${LIBM} +LDADD.strtod_test+= -lm + +.include diff --git a/lib/libc/tests/string/Makefile b/lib/libc/tests/string/Makefile new file mode 100644 index 000000000000..3c30ab67ec73 --- /dev/null +++ b/lib/libc/tests/string/Makefile @@ -0,0 +1,33 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/string + +# TODO: popcount, stresep + +NETBSD_ATF_TESTS_C+= memchr +NETBSD_ATF_TESTS_C+= memcpy +NETBSD_ATF_TESTS_C+= memmem +NETBSD_ATF_TESTS_C+= memset +NETBSD_ATF_TESTS_C+= strcat +NETBSD_ATF_TESTS_C+= strchr +NETBSD_ATF_TESTS_C+= strcmp +NETBSD_ATF_TESTS_C+= strcpy +NETBSD_ATF_TESTS_C+= strcspn +NETBSD_ATF_TESTS_C+= strerror +NETBSD_ATF_TESTS_C+= strlen +NETBSD_ATF_TESTS_C+= strpbrk +NETBSD_ATF_TESTS_C+= strrchr +NETBSD_ATF_TESTS_C+= strspn +NETBSD_ATF_TESTS_C+= swab + +.include "../Makefile.netbsd-tests" + +LDADD.memchr+= -lmd +DPADD.memchr+= ${LIBMD} + +LDADD.memcpy+= -lmd +DPADD.memcpy+= ${LIBMD} + +.include diff --git a/lib/libc/tests/sys/Makefile b/lib/libc/tests/sys/Makefile new file mode 100644 index 000000000000..89431bced322 --- /dev/null +++ b/lib/libc/tests/sys/Makefile @@ -0,0 +1,85 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/sys + +# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg, +# swapcontext +NETBSD_ATF_TESTS_C+= access_test +NETBSD_ATF_TESTS_C+= chroot_test +NETBSD_ATF_TESTS_C+= clock_gettime_test +NETBSD_ATF_TESTS_C+= connect_test +NETBSD_ATF_TESTS_C+= dup_test +NETBSD_ATF_TESTS_C+= fsync_test +NETBSD_ATF_TESTS_C+= getcontext_test +NETBSD_ATF_TESTS_C+= getgroups_test +NETBSD_ATF_TESTS_C+= getitimer_test +NETBSD_ATF_TESTS_C+= getlogin_test +NETBSD_ATF_TESTS_C+= getpid_test +NETBSD_ATF_TESTS_C+= getrusage_test +NETBSD_ATF_TESTS_C+= getsid_test +NETBSD_ATF_TESTS_C+= gettimeofday_test +NETBSD_ATF_TESTS_C+= issetugid_test +NETBSD_ATF_TESTS_C+= kevent_test +NETBSD_ATF_TESTS_C+= kill_test +NETBSD_ATF_TESTS_C+= link_test +NETBSD_ATF_TESTS_C+= listen_test +NETBSD_ATF_TESTS_C+= mincore_test +NETBSD_ATF_TESTS_C+= mkdir_test +NETBSD_ATF_TESTS_C+= mkfifo_test +NETBSD_ATF_TESTS_C+= mknod_test +NETBSD_ATF_TESTS_C+= mlock_test +NETBSD_ATF_TESTS_C+= mmap_test +NETBSD_ATF_TESTS_C+= mprotect_test +NETBSD_ATF_TESTS_C+= msgctl_test +NETBSD_ATF_TESTS_C+= msgget_test +NETBSD_ATF_TESTS_C+= msgrcv_test +NETBSD_ATF_TESTS_C+= msgsnd_test +NETBSD_ATF_TESTS_C+= msync_test +NETBSD_ATF_TESTS_C+= nanosleep_test +NETBSD_ATF_TESTS_C+= pipe_test +NETBSD_ATF_TESTS_C+= pipe2_test +NETBSD_ATF_TESTS_C+= poll_test +NETBSD_ATF_TESTS_C+= revoke_test +NETBSD_ATF_TESTS_C+= select_test +NETBSD_ATF_TESTS_C+= setrlimit_test +NETBSD_ATF_TESTS_C+= setuid_test +NETBSD_ATF_TESTS_C+= sigaction_test +NETBSD_ATF_TESTS_C+= sigqueue_test +NETBSD_ATF_TESTS_C+= sigtimedwait_test +NETBSD_ATF_TESTS_C+= socketpair_test +NETBSD_ATF_TESTS_C+= stat_test +NETBSD_ATF_TESTS_C+= timer_create_test +NETBSD_ATF_TESTS_C+= truncate_test +NETBSD_ATF_TESTS_C+= ucontext_test +NETBSD_ATF_TESTS_C+= umask_test +NETBSD_ATF_TESTS_C+= unlink_test +NETBSD_ATF_TESTS_C+= write_test + +DPADD.getpid_test+= ${LIBPTHREAD} +LDADD.getpid_test+= -lpthread +DPADD.timer_create_test+= ${LIBRT} +LDADD.timer_create_test+= -lrt + +.include "../Makefile.netbsd-tests" + +.if ${COMPILER_TYPE} == "gcc" +WARNS?= 3 +.else +WARNS?= 4 +.endif + +FILESGROUPS= FILES truncate_test_FILES + +truncate_test_FILES= truncate_test.root_owned +truncate_test_FILESDIR= ${TESTSDIR} +truncate_test_FILESMODE= 0600 +truncate_test_FILESOWNER= root +truncate_test_FILESGRP= wheel + +CLEANFILES= truncate_test.root_owned +truncate_test.root_owned: + dd if=/dev/null bs=1 count=1 of=${.TARGET} + +.include diff --git a/lib/libc/tests/termios/Makefile b/lib/libc/tests/termios/Makefile new file mode 100644 index 000000000000..9a3fd66a5aac --- /dev/null +++ b/lib/libc/tests/termios/Makefile @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/termios + +NETBSD_ATF_TESTS_C= tcsetpgrp_test + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/time/Makefile b/lib/libc/tests/time/Makefile new file mode 100644 index 000000000000..c2a55df15be5 --- /dev/null +++ b/lib/libc/tests/time/Makefile @@ -0,0 +1,12 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/time + +NETBSD_ATF_TESTS_C= mktime_test +NETBSD_ATF_TESTS_C+= strptime_test + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/tls/Makefile b/lib/libc/tests/tls/Makefile new file mode 100644 index 000000000000..e2248959ab14 --- /dev/null +++ b/lib/libc/tests/tls/Makefile @@ -0,0 +1,35 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/tls +.if !defined(NO_PIC) +SUBDIR+= dso +.endif + +# TODO: doesn't link properly (for some odd reason it's trying to link in +# libatf.so) +#NETBSD_ATF_TESTS_C= tls_static_test +.if !defined(NO_PIC) +NETBSD_ATF_TESTS_C+= tls_dlopen_test +NETBSD_ATF_TESTS_C+= tls_dynamic_test +.endif + +.include "../Makefile.netbsd-tests" + +DSODIR= ${.OBJDIR}/../tls_dso + +DPADD.tls_static_test+= ${LIBPTHREAD} +LDADD.tls_static_test+= -lpthread +LDFLAGS.tls_static_test+= -static +SRCS.tls_static_test= t_tls_static.c t_tls_static_helper.c + +DPADD.tls_dynamic_test+= ${LIBPTHREAD} ${DSODIR}/libh_tls_dynamic.so +LDADD.tls_dynamic_test+= -lpthread -lh_tls_dynamic +LDFLAGS.tls_dynamic_test+= -Wl,-rpath,${TESTSDIR} -L${DSODIR} + +DPADD.tls_dlopen_test+= ${LIBPTHREAD} +LDADD.tls_dlopen_test+= -lpthread +LDFLAGS.tls_dlopen_test+= -Wl,-rpath,${TESTSDIR} -Wl,-export-dynamic + +.include diff --git a/lib/libc/tests/tls/dso/Makefile b/lib/libc/tests/tls/dso/Makefile new file mode 100644 index 000000000000..466f950061f8 --- /dev/null +++ b/lib/libc/tests/tls/dso/Makefile @@ -0,0 +1,18 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libc/tls/${.CURDIR:T} + +LIB= h_tls_dlopen +SHLIB_NAME= h_tls_dlopen.so +SRCS= h_tls_dlopen.c + +MAN= + +LIBDIR= ${TESTSBASE}/lib/libc/tls +SHLIB_MAJOR= 1 + +.include "../../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/tls_dso/Makefile b/lib/libc/tests/tls_dso/Makefile new file mode 100644 index 000000000000..5449799de96c --- /dev/null +++ b/lib/libc/tests/tls_dso/Makefile @@ -0,0 +1,20 @@ +# $FreeBSD$ + +.include + +LIB= h_tls_dynamic +SRCS= h_tls_dynamic.c + +LIBDIR= ${TESTSBASE}/lib/libc/tls +SHLIBDIR= ${TESTSBASE}/lib/libc/tls +SHLIB_MAJOR= 1 + +WITHOUT_STATIC= +WITHOUT_PROFILE= +WITHOUT_PIC= + +MAN= + +.include "../Makefile.netbsd-tests" + +.include diff --git a/lib/libc/tests/ttyio/Makefile b/lib/libc/tests/ttyio/Makefile new file mode 100644 index 000000000000..a1f320d6fd4d --- /dev/null +++ b/lib/libc/tests/ttyio/Makefile @@ -0,0 +1,15 @@ +# $FreeBSD$ + +.include + +TESTSDIR= ${TESTSBASE}/lib/libc/ttyio + +# TODO: ptm_test +NETBSD_ATF_TESTS_C= ttyio_test + +DPADD.ttyio_test+= ${LIBUTIL} +LDADD.ttyio_test+= -lutil + +.include "../Makefile.netbsd-tests" + +.include -- cgit v1.3 From 81e6fb172f1d3785930c201021d333b76e3b130c Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 5 Nov 2014 06:42:07 +0000 Subject: Avoid installing security.functions with executable bits, periodic(8) will try to execute all files with an executable bit in /etc/periodic/*/ while this file is supposed only to be sourced by others MFC after: 1 week --- etc/periodic/security/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'etc') diff --git a/etc/periodic/security/Makefile b/etc/periodic/security/Makefile index 026948b9d854..8174133b64bb 100644 --- a/etc/periodic/security/Makefile +++ b/etc/periodic/security/Makefile @@ -2,6 +2,8 @@ .include +FILESGROUPS= FILES DATA + FILES= 100.chksetuid \ 110.neggrpperm \ 200.chkmounts \ @@ -10,8 +12,8 @@ FILES= 100.chksetuid \ 410.logincheck \ 700.kernelmsg \ 800.loginfail \ - 900.tcpwrap \ - security.functions + 900.tcpwrap +DATA= security.functions # NB: keep these sorted by MK_* knobs -- cgit v1.3 From 982247d2cf1d1c43b7e9790f6629d38288a319f7 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 5 Nov 2014 22:50:33 +0000 Subject: Create a directory for the PAM tests. --- etc/mtree/BSD.tests.dist | 2 ++ 1 file changed, 2 insertions(+) (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 3c868b9352e2..ae377acedc16 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -145,6 +145,8 @@ .. libnv .. + libpam + .. libproc .. libutil -- cgit v1.3 From 37d801706bb0f1de117acaf9137173848a7a683b Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Thu, 6 Nov 2014 07:27:14 +0000 Subject: remove comment about the bug... I don't remeber what it was... It may be an issue w/ using awk which is in /usr (and isn't always present), or another issue... Suggestion by: brooks --- etc/rc.d/growfs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'etc') diff --git a/etc/rc.d/growfs b/etc/rc.d/growfs index ec3633dc8f2a..cc0ed119968f 100755 --- a/etc/rc.d/growfs +++ b/etc/rc.d/growfs @@ -35,9 +35,7 @@ # and have it work on essentially any size drive. # # TODO: Figure out where this should really be ordered. -# I suspect it should go just after fsck but before mountcritlocal -# but it's hard to tell for sure because of the bug described -# below. +# I suspect it should go just after fsck but before mountcritlocal. # . /etc/rc.subr -- cgit v1.3 From 603eaf792b659f91d7d1a065d82503966d1386fc Mon Sep 17 00:00:00 2001 From: "Alexander V. Chernikov" Date: Sun, 9 Nov 2014 21:33:01 +0000 Subject: Renove faith(4) and faithd(8) from base. It looks like industry have chosen different (and more traditional) stateless/statuful NAT64 as translation mechanism. Last non-trivial commits to both faith(4) and faithd(8) happened more than 12 years ago, so I assume it is time to drop RFC3142 in FreeBSD. No objections from: net@ --- ObsoleteFiles.inc | 6 + UPDATING | 4 + etc/defaults/rc.conf | 3 - etc/network.subr | 2 - etc/rc.d/Makefile | 1 - etc/rc.d/NETWORKING | 2 +- etc/rc.d/bridge | 2 +- etc/rc.d/defaultroute | 2 +- etc/rc.d/faith | 75 -- etc/rc.d/routing | 4 +- lib/libc/net/getaddrinfo.c | 52 -- lib/libc/net/getnameinfo.c | 1 - release/picobsd/bridge/PICOBSD | 1 - release/picobsd/qemu/PICOBSD | 1 - share/man/man4/Makefile | 2 - share/man/man4/faith.4 | 133 --- share/man/man4/inet6.4 | 11 - share/man/man4/ip6.4 | 4 - share/man/man5/rc.conf.5 | 9 - sys/amd64/conf/GENERIC | 1 - sys/arm/conf/ATMEL | 1 - sys/arm/conf/DOCKSTAR | 1 - sys/arm/conf/DREAMPLUG-1001 | 1 - sys/arm/conf/EFIKA_MX | 1 - sys/arm/conf/ETHERNUT5 | 1 - sys/arm/conf/IMX53 | 1 - sys/arm/conf/IMX6 | 1 - sys/arm/conf/SAM9260EK | 1 - sys/boot/forth/loader.conf | 1 - sys/conf/NOTES | 3 - sys/conf/files | 1 - sys/i386/conf/GENERIC | 1 - sys/i386/conf/XBOX | 1 - sys/i386/conf/XEN | 1 - sys/mips/conf/GXEMUL | 1 - sys/mips/conf/GXEMUL32 | 1 - sys/mips/conf/OCTEON1 | 1 - sys/mips/rmi/rootfs_list.txt | 1 - sys/modules/Makefile | 1 - sys/modules/if_faith/Makefile | 8 - sys/net/if_faith.c | 331 ------- sys/net/if_types.h | 1 - sys/netinet/in.h | 5 +- sys/netinet/in_pcb.c | 19 - sys/netinet/in_pcb.h | 2 +- sys/netinet/ip_icmp.c | 13 - sys/netinet/ip_input.c | 18 - sys/netinet/ip_output.c | 10 - sys/netinet6/icmp6.c | 16 - sys/netinet6/in6.c | 40 +- sys/netinet6/in6.h | 6 +- sys/netinet6/in6_pcb.c | 24 - sys/netinet6/in6_proto.c | 3 - sys/netinet6/ip6_output.c | 10 - sys/netinet6/ip6_var.h | 2 - sys/netinet6/raw_ip6.c | 6 - sys/netinet6/sctp6_usrreq.c | 4 - sys/netinet6/udp6_usrreq.c | 6 - sys/pc98/conf/GENERIC | 1 - sys/powerpc/conf/GENERIC | 1 - sys/powerpc/conf/GENERIC64 | 1 - sys/powerpc/conf/WII | 1 - sys/sparc64/conf/GENERIC | 1 - tools/build/mk/OptionalObsoleteFiles.inc | 1 - tools/tools/nanobsd/pcengines/ALIX_DSK | 1 - tools/tools/nanobsd/pcengines/ALIX_NFS | 1 - tools/tools/sysdoc/tunables.mdoc | 8 - tools/tools/tinybsd/conf/default/TINYBSD | 1 - tools/tools/tinybsd/conf/vpn/TINYBSD | 1 - tools/tools/tinybsd/conf/wrap/TINYBSD | 1 - usr.sbin/Makefile | 1 - usr.sbin/bsdconfig/networking/share/device.subr | 2 +- usr.sbin/faithd/Makefile | 25 - usr.sbin/faithd/README | 148 ---- usr.sbin/faithd/faithd.8 | 404 --------- usr.sbin/faithd/faithd.c | 908 ------------------- usr.sbin/faithd/faithd.h | 70 -- usr.sbin/faithd/ftp.c | 1085 ----------------------- usr.sbin/faithd/prefix.c | 345 ------- usr.sbin/faithd/prefix.h | 52 -- usr.sbin/faithd/tcp.c | 324 ------- usr.sbin/faithd/test/faithd.rb | 312 ------- usr.sbin/inetd/inetd.c | 20 +- 83 files changed, 39 insertions(+), 4537 deletions(-) delete mode 100755 etc/rc.d/faith delete mode 100644 share/man/man4/faith.4 delete mode 100644 sys/modules/if_faith/Makefile delete mode 100644 sys/net/if_faith.c delete mode 100644 usr.sbin/faithd/Makefile delete mode 100644 usr.sbin/faithd/README delete mode 100644 usr.sbin/faithd/faithd.8 delete mode 100644 usr.sbin/faithd/faithd.c delete mode 100644 usr.sbin/faithd/faithd.h delete mode 100644 usr.sbin/faithd/ftp.c delete mode 100644 usr.sbin/faithd/prefix.c delete mode 100644 usr.sbin/faithd/prefix.h delete mode 100644 usr.sbin/faithd/tcp.c delete mode 100644 usr.sbin/faithd/test/faithd.rb (limited to 'etc') diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index c8072d446059..be0b7c90924c 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,6 +38,12 @@ # xargs -n1 | sort | uniq -d; # done +# 20141109: faith/faithd removal +OLD_FILES+=etc/rc.d/faith +OLD_FILES+=usr/share/man/man4/faith.4.gz +OLD_FILES+=usr/share/man/man4/if_faith.4.gz +OLD_FILES+=usr/sbin/faithd +OLD_FILES+=usr/share/man/man8/faithd.8.gz # 20141102: postrandom obsoleted by new /dev/random code OLD_FILES+=etc/rc.d/postrandom # 20141031: initrandom obsoleted by new /dev/random code diff --git a/UPDATING b/UPDATING index 507055d69314..b9a7b3552fb9 100644 --- a/UPDATING +++ b/UPDATING @@ -31,6 +31,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 11.x IS SLOW: disable the most expensive debugging functionality run "ln -s 'abort:false,junk:false' /etc/malloc.conf".) +20141109: + faith(4) and faithd(8) has been removed from base system. It + has been obsolete for a very long time. + 20141104: vt(4), the new console driver, is enabled by default. It brings support for Unicode and double-width characters, as well as diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 79799bf91654..1422390e978d 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -514,9 +514,6 @@ stf_interface_ipv4plen="0" # Prefix length for 6to4 IPv4 addr, stf_interface_ipv6_ifid="0:0:0:1" # IPv6 interface id for stf0. # If you like, you can set "AUTO" for this. stf_interface_ipv6_slaid="0000" # IPv6 Site Level Aggregator for stf0 -ipv6_faith_prefix="NO" # Set faith prefix to enable a FAITH - # IPv6-to-IPv4 TCP translator. You also need - # faithd(8) setup. ipv6_ipv4mapping="NO" # Set to "YES" to enable IPv4 mapped IPv6 addr # communication. (like ::ffff:a.b.c.d) ipv6_ipfilter_rules="/etc/ipf6.rules" # rules definition file for ipfilter, diff --git a/etc/network.subr b/etc/network.subr index 520c9e86a7e5..b8e06544ff90 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -372,7 +372,6 @@ dhcpif() case $1 in lo[0-9]*|\ stf[0-9]*|\ - faith[0-9]*|\ lp[0-9]*|\ sl[0-9]*) return 1 @@ -591,7 +590,6 @@ ipv6_autoconfif() case $_if in lo[0-9]*|\ stf[0-9]*|\ - faith[0-9]*|\ lp[0-9]*|\ sl[0-9]*) return 1 diff --git a/etc/rc.d/Makefile b/etc/rc.d/Makefile index bfa22bfcfd09..f26c190fe9dd 100644 --- a/etc/rc.d/Makefile +++ b/etc/rc.d/Makefile @@ -42,7 +42,6 @@ FILES= DAEMON \ dhclient \ dmesg \ dumpon \ - faith \ fsck \ ftpd \ gbde \ diff --git a/etc/rc.d/NETWORKING b/etc/rc.d/NETWORKING index c86150f85ff0..12dd3b0d71b5 100755 --- a/etc/rc.d/NETWORKING +++ b/etc/rc.d/NETWORKING @@ -4,7 +4,7 @@ # # PROVIDE: NETWORKING NETWORK -# REQUIRE: netif netoptions routing ppp ipfw stf faith +# REQUIRE: netif netoptions routing ppp ipfw stf # REQUIRE: defaultroute routed mrouted route6d mroute6d resolv bridge # REQUIRE: static_arp static_ndp local_unbound diff --git a/etc/rc.d/bridge b/etc/rc.d/bridge index 4c3b34021d8c..93e68a20ab07 100755 --- a/etc/rc.d/bridge +++ b/etc/rc.d/bridge @@ -26,7 +26,7 @@ # # PROVIDE: bridge -# REQUIRE: netif faith ppp stf +# REQUIRE: netif ppp stf # KEYWORD: nojail . /etc/rc.subr diff --git a/etc/rc.d/defaultroute b/etc/rc.d/defaultroute index ea54c83ac0cd..8e87775ffb98 100755 --- a/etc/rc.d/defaultroute +++ b/etc/rc.d/defaultroute @@ -6,7 +6,7 @@ # # PROVIDE: defaultroute -# REQUIRE: devd faith netif stf +# REQUIRE: devd netif stf # KEYWORD: nojail . /etc/rc.subr diff --git a/etc/rc.d/faith b/etc/rc.d/faith deleted file mode 100755 index 4790ebd0a572..000000000000 --- a/etc/rc.d/faith +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh -# $FreeBSD$ -# - -# PROVIDE: faith -# REQUIRE: netif -# KEYWORD: nojail - -. /etc/rc.subr -. /etc/network.subr - -name="faith" -start_cmd="faith_up" -stop_cmd="faith_down" - -faith_up() -{ - case ${ipv6_faith_prefix} in - [Nn][Oo] | '') - ;; - *) - echo "Configuring IPv6-to-IPv4 TCP relay capturing interface:" \ - " faith0." - ${SYSCTL} net.inet6.ip6.keepfaith=1 - ifconfig faith0 create >/dev/null 2>&1 - ifconfig faith0 up - for prefix in ${ipv6_faith_prefix}; do - prefixlen=`expr "${prefix}" : ".*/\(.*\)"` - case ${prefixlen} in - '') - prefixlen=96 - ;; - *) - prefix=`expr "${prefix}" : \ - "\(.*\)/${prefixlen}"` - ;; - esac - route add -inet6 ${prefix} -prefixlen ${prefixlen} ::1 - route change -inet6 ${prefix} -prefixlen ${prefixlen} \ - -ifp faith0 - done - check_startmsgs && ifconfig faith0 - ;; - esac -} - -faith_down() -{ - echo "Removing IPv6-to-IPv4 TCP relay capturing interface: faith0." - ifconfig faith0 destroy - ${SYSCTL} net.inet6.ip6.keepfaith=0 - - case ${ipv6_faith_prefix} in - [Nn][Oo] | '') - ;; - *) - for prefix in ${ipv6_faith_prefix}; do - prefixlen=`expr "${prefix}" : ".*/\(.*\)"` - case ${prefixlen} in - '') - prefixlen=96 - ;; - *) - prefix=`expr "${prefix}" : \ - "\(.*\)/${prefixlen}"` - ;; - esac - route delete -inet6 ${prefix} -prefixlen ${prefixlen} - done - ;; - esac -} - -load_rc_config $name -run_rc_command "$1" diff --git a/etc/rc.d/routing b/etc/rc.d/routing index 9cb07e576980..b38147153b0a 100755 --- a/etc/rc.d/routing +++ b/etc/rc.d/routing @@ -6,7 +6,7 @@ # # PROVIDE: routing -# REQUIRE: faith netif ppp stf +# REQUIRE: netif ppp stf # KEYWORD: nojailvnet . /etc/rc.subr @@ -245,7 +245,7 @@ static_inet6() [Nn][Oo][Nn][Ee]) return ;; - lo0|faith[0-9]*) + lo0) continue ;; esac diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c index b4c1a33ddff4..c50374e7287a 100644 --- a/lib/libc/net/getaddrinfo.c +++ b/lib/libc/net/getaddrinfo.c @@ -30,8 +30,6 @@ */ /* - * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator. - * * Issues to be discussed: * - Return values. There are nonstandard return values defined and used * in the source code. This is because RFC2553 is silent about which error @@ -101,10 +99,6 @@ __FBSDID("$FreeBSD$"); #include "nscache.h" #endif -#if defined(__KAME__) && defined(INET6) -# define FAITH -#endif - #define ANY 0 #define YES 1 #define NO 0 @@ -1316,47 +1310,6 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) { char *p; struct addrinfo *ai; -#ifdef FAITH - struct in6_addr faith_prefix; - char *fp_str; - int translate = 0; -#endif - -#ifdef FAITH - /* - * Transfrom an IPv4 addr into a special IPv6 addr format for - * IPv6->IPv4 translation gateway. (only TCP is supported now) - * - * +-----------------------------------+------------+ - * | faith prefix part (12 bytes) | embedded | - * | | IPv4 addr part (4 bytes) - * +-----------------------------------+------------+ - * - * faith prefix part is specified as ascii IPv6 addr format - * in environmental variable GAI. - * For FAITH to work correctly, routing to faith prefix must be - * setup toward a machine where a FAITH daemon operates. - * Also, the machine must enable some mechanizm - * (e.g. faith interface hack) to divert those packet with - * faith prefixed destination addr to user-land FAITH daemon. - */ - fp_str = getenv("GAI"); - if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 && - afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) { - u_int32_t v4a; - u_int8_t v4a_top; - - memcpy(&v4a, addr, sizeof v4a); - v4a_top = v4a >> IN_CLASSA_NSHIFT; - if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) && - v4a_top != 0 && v4a != IN_LOOPBACKNET) { - afd = &afdl[N_INET6]; - memcpy(&faith_prefix.s6_addr[12], addr, - sizeof(struct in_addr)); - translate = 1; - } - } -#endif ai = (struct addrinfo *)malloc(sizeof(struct addrinfo) + (afd->a_socklen)); @@ -1370,11 +1323,6 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr) ai->ai_addrlen = afd->a_socklen; ai->ai_addr->sa_family = ai->ai_family = afd->a_af; p = (char *)(void *)(ai->ai_addr); -#ifdef FAITH - if (translate == 1) - memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen); - else -#endif memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen); return ai; } diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index ffd34a137ec2..005b8773bfc1 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -414,7 +414,6 @@ getnameinfo_link(const struct sockaddr *sa, socklen_t salen, /* * The following have zero-length addresses. * IFT_ATM (net/if_atmsubr.c) - * IFT_FAITH (net/if_faith.c) * IFT_GIF (net/if_gif.c) * IFT_LOOP (net/if_loop.c) * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c) diff --git a/release/picobsd/bridge/PICOBSD b/release/picobsd/bridge/PICOBSD index 47f889632650..bc1185d61c64 100644 --- a/release/picobsd/bridge/PICOBSD +++ b/release/picobsd/bridge/PICOBSD @@ -109,7 +109,6 @@ device tun # Packet tunnel. device pty # Pseudo-ttys (telnet etc) device md # Memory "disks" #device gif 4 # IPv6 and IPv4 tunneling -#device faith 1 # IPv6-to-IPv4 relaying (translation) device tap #options DEVICE_POLLING diff --git a/release/picobsd/qemu/PICOBSD b/release/picobsd/qemu/PICOBSD index 2b4cdabec3c8..16b175385b0a 100644 --- a/release/picobsd/qemu/PICOBSD +++ b/release/picobsd/qemu/PICOBSD @@ -114,7 +114,6 @@ device tun # Packet tunnel. device pty # Pseudo-ttys (telnet etc) device md # Memory "disks" #device gif 4 # IPv6 and IPv4 tunneling -#device faith 1 # IPv6-to-IPv4 relaying (translation) device tap #options VIMAGE # soner or later we may want to test this diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 346f2972e735..76b3d55c2c61 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -132,7 +132,6 @@ MAN= aac.4 \ et.4 \ eventtimers.4 \ exca.4 \ - faith.4 \ fatm.4 \ fd.4 \ fdc.4 \ @@ -637,7 +636,6 @@ MLINKS+=en.4 if_en.4 MLINKS+=enc.4 if_enc.4 MLINKS+=epair.4 if_epair.4 MLINKS+=et.4 if_et.4 -MLINKS+=faith.4 if_faith.4 MLINKS+=fatm.4 if_fatm.4 MLINKS+=fd.4 stderr.4 \ fd.4 stdin.4 \ diff --git a/share/man/man4/faith.4 b/share/man/man4/faith.4 deleted file mode 100644 index f0a2df6f6c3c..000000000000 --- a/share/man/man4/faith.4 +++ /dev/null @@ -1,133 +0,0 @@ -.\" $KAME: faith.4,v 1.9 2001/04/27 17:26:35 itojun Exp $ -.\" -.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. -.\" 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. -.\" 3. Neither the name of the project nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. -.\" -.\" $FreeBSD$ -.\" -.Dd January 23, 2012 -.Dt FAITH 4 -.Os -.Sh NAME -.Nm faith -.Nd IPv6-to-IPv4 TCP relay capturing interface -.Sh SYNOPSIS -.Cd "device faith" -.Sh DESCRIPTION -The -.Nm -interface captures IPv6 TCP traffic, -for implementing userland IPv6-to-IPv4 TCP relay -like -.Xr faithd 8 . -.Pp -Each -.Nm -interface is created at runtime using interface cloning. -This is -most easily done with the -.Xr ifconfig 8 -.Cm create -command or using the -.Va cloned_interfaces -variable in -.Xr rc.conf 5 . -.Pp -Special action will be taken when IPv6 TCP traffic is seen on a router, -and the default routing table suggests to route it to the -.Nm -interface. -In this case, the packet will be accepted by the router, -regardless of the list of IPv6 interface addresses assigned to the router. -The packet will be captured by an IPv6 TCP socket, if it has the -.Dv IN6P_FAITH -flag turned on and matching address/port pairs. -As a result, -.Nm -will let you capture IPv6 TCP traffic to some specific destination addresses. -Userland programs, such as -.Xr faithd 8 -can use this behavior to relay IPv6 TCP traffic to IPv4 TCP traffic. -The program can accept some specific IPv6 TCP traffic, perform -.Xr getsockname 2 -to get the IPv6 destination address specified by the client, -and perform application-specific address mapping to relay IPv6 TCP to IPv4 TCP. -.Pp -The -.Dv IN6P_FAITH -flag on a IPv6 TCP socket can be set by using -.Xr setsockopt 2 , -with level -.Dv IPPROTO_IPV6 -and optname -.Dv IPv6_FAITH . -.Pp -To handle error reports by ICMPv6, some ICMPv6 packets routed to an -.Nm -interface will be delivered to IPv6 TCP, as well. -.Pp -To understand how -.Nm -can be used, take a look at the source code of -.Xr faithd 8 . -.Pp -As the -.Nm -interface implements potentially dangerous operations, -great care must be taken when configuring it. -To avoid possible misuse, the -.Xr sysctl 8 -variable -.Li net.inet6.ip6.keepfaith -must be set to -.Li 1 -prior to using the interface. -When -.Li net.inet6.ip6.keepfaith -is -.Li 0 , -no packets will be captured by the -.Nm -interface. -.Pp -The -.Nm -interface is intended to be used on routers, not on hosts. -.\" -.Sh SEE ALSO -.Xr inet 4 , -.Xr inet6 4 , -.Xr faithd 8 -.Rs -.%A Jun-ichiro itojun Hagino -.%A Kazu Yamamoto -.%T "An IPv6-to-IPv4 transport relay translator" -.%O RFC3142 -.Re -.Sh HISTORY -The FAITH IPv6-to-IPv4 TCP relay translator first appeared in the -WIDE hydrangea IPv6 stack. diff --git a/share/man/man4/inet6.4 b/share/man/man4/inet6.4 index 93015e0551be..0e505db691cd 100644 --- a/share/man/man4/inet6.4 +++ b/share/man/man4/inet6.4 @@ -241,17 +241,6 @@ Defaults to off. Boolean: the default value of a per-interface flag to enable/disable performing automatic link-local address configuration. Defaults to on. -.It Dv IPV6CTL_KEEPFAITH -.Pq ip6.keepfaith -Boolean: enable/disable -.Dq FAITH -TCP relay IPv6-to-IPv4 translator code in the kernel. -Refer -.Xr faith 4 -and -.Xr faithd 8 -for detail. -Defaults to off. .It Dv IPV6CTL_LOG_INTERVAL .Pq ip6.log_interval Integer: default interval between diff --git a/share/man/man4/ip6.4 b/share/man/man4/ip6.4 index fcd396c1e7d4..dba5e8de5396 100644 --- a/share/man/man4/ip6.4 +++ b/share/man/man4/ip6.4 @@ -393,10 +393,6 @@ For wildcard sockets, this can restrict connections to IPv6 only. .\".Ox .\"IPv6 sockets are always IPv6-only, so the socket option is read-only .\"(not modifiable). -.It Dv IPV6_FAITH Fa "int *" -Get or set the status of whether -.Xr faith 4 -connections can be made to this socket. .It Dv IPV6_USE_MIN_MTU Fa "int *" Get or set whether the minimal IPv6 maximum transmission unit (MTU) size will be used to avoid fragmentation from occurring for subsequent diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5 index 721fef01c1c2..09583ec10423 100644 --- a/share/man/man5/rc.conf.5 +++ b/share/man/man5/rc.conf.5 @@ -2948,15 +2948,6 @@ This can be set to .Pq Vt str IPv6 Site Level Aggregator for .Xr stf 4 . -.It Va ipv6_faith_prefix -.Pq Vt str -If not set to -.Dq Li NO , -this is the faith prefix to enable a FAITH IPv6-to-IPv4 TCP -translator. -You also need -.Xr faithd 8 -setup. .It Va ipv6_ipv4mapping .Pq Vt bool If set to diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index f8ccd4cba5bd..c8d509849b5f 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -310,7 +310,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/arm/conf/ATMEL b/sys/arm/conf/ATMEL index 6cc6fb4c8eff..615e06e4af59 100644 --- a/sys/arm/conf/ATMEL +++ b/sys/arm/conf/ATMEL @@ -143,7 +143,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module # SCSI peripherals diff --git a/sys/arm/conf/DOCKSTAR b/sys/arm/conf/DOCKSTAR index c95a5974961a..a3c57a121773 100644 --- a/sys/arm/conf/DOCKSTAR +++ b/sys/arm/conf/DOCKSTAR @@ -54,7 +54,6 @@ options FDT_DTB_STATIC # Misc pseudo devices device bpf # Required for DHCP -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware(9) required for USB wlan device gif # IPv6 and IPv4 tunneling device loop # Network loopback diff --git a/sys/arm/conf/DREAMPLUG-1001 b/sys/arm/conf/DREAMPLUG-1001 index 3bfdd913ef6d..736959299476 100644 --- a/sys/arm/conf/DREAMPLUG-1001 +++ b/sys/arm/conf/DREAMPLUG-1001 @@ -57,7 +57,6 @@ options FDT_DTB_STATIC # Misc pseudo devices device bpf # Required for DHCP -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware(9) required for USB wlan device gif # IPv6 and IPv4 tunneling device loop # Network loopback diff --git a/sys/arm/conf/EFIKA_MX b/sys/arm/conf/EFIKA_MX index df7a9efc7ba9..677d73d9edc2 100644 --- a/sys/arm/conf/EFIKA_MX +++ b/sys/arm/conf/EFIKA_MX @@ -104,7 +104,6 @@ device ether # Ethernet support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module # Serial (COM) ports diff --git a/sys/arm/conf/ETHERNUT5 b/sys/arm/conf/ETHERNUT5 index 9df7f9c55aaf..88f9949059e0 100644 --- a/sys/arm/conf/ETHERNUT5 +++ b/sys/arm/conf/ETHERNUT5 @@ -136,7 +136,6 @@ device ether # Ethernet support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module # SCSI peripherals diff --git a/sys/arm/conf/IMX53 b/sys/arm/conf/IMX53 index 1396578e3e58..5fd56979fbf6 100644 --- a/sys/arm/conf/IMX53 +++ b/sys/arm/conf/IMX53 @@ -92,7 +92,6 @@ device ether # Ethernet support #device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module # Ethernet diff --git a/sys/arm/conf/IMX6 b/sys/arm/conf/IMX6 index 88a6462b617b..007862bc6d1f 100644 --- a/sys/arm/conf/IMX6 +++ b/sys/arm/conf/IMX6 @@ -75,7 +75,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module device ether # Ethernet support device miibus # Required for ethernet diff --git a/sys/arm/conf/SAM9260EK b/sys/arm/conf/SAM9260EK index 34b64afd234b..c3cba33f8b7d 100644 --- a/sys/arm/conf/SAM9260EK +++ b/sys/arm/conf/SAM9260EK @@ -146,7 +146,6 @@ device ether # Ethernet support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) #device firmware # firmware assist module # SCSI peripherals diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index 241b14aaf973..bd7d296e9840 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -254,7 +254,6 @@ if_disc_load="NO" # Discard device if_ef_load="NO" # pseudo-device providing support for multiple # ethernet frame types if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair -if_faith_load="NO" # IPv6-to-IPv4 TCP relay capturing interface if_gif_load="NO" # generic tunnel interface if_gre_load="NO" # encapsulating network device if_stf_load="NO" # 6to4 tunnel interface diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 45b38d9a69fa..1436a3bc1665 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -890,10 +890,7 @@ device gre device me options XBONEHACK -# The `faith' device captures packets sent to it and diverts them -# to the IPv4/IPv6 translation daemon. # The `stf' device implements 6to4 encapsulation. -device faith device stf # The pf packet filter consists of three devices: diff --git a/sys/conf/files b/sys/conf/files index 351155d59b27..f7a4310b8683 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -3229,7 +3229,6 @@ net/if_edsc.c optional edsc net/if_enc.c optional enc ipsec inet | enc ipsec inet6 net/if_epair.c optional epair net/if_ethersubr.c optional ether -net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_fwsubr.c optional fwip net/if_gif.c optional gif inet | gif inet6 | \ diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index b01af819398e..889a20a7fe30 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -318,7 +318,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/i386/conf/XBOX b/sys/i386/conf/XBOX index fb6a5c1570f0..73f81e44cc60 100644 --- a/sys/i386/conf/XBOX +++ b/sys/i386/conf/XBOX @@ -66,7 +66,6 @@ device ether # Ethernet support #device tun # Packet tunnel. #device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling -#device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/sys/i386/conf/XEN b/sys/i386/conf/XEN index 62bbbb6ba3f5..108224cd5570 100644 --- a/sys/i386/conf/XEN +++ b/sys/i386/conf/XEN @@ -82,7 +82,6 @@ device ether # Ethernet support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # Wireless cards options IEEE80211_SUPPORT_MESH diff --git a/sys/mips/conf/GXEMUL b/sys/mips/conf/GXEMUL index ea5862287ccc..fa0b9b51899e 100644 --- a/sys/mips/conf/GXEMUL +++ b/sys/mips/conf/GXEMUL @@ -55,7 +55,6 @@ device ether # Ethernet support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/sys/mips/conf/GXEMUL32 b/sys/mips/conf/GXEMUL32 index 6bd756f20f7d..27854c5fa2a8 100644 --- a/sys/mips/conf/GXEMUL32 +++ b/sys/mips/conf/GXEMUL32 @@ -53,7 +53,6 @@ device ether # Ethernet support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/sys/mips/conf/OCTEON1 b/sys/mips/conf/OCTEON1 index fb417cfccc0c..9f22030c1709 100644 --- a/sys/mips/conf/OCTEON1 +++ b/sys/mips/conf/OCTEON1 @@ -261,7 +261,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/mips/rmi/rootfs_list.txt b/sys/mips/rmi/rootfs_list.txt index 048321a30ad9..86895b6a2f5c 100644 --- a/sys/mips/rmi/rootfs_list.txt +++ b/sys/mips/rmi/rootfs_list.txt @@ -197,7 +197,6 @@ ./etc/rc.d/dmesg ./etc/rc.d/dumpon ./etc/rc.d/encswap -./etc/rc.d/faith ./etc/rc.d/fsck ./etc/rc.d/ftp-proxy ./etc/rc.d/ftpd diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 0ca6f63df72c..fedc92e362c4 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -145,7 +145,6 @@ SUBDIR= \ if_disc \ if_edsc \ if_epair \ - if_faith \ ${_if_gif} \ ${_if_gre} \ ${_if_me} \ diff --git a/sys/modules/if_faith/Makefile b/sys/modules/if_faith/Makefile deleted file mode 100644 index fe78ec9be48c..000000000000 --- a/sys/modules/if_faith/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../net - -KMOD= if_faith -SRCS= if_faith.c opt_inet.h opt_inet6.h - -.include diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c deleted file mode 100644 index a8a103de489c..000000000000 --- a/sys/net/if_faith.c +++ /dev/null @@ -1,331 +0,0 @@ -/* $KAME: if_faith.c,v 1.23 2001/12/17 13:55:29 sumikawa Exp $ */ - -/*- - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. 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. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - * - * $FreeBSD$ - */ -/* - * derived from - * @(#)if_loop.c 8.1 (Berkeley) 6/10/93 - * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp - */ - -/* - * Loopback interface driver for protocol testing and timing. - */ -#include "opt_inet.h" -#include "opt_inet6.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef INET -#include -#include -#include -#include -#endif - -#ifdef INET6 -#ifndef INET -#include -#endif -#include -#include -#include -#endif - -struct faith_softc { - struct ifnet *sc_ifp; -}; - -static int faithioctl(struct ifnet *, u_long, caddr_t); -static int faithoutput(struct ifnet *, struct mbuf *, const struct sockaddr *, - struct route *); -#ifdef INET6 -static int faithprefix(struct in6_addr *); -#endif - -static int faithmodevent(module_t, int, void *); - -static const char faithname[] = "faith"; -static MALLOC_DEFINE(M_FAITH, faithname, "Firewall Assisted Tunnel Interface"); - -static int faith_clone_create(struct if_clone *, int, caddr_t); -static void faith_clone_destroy(struct ifnet *); -static struct if_clone *faith_cloner; - -#define FAITHMTU 1500 - -static int -faithmodevent(mod, type, data) - module_t mod; - int type; - void *data; -{ - - switch (type) { - case MOD_LOAD: - faith_cloner = if_clone_simple(faithname, faith_clone_create, - faith_clone_destroy, 0); -#ifdef INET6 - faithprefix_p = faithprefix; -#endif - - break; - case MOD_UNLOAD: -#ifdef INET6 - faithprefix_p = NULL; -#endif - - if_clone_detach(faith_cloner); - break; - default: - return EOPNOTSUPP; - } - return 0; -} - -static moduledata_t faith_mod = { - "if_faith", - faithmodevent, - 0 -}; - -DECLARE_MODULE(if_faith, faith_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); -MODULE_VERSION(if_faith, 1); - -static int -faith_clone_create(ifc, unit, params) - struct if_clone *ifc; - int unit; - caddr_t params; -{ - struct ifnet *ifp; - struct faith_softc *sc; - - sc = malloc(sizeof(struct faith_softc), M_FAITH, M_WAITOK | M_ZERO); - ifp = sc->sc_ifp = if_alloc(IFT_FAITH); - if (ifp == NULL) { - free(sc, M_FAITH); - return (ENOSPC); - } - - ifp->if_softc = sc; - if_initname(sc->sc_ifp, faithname, unit); - - ifp->if_mtu = FAITHMTU; - /* Change to BROADCAST experimentaly to announce its prefix. */ - ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST; - ifp->if_ioctl = faithioctl; - ifp->if_output = faithoutput; - ifp->if_hdrlen = 0; - ifp->if_addrlen = 0; - ifp->if_snd.ifq_maxlen = ifqmaxlen; - if_attach(ifp); - bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); - return (0); -} - -static void -faith_clone_destroy(ifp) - struct ifnet *ifp; -{ - struct faith_softc *sc = ifp->if_softc; - - bpfdetach(ifp); - if_detach(ifp); - if_free(ifp); - free(sc, M_FAITH); -} - -static int -faithoutput(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, - struct route *ro) -{ - int isr; - u_int32_t af; - struct rtentry *rt = NULL; - - M_ASSERTPKTHDR(m); - - if (ro != NULL) - rt = ro->ro_rt; - /* BPF writes need to be handled specially. */ - if (dst->sa_family == AF_UNSPEC) - bcopy(dst->sa_data, &af, sizeof(af)); - else - af = dst->sa_family; - - if (bpf_peers_present(ifp->if_bpf)) - bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); - - if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { - m_freem(m); - return (rt->rt_flags & RTF_BLACKHOLE ? 0 : - rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); - } - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - if_inc_counter(ifp, IFCOUNTER_OBYTES, m->m_pkthdr.len); - switch (af) { -#ifdef INET - case AF_INET: - isr = NETISR_IP; - break; -#endif -#ifdef INET6 - case AF_INET6: - isr = NETISR_IPV6; - break; -#endif - default: - m_freem(m); - return EAFNOSUPPORT; - } - - /* XXX do we need more sanity checks? */ - - m->m_pkthdr.rcvif = ifp; - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); - netisr_dispatch(isr, m); - return (0); -} - -/* - * Process an ioctl request. - */ -/* ARGSUSED */ -static int -faithioctl(ifp, cmd, data) - struct ifnet *ifp; - u_long cmd; - caddr_t data; -{ - struct ifreq *ifr = (struct ifreq *)data; - int error = 0; - - switch (cmd) { - - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - ifp->if_drv_flags |= IFF_DRV_RUNNING; - - /* - * Everything else is done at a higher level. - */ - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - if (ifr == 0) { - error = EAFNOSUPPORT; /* XXX */ - break; - } - switch (ifr->ifr_addr.sa_family) { -#ifdef INET - case AF_INET: - break; -#endif -#ifdef INET6 - case AF_INET6: - break; -#endif - - default: - error = EAFNOSUPPORT; - break; - } - break; - -#ifdef SIOCSIFMTU - case SIOCSIFMTU: - ifp->if_mtu = ifr->ifr_mtu; - break; -#endif - - case SIOCSIFFLAGS: - break; - - default: - error = EINVAL; - } - return (error); -} - -#ifdef INET6 -/* - * XXX could be slow - * XXX could be layer violation to call sys/net from sys/netinet6 - */ -static int -faithprefix(in6) - struct in6_addr *in6; -{ - struct rtentry *rt; - struct sockaddr_in6 sin6; - int ret; - - if (V_ip6_keepfaith == 0) - return 0; - - bzero(&sin6, sizeof(sin6)); - sin6.sin6_family = AF_INET6; - sin6.sin6_len = sizeof(struct sockaddr_in6); - sin6.sin6_addr = *in6; - rt = in6_rtalloc1((struct sockaddr *)&sin6, 0, 0UL, RT_DEFAULT_FIB); - if (rt && rt->rt_ifp && rt->rt_ifp->if_type == IFT_FAITH && - (rt->rt_ifp->if_flags & IFF_UP) != 0) - ret = 1; - else - ret = 0; - if (rt) - RTFREE_LOCKED(rt); - return ret; -} -#endif diff --git a/sys/net/if_types.h b/sys/net/if_types.h index 80a5606ba8a1..c9b20db719ee 100644 --- a/sys/net/if_types.h +++ b/sys/net/if_types.h @@ -246,7 +246,6 @@ /* not based on IANA assignments */ #define IFT_GIF 0xf0 #define IFT_PVC 0xf1 -#define IFT_FAITH 0xf2 #define IFT_ENC 0xf4 #define IFT_PFLOG 0xf6 #define IFT_PFSYNC 0xf7 diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 4776278e1b17..f2dbce29c692 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -428,8 +428,7 @@ __END_DECLS #define IP_RECVIF 20 /* bool; receive reception if w/dgram */ /* for IPSEC */ #define IP_IPSEC_POLICY 21 /* int; set/get security policy */ -#define IP_FAITH 22 /* bool; accept FAITH'ed connections */ - + /* unused; was IP_FAITH */ #define IP_ONESBCAST 23 /* bool: send all-ones broadcast */ #define IP_BINDANY 24 /* bool: allow bind to any address */ #define IP_BINDMULTI 25 /* bool: allow multiple listeners on a tuple */ @@ -630,7 +629,7 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t, #define IPCTL_STATS 12 /* ipstat structure */ #define IPCTL_ACCEPTSOURCEROUTE 13 /* may accept source routed packets */ #define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */ -#define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */ + /* 15, unused, was: IPCTL_KEEPFAITH */ #define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */ #endif /* __BSD_VISIBLE */ diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index c7f0511133da..6bec7efc256c 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -1645,11 +1645,6 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, inp->inp_lport != lport) continue; - /* XXX inp locking */ - if (ifp && ifp->if_type == IFT_FAITH && - (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP4); if (injail) { if (prison_check_ip4(inp->inp_cred, @@ -1724,11 +1719,6 @@ in_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, inp->inp_lport != lport) continue; - /* XXX inp locking */ - if (ifp && ifp->if_type == IFT_FAITH && - (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP4); if (injail) { if (prison_check_ip4(inp->inp_cred, @@ -1869,11 +1859,6 @@ in_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in_addr faddr, inp->inp_lport != lport) continue; - /* XXX inp locking */ - if (ifp && ifp->if_type == IFT_FAITH && - (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP4); if (injail) { if (prison_check_ip4(inp->inp_cred, @@ -2468,10 +2453,6 @@ db_print_inpflags(int inp_flags) db_printf("%sINP_MTUDISC", comma ? ", " : ""); comma = 1; } - if (inp_flags & INP_FAITH) { - db_printf("%sINP_FAITH", comma ? ", " : ""); - comma = 1; - } if (inp_flags & INP_RECVTTL) { db_printf("%sINP_RECVTTL", comma ? ", " : ""); comma = 1; diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 185bcfb2d06e..04ed0b0bdf83 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -511,7 +511,7 @@ short inp_so_options(const struct inpcb *inp); #define INP_ANONPORT 0x00000040 /* port chosen for user */ #define INP_RECVIF 0x00000080 /* receive incoming interface */ #define INP_MTUDISC 0x00000100 /* user can do MTU discovery */ -#define INP_FAITH 0x00000200 /* accept FAITH'ed connections */ + /* 0x000200 unused: was INP_FAITH */ #define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */ #define INP_DONTFRAG 0x00000800 /* don't fragment packet */ #define INP_BINDANY 0x00001000 /* allow bind to any address */ diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index 916124a7efb2..23f7a567c74e 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -410,19 +410,6 @@ icmp_input(struct mbuf **mp, int *offp, int proto) m->m_len += hlen; m->m_data -= hlen; - if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_type == IFT_FAITH) { - /* - * Deliver very specific ICMP type only. - */ - switch (icp->icmp_type) { - case ICMP_UNREACH: - case ICMP_TIMXCEED: - break; - default: - goto freeit; - } - } - #ifdef ICMPPRINTFS if (icmpprintfs) printf("icmp_input, type %d code %d\n", icp->icmp_type, diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index ac7568248f9f..1ad020a21146 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -104,12 +104,6 @@ SYSCTL_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_VNET | CTLFLAG_R &VNET_NAME(ipsendredirects), 0, "Enable sending IP redirects"); -static VNET_DEFINE(int, ip_keepfaith); -#define V_ip_keepfaith VNET(ip_keepfaith) -SYSCTL_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_VNET | CTLFLAG_RW, - &VNET_NAME(ip_keepfaith), 0, - "Enable packet capture for FAITH IPv4->IPv6 translater daemon"); - static VNET_DEFINE(int, ip_sendsourcequench); #define V_ip_sendsourcequench VNET(ip_sendsourcequench) SYSCTL_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_VNET | CTLFLAG_RW, @@ -752,18 +746,6 @@ passin: if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; - /* - * FAITH(Firewall Aided Internet Translator) - */ - if (ifp && ifp->if_type == IFT_FAITH) { - if (V_ip_keepfaith) { - if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_ICMP) - goto ours; - } - m_freem(m); - return; - } - /* * Not for us; forward if possible and desirable. */ diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 25e7cceaf985..5e4a5074e3f6 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -991,7 +991,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_RECVDSTADDR: case IP_RECVTTL: case IP_RECVIF: - case IP_FAITH: case IP_ONESBCAST: case IP_DONTFRAG: case IP_RECVTOS: @@ -1058,10 +1057,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) OPTSET(INP_RECVIF); break; - case IP_FAITH: - OPTSET(INP_FAITH); - break; - case IP_ONESBCAST: OPTSET(INP_ONESBCAST); break; @@ -1200,7 +1195,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) case IP_RECVTTL: case IP_RECVIF: case IP_PORTRANGE: - case IP_FAITH: case IP_ONESBCAST: case IP_DONTFRAG: case IP_BINDANY: @@ -1259,10 +1253,6 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt) optval = 0; break; - case IP_FAITH: - optval = OPTBIT(INP_FAITH); - break; - case IP_ONESBCAST: optval = OPTBIT(INP_ONESBCAST); break; diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 8169e56bc38d..891e8eb97ade 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -482,22 +482,6 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) goto freeit; } - if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { - /* - * Deliver very specific ICMP6 type only. - * This is important to deliver TOOBIG. Otherwise PMTUD - * will not work. - */ - switch (icmp6->icmp6_type) { - case ICMP6_DST_UNREACH: - case ICMP6_PACKET_TOO_BIG: - case ICMP6_TIME_EXCEEDED: - break; - default: - goto freeit; - } - } - ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]); icmp6_ifstat_inc(ifp, ifs6_in_msg); if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 89ec855243ac..4ea398a8866d 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -137,8 +137,6 @@ static int in6_notify_ifa(struct ifnet *, struct in6_ifaddr *, struct in6_aliasreq *, int); static void in6_unlink_ifa(struct in6_ifaddr *, struct ifnet *); -int (*faithprefix_p)(struct in6_addr *); - static int in6_validate_ifra(struct ifnet *, struct in6_aliasreq *, struct in6_ifaddr *, int); static struct in6_ifaddr *in6_alloc_ifa(struct ifnet *, @@ -1948,34 +1946,20 @@ in6if_do_dad(struct ifnet *ifp) if (ND_IFINFO(ifp)->flags & ND6_IFF_IFDISABLED) return (0); - switch (ifp->if_type) { -#ifdef IFT_DUMMY - case IFT_DUMMY: -#endif - case IFT_FAITH: - /* - * These interfaces do not have the IFF_LOOPBACK flag, - * but loop packets back. We do not have to do DAD on such - * interfaces. We should even omit it, because loop-backed - * NS would confuse the DAD procedure. - */ + /* + * Our DAD routine requires the interface up and running. + * However, some interfaces can be up before the RUNNING + * status. Additionaly, users may try to assign addresses + * before the interface becomes up (or running). + * We simply skip DAD in such a case as a work around. + * XXX: we should rather mark "tentative" on such addresses, + * and do DAD after the interface becomes ready. + */ + if (!((ifp->if_flags & IFF_UP) && + (ifp->if_drv_flags & IFF_DRV_RUNNING))) return (0); - default: - /* - * Our DAD routine requires the interface up and running. - * However, some interfaces can be up before the RUNNING - * status. Additionaly, users may try to assign addresses - * before the interface becomes up (or running). - * We simply skip DAD in such a case as a work around. - * XXX: we should rather mark "tentative" on such addresses, - * and do DAD after the interface becomes ready. - */ - if (!((ifp->if_flags & IFF_UP) && - (ifp->if_drv_flags & IFF_DRV_RUNNING))) - return (0); - return (1); - } + return (1); } /* diff --git a/sys/netinet6/in6.h b/sys/netinet6/in6.h index 5fbcf5f23d9f..7187aec7b7d2 100644 --- a/sys/netinet6/in6.h +++ b/sys/netinet6/in6.h @@ -424,8 +424,7 @@ struct route_in6 { #define IPV6_IPSEC_POLICY 28 /* struct; get/set security policy */ #endif /* IPSEC */ -#define IPV6_FAITH 29 /* bool; accept FAITH'ed connections */ - + /* 29; unused; was IPV6_FAITH */ #if 1 /* IPV6FIREWALL */ #define IPV6_FW_ADD 30 /* add a firewall rule to chain */ #define IPV6_FW_DEL 31 /* delete a firewall rule from chain */ @@ -580,7 +579,7 @@ struct ip6_mtuinfo { #define IPV6CTL_SOURCECHECK 10 /* verify source route and intf */ #define IPV6CTL_SOURCECHECK_LOGINT 11 /* minimume logging interval */ #define IPV6CTL_ACCEPT_RTADV 12 -#define IPV6CTL_KEEPFAITH 13 + /* 13; unused; was: IPV6CTL_KEEPFAITH */ #define IPV6CTL_LOG_INTERVAL 14 #define IPV6CTL_HDRNESTLIMIT 15 #define IPV6CTL_DAD_COUNT 16 @@ -669,7 +668,6 @@ extern void addrsel_policy_init(void); #define sin6tosa(sin6) ((struct sockaddr *)(sin6)) #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa)) -extern int (*faithprefix_p)(struct in6_addr *); #endif /* _KERNEL */ #ifndef _SIZE_T_DECLARED diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index 2be2e8366af2..2a7b9dcf40f5 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -870,12 +870,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, struct inpcbhead *head; struct inpcb *inp, *tmpinp; u_short fport = fport_arg, lport = lport_arg; - int faith; - - if (faithprefix_p != NULL) - faith = (*faithprefix_p)(laddr); - else - faith = 0; /* * First look for an exact match. @@ -935,10 +929,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, continue; } - /* XXX inp locking */ - if (faith && (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP6); if (injail) { if (prison_check_ip6(inp->inp_cred, @@ -1001,10 +991,6 @@ in6_pcblookup_group(struct inpcbinfo *pcbinfo, struct inpcbgroup *pcbgroup, continue; } - /* XXX inp locking */ - if (faith && (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP6); if (injail) { if (prison_check_ip6(inp->inp_cred, @@ -1069,18 +1055,12 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, struct inpcbhead *head; struct inpcb *inp, *tmpinp; u_short fport = fport_arg, lport = lport_arg; - int faith; KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0, ("%s: invalid lookup flags %d", __func__, lookupflags)); INP_HASH_LOCK_ASSERT(pcbinfo); - if (faithprefix_p != NULL) - faith = (*faithprefix_p)(laddr); - else - faith = 0; - /* * First look for an exact match. */ @@ -1137,10 +1117,6 @@ in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo, struct in6_addr *faddr, continue; } - /* XXX inp locking */ - if (faith && (inp->inp_flags & INP_FAITH) == 0) - continue; - injail = prison_flag(inp->inp_cred, PR_IP6); if (injail) { if (prison_check_ip6(inp->inp_cred, diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 3798636696e3..4d328d282ec3 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -434,7 +434,6 @@ VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */ VNET_DEFINE(int, ip6_v6only) = 1; -VNET_DEFINE(int, ip6_keepfaith) = 0; VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L; #ifdef IPSTEALTH VNET_DEFINE(int, ip6stealth) = 0; @@ -543,8 +542,6 @@ SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RFC6204W3, rfc6204w3, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_rfc6204w3), 0, "Accept the default router list from ICMPv6 RA messages even " "when packet forwarding enabled."); -SYSCTL_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH, keepfaith, - CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_keepfaith), 0, ""); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL, log_interval, CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(ip6_log_interval), 0, ""); SYSCTL_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT, hdrnestlimit, diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index f574fb22c864..1763041595fd 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1408,7 +1408,6 @@ ip6_ctloutput(struct socket *so, struct sockopt *sopt) /* FALLTHROUGH */ case IPV6_UNICAST_HOPS: case IPV6_HOPLIMIT: - case IPV6_FAITH: case IPV6_RECVPKTINFO: case IPV6_RECVHOPLIMIT: @@ -1552,10 +1551,6 @@ do { \ OPTSET(IN6P_RTHDR); break; - case IPV6_FAITH: - OPTSET(INP_FAITH); - break; - case IPV6_RECVPATHMTU: /* * We ignore this option for TCP @@ -1823,7 +1818,6 @@ do { \ case IPV6_RECVRTHDR: case IPV6_RECVPATHMTU: - case IPV6_FAITH: case IPV6_V6ONLY: case IPV6_PORTRANGE: case IPV6_RECVTCLASS: @@ -1868,10 +1862,6 @@ do { \ optval = OPTBIT(IN6P_MTU); break; - case IPV6_FAITH: - optval = OPTBIT(INP_FAITH); - break; - case IPV6_V6ONLY: optval = OPTBIT(IN6P_IPV6_V6ONLY); break; diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 0889d987c6e2..155a607a7404 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -296,7 +296,6 @@ VNET_DECLARE(int, ip6_norbit_raif); /* Disable R-bit in NA on RA * receiving IF. */ VNET_DECLARE(int, ip6_rfc6204w3); /* Accept defroute from RA even when forwarding enabled */ -VNET_DECLARE(int, ip6_keepfaith); /* Firewall Aided Internet Translator */ VNET_DECLARE(int, ip6_log_interval); VNET_DECLARE(time_t, ip6_log_time); VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension @@ -310,7 +309,6 @@ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */ #define V_ip6_no_radr VNET(ip6_no_radr) #define V_ip6_norbit_raif VNET(ip6_norbit_raif) #define V_ip6_rfc6204w3 VNET(ip6_rfc6204w3) -#define V_ip6_keepfaith VNET(ip6_keepfaith) #define V_ip6_log_interval VNET(ip6_log_interval) #define V_ip6_log_time VNET(ip6_log_time) #define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit) diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 34e38e496b78..685d7f527cef 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -169,12 +169,6 @@ rip6_input(struct mbuf **mp, int *offp, int proto) RIP6STAT_INC(rip6s_ipackets); - if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { - /* XXX Send icmp6 host/port unreach? */ - m_freem(m); - return (IPPROTO_DONE); - } - init_sin6(&fromsa, m); /* general init */ ifp = m->m_pkthdr.rcvif; diff --git a/sys/netinet6/sctp6_usrreq.c b/sys/netinet6/sctp6_usrreq.c index a2393ec51202..037127eef689 100644 --- a/sys/netinet6/sctp6_usrreq.c +++ b/sys/netinet6/sctp6_usrreq.c @@ -149,10 +149,6 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port) if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) { goto out; } - if (faithprefix_p != NULL && (*faithprefix_p) (&dst.sin6_addr)) { - /* XXX send icmp6 host/port unreach? */ - goto out; - } length = ntohs(ip6->ip6_plen) + iphlen; /* Validate mbuf chain length with IP payload length. */ if (SCTP_HEADER_LEN(m) != length) { diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c index de79816f0eb9..6c6f27a6e5d3 100644 --- a/sys/netinet6/udp6_usrreq.c +++ b/sys/netinet6/udp6_usrreq.c @@ -208,12 +208,6 @@ udp6_input(struct mbuf **mp, int *offp, int proto) ifp = m->m_pkthdr.rcvif; ip6 = mtod(m, struct ip6_hdr *); - if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { - /* XXX send icmp6 host/port unreach? */ - m_freem(m); - return (IPPROTO_DONE); - } - #ifndef PULLDOWN_TEST IP6_EXTHDR_CHECK(m, off, sizeof(struct udphdr), IPPROTO_DONE); ip6 = mtod(m, struct ip6_hdr *); diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC index ea89d3258749..299606aa827a 100644 --- a/sys/pc98/conf/GENERIC +++ b/sys/pc98/conf/GENERIC @@ -231,7 +231,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC index dfd5a61945dd..d1ee43c9cf73 100644 --- a/sys/powerpc/conf/GENERIC +++ b/sys/powerpc/conf/GENERIC @@ -154,7 +154,6 @@ device tun # Packet tunnel. device md # Memory "disks" device ofwd # Open Firmware disks device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying/(translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/powerpc/conf/GENERIC64 b/sys/powerpc/conf/GENERIC64 index 3ce6e3cdbd5e..3e4d72f6581b 100644 --- a/sys/powerpc/conf/GENERIC64 +++ b/sys/powerpc/conf/GENERIC64 @@ -157,7 +157,6 @@ device tun # Packet tunnel. device md # Memory "disks" device ofwd # Open Firmware disks device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying/(translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/sys/powerpc/conf/WII b/sys/powerpc/conf/WII index e4d61b253521..8e21f2a0d50b 100644 --- a/sys/powerpc/conf/WII +++ b/sys/powerpc/conf/WII @@ -77,7 +77,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying/(translation) device firmware # firmware assist module diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC index 306f1dad24bb..0f9aa1bc1eed 100644 --- a/sys/sparc64/conf/GENERIC +++ b/sys/sparc64/conf/GENERIC @@ -225,7 +225,6 @@ device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) device firmware # firmware assist module # The `bpf' device enables the Berkeley Packet Filter. diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index d0b76ad77cb1..d77cef267907 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -1954,7 +1954,6 @@ OLD_FILES+=usr/share/man/man3/iconvlist.3.gz .if ${MK_INET6} == no OLD_FILES+=sbin/ping6 OLD_FILES+=sbin/rtsol -OLD_FILES+=usr/sbin/faithd OLD_FILES+=usr/sbin/ip6addrctl OLD_FILES+=usr/sbin/mld6query OLD_FILES+=usr/sbin/ndp diff --git a/tools/tools/nanobsd/pcengines/ALIX_DSK b/tools/tools/nanobsd/pcengines/ALIX_DSK index 32b0b8ca1369..1d750e5e2bd6 100644 --- a/tools/tools/nanobsd/pcengines/ALIX_DSK +++ b/tools/tools/nanobsd/pcengines/ALIX_DSK @@ -71,7 +71,6 @@ device tun device pty device md device gif -device faith device firmware device bpf device uhci diff --git a/tools/tools/nanobsd/pcengines/ALIX_NFS b/tools/tools/nanobsd/pcengines/ALIX_NFS index fe911da613f6..3c0f0da6237e 100644 --- a/tools/tools/nanobsd/pcengines/ALIX_NFS +++ b/tools/tools/nanobsd/pcengines/ALIX_NFS @@ -69,7 +69,6 @@ device tun device pty device md device gif -device faith device firmware device bpf device uhci diff --git a/tools/tools/sysdoc/tunables.mdoc b/tools/tools/sysdoc/tunables.mdoc index 1c5569bee9a2..6d88856cfd00 100644 --- a/tools/tools/sysdoc/tunables.mdoc +++ b/tools/tools/sysdoc/tunables.mdoc @@ -1311,14 +1311,6 @@ net.inet.ip.intr_queue_drops --- net.inet.ip.intr_queue_maxlen ---- -net.inet.ip.keepfaith -bool - -This is used in conjunction with -.Xr faithd 8 -to control the FAITH IPv6/v4 translator daemon. - --- net.inet.ip.maxfragpackets diff --git a/tools/tools/tinybsd/conf/default/TINYBSD b/tools/tools/tinybsd/conf/default/TINYBSD index ae7c9f6390bf..aba05c5bcfc5 100644 --- a/tools/tools/tinybsd/conf/default/TINYBSD +++ b/tools/tools/tinybsd/conf/default/TINYBSD @@ -148,7 +148,6 @@ device tun # Packet tunnel. device pty # Pseudo-ttys (telnet etc) device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/tools/tools/tinybsd/conf/vpn/TINYBSD b/tools/tools/tinybsd/conf/vpn/TINYBSD index f7159ad8a9b7..7e6da0edf1e0 100644 --- a/tools/tools/tinybsd/conf/vpn/TINYBSD +++ b/tools/tools/tinybsd/conf/vpn/TINYBSD @@ -138,7 +138,6 @@ device tun # Packet tunnel. device pty # Pseudo-ttys (telnet etc) device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/tools/tools/tinybsd/conf/wrap/TINYBSD b/tools/tools/tinybsd/conf/wrap/TINYBSD index aff67ea95efa..d04b0659c4e5 100644 --- a/tools/tools/tinybsd/conf/wrap/TINYBSD +++ b/tools/tools/tinybsd/conf/wrap/TINYBSD @@ -110,7 +110,6 @@ device tun # Packet tunnel. device pty # Pseudo-ttys (telnet etc) device md # Memory "disks" device gif # IPv6 and IPv4 tunneling -device faith # IPv6-to-IPv4 relaying (translation) # The `bpf' device enables the Berkeley Packet Filter. # Be aware of the administrative consequences of enabling this! diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index b0cff950bf2b..df9f8674793d 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -160,7 +160,6 @@ SUBDIR+= gpioctl .endif .if ${MK_INET6} != "no" -SUBDIR+= faithd SUBDIR+= ip6addrctl SUBDIR+= mld6query SUBDIR+= ndp diff --git a/usr.sbin/bsdconfig/networking/share/device.subr b/usr.sbin/bsdconfig/networking/share/device.subr index 42010ab10bf0..bb41be300a0c 100644 --- a/usr.sbin/bsdconfig/networking/share/device.subr +++ b/usr.sbin/bsdconfig/networking/share/device.subr @@ -82,7 +82,7 @@ f_dialog_menu_netdev() f_struct "$dev" get name if || continue # Skip unsavory interfaces case "$if" in - lo[0-9]*|ppp[0-9]*|sl[0-9]*|faith[0-9]*) continue ;; + lo[0-9]*|ppp[0-9]*|sl[0-9]*) continue ;; esac iflist="$iflist $if" done diff --git a/usr.sbin/faithd/Makefile b/usr.sbin/faithd/Makefile deleted file mode 100644 index dec45b9645b0..000000000000 --- a/usr.sbin/faithd/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 1996 WIDE Project. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modifications, are permitted provided that the above copyright notice -# and this paragraph are duplicated in all such forms and that any -# documentation, advertising materials, and other materials related to -# such distribution and use acknowledge that the software was developed -# by the WIDE Project, Japan. The name of the Project may not be used to -# endorse or promote products derived from this software without -# specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' -# AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT -# LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE. -# -# $FreeBSD$ - -PROG= faithd -MAN= faithd.8 -SRCS= faithd.c tcp.c ftp.c prefix.c - -CFLAGS+= -DHAVE_POLL_H - -WARNS?= 2 - -.include diff --git a/usr.sbin/faithd/README b/usr.sbin/faithd/README deleted file mode 100644 index 6628bf63dcbc..000000000000 --- a/usr.sbin/faithd/README +++ /dev/null @@ -1,148 +0,0 @@ -Configuring FAITH IPv6-to-IPv4 TCP relay - -Kazu Yamamoto and Jun-ichiro itojun Hagino -$KAME: README,v 1.10 2003/01/06 21:40:33 sumikawa Exp $ -$FreeBSD$ - - -Introduction -============ - -FAITH is an IPv6-to-IPv4 TCP relay. It performs tcp relay just as some of -firewall-oriented gateway does, but between IPv6 and IPv4 with address -translation. -TCP connections has to be made from IPv6 node to IPv4 node. FAITH will -not relay connections for the opposite direction. -To perform relays, FAITH daemon needs to be executed on a router between -your local IPv6 site and outside IPv4 network. The daemon needs to be -invoked per each TCP services (TCP port number). - - IPv4 node "dest" = 123.4.5.6 - | - [[[[ outside IPv4 ocean ]]]] - | - node that runs FAITH-daemon (usually a router) - | - ==+=====+===+==== IPv6, or IPv4/v6 network in your site ^ - | | | connection - clients IPv6 node "src" | - -You will have to allocate an IPv6 address prefix to map IPv4 addresses into. -The following description uses 3ffe:0501:ffff:0000:: as example. -Please use a prefix which belongs to your site. -FAITH will make it possible to make an IPv6 TCP connection From IPv6 node -"src", toward IPv4 node "dest", by specifying FAITH-mapped address -3ffe:0501:ffff:0000::123.4.5.6 -(which is, 3ffe:0501:ffff:0000:0000:0000:7b04:0506). -The address mapping can be performed by hand:-), by special nameserver on -the network, or by special resolver on the source node. - - -Setup -===== - -The following example assumes: -- You have assigned 3ffe:0501:ffff:0000:: as FAITH adderss prefix. -- You are willing to provide IPv6-to IPv4 TCP relay for telnet. - -<> - -(1) If you have IPv6 TCP server for the "telnet" service, i.e. telnetd via - inet6d, disable that daemon. Comment out the line from "inet6d.conf" - and send the HUP signal to "inet6d". - -(2) Execute sysctl as root to enable FAITH support in the kernel. - - # sysctl net.inet6.ip6.keepfaith=1 - -(3) Route packets toward FAITH prefix into "faith0" interface. - - # ifconfig faith0 up - # route add -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 ::1 - # route change -inet6 3ffe:0501:ffff:0000:: -prefixlen 64 -ifp faith0 - -(4) Execute "faithd" by root as follows: - - # faithd telnet /usr/libexec/telnetd telnetd - - 1st argument is a service name you are willing to provide TCP relay. - (it can be specified either by number "23" or by string "telnet") - 2nd argument is a path name for local IPv6 TCP server. If there is a - connection toward the router itself, this program will be invoked. - 3rd and the following arguments are arguments for the local IPv6 TCP - server. (3rd argument is typically the program name without its path.) - - More examples: - - # faithd ftpd /usr/libexec/ftpd ftpd -l - # faithd sshd - -If inetd(8) on your platform have special support for faithd, it is possible -to setup faithd services via inetd(8). Consult manpage for details. - - -<> - -(4) Make sure that packets whose destinations match the prefix can -reach from the IPv6 host to the translating router. - -<> - -There are two ways to translate IPv4 address to IPv6 address: - (a) Faked by DNS - (b) Faked by /etc/hosts. - -(5.a) Install "newbie" and set up FAITH mode. See kit/ports/newbie. - -(5.b) Add an entry into /etc/hosts so that you can resolve hostname into -faked IPv6 addrss. For example, add the following line for www.netbsd.org: - - 3ffe:0501:ffff:0000::140.160.140.252 www.netbsd.org - -<> - -(6) To see if "faithd" works, watch "/var/log/daemon". Note: please -setup "/etc/syslog.conf" so that LOG_DAEMON messages are to be stored -in "/var/log/daemon". - - - daemon.* /var/log/daemon - - -Access control -============== - -Since faithd implements TCP relaying service, it is critical to implement -proper access control to cope with malicious use. Bad guy may try to -use your relay router to circumvent access controls, or may try to -abuse your network (like sending SPAMs from IPv4 address that belong to you). -Install IPv6 packet filter directives that would reject traffic from -unwanted source. If you are using inetd-based setup, you may be able to -use access control mechanisms in inetd. - - -Advanced configuration -====================== - -If you would like to restrict IPv4 destination for translation, you may -want to do the following: - - # route add -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 ::1 - # route change -inet6 3ffe:0501:ffff:0000::123.0.0.0 -prefixlen 104 \ - -ifp faith0 - -By this way, you can restrict IPv4 destination to 123.0.0.0/8. -You may also want to reject packets toward 3ffe:0501:ffff:0000::/64 which -is not in 3ffe:0501:ffff:0000::123.0.0.0/104. This will be left as excerside -for the reader. - -By doing this, you will be able to provide your IPv4 web server to outside -IPv6 customers, without risks of unwanted open relays. - - [[[[ IPv6 network outside ]]]] | - | | connection - node that runs FAITH-daemon (usually a router) v - | - ========+======== IPv4/v6 network in your site - | (123.0.0.0/8) - IPv4 web server diff --git a/usr.sbin/faithd/faithd.8 b/usr.sbin/faithd/faithd.8 deleted file mode 100644 index 93a835b9a97b..000000000000 --- a/usr.sbin/faithd/faithd.8 +++ /dev/null @@ -1,404 +0,0 @@ -.\" $KAME: faithd.8,v 1.37 2002/05/09 14:21:23 itojun Exp $ -.\" -.\" Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. -.\" 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. -.\" 3. Neither the name of the project nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. -.\" -.\" $FreeBSD$ -.\" -.Dd August 2, 2011 -.Dt FAITHD 8 -.Os -.Sh NAME -.Nm faithd -.Nd FAITH IPv6/v4 translator daemon -.Sh SYNOPSIS -.Nm -.Op Fl dp -.Op Fl f Ar configfile -.Ar service -.Op Ar serverpath Op Ar serverargs -.Sh DESCRIPTION -The -.Nm -utility provides IPv6-to-IPv4 TCP relaying. -It can only be used on an IPv4/v6 dual stack router. -.Pp -When -.Nm -receives -.Tn TCPv6 -traffic, it will relay the -.Tn TCPv6 -traffic to -.Tn TCPv4 . -The destination for the relayed -.Tn TCPv4 -connection will be determined by the last 4 octets of the original -.Tn IPv6 -destination. -For example, if -.Li 3ffe:0501:4819:ffff:: -is reserved for -.Nm , -and the -.Tn TCPv6 -destination address is -.Li 3ffe:0501:4819:ffff::0a01:0101 , -the traffic will be relayed to IPv4 destination -.Li 10.1.1.1 . -.Pp -To use the -.Nm -translation service, -an IPv6 address prefix must be reserved for mapping IPv4 addresses into. -The kernel must be properly configured to route all the TCP connections -toward the reserved IPv6 address prefix into the -.Xr faith 4 -pseudo interface, using the -.Xr route 8 -command. -Also, -.Xr sysctl 8 -should be used to configure -.Dv net.inet6.ip6.keepfaith -to -.Dv 1 . -.Pp -The router must be configured to capture all the TCP traffic -for the reserved -.Tn IPv6 -address prefix, by using -.Xr route 8 -and -.Xr sysctl 8 -commands. -.Pp -The -.Nm -utility needs special name-to-address translation logic, so that -hostnames get resolved into the special -.Tn IPv6 -address prefix. -For small-scale installations, use -.Xr hosts 5 ; -For large-scale installations, it is useful to have -a DNS server with special address translation support. -An implementation called -.Nm totd -is available at -.Pa http://www.vermicelli.pasta.cs.uit.no/software/totd.html . -Make sure you do not propagate translated DNS records over to normal -DNS, as it can cause severe problems. -.Ss Daemon mode -When -.Nm -is invoked as a standalone program, -.Nm -will daemonize itself. -The -.Nm -utility will listen to -.Tn TCPv6 -port -.Ar service . -If -.Tn TCPv6 -traffic to port -.Ar service -is found, it relays the connection. -.Pp -Since -.Nm -listens to TCP port -.Ar service , -it is not possible to run local TCP daemons for port -.Ar service -on the router, using -.Xr inetd 8 -or other standard mechanisms. -By specifying -.Ar serverpath -to -.Nm , -you can run local daemons on the router. -The -.Nm -utility will invoke a local daemon at -.Ar serverpath -if the destination address is a local interface address, -and will perform translation to IPv4 TCP in other cases. -You can also specify -.Ar serverargs -for the arguments for the local daemon. -.Pp -The following options are available: -.Bl -tag -width indent -.It Fl d -Debugging information will be generated using -.Xr syslog 3 . -.It Fl f Ar configfile -Specify a configuration file for access control. -See below. -.It Fl p -Use privileged TCP port number as source port, -for IPv4 TCP connection toward final destination. -For relaying -.Xr ftp 1 , -this flag is not necessary as special program code is supplied. -.El -.Pp -The -.Nm -utility will relay both normal and out-of-band TCP data. -It is capable of emulating TCP half close as well. -The -.Nm -utility includes special support for protocols used by -.Xr ftp 1 . -When translating the FTP protocol, -.Nm -translates network level addresses in -.Li PORT/LPRT/EPRT -and -.Li PASV/LPSV/EPSV -commands. -.Pp -Inactive sessions will be disconnected in 30 minutes, -to prevent stale sessions from chewing up resources. -This may be inappropriate for some services -(should this be configurable?). -.Ss inetd mode -When -.Nm -is invoked via -.Xr inetd 8 , -.Nm -will handle connections passed from standard input. -If the connection endpoint is in the reserved IPv6 address prefix, -.Nm -will relay the connection. -Otherwise, -.Nm -will invoke a service-specific daemon like -.Xr telnetd 8 , -by using the command argument passed from -.Xr inetd 8 . -.Pp -The -.Nm -utility determines operation mode by the local TCP port number, -and enables special protocol handling whenever necessary/possible. -For example, if -.Nm -is invoked via -.Xr inetd 8 -on the FTP port, it will operate as an FTP relay. -.Pp -The operation mode requires special support for -.Nm -in -.Xr inetd 8 . -.Ss Access control -To prevent malicious access, -.Nm -implements simple address-based access control. -With -.Pa /etc/faithd.conf -(or -.Ar configfile -specified by -.Fl f ) , -.Nm -will avoid relaying unwanted traffic. -The -.Pa faithd.conf -configuration file contains directives of the following format: -.Bl -bullet -.It -.Ar src Ns / Ns Ar slen Cm deny Ar dst Ns / Ns Ar dlen -.Pp -If the source address of a query matches -.Ar src Ns / Ns Ar slen , -and the translated destination address matches -.Ar dst Ns / Ns Ar dlen , -deny the connection. -.It -.Ar src Ns / Ns Ar slen Cm permit Ar dst Ns / Ns Ar dlen -.Pp -If the source address of a query matches -.Ar src Ns / Ns Ar slen , -and the translated destination address matches -.Ar dst Ns / Ns Ar dlen , -permit the connection. -.El -.Pp -The directives are evaluated in sequence, -and the first matching entry will be effective. -If there is no match -(if we reach the end of the ruleset) -the traffic will be denied. -.Pp -With inetd mode, -traffic may be filtered by using access control functionality in -.Xr inetd 8 . -.Sh EXIT STATUS -The -.Nm -utility exits with -.Dv EXIT_SUCCESS -.Pq 0 -on success, and -.Dv EXIT_FAILURE -.Pq 1 -on error. -.Sh EXAMPLES -Before invoking -.Nm , -the -.Xr faith 4 -interface has to be configured properly. -.Bd -literal -offset indent -# sysctl net.inet6.ip6.accept_rtadv=0 -# sysctl net.inet6.ip6.forwarding=1 -# sysctl net.inet6.ip6.keepfaith=1 -# ifconfig faith0 up -# route add -inet6 3ffe:501:4819:ffff:: -prefixlen 96 ::1 -# route change -inet6 3ffe:501:4819:ffff:: -prefixlen 96 -ifp faith0 -.Ed -.Ss Daemon mode samples -To translate -.Li telnet -service, and provide no local telnet service, invoke -.Nm -as follows: -.Bd -literal -offset indent -# faithd telnet -.Ed -.Pp -If you would like to provide local telnet service via -.Xr telnetd 8 -on -.Pa /usr/libexec/telnetd , -use the following command line: -.Bd -literal -offset indent -# faithd telnet /usr/libexec/telnetd telnetd -.Ed -.Pp -If you would like to pass extra arguments to the local daemon: -.Bd -literal -offset indent -# faithd ftp /usr/libexec/ftpd ftpd -l -.Ed -.Pp -Here are some other examples. -You may need -.Fl p -if the service checks the source port range. -.Bd -literal -offset indent -# faithd ssh -# faithd telnet /usr/libexec/telnetd telnetd -.Ed -.Ss inetd mode samples -Add the following lines into -.Xr inetd.conf 5 . -Syntax may vary depending upon your operating system. -.Bd -literal -offset indent -telnet stream tcp6/faith nowait root faithd telnetd -ftp stream tcp6/faith nowait root faithd ftpd -l -ssh stream tcp6/faith nowait root faithd /usr/sbin/sshd -i -.Ed -.Pp -.Xr inetd 8 -will open listening sockets with kernel TCP relay support enabled. -Whenever a connection comes in, -.Nm -will be invoked by -.Xr inetd 8 . -If the connection endpoint is in the reserved IPv6 address prefix. -The -.Nm -utility will relay the connection. -Otherwise, -.Nm -will invoke service-specific daemon like -.Xr telnetd 8 . -.Ss Access control samples -The following illustrates a simple -.Pa faithd.conf -setting. -.Bd -literal -offset indent -# permit anyone from 3ffe:501:ffff::/48 to use the translator, -# to connect to the following IPv4 destinations: -# - any location except 10.0.0.0/8 and 127.0.0.0/8. -# Permit no other connections. -# -3ffe:501:ffff::/48 deny 10.0.0.0/8 -3ffe:501:ffff::/48 deny 127.0.0.0/8 -3ffe:501:ffff::/48 permit 0.0.0.0/0 -.Ed -.Sh SEE ALSO -.Xr faith 4 , -.Xr route 8 , -.Xr sysctl 8 -.Rs -.%A Jun-ichiro itojun Hagino -.%A Kazu Yamamoto -.%T "An IPv6-to-IPv4 transport relay translator" -.%B RFC3142 -.%U http://tools.ietf.org/html/rfc3142 -.%D June 2001 -.Re -.\" -.Sh HISTORY -The -.Nm -utility first appeared in the WIDE Hydrangea IPv6 protocol stack kit. -.\" -.Pp -IPv6 and IPsec support based on the KAME Project (http://www.kame.net/) stack -was initially integrated into -.Fx 4.0 . -.Sh SECURITY CONSIDERATIONS -It is very insecure to use IP-address based authentication, for connections relayed by -.Nm , -and any other TCP relaying services. -.Pp -Administrators are advised to limit accesses to -.Nm -using -.Pa faithd.conf , -or by using IPv6 packet filters, to protect the -.Nm -service from malicious parties, and to avoid theft of service/bandwidth. -IPv6 destination addresses can be limited by -carefully configuring routing entries that point to -.Xr faith 4 , -using -.Xr route 8 . -The IPv6 source address needs to be filtered using packet filters. -The documents listed in -.Sx SEE ALSO -have more information on this topic. diff --git a/usr.sbin/faithd/faithd.c b/usr.sbin/faithd/faithd.c deleted file mode 100644 index 1745de1f6b1a..000000000000 --- a/usr.sbin/faithd/faithd.c +++ /dev/null @@ -1,908 +0,0 @@ -/* $KAME: faithd.c,v 1.67 2003/10/16 05:26:21 itojun Exp $ */ - -/* - * Copyright (C) 1997 and 1998 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ - -/* - * User level translator from IPv6 to IPv4. - * - * Usage: faithd [ ...] - * e.g. faithd telnet /usr/libexec/telnetd telnetd - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_POLL_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifdef IFT_FAITH -# define USE_ROUTE -# include -# include -# include -#endif - -#include -#include -#include -#include - -#include "faithd.h" -#include "prefix.h" - -char *serverpath = NULL; -char *serverarg[MAXARGV + 1]; -static char *faithdname = NULL; -char logname[BUFSIZ]; -char procname[BUFSIZ]; - -struct myaddrs { - struct myaddrs *next; - struct sockaddr *addr; -}; -struct myaddrs *myaddrs = NULL; - -static const char *service; -#ifdef USE_ROUTE -static int sockfd = 0; -#endif -int dflag = 0; -static int pflag = 0; -static int inetd = 0; -static char *configfile = NULL; - -int main(int, char **); -static int inetd_main(int, char **); -static int daemon_main(int, char **); -static void play_service(int); -static void play_child(int, struct sockaddr *); -static int faith_prefix(struct sockaddr *); -static int map6to4(struct sockaddr_in6 *, struct sockaddr_in *); -static void sig_child(int); -static void sig_terminate(int); -static void start_daemon(void); -static void exit_stderr(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -static void grab_myaddrs(void); -static void free_myaddrs(void); -static void update_myaddrs(void); -static void usage(void); - -int -main(int argc, char **argv) -{ - - /* - * Initializing stuff - */ - - faithdname = strrchr(argv[0], '/'); - if (faithdname) - faithdname++; - else - faithdname = argv[0]; - - if (strcmp(faithdname, "faithd") != 0) { - inetd = 1; - return inetd_main(argc, argv); - } else - return daemon_main(argc, argv); -} - -static int -inetd_main(int argc, char **argv) -{ - char path[MAXPATHLEN]; - struct sockaddr_storage me; - struct sockaddr_storage from; - socklen_t melen, fromlen; - int i; - int error; - const int on = 1; - char sbuf[NI_MAXSERV], snum[NI_MAXSERV]; - - if (config_load(configfile) < 0 && configfile) { - exit_failure("could not load config file"); - /*NOTREACHED*/ - } - - if (strrchr(argv[0], '/') == NULL) - snprintf(path, sizeof(path), "%s/%s", DEFAULT_DIR, argv[0]); - else - snprintf(path, sizeof(path), "%s", argv[0]); - -#ifdef USE_ROUTE - grab_myaddrs(); - - sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); - if (sockfd < 0) { - exit_failure("socket(PF_ROUTE): %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - melen = sizeof(me); - if (getsockname(STDIN_FILENO, (struct sockaddr *)&me, &melen) < 0) { - exit_failure("getsockname: %s", strerror(errno)); - /*NOTREACHED*/ - } - fromlen = sizeof(from); - if (getpeername(STDIN_FILENO, (struct sockaddr *)&from, &fromlen) < 0) { - exit_failure("getpeername: %s", strerror(errno)); - /*NOTREACHED*/ - } - if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, - sbuf, sizeof(sbuf), NI_NUMERICHOST) == 0) - service = sbuf; - else - service = DEFAULT_PORT_NAME; - if (getnameinfo((struct sockaddr *)&me, melen, NULL, 0, - snum, sizeof(snum), NI_NUMERICHOST) != 0) - snprintf(snum, sizeof(snum), "?"); - - snprintf(logname, sizeof(logname), "faithd %s", snum); - snprintf(procname, sizeof(procname), "accepting port %s", snum); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - - if (argc >= MAXARGV) { - exit_failure("too many arguments"); - /*NOTREACHED*/ - } - serverarg[0] = serverpath = path; - for (i = 1; i < argc; i++) - serverarg[i] = argv[i]; - serverarg[i] = NULL; - - error = setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &on, - sizeof(on)); - if (error < 0) { - exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); - /*NOTREACHED*/ - } - - play_child(STDIN_FILENO, (struct sockaddr *)&from); - exit_failure("should not reach here"); - return 0; /*dummy!*/ -} - -static int -daemon_main(int argc, char **argv) -{ - struct addrinfo hints, *res; - int s_wld, error, i, serverargc, on = 1; - int family = AF_INET6; - int c; - - while ((c = getopt(argc, argv, "df:p")) != -1) { - switch (c) { - case 'd': - dflag++; - break; - case 'f': - configfile = optarg; - break; - case 'p': - pflag++; - break; - default: - usage(); - /*NOTREACHED*/ - } - } - argc -= optind; - argv += optind; - - if (config_load(configfile) < 0 && configfile) { - exit_failure("could not load config file"); - /*NOTREACHED*/ - } - - -#ifdef USE_ROUTE - grab_myaddrs(); -#endif - - switch (argc) { - case 0: - usage(); - /*NOTREACHED*/ - default: - serverargc = argc - NUMARG; - if (serverargc >= MAXARGV) - exit_stderr("too many arguments"); - - serverpath = strdup(argv[NUMPRG]); - if (!serverpath) - exit_stderr("not enough core"); - for (i = 0; i < serverargc; i++) { - serverarg[i] = strdup(argv[i + NUMARG]); - if (!serverarg[i]) - exit_stderr("not enough core"); - } - serverarg[i] = NULL; - /* fall throuth */ - case 1: /* no local service */ - service = argv[NUMPRT]; - break; - } - - start_daemon(); - - /* - * Opening wild card socket for this service. - */ - - memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_PASSIVE; - hints.ai_family = family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; /* SCTP? */ - error = getaddrinfo(NULL, service, &hints, &res); - if (error) - exit_failure("getaddrinfo: %s", gai_strerror(error)); - - s_wld = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (s_wld == -1) - exit_failure("socket: %s", strerror(errno)); - -#ifdef IPV6_FAITH - if (res->ai_family == AF_INET6) { - error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_FAITH, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(IPV6_FAITH): %s", - strerror(errno)); - } -#endif - - error = setsockopt(s_wld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(SO_REUSEADDR): %s", strerror(errno)); - - error = setsockopt(s_wld, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); - -#ifdef IPV6_V6ONLY - error = setsockopt(s_wld, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(IPV6_V6ONLY): %s", strerror(errno)); -#endif - - error = bind(s_wld, (struct sockaddr *)res->ai_addr, res->ai_addrlen); - if (error == -1) - exit_failure("bind: %s", strerror(errno)); - - error = listen(s_wld, 5); - if (error == -1) - exit_failure("listen: %s", strerror(errno)); - -#ifdef USE_ROUTE - sockfd = socket(PF_ROUTE, SOCK_RAW, PF_UNSPEC); - if (sockfd < 0) { - exit_failure("socket(PF_ROUTE): %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - /* - * Everything is OK. - */ - - snprintf(logname, sizeof(logname), "faithd %s", service); - snprintf(procname, sizeof(procname), "accepting port %s", service); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - syslog(LOG_INFO, "Starting faith daemon for %s port", service); - - play_service(s_wld); - /* NOTREACHED */ - exit(1); /*pacify gcc*/ -} - -static void -play_service(int s_wld) -{ - struct sockaddr_storage srcaddr; - socklen_t len; - int s_src; - pid_t child_pid; -#ifdef HAVE_POLL_H - struct pollfd pfd[2]; -#else - fd_set rfds; - int maxfd; -#endif - int error; - - /* - * Wait, accept, fork, faith.... - */ -again: - setproctitle("%s", procname); - -#ifdef HAVE_POLL_H - pfd[0].fd = s_wld; - pfd[0].events = POLLIN; - pfd[1].fd = -1; - pfd[1].revents = 0; -#else - FD_ZERO(&rfds); - if (s_wld >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_wld, &rfds); - maxfd = s_wld; -#endif -#ifdef USE_ROUTE - if (sockfd) { -#ifdef HAVE_POLL_H - pfd[1].fd = sockfd; - pfd[1].events = POLLIN; -#else - if (sockfd >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(sockfd, &rfds); - maxfd = (maxfd < sockfd) ? sockfd : maxfd; -#endif - } -#endif - -#ifdef HAVE_POLL_H - error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), INFTIM); -#else - error = select(maxfd + 1, &rfds, NULL, NULL, NULL); -#endif - if (error < 0) { - if (errno == EINTR) - goto again; - exit_failure("select: %s", strerror(errno)); - /*NOTREACHED*/ - } - -#ifdef USE_ROUTE -#ifdef HAVE_POLL_H - if (pfd[1].revents & POLLIN) -#else - if (FD_ISSET(sockfd, &rfds)) -#endif - { - update_myaddrs(); - } -#endif -#ifdef HAVE_POLL_H - if (pfd[0].revents & POLLIN) -#else - if (FD_ISSET(s_wld, &rfds)) -#endif - { - len = sizeof(srcaddr); - s_src = accept(s_wld, (struct sockaddr *)&srcaddr, &len); - if (s_src < 0) { - if (errno == ECONNABORTED) - goto again; - exit_failure("socket: %s", strerror(errno)); - /*NOTREACHED*/ - } - if (srcaddr.ss_family == AF_INET6 && - IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&srcaddr)->sin6_addr)) { - close(s_src); - syslog(LOG_ERR, "connection from IPv4 mapped address?"); - goto again; - } - - child_pid = fork(); - - if (child_pid == 0) { - /* child process */ - close(s_wld); - closelog(); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - play_child(s_src, (struct sockaddr *)&srcaddr); - exit_failure("should never reach here"); - /*NOTREACHED*/ - } else { - /* parent process */ - close(s_src); - if (child_pid == -1) - syslog(LOG_ERR, "can't fork"); - } - } - goto again; -} - -static void -play_child(int s_src, struct sockaddr *srcaddr) -{ - struct sockaddr_storage dstaddr6; - struct sockaddr_storage dstaddr4; - char src[NI_MAXHOST]; - char dst6[NI_MAXHOST]; - char dst4[NI_MAXHOST]; - socklen_t len = sizeof(dstaddr6); - int s_dst, error, hport, nresvport, on = 1; - struct timeval tv; - struct sockaddr *sa4; - const struct config *conf; - - tv.tv_sec = 1; - tv.tv_usec = 0; - - getnameinfo(srcaddr, srcaddr->sa_len, - src, sizeof(src), NULL, 0, NI_NUMERICHOST); - syslog(LOG_INFO, "accepted a client from %s", src); - - error = getsockname(s_src, (struct sockaddr *)&dstaddr6, &len); - if (error == -1) { - exit_failure("getsockname: %s", strerror(errno)); - /*NOTREACHED*/ - } - - getnameinfo((struct sockaddr *)&dstaddr6, len, - dst6, sizeof(dst6), NULL, 0, NI_NUMERICHOST); - syslog(LOG_INFO, "the client is connecting to %s", dst6); - - if (!faith_prefix((struct sockaddr *)&dstaddr6)) { - if (serverpath) { - /* - * Local service - */ - syslog(LOG_INFO, "executing local %s", serverpath); - if (!inetd) { - dup2(s_src, 0); - close(s_src); - dup2(0, 1); - dup2(0, 2); - } - execv(serverpath, serverarg); - syslog(LOG_ERR, "execv %s: %s", serverpath, - strerror(errno)); - _exit(EXIT_FAILURE); - } else { - close(s_src); - exit_success("no local service for %s", service); - } - } - - /* - * Act as a translator - */ - - switch (((struct sockaddr *)&dstaddr6)->sa_family) { - case AF_INET6: - if (!map6to4((struct sockaddr_in6 *)&dstaddr6, - (struct sockaddr_in *)&dstaddr4)) { - close(s_src); - exit_failure("map6to4 failed"); - /*NOTREACHED*/ - } - syslog(LOG_INFO, "translating from v6 to v4"); - break; - default: - close(s_src); - exit_failure("family not supported"); - /*NOTREACHED*/ - } - - sa4 = (struct sockaddr *)&dstaddr4; - getnameinfo(sa4, sa4->sa_len, - dst4, sizeof(dst4), NULL, 0, NI_NUMERICHOST); - - conf = config_match(srcaddr, sa4); - if (!conf || !conf->permit) { - close(s_src); - if (conf) { - exit_failure("translation to %s not permitted for %s", - dst4, prefix_string(&conf->match)); - /*NOTREACHED*/ - } else { - exit_failure("translation to %s not permitted", dst4); - /*NOTREACHED*/ - } - } - - syslog(LOG_INFO, "the translator is connecting to %s", dst4); - - setproctitle("port %s, %s -> %s", service, src, dst4); - - if (sa4->sa_family == AF_INET6) - hport = ntohs(((struct sockaddr_in6 *)&dstaddr4)->sin6_port); - else /* AF_INET */ - hport = ntohs(((struct sockaddr_in *)&dstaddr4)->sin_port); - - if (pflag) - s_dst = rresvport_af(&nresvport, sa4->sa_family); - else - s_dst = socket(sa4->sa_family, SOCK_STREAM, 0); - if (s_dst < 0) { - exit_failure("socket: %s", strerror(errno)); - /*NOTREACHED*/ - } - - if (conf->src.a.ss_family) { - if (bind(s_dst, (const struct sockaddr *)&conf->src.a, - conf->src.a.ss_len) < 0) { - exit_failure("bind: %s", strerror(errno)); - /*NOTREACHED*/ - } - } - - error = setsockopt(s_dst, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)); - if (error < 0) { - exit_failure("setsockopt(SO_OOBINLINE): %s", strerror(errno)); - /*NOTREACHED*/ - } - - error = setsockopt(s_src, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (error < 0) { - exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); - /*NOTREACHED*/ - } - error = setsockopt(s_dst, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); - if (error < 0) { - exit_failure("setsockopt(SO_SNDTIMEO): %s", strerror(errno)); - /*NOTREACHED*/ - } - - error = connect(s_dst, sa4, sa4->sa_len); - if (error < 0) { - exit_failure("connect: %s", strerror(errno)); - /*NOTREACHED*/ - } - - switch (hport) { - case FTP_PORT: - ftp_relay(s_src, s_dst); - break; - default: - tcp_relay(s_src, s_dst, service); - break; - } - - /* NOTREACHED */ -} - -/* 0: non faith, 1: faith */ -static int -faith_prefix(struct sockaddr *dst) -{ -#ifndef USE_ROUTE - int mib[4], size; - struct in6_addr faith_prefix; - struct sockaddr_in6 *dst6 = (struct sockaddr_in *)dst; - - if (dst->sa_family != AF_INET6) - return 0; - - mib[0] = CTL_NET; - mib[1] = PF_INET6; - mib[2] = IPPROTO_IPV6; - mib[3] = IPV6CTL_FAITH_PREFIX; - size = sizeof(struct in6_addr); - if (sysctl(mib, 4, &faith_prefix, &size, NULL, 0) < 0) { - exit_failure("sysctl: %s", strerror(errno)); - /*NOTREACHED*/ - } - - if (memcmp(dst, &faith_prefix, - sizeof(struct in6_addr) - sizeof(struct in_addr) == 0) { - return 1; - } - return 0; -#else - struct myaddrs *p; - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin4; - struct sockaddr_in6 *dst6; - struct sockaddr_in *dst4; - struct sockaddr_in dstmap; - - dst6 = (struct sockaddr_in6 *)dst; - if (dst->sa_family == AF_INET6 - && IN6_IS_ADDR_V4MAPPED(&dst6->sin6_addr)) { - /* ugly... */ - memset(&dstmap, 0, sizeof(dstmap)); - dstmap.sin_family = AF_INET; - dstmap.sin_len = sizeof(dstmap); - memcpy(&dstmap.sin_addr, &dst6->sin6_addr.s6_addr[12], - sizeof(dstmap.sin_addr)); - dst = (struct sockaddr *)&dstmap; - } - - dst6 = (struct sockaddr_in6 *)dst; - dst4 = (struct sockaddr_in *)dst; - - for (p = myaddrs; p; p = p->next) { - sin6 = (struct sockaddr_in6 *)p->addr; - sin4 = (struct sockaddr_in *)p->addr; - - if (p->addr->sa_len != dst->sa_len - || p->addr->sa_family != dst->sa_family) - continue; - - switch (dst->sa_family) { - case AF_INET6: - if (sin6->sin6_scope_id == dst6->sin6_scope_id - && IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &dst6->sin6_addr)) - return 0; - break; - case AF_INET: - if (sin4->sin_addr.s_addr == dst4->sin_addr.s_addr) - return 0; - break; - } - } - return 1; -#endif -} - -/* 0: non faith, 1: faith */ -static int -map6to4(struct sockaddr_in6 *dst6, struct sockaddr_in *dst4) -{ - memset(dst4, 0, sizeof(*dst4)); - dst4->sin_len = sizeof(*dst4); - dst4->sin_family = AF_INET; - dst4->sin_port = dst6->sin6_port; - memcpy(&dst4->sin_addr, &dst6->sin6_addr.s6_addr[12], - sizeof(dst4->sin_addr)); - - if (dst4->sin_addr.s_addr == INADDR_ANY - || dst4->sin_addr.s_addr == INADDR_BROADCAST - || IN_MULTICAST(ntohl(dst4->sin_addr.s_addr))) - return 0; - - return 1; -} - - -static void -sig_child(int sig __unused) -{ - int status; - pid_t pid; - - while ((pid = wait3(&status, WNOHANG, (struct rusage *)0)) > 0) - if (WEXITSTATUS(status)) - syslog(LOG_WARNING, "child %ld exit status 0x%x", - (long)pid, status); -} - -void -sig_terminate(int sig __unused) -{ - syslog(LOG_INFO, "Terminating faith daemon"); - exit(EXIT_SUCCESS); -} - -static void -start_daemon(void) -{ -#ifdef SA_NOCLDWAIT - struct sigaction sa; -#endif - - if (daemon(0, 0) == -1) - exit_stderr("daemon: %s", strerror(errno)); - -#ifdef SA_NOCLDWAIT - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = sig_child; - sa.sa_flags = SA_NOCLDWAIT; - sigemptyset(&sa.sa_mask); - sigaction(SIGCHLD, &sa, (struct sigaction *)0); -#else - if (signal(SIGCHLD, sig_child) == SIG_ERR) { - exit_failure("signal CHLD: %s", strerror(errno)); - /*NOTREACHED*/ - } -#endif - - if (signal(SIGTERM, sig_terminate) == SIG_ERR) { - exit_failure("signal TERM: %s", strerror(errno)); - /*NOTREACHED*/ - } -} - -static void -exit_stderr(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - fprintf(stderr, "%s\n", buf); - exit(EXIT_FAILURE); -} - -void -exit_failure(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - syslog(LOG_ERR, "%s", buf); - exit(EXIT_FAILURE); -} - -void -exit_success(const char *fmt, ...) -{ - va_list ap; - char buf[BUFSIZ]; - - va_start(ap, fmt); - vsnprintf(buf, sizeof(buf), fmt, ap); - va_end(ap); - syslog(LOG_INFO, "%s", buf); - exit(EXIT_SUCCESS); -} - -#ifdef USE_ROUTE -static void -grab_myaddrs(void) -{ - struct ifaddrs *ifap, *ifa; - struct myaddrs *p; - struct sockaddr_in6 *sin6; - - if (getifaddrs(&ifap) != 0) { - exit_failure("getifaddrs"); - /*NOTREACHED*/ - } - - for (ifa = ifap; ifa; ifa = ifa->ifa_next) { - switch (ifa->ifa_addr->sa_family) { - case AF_INET: - case AF_INET6: - break; - default: - continue; - } - - p = (struct myaddrs *)malloc(sizeof(struct myaddrs) + - ifa->ifa_addr->sa_len); - if (!p) { - exit_failure("not enough core"); - /*NOTREACHED*/ - } - memcpy(p + 1, ifa->ifa_addr, ifa->ifa_addr->sa_len); - p->next = myaddrs; - p->addr = (struct sockaddr *)(p + 1); -#ifdef __KAME__ - if (ifa->ifa_addr->sa_family == AF_INET6) { - sin6 = (struct sockaddr_in6 *)p->addr; - if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) - || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr)) { - sin6->sin6_scope_id = - ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]); - sin6->sin6_addr.s6_addr[2] = 0; - sin6->sin6_addr.s6_addr[3] = 0; - } - } -#endif - myaddrs = p; - if (dflag) { - char hbuf[NI_MAXHOST]; - getnameinfo(p->addr, p->addr->sa_len, - hbuf, sizeof(hbuf), NULL, 0, - NI_NUMERICHOST); - syslog(LOG_INFO, "my interface: %s %s", hbuf, - ifa->ifa_name); - } - } - - freeifaddrs(ifap); -} - -static void -free_myaddrs(void) -{ - struct myaddrs *p, *q; - - p = myaddrs; - while (p) { - q = p->next; - free(p); - p = q; - } - myaddrs = NULL; -} - -static void -update_myaddrs(void) -{ - char msg[BUFSIZ]; - int len; - struct rt_msghdr *rtm; - - len = read(sockfd, msg, sizeof(msg)); - if (len < 0) { - syslog(LOG_ERR, "read(PF_ROUTE) failed"); - return; - } - rtm = (struct rt_msghdr *)msg; - if (len < 4 || len < rtm->rtm_msglen) { - syslog(LOG_ERR, "read(PF_ROUTE) short read"); - return; - } - if (rtm->rtm_version != RTM_VERSION) { - syslog(LOG_ERR, "routing socket version mismatch"); - close(sockfd); - sockfd = 0; - return; - } - switch (rtm->rtm_type) { - case RTM_NEWADDR: - case RTM_DELADDR: - case RTM_IFINFO: - break; - default: - return; - } - /* XXX more filters here? */ - - syslog(LOG_INFO, "update interface address list"); - free_myaddrs(); - grab_myaddrs(); -} -#endif /*USE_ROUTE*/ - -static void -usage(void) -{ - fprintf(stderr, "usage: %s [-dp] [-f conf] service [serverpath [serverargs]]\n", - faithdname); - exit(0); -} diff --git a/usr.sbin/faithd/faithd.h b/usr.sbin/faithd/faithd.h deleted file mode 100644 index c578d46c4d2f..000000000000 --- a/usr.sbin/faithd/faithd.h +++ /dev/null @@ -1,70 +0,0 @@ -/* $KAME: faithd.h,v 1.9 2002/05/09 09:41:24 itojun Exp $ */ - -/* - * Copyright (C) 1997 and 1998 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - * - * $FreeBSD$ - */ - -extern char logname[]; -extern int dflag; - -extern void tcp_relay(int, int, const char *); -extern void ftp_relay(int, int); -extern int ftp_active(int, int, int *, int *); -extern int ftp_passive(int, int, int *, int *); -extern void exit_success(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); -extern void exit_failure(const char *, ...) - __attribute__((__format__(__printf__, 1, 2))); - -#define DEFAULT_PORT_NAME "telnet" -#define DEFAULT_DIR "/usr/libexec" -#define DEFAULT_NAME "telnetd" -#define DEFAULT_PATH (DEFAULT_DIR "/" DEFAULT_NAME) - -#define FTP_PORT 21 -#define RLOGIN_PORT 513 -#define RSH_PORT 514 - -#define RETURN_SUCCESS 0 -#define RETURN_FAILURE 1 - -#define YES 1 -#define NO 0 - -#define MSS 2048 -#define MAXARGV 20 - -#define NUMPRT 0 -#define NUMPRG 1 -#define NUMARG 2 - -#define UC(b) (((int)b)&0xff) - -#define FAITH_TIMEOUT (30 * 60) /*second*/ diff --git a/usr.sbin/faithd/ftp.c b/usr.sbin/faithd/ftp.c deleted file mode 100644 index c54371a2c20e..000000000000 --- a/usr.sbin/faithd/ftp.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* $KAME: ftp.c,v 1.24 2005/03/16 05:05:48 itojun Exp $ */ - -/* - * Copyright (C) 1997 and 1998 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - * - * $FreeBSD$ - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_POLL_H -#include -#endif -#include -#include - -#include -#include -#include - -#include "faithd.h" - -static char rbuf[MSS]; -static char sbuf[MSS]; -static int passivemode = 0; -static int wport4 = -1; /* listen() to active */ -static int wport6 = -1; /* listen() to passive */ -static int port4 = -1; /* active: inbound passive: outbound */ -static int port6 = -1; /* active: outbound passive: inbound */ -static struct sockaddr_storage data4; /* server data address */ -static struct sockaddr_storage data6; /* client data address */ -static int epsvall = 0; - -enum state { NONE, LPRT, EPRT, LPSV, EPSV }; - -static int ftp_activeconn(void); -static int ftp_passiveconn(void); -static int ftp_copy(int, int); -static int ftp_copyresult(int, int, enum state); -static int ftp_copycommand(int, int, enum state *); - -void -ftp_relay(int ctl6, int ctl4) -{ -#ifdef HAVE_POLL_H - struct pollfd pfd[6]; -#else - fd_set readfds; -#endif - int error; - enum state state = NONE; - struct timeval tv; - - syslog(LOG_INFO, "starting ftp control connection"); - - for (;;) { -#ifdef HAVE_POLL_H - pfd[0].fd = ctl4; - pfd[0].events = POLLIN; - pfd[1].fd = ctl6; - pfd[1].events = POLLIN; - if (0 <= port4) { - pfd[2].fd = port4; - pfd[2].events = POLLIN; - } else - pfd[2].fd = -1; - if (0 <= port6) { - pfd[3].fd = port6; - pfd[3].events = POLLIN; - } else - pfd[3].fd = -1; -#if 0 - if (0 <= wport4) { - pfd[4].fd = wport4; - pfd[4].events = POLLIN; - } else - pfd[4].fd = -1; - if (0 <= wport6) { - pfd[5].fd = wport4; - pfd[5].events = POLLIN; - } else - pfd[5].fd = -1; -#else - pfd[4].fd = pfd[5].fd = -1; - pfd[4].events = pfd[5].events = 0; -#endif -#else - int maxfd = 0; - - FD_ZERO(&readfds); - if (ctl4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(ctl4, &readfds); - maxfd = ctl4; - if (ctl6 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(ctl6, &readfds); - maxfd = (ctl6 > maxfd) ? ctl6 : maxfd; - if (0 <= port4) { - if (port4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(port4, &readfds); - maxfd = (port4 > maxfd) ? port4 : maxfd; - } - if (0 <= port6) { - if (port6 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(port6, &readfds); - maxfd = (port6 > maxfd) ? port6 : maxfd; - } -#if 0 - if (0 <= wport4) { - if (wport4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(wport4, &readfds); - maxfd = (wport4 > maxfd) ? wport4 : maxfd; - } - if (0 <= wport6) { - if (wport6 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(wport6, &readfds); - maxfd = (wport6 > maxfd) ? wport6 : maxfd; - } -#endif -#endif - tv.tv_sec = FAITH_TIMEOUT; - tv.tv_usec = 0; - -#ifdef HAVE_POLL_H - error = poll(pfd, sizeof(pfd)/sizeof(pfd[0]), tv.tv_sec * 1000); -#else - error = select(maxfd + 1, &readfds, NULL, NULL, &tv); -#endif - if (error == -1) { -#ifdef HAVE_POLL_H - exit_failure("poll: %s", strerror(errno)); -#else - exit_failure("select: %s", strerror(errno)); -#endif - } - else if (error == 0) - exit_failure("connection timeout"); - - /* - * The order of the following checks does (slightly) matter. - * It is important to visit all checks (do not use "continue"), - * otherwise some of the pipe may become full and we cannot - * relay correctly. - */ -#ifdef HAVE_POLL_H - if (pfd[1].revents & POLLIN) -#else - if (FD_ISSET(ctl6, &readfds)) -#endif - { - /* - * copy control connection from the client. - * command translation is necessary. - */ - error = ftp_copycommand(ctl6, ctl4, &state); - - if (error < 0) - goto bad; - else if (error == 0) { - close(ctl4); - close(ctl6); - exit_success("terminating ftp control connection"); - /*NOTREACHED*/ - } - } -#ifdef HAVE_POLL_H - if (pfd[0].revents & POLLIN) -#else - if (FD_ISSET(ctl4, &readfds)) -#endif - { - /* - * copy control connection from the server - * translation of result code is necessary. - */ - error = ftp_copyresult(ctl4, ctl6, state); - - if (error < 0) - goto bad; - else if (error == 0) { - close(ctl4); - close(ctl6); - exit_success("terminating ftp control connection"); - /*NOTREACHED*/ - } - } -#ifdef HAVE_POLL_H - if (0 <= port4 && 0 <= port6 && (pfd[2].revents & POLLIN)) -#else - if (0 <= port4 && 0 <= port6 && FD_ISSET(port4, &readfds)) -#endif - { - /* - * copy data connection. - * no special treatment necessary. - */ -#ifdef HAVE_POLL_H - if (pfd[2].revents & POLLIN) -#else - if (FD_ISSET(port4, &readfds)) -#endif - error = ftp_copy(port4, port6); - switch (error) { - case -1: - goto bad; - case 0: - close(port4); - close(port6); - port4 = port6 = -1; - syslog(LOG_INFO, "terminating data connection"); - break; - default: - break; - } - } -#ifdef HAVE_POLL_H - if (0 <= port4 && 0 <= port6 && (pfd[3].revents & POLLIN)) -#else - if (0 <= port4 && 0 <= port6 && FD_ISSET(port6, &readfds)) -#endif - { - /* - * copy data connection. - * no special treatment necessary. - */ -#ifdef HAVE_POLL_H - if (pfd[3].revents & POLLIN) -#else - if (FD_ISSET(port6, &readfds)) -#endif - error = ftp_copy(port6, port4); - switch (error) { - case -1: - goto bad; - case 0: - close(port4); - close(port6); - port4 = port6 = -1; - syslog(LOG_INFO, "terminating data connection"); - break; - default: - break; - } - } -#if 0 -#ifdef HAVE_POLL_H - if (wport4 && (pfd[4].revents & POLLIN)) -#else - if (wport4 && FD_ISSET(wport4, &readfds)) -#endif - { - /* - * establish active data connection from the server. - */ - ftp_activeconn(); - } -#ifdef HAVE_POLL_H - if (wport4 && (pfd[5].revents & POLLIN)) -#else - if (wport6 && FD_ISSET(wport6, &readfds)) -#endif - { - /* - * establish passive data connection from the client. - */ - ftp_passiveconn(); - } -#endif - } - - bad: - exit_failure("%s", strerror(errno)); -} - -static int -ftp_activeconn() -{ - socklen_t n; - int error; -#ifdef HAVE_POLL_H - struct pollfd pfd[1]; -#else - fd_set set; -#endif - struct timeval timeout; - struct sockaddr *sa; - - /* get active connection from server */ -#ifdef HAVE_POLL_H - pfd[0].fd = wport4; - pfd[0].events = POLLIN; -#else - FD_ZERO(&set); - if (wport4 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(wport4, &set); -#endif - timeout.tv_sec = 120; - timeout.tv_usec = 0; - n = sizeof(data4); -#ifdef HAVE_POLL_H - if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || - (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) -#else - if (select(wport4 + 1, &set, NULL, NULL, &timeout) == 0 || - (port4 = accept(wport4, (struct sockaddr *)&data4, &n)) < 0) -#endif - { - close(wport4); - wport4 = -1; - syslog(LOG_INFO, "active mode data connection failed"); - return -1; - } - - /* ask active connection to client */ - sa = (struct sockaddr *)&data6; - port6 = socket(sa->sa_family, SOCK_STREAM, 0); - if (port6 == -1) { - close(port4); - close(wport4); - port4 = wport4 = -1; - syslog(LOG_INFO, "active mode data connection failed"); - return -1; - } - error = connect(port6, sa, sa->sa_len); - if (error < 0) { - close(port6); - close(port4); - close(wport4); - port6 = port4 = wport4 = -1; - syslog(LOG_INFO, "active mode data connection failed"); - return -1; - } - - syslog(LOG_INFO, "active mode data connection established"); - return 0; -} - -static int -ftp_passiveconn() -{ - socklen_t len; - int error; -#ifdef HAVE_POLL_H - struct pollfd pfd[1]; -#else - fd_set set; -#endif - struct timeval timeout; - struct sockaddr *sa; - - /* get passive connection from client */ -#ifdef HAVE_POLL_H - pfd[0].fd = wport6; - pfd[0].events = POLLIN; -#else - FD_ZERO(&set); - if (wport6 >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(wport6, &set); -#endif - timeout.tv_sec = 120; - timeout.tv_usec = 0; - len = sizeof(data6); -#ifdef HAVE_POLL_H - if (poll(pfd, sizeof(pfd)/sizeof(pfd[0]), timeout.tv_sec * 1000) == 0 || - (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) -#else - if (select(wport6 + 1, &set, NULL, NULL, &timeout) == 0 || - (port6 = accept(wport6, (struct sockaddr *)&data6, &len)) < 0) -#endif - { - close(wport6); - wport6 = -1; - syslog(LOG_INFO, "passive mode data connection failed"); - return -1; - } - - /* ask passive connection to server */ - sa = (struct sockaddr *)&data4; - port4 = socket(sa->sa_family, SOCK_STREAM, 0); - if (port4 == -1) { - close(wport6); - close(port6); - wport6 = port6 = -1; - syslog(LOG_INFO, "passive mode data connection failed"); - return -1; - } - error = connect(port4, sa, sa->sa_len); - if (error < 0) { - close(wport6); - close(port4); - close(port6); - wport6 = port4 = port6 = -1; - syslog(LOG_INFO, "passive mode data connection failed"); - return -1; - } - - syslog(LOG_INFO, "passive mode data connection established"); - return 0; -} - -static int -ftp_copy(int src, int dst) -{ - int error, atmark, n; - - /* OOB data handling */ - error = ioctl(src, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - switch (n) { - case -1: - case 0: - return n; - default: - write(dst, rbuf, n); - return n; - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} - -static int -ftp_copyresult(int src, int dst, enum state state) -{ - int error, atmark, n; - socklen_t len; - char *param; - int code; - char *a, *p; - int i; - - /* OOB data handling */ - error = ioctl(src, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - if (n <= 0) - return n; - rbuf[n] = '\0'; - - /* - * parse argument - */ - p = rbuf; - for (i = 0; i < 3; i++) { - if (!isdigit(*p)) { - /* invalid reply */ - write(dst, rbuf, n); - return n; - } - p++; - } - if (!isspace(*p)) { - /* invalid reply */ - write(dst, rbuf, n); - return n; - } - code = atoi(rbuf); - param = p; - /* param points to first non-command token, if any */ - while (*param && isspace(*param)) - param++; - if (!*param) - param = NULL; - - switch (state) { - case NONE: - if (!passivemode && rbuf[0] == '1') { - if (ftp_activeconn() < 0) { - n = snprintf(rbuf, sizeof(rbuf), - "425 Cannot open data connetion\r\n"); - if (n < 0 || n >= sizeof(rbuf)) - n = 0; - } - } - if (n) - write(dst, rbuf, n); - return n; - case LPRT: - case EPRT: - /* expecting "200 PORT command successful." */ - if (code == 200) { - p = strstr(rbuf, "PORT"); - if (p) { - p[0] = (state == LPRT) ? 'L' : 'E'; - p[1] = 'P'; - } - } else { - close(wport4); - wport4 = -1; - } - write(dst, rbuf, n); - return n; - case LPSV: - case EPSV: - /* - * expecting "227 Entering Passive Mode (x,x,x,x,x,x,x)" - * (in some cases result comes without paren) - */ - if (code != 227) { -passivefail0: - close(wport6); - wport6 = -1; - write(dst, rbuf, n); - return n; - } - - { - unsigned int ho[4], po[2]; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - u_short port; - - /* - * PASV result -> LPSV/EPSV result - */ - p = param; - while (*p && *p != '(' && !isdigit(*p)) /*)*/ - p++; - if (!*p) - goto passivefail0; /*XXX*/ - if (*p == '(') /*)*/ - p++; - n = sscanf(p, "%u,%u,%u,%u,%u,%u", - &ho[0], &ho[1], &ho[2], &ho[3], &po[0], &po[1]); - if (n != 6) - goto passivefail0; /*XXX*/ - - /* keep PORT parameter */ - memset(&data4, 0, sizeof(data4)); - sin = (struct sockaddr_in *)&data4; - sin->sin_len = sizeof(*sin); - sin->sin_family = AF_INET; - sin->sin_addr.s_addr = 0; - for (n = 0; n < 4; n++) { - sin->sin_addr.s_addr |= - htonl((ho[n] & 0xff) << ((3 - n) * 8)); - } - sin->sin_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); - - /* get ready for passive data connection */ - memset(&data6, 0, sizeof(data6)); - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - wport6 = socket(sin6->sin6_family, SOCK_STREAM, 0); - if (wport6 == -1) { -passivefail: - n = snprintf(sbuf, sizeof(sbuf), - "500 could not translate from PASV\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } -#ifdef IPV6_FAITH - { - int on = 1; - error = setsockopt(wport6, IPPROTO_IPV6, IPV6_FAITH, - &on, sizeof(on)); - if (error == -1) - exit_failure("setsockopt(IPV6_FAITH): %s", strerror(errno)); - } -#endif - error = bind(wport6, (struct sockaddr *)sin6, sin6->sin6_len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - error = listen(wport6, 1); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - - /* transmit LPSV or EPSV */ - /* - * addr from dst, port from wport6 - */ - len = sizeof(data6); - error = getsockname(wport6, (struct sockaddr *)&data6, &len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - sin6 = (struct sockaddr_in6 *)&data6; - port = sin6->sin6_port; - - len = sizeof(data6); - error = getsockname(dst, (struct sockaddr *)&data6, &len); - if (error == -1) { - close(wport6); - wport6 = -1; - goto passivefail; - } - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_port = port; - - if (state == LPSV) { - a = (char *)&sin6->sin6_addr; - p = (char *)&sin6->sin6_port; - n = snprintf(sbuf, sizeof(sbuf), -"228 Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)\r\n", - 6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), - UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), - UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), - UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), - 2, UC(p[0]), UC(p[1])); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - passivemode = 1; - return n; - } else { - n = snprintf(sbuf, sizeof(sbuf), -"229 Entering Extended Passive Mode (|||%d|)\r\n", - ntohs(sin6->sin6_port)); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - passivemode = 1; - return n; - } - } - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} - -static int -ftp_copycommand(int src, int dst, enum state *state) -{ - int error, atmark, n; - socklen_t len; - unsigned int af, hal, ho[16], pal, po[2]; - char *a, *p, *q; - char cmd[5], *param; - struct sockaddr_in *sin; - struct sockaddr_in6 *sin6; - enum state nstate; - char ch; - int i; - - /* OOB data handling */ - error = ioctl(src, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - n = read(src, rbuf, 1); - if (n == -1) - goto bad; - send(dst, rbuf, n, MSG_OOB); -#if 0 - n = read(src, rbuf, sizeof(rbuf)); - if (n == -1) - goto bad; - write(dst, rbuf, n); - return n; -#endif - } - - n = read(src, rbuf, sizeof(rbuf)); - if (n <= 0) - return n; - rbuf[n] = '\0'; - - if (n < 4) { - write(dst, rbuf, n); - return n; - } - - /* - * parse argument - */ - p = rbuf; - q = cmd; - for (i = 0; i < 4; i++) { - if (!isalpha(*p)) { - /* invalid command */ - write(dst, rbuf, n); - return n; - } - *q++ = islower(*p) ? toupper(*p) : *p; - p++; - } - if (!isspace(*p)) { - /* invalid command */ - write(dst, rbuf, n); - return n; - } - *q = '\0'; - param = p; - /* param points to first non-command token, if any */ - while (*param && isspace(*param)) - param++; - if (!*param) - param = NULL; - - *state = NONE; - - if (strcmp(cmd, "LPRT") == 0 && param) { - /* - * LPRT -> PORT - */ - nstate = LPRT; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - n = sscanf(param, -"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", - &af, &hal, &ho[0], &ho[1], &ho[2], &ho[3], - &ho[4], &ho[5], &ho[6], &ho[7], - &ho[8], &ho[9], &ho[10], &ho[11], - &ho[12], &ho[13], &ho[14], &ho[15], - &pal, &po[0], &po[1]); - if (n != 21 || af != 6 || hal != 16|| pal != 2) { - n = snprintf(sbuf, sizeof(sbuf), - "501 illegal parameter to LPRT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - /* keep LPRT parameter */ - memset(&data6, 0, sizeof(data6)); - sin6 = (struct sockaddr_in6 *)&data6; - sin6->sin6_len = sizeof(*sin6); - sin6->sin6_family = AF_INET6; - for (n = 0; n < 16; n++) - sin6->sin6_addr.s6_addr[n] = ho[n]; - sin6->sin6_port = htons(((po[0] & 0xff) << 8) | (po[1] & 0xff)); - -sendport: - /* get ready for active data connection */ - len = sizeof(data4); - error = getsockname(dst, (struct sockaddr *)&data4, &len); - if (error == -1) { -lprtfail: - n = snprintf(sbuf, sizeof(sbuf), - "500 could not translate to PORT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - if (((struct sockaddr *)&data4)->sa_family != AF_INET) - goto lprtfail; - sin = (struct sockaddr_in *)&data4; - sin->sin_port = 0; - wport4 = socket(sin->sin_family, SOCK_STREAM, 0); - if (wport4 == -1) - goto lprtfail; - error = bind(wport4, (struct sockaddr *)sin, sin->sin_len); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - error = listen(wport4, 1); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - - /* transmit PORT */ - len = sizeof(data4); - error = getsockname(wport4, (struct sockaddr *)&data4, &len); - if (error == -1) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - if (((struct sockaddr *)&data4)->sa_family != AF_INET) { - close(wport4); - wport4 = -1; - goto lprtfail; - } - sin = (struct sockaddr_in *)&data4; - a = (char *)&sin->sin_addr; - p = (char *)&sin->sin_port; - n = snprintf(sbuf, sizeof(sbuf), "PORT %d,%d,%d,%d,%d,%d\r\n", - UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), - UC(p[0]), UC(p[1])); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - *state = nstate; - passivemode = 0; - return n; - } else if (strcmp(cmd, "EPRT") == 0 && param) { - /* - * EPRT -> PORT - */ - char *afp, *hostp, *portp; - struct addrinfo hints, *res; - - nstate = EPRT; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - p = param; - ch = *p++; /* boundary character */ - afp = p; - while (*p && *p != ch) - p++; - if (!*p) { -eprtparamfail: - n = snprintf(sbuf, sizeof(sbuf), - "501 illegal parameter to EPRT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - *p++ = '\0'; - hostp = p; - while (*p && *p != ch) - p++; - if (!*p) - goto eprtparamfail; - *p++ = '\0'; - portp = p; - while (*p && *p != ch) - p++; - if (!*p) - goto eprtparamfail; - *p++ = '\0'; - - n = sscanf(afp, "%d", &af); - if (n != 1 || af != 2) { - n = snprintf(sbuf, sizeof(sbuf), - "501 unsupported address family to EPRT\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - error = getaddrinfo(hostp, portp, &hints, &res); - if (error) { - n = snprintf(sbuf, sizeof(sbuf), - "501 EPRT: %s\r\n", gai_strerror(error)); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - if (res->ai_next) { - n = snprintf(sbuf, sizeof(sbuf), - "501 EPRT: %s resolved to multiple addresses\r\n", hostp); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - freeaddrinfo(res); - return n; - } - - memcpy(&data6, res->ai_addr, res->ai_addrlen); - - freeaddrinfo(res); - goto sendport; - } else if (strcmp(cmd, "LPSV") == 0 && !param) { - /* - * LPSV -> PASV - */ - nstate = LPSV; - - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - if (epsvall) { - n = snprintf(sbuf, sizeof(sbuf), "501 %s disallowed in EPSV ALL\r\n", - cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } - - /* transmit PASV */ - n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - *state = LPSV; - passivemode = 0; /* to be set to 1 later */ - return n; - } else if (strcmp(cmd, "EPSV") == 0 && !param) { - /* - * EPSV -> PASV - */ - close(wport4); - close(wport6); - close(port4); - close(port6); - wport4 = wport6 = port4 = port6 = -1; - - n = snprintf(sbuf, sizeof(sbuf), "PASV\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(dst, sbuf, n); - *state = EPSV; - passivemode = 0; /* to be set to 1 later */ - return n; - } else if (strcmp(cmd, "EPSV") == 0 && param - && strncasecmp(param, "ALL", 3) == 0 && isspace(param[3])) { - /* - * EPSV ALL - */ - epsvall = 1; - n = snprintf(sbuf, sizeof(sbuf), "200 EPSV ALL command successful.\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } else if (strcmp(cmd, "PORT") == 0 || strcmp(cmd, "PASV") == 0) { - /* - * reject PORT/PASV - */ - n = snprintf(sbuf, sizeof(sbuf), "502 %s not implemented.\r\n", cmd); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - return n; - } else if (passivemode - && (strcmp(cmd, "STOR") == 0 - || strcmp(cmd, "STOU") == 0 - || strcmp(cmd, "RETR") == 0 - || strcmp(cmd, "LIST") == 0 - || strcmp(cmd, "NLST") == 0 - || strcmp(cmd, "APPE") == 0)) { - /* - * commands with data transfer. need to care about passive - * mode data connection. - */ - - if (ftp_passiveconn() < 0) { - n = snprintf(sbuf, sizeof(sbuf), "425 Cannot open data connetion\r\n"); - if (n < 0 || n >= sizeof(sbuf)) - n = 0; - if (n) - write(src, sbuf, n); - } else { - /* simply relay the command */ - write(dst, rbuf, n); - } - - *state = NONE; - return n; - } else { - /* simply relay it */ - *state = NONE; - write(dst, rbuf, n); - return n; - } - - bad: - exit_failure("%s", strerror(errno)); - /*NOTREACHED*/ - return 0; /* to make gcc happy */ -} diff --git a/usr.sbin/faithd/prefix.c b/usr.sbin/faithd/prefix.c deleted file mode 100644 index bdb763ad6f5b..000000000000 --- a/usr.sbin/faithd/prefix.c +++ /dev/null @@ -1,345 +0,0 @@ -/* $KAME: prefix.c,v 1.13 2003/09/02 22:50:17 itojun Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (C) 2000 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef offsetof -#define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member)) -#endif - -#include "faithd.h" -#include "prefix.h" - -static int prefix_set(const char *, struct prefix *, int); -static struct config *config_load1(const char *); -#if 0 -static void config_show1(const struct config *); -static void config_show(void); -#endif - -struct config *config_list = NULL; -const int niflags = NI_NUMERICHOST; - -static int -prefix_set(const char *s, struct prefix *prefix, int slash) -{ - char *p = NULL, *q, *r; - struct addrinfo hints, *res = NULL; - int max; - - p = strdup(s); - if (!p) - goto fail; - q = strchr(p, '/'); - if (q) { - if (!slash) - goto fail; - *q++ = '\0'; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_family = PF_UNSPEC; - hints.ai_socktype = SOCK_DGRAM; /*dummy*/ - hints.ai_flags = AI_NUMERICHOST; - if (getaddrinfo(p, "0", &hints, &res)) - goto fail; - if (res->ai_next || res->ai_addrlen > sizeof(prefix->a)) - goto fail; - memcpy(&prefix->a, res->ai_addr, res->ai_addrlen); - - switch (prefix->a.ss_family) { - case AF_INET: - max = 32; - break; - case AF_INET6: - max = 128; - break; - default: - max = -1; - break; - } - - if (q) { - r = NULL; - prefix->l = (int)strtoul(q, &r, 10); - if (!*q || *r) - goto fail; - if (prefix->l < 0 || prefix->l > max) - goto fail; - } else - prefix->l = max; - - if (p) - free(p); - if (res) - freeaddrinfo(res); - return 0; - -fail: - if (p) - free(p); - if (res) - freeaddrinfo(res); - return -1; -} - -const char * -prefix_string(const struct prefix *prefix) -{ - static char buf[NI_MAXHOST + 20]; - char hbuf[NI_MAXHOST]; - - if (getnameinfo((const struct sockaddr *)&prefix->a, prefix->a.ss_len, - hbuf, sizeof(hbuf), NULL, 0, niflags)) - return NULL; - snprintf(buf, sizeof(buf), "%s/%d", hbuf, prefix->l); - return buf; -} - -int -prefix_match(const struct prefix *prefix, const struct sockaddr *sa) -{ - struct sockaddr_storage a, b; - char *pa, *pb; - int off, l; - - if (prefix->a.ss_family != sa->sa_family || - prefix->a.ss_len != sa->sa_len) - return 0; - - if (prefix->a.ss_len > sizeof(a) || sa->sa_len > sizeof(b)) - return 0; - - switch (prefix->a.ss_family) { - case AF_INET: - off = offsetof(struct sockaddr_in, sin_addr); - break; - case AF_INET6: - off = offsetof(struct sockaddr_in6, sin6_addr); - break; - default: - if (memcmp(&prefix->a, sa, prefix->a.ss_len) != 0) - return 0; - else - return 1; - } - - memcpy(&a, &prefix->a, prefix->a.ss_len); - memcpy(&b, sa, sa->sa_len); - l = prefix->l / 8 + (prefix->l % 8 ? 1 : 0); - - /* overrun check */ - if (off + l > a.ss_len) - return 0; - - pa = ((char *)&a) + off; - pb = ((char *)&b) + off; - if (prefix->l % 8) { - pa[prefix->l / 8] &= 0xff00 >> (prefix->l % 8); - pb[prefix->l / 8] &= 0xff00 >> (prefix->l % 8); - } - if (memcmp(pa, pb, l) != 0) - return 0; - else - return 1; -} - -/* - * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr] - * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1 - */ -static struct config * -config_load1(const char *line) -{ - struct config *conf; - char buf[BUFSIZ]; - char *p; - char *token[4]; - int i; - - if (strlen(line) + 1 > sizeof(buf)) - return NULL; - strlcpy(buf, line, sizeof(buf)); - - p = strchr(buf, '\n'); - if (!p) - return NULL; - *p = '\0'; - p = strchr(buf, '#'); - if (p) - *p = '\0'; - if (strlen(buf) == 0) - return NULL; - - p = buf; - memset(token, 0, sizeof(token)); - for (i = 0; i < sizeof(token) / sizeof(token[0]); i++) { - token[i] = strtok(p, "\t "); - p = NULL; - if (token[i] == NULL) - break; - } - /* extra tokens? */ - if (strtok(p, "\t ") != NULL) - return NULL; - /* insufficient tokens */ - switch (i) { - case 3: - case 4: - break; - default: - return NULL; - } - - conf = (struct config *)malloc(sizeof(*conf)); - if (conf == NULL) - return NULL; - memset(conf, 0, sizeof(*conf)); - - if (strcasecmp(token[1], "permit") == 0) - conf->permit = 1; - else if (strcasecmp(token[1], "deny") == 0) - conf->permit = 0; - else { - /* invalid keyword is considered as "deny" */ - conf->permit = 0; - } - - if (prefix_set(token[0], &conf->match, 1) < 0) - goto fail; - if (prefix_set(token[2], &conf->dest, 1) < 0) - goto fail; - if (token[3]) { - if (prefix_set(token[3], &conf->src, 0) < 0) - goto fail; - } - - return conf; - -fail: - free(conf); - return NULL; -} - -int -config_load(const char *configfile) -{ - FILE *fp; - char buf[BUFSIZ]; - struct config *conf, *p; - struct config sentinel; - - config_list = NULL; - - if (!configfile) - configfile = _PATH_PREFIX_CONF; - fp = fopen(configfile, "r"); - if (fp == NULL) - return -1; - - p = &sentinel; - sentinel.next = NULL; - while (fgets(buf, sizeof(buf), fp) != NULL) { - conf = config_load1(buf); - if (conf) { - p->next = conf; - p = p->next; - } - } - config_list = sentinel.next; - - fclose(fp); - return 0; -} - -#if 0 -static void -config_show1(const struct config *conf) -{ - const char *p; - - p = prefix_string(&conf->match); - printf("%s", p ? p : "?"); - - if (conf->permit) - printf(" permit"); - else - printf(" deny"); - - p = prefix_string(&conf->dest); - printf(" %s", p ? p : "?"); - - printf("\n"); -} - -static void -config_show() -{ - struct config *conf; - - for (conf = config_list; conf; conf = conf->next) - config_show1(conf); -} -#endif - -const struct config * -config_match(struct sockaddr *sa1, struct sockaddr *sa2) -{ - static struct config conf; - const struct config *p; - - if (sa1->sa_len > sizeof(conf.match.a) || - sa2->sa_len > sizeof(conf.dest.a)) - return NULL; - - memset(&conf, 0, sizeof(conf)); - if (!config_list) { - conf.permit = 1; - memcpy(&conf.match.a, sa1, sa1->sa_len); - memcpy(&conf.dest.a, sa2, sa2->sa_len); - return &conf; - } - - for (p = config_list; p; p = p->next) - if (prefix_match(&p->match, sa1) && prefix_match(&p->dest, sa2)) - return p; - - return NULL; -} diff --git a/usr.sbin/faithd/prefix.h b/usr.sbin/faithd/prefix.h deleted file mode 100644 index 4d6b3d59c463..000000000000 --- a/usr.sbin/faithd/prefix.h +++ /dev/null @@ -1,52 +0,0 @@ -/* $KAME: prefix.h,v 1.4 2001/09/05 03:04:21 itojun Exp $ */ -/* $FreeBSD$ */ - -/* - * Copyright (C) 2000 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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. - */ - -struct prefix { - struct sockaddr_storage a; - int l; -}; - -struct config { - struct config *next; - - int permit; - struct prefix match; - struct prefix dest; - struct prefix src; /* src to use for outgoing connection */ -}; - -#define _PATH_PREFIX_CONF "/etc/faithd.conf" - -extern const char *prefix_string(const struct prefix *); -extern int prefix_match(const struct prefix *, const struct sockaddr *); -extern int config_load(const char *); -extern const struct config *config_match(struct sockaddr *, struct sockaddr *); diff --git a/usr.sbin/faithd/tcp.c b/usr.sbin/faithd/tcp.c deleted file mode 100644 index 219769441471..000000000000 --- a/usr.sbin/faithd/tcp.c +++ /dev/null @@ -1,324 +0,0 @@ -/* $KAME: tcp.c,v 1.13 2003/09/02 22:49:21 itojun Exp $ */ - -/* - * Copyright (C) 1997 and 1998 WIDE Project. - * 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. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "faithd.h" - -static char tcpbuf[16*1024]; - /* bigger than MSS and may be lesser than window size */ -static int tblen, tboff, oob_exists; -static fd_set readfds, writefds, exceptfds; -static char atmark_buf[2]; -static pid_t cpid = (pid_t)0; -static pid_t ppid = (pid_t)0; -volatile time_t child_lastactive = (time_t)0; -static time_t parent_lastactive = (time_t)0; - -static void sig_ctimeout(int); -static void sig_child(int); -static void notify_inactive(void); -static void notify_active(void); -static void send_data(int, int, const char *, int); -static void relay(int, int, const char *, int); - -/* - * Inactivity timer: - * - child side (ppid != 0) will send SIGUSR1 to parent every (FAITH_TIMEOUT/4) - * second if traffic is active. if traffic is inactive, don't send SIGUSR1. - * - parent side (ppid == 0) will check the last SIGUSR1 it have seen. - */ -static void -sig_ctimeout(int sig __unused) -{ - /* parent side: record notification from the child */ - if (dflag) - syslog(LOG_DEBUG, "activity timer from child"); - child_lastactive = time(NULL); -} - -/* parent will terminate if child dies. */ -static void -sig_child(int sig __unused) -{ - int status; - pid_t pid; - - pid = wait3(&status, WNOHANG, (struct rusage *)0); - if (pid > 0 && WEXITSTATUS(status)) - syslog(LOG_WARNING, "child %ld exit status 0x%x", - (long)pid, status); - exit_success("terminate connection due to child termination"); -} - -static void -notify_inactive() -{ - time_t t; - - /* only on parent side... */ - if (ppid) - return; - - /* parent side should check for timeout. */ - t = time(NULL); - if (dflag) { - syslog(LOG_DEBUG, "parent side %sactive, child side %sactive", - (FAITH_TIMEOUT < t - parent_lastactive) ? "in" : "", - (FAITH_TIMEOUT < t - child_lastactive) ? "in" : ""); - } - - if (FAITH_TIMEOUT < t - child_lastactive - && FAITH_TIMEOUT < t - parent_lastactive) { - /* both side timeouted */ - signal(SIGCHLD, SIG_DFL); - kill(cpid, SIGTERM); - wait(NULL); - exit_failure("connection timeout"); - /* NOTREACHED */ - } -} - -static void -notify_active() -{ - if (ppid) { - /* child side: notify parent of active traffic */ - time_t t; - t = time(NULL); - if (FAITH_TIMEOUT / 4 < t - child_lastactive) { - if (kill(ppid, SIGUSR1) < 0) { - exit_failure("terminate connection due to parent termination"); - /* NOTREACHED */ - } - child_lastactive = t; - } - } else { - /* parent side */ - parent_lastactive = time(NULL); - } -} - -static void -send_data(int s_rcv, int s_snd, const char *service __unused, int direction) -{ - int cc; - - if (oob_exists) { - cc = send(s_snd, atmark_buf, 1, MSG_OOB); - if (cc == -1) - goto retry_or_err; - oob_exists = 0; - if (s_rcv >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_rcv, &exceptfds); - } - - for (; tboff < tblen; tboff += cc) { - cc = write(s_snd, tcpbuf + tboff, tblen - tboff); - if (cc < 0) - goto retry_or_err; - } -#ifdef DEBUG - if (tblen) { - if (tblen >= sizeof(tcpbuf)) - tblen = sizeof(tcpbuf) - 1; - tcpbuf[tblen] = '\0'; - syslog(LOG_DEBUG, "from %s (%dbytes): %s", - direction == 1 ? "client" : "server", tblen, tcpbuf); - } -#endif /* DEBUG */ - tblen = 0; tboff = 0; - if (s_snd >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_CLR(s_snd, &writefds); - if (s_rcv >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_rcv, &readfds); - return; - retry_or_err: - if (errno != EAGAIN) - exit_failure("writing relay data failed: %s", strerror(errno)); - if (s_snd >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_snd, &writefds); -} - -static void -relay(int s_rcv, int s_snd, const char *service, int direction) -{ - int atmark, error, maxfd; - struct timeval tv; - fd_set oreadfds, owritefds, oexceptfds; - - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_ZERO(&exceptfds); - fcntl(s_snd, F_SETFD, O_NONBLOCK); - oreadfds = readfds; owritefds = writefds; oexceptfds = exceptfds; - if (s_rcv >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_rcv, &readfds); - FD_SET(s_rcv, &exceptfds); - oob_exists = 0; - maxfd = (s_rcv > s_snd) ? s_rcv : s_snd; - - for (;;) { - tv.tv_sec = FAITH_TIMEOUT / 4; - tv.tv_usec = 0; - oreadfds = readfds; - owritefds = writefds; - oexceptfds = exceptfds; - error = select(maxfd + 1, &readfds, &writefds, &exceptfds, &tv); - if (error == -1) { - if (errno == EINTR) - continue; - exit_failure("select: %s", strerror(errno)); - } else if (error == 0) { - readfds = oreadfds; - writefds = owritefds; - exceptfds = oexceptfds; - notify_inactive(); - continue; - } - - /* activity notification */ - notify_active(); - - if (FD_ISSET(s_rcv, &exceptfds)) { - error = ioctl(s_rcv, SIOCATMARK, &atmark); - if (error != -1 && atmark == 1) { - int cc; - oob_read_retry: - cc = read(s_rcv, atmark_buf, 1); - if (cc == 1) { - if (s_rcv >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_CLR(s_rcv, &exceptfds); - if (s_snd >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_snd, &writefds); - oob_exists = 1; - } else if (cc == -1) { - if (errno == EINTR) - goto oob_read_retry; - exit_failure("reading oob data failed" - ": %s", - strerror(errno)); - } - } - } - if (FD_ISSET(s_rcv, &readfds)) { - relaydata_read_retry: - tblen = read(s_rcv, tcpbuf, sizeof(tcpbuf)); - tboff = 0; - - switch (tblen) { - case -1: - if (errno == EINTR) - goto relaydata_read_retry; - exit_failure("reading relay data failed: %s", - strerror(errno)); - /* NOTREACHED */ - case 0: - /* to close opposite-direction relay process */ - shutdown(s_snd, 0); - - close(s_rcv); - close(s_snd); - exit_success("terminating %s relay", service); - /* NOTREACHED */ - default: - if (s_rcv >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_CLR(s_rcv, &readfds); - if (s_snd >= FD_SETSIZE) - exit_failure("descriptor too big"); - FD_SET(s_snd, &writefds); - break; - } - } - if (FD_ISSET(s_snd, &writefds)) - send_data(s_rcv, s_snd, service, direction); - } -} - -void -tcp_relay(int s_src, int s_dst, const char *service) -{ - syslog(LOG_INFO, "starting %s relay", service); - - child_lastactive = parent_lastactive = time(NULL); - - cpid = fork(); - switch (cpid) { - case -1: - exit_failure("tcp_relay: can't fork grand child: %s", - strerror(errno)); - /* NOTREACHED */ - case 0: - /* child process: relay going traffic */ - ppid = getppid(); - /* this is child so reopen log */ - closelog(); - openlog(logname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); - relay(s_src, s_dst, service, 1); - /* NOTREACHED */ - default: - /* parent process: relay coming traffic */ - ppid = (pid_t)0; - signal(SIGUSR1, sig_ctimeout); - signal(SIGCHLD, sig_child); - relay(s_dst, s_src, service, 0); - /* NOTREACHED */ - } -} diff --git a/usr.sbin/faithd/test/faithd.rb b/usr.sbin/faithd/test/faithd.rb deleted file mode 100644 index 682f540db98a..000000000000 --- a/usr.sbin/faithd/test/faithd.rb +++ /dev/null @@ -1,312 +0,0 @@ -# faithd, ruby version. requires v6-enabled ruby. -# -# highly experimental (not working right at all) and very limited -# functionality. -# -# $Id: faithd.rb,v 1.1.2.4 1999/05/10 17:06:30 itojun Exp $ -# $FreeBSD$ - -require "socket" -require "thread" - -# XXX should be derived from system headers -IPPROTO_IPV6 = 41 -IPV6_FAITH = 29 -DEBUG = true -DEBUG_LOOPBACK = true - -# TODO: OOB data handling -def tcpcopy(s1, s2, m) - STDERR.print "tcpcopy #{s1} #{s2}\n" if DEBUG - buf = "" - while TRUE - begin - buf = s1.sysread(100) - s2.syswrite(buf) - rescue EOFError - break - rescue IOError - break - end - end - STDERR.print "tcpcopy #{s1} #{s2} finished\n" if DEBUG - s1.shutdown(0) - s2.shutdown(1) -end - -def relay_ftp_passiveconn(s6, s4, dport6, dport4) - Thread.start do - d6 = TCPserver.open("::", dport6).accept - d4 = TCPsocket.open(s4.getpeer[3], dport4) - t = [] - t[0] = Thread.start do - tcpcopy(d6, d4) - end - t[1] = Thread.start do - tcpcopy(d4, d6) - end - for i in t - i.join - end - d4.close - d6.close - end -end - -def ftp_parse_2428(line) - if (line[0] != line[line.length - 1]) - return nil - end - t = line.split(line[0 .. 0]) # as string - if (t.size != 4 || t[1] !~ /^[12]$/ || t[3] !~ /^\d+$/) - return nil - end - return t[1 .. 3] -end - -def relay_ftp_command(s6, s4, state) - STDERR.print "relay_ftp_command start\n" if DEBUG - while TRUE - begin - STDERR.print "s6.gets\n" if DEBUG - line = s6.gets - STDERR.print "line is #{line}\n" if DEBUG - if line == nil - return nil - end - - # translate then copy - STDERR.print "line is #{line}\n" if DEBUG - if (line =~ /^EPSV\r\n/i) - STDERR.print "EPSV -> PASV\n" if DEBUG - line = "PASV\n" - state = "EPSV" - elsif (line =~ /^EPRT\s+(.+)\r\n/i) - t = ftp_parse_2428($1) - if t == nil - s6.puts "501 illegal parameter to EPRT\r\n" - next - end - - # some tricks should be here - s6.puts "501 illegal parameter to EPRT\r\n" - next - end - STDERR.print "fail: send #{line} as is\n" if DEBUG - s4.puts(line) - break - rescue EOFError - return nil - rescue IOError - return nil - end - end - STDERR.print "relay_ftp_command finish\n" if DEBUG - return state -end - -def relay_ftp_status(s4, s6, state) - STDERR.print "relay_ftp_status start\n" if DEBUG - while TRUE - begin - line = s4.gets - if line == nil - return nil - end - - # translate then copy - s6.puts(line) - - next if line =~ /^\d\d\d-/ - next if line !~ /^\d/ - - # special post-processing - case line - when /^221 / # result to QUIT - s4.shutdown(0) - s6.shutdown(1) - end - - break if (line =~ /^\d\d\d /) - rescue EOFError - return nil - rescue IOError - return nil - end - end - STDERR.print "relay_ftp_status finish\n" if DEBUG - return state -end - -def relay_ftp(sock, name) - STDERR.print "relay_ftp(#{sock}, #{name})\n" if DEBUG - while TRUE - STDERR.print "relay_ftp(#{sock}, #{name}) accepting\n" if DEBUG - s = sock.accept - STDERR.print "relay_ftp(#{sock}, #{name}) accepted #{s}\n" if DEBUG - Thread.start do - threads = [] - STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG - s6 = s - dest6 = s.addr[3] - if !DEBUG_LOOPBACK - t = s.getsockname.unpack("x8 x12 C4") - dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}" - port4 = s.addr[1] - else - dest4 = "127.0.0.1" - port4 = "ftp" - end - if DEBUG - STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG - end - STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG - s4 = TCPsocket.open(dest4, port4) - STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG - state = 0 - while TRUE - # translate status line - state = relay_ftp_status(s4, s6, state) - break if state == nil - # translate command line - state = relay_ftp_command(s6, s4, state) - break if state == nil - end - STDERR.print "relay_ftp(#{sock}, #{name}) closing s4\n" if DEBUG - s4.close - STDERR.print "relay_ftp(#{sock}, #{name}) closing s6\n" if DEBUG - s6.close - STDERR.print "relay_ftp(#{sock}, #{name}) done\n" if DEBUG - end - end - STDERR.print "relay_ftp(#{sock}, #{name}) finished\n" if DEBUG -end - -def relay_tcp(sock, name) - STDERR.print "relay_tcp(#{sock}, #{name})\n" if DEBUG - while TRUE - STDERR.print "relay_tcp(#{sock}, #{name}) accepting\n" if DEBUG - s = sock.accept - STDERR.print "relay_tcp(#{sock}, #{name}) accepted #{s}\n" if DEBUG - Thread.start do - threads = [] - STDERR.print "accepted #{s} -> #{Thread.current}\n" if DEBUG - s6 = s - dest6 = s.addr[3] - if !DEBUG_LOOPBACK - t = s.getsockname.unpack("x8 x12 C4") - dest4 = "#{t[0]}.#{t[1]}.#{t[2]}.#{t[3]}" - port4 = s.addr[1] - else - dest4 = "127.0.0.1" - port4 = "telnet" - end - if DEBUG - STDERR.print "IPv6 dest: #{dest6} IPv4 dest: #{dest4}\n" if DEBUG - end - STDERR.print "connect to #{dest4} #{port4}\n" if DEBUG - s4 = TCPsocket.open(dest4, port4) - STDERR.print "connected to #{dest4} #{port4}, #{s4.addr[1]}\n" if DEBUG - [0, 1].each do |i| - threads[i] = Thread.start do - if (i == 0) - tcpcopy(s6, s4) - else - tcpcopy(s4, s6) - end - end - end - STDERR.print "relay_tcp(#{sock}, #{name}) wait\n" if DEBUG - for i in threads - STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i}\n" if DEBUG - i.join - STDERR.print "relay_tcp(#{sock}, #{name}) wait #{i} done\n" if DEBUG - end - STDERR.print "relay_tcp(#{sock}, #{name}) closing s4\n" if DEBUG - s4.close - STDERR.print "relay_tcp(#{sock}, #{name}) closing s6\n" if DEBUG - s6.close - STDERR.print "relay_tcp(#{sock}, #{name}) done\n" if DEBUG - end - end - STDERR.print "relay_tcp(#{sock}, #{name}) finished\n" if DEBUG -end - -def usage() - STDERR.print "usage: #{$0} [-f] port...\n" -end - -#------------------------------------------------------------ - -$mode = "tcp" - -while ARGV[0] =~ /^-/ do - case ARGV[0] - when /^-f/ - $mode = "ftp" - else - usage() - exit 0 - end - ARGV.shift -end - -if ARGV.length == 0 - usage() - exit 1 -end - -ftpport = Socket.getservbyname("ftp") - -res = [] -for port in ARGV - t = Socket.getaddrinfo(nil, port, Socket::PF_INET6, Socket::SOCK_STREAM, - nil, Socket::AI_PASSIVE) - if (t.size <= 0) - STDERR.print "FATAL: getaddrinfo failed (port=#{port})\n" - exit 1 - end - res += t -end - -sockpool = [] -names = [] -listenthreads = [] - -res.each do |i| - s = TCPserver.new(i[3], i[1]) - n = Socket.getnameinfo(s.getsockname, Socket::NI_NUMERICHOST|Socket::NI_NUMERICSERV).join(" port ") - if i[6] == IPPROTO_IPV6 - s.setsockopt(i[6], IPV6_FAITH, 1) - end - s.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1) - sockpool.push s - names.push n -end - -if DEBUG - (0 .. sockpool.size - 1).each do |i| - STDERR.print "listen[#{i}]: #{sockpool[i]} #{names[i]}\n" if DEBUG - end -end - -(0 .. sockpool.size - 1).each do |i| - listenthreads[i] = Thread.start do - if DEBUG - STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG - end - STDERR.print "listen[#{i}]: thread #{Thread.current}\n" if DEBUG - case $mode - when "tcp" - relay_tcp(sockpool[i], names[i]) - when "ftp" - relay_ftp(sockpool[i], names[i]) - end - end -end - -for i in listenthreads - i.join -end - -exit 0 diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index eebcfea6f601..c48f33ca93ed 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -69,7 +69,7 @@ __FBSDID("$FreeBSD$"); * or name a tcpmux service * or specify a unix domain socket * socket type stream/dgram/raw/rdm/seqpacket - * protocol tcp[4][6][/faith], udp[4][6], unix + * protocol tcp[4][6], udp[4][6], unix * wait/nowait single-threaded/multi-threaded * user[:group][/login-class] user/group/login-class to run daemon as * server program full path name @@ -1305,14 +1305,6 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m"); } #undef turnon -#ifdef IPV6_FAITH - if (sep->se_type == FAITH_TYPE) { - if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on, - sizeof(on)) < 0) { - syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m"); - } - } -#endif #ifdef IPSEC ipsecsetup(sep); #endif @@ -1744,15 +1736,15 @@ more: arg = sskip(&cp); if (strncmp(arg, "tcp", 3) == 0) { sep->se_proto = newstr(strsep(&arg, "/")); - if (arg != NULL) { - if (strcmp(arg, "faith") == 0) - sep->se_type = FAITH_TYPE; + if (arg != NULL && (strcmp(arg, "faith") == 0)) { + syslog(LOG_ERR, "faith has been deprecated"); + goto more; } } else { if (sep->se_type == NORM_TYPE && strncmp(arg, "faith/", 6) == 0) { - arg += 6; - sep->se_type = FAITH_TYPE; + syslog(LOG_ERR, "faith has been deprecated"); + goto more; } sep->se_proto = newstr(arg); } -- cgit v1.3 From 3eee258dfbccde59303cbf570d23ee96b8d969c5 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Sun, 16 Nov 2014 06:35:20 +0000 Subject: Add reachover Makefiles for contrib/netbsd-tests/lib/libpthread as lib/libthr/tests A variant of this code has been tested on amd64/i386 for some time by EMC/Isilon on 10-STABLE/11-CURRENT. It builds on other architectures, but the code will remain off until it's proven it works on virtual hardware or real hardware on other architectures Original work by: pho Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 4 +++ lib/libthr/Makefile | 2 ++ lib/libthr/Makefile.amd64 | 6 ++++ lib/libthr/Makefile.i386 | 6 ++++ lib/libthr/tests/Makefile | 58 ++++++++++++++++++++++++++++++++++++ lib/libthr/tests/dlopen/Makefile | 30 +++++++++++++++++++ lib/libthr/tests/dlopen/dso/Makefile | 19 ++++++++++++ 7 files changed, 125 insertions(+) create mode 100644 lib/libthr/Makefile.amd64 create mode 100644 lib/libthr/Makefile.i386 create mode 100644 lib/libthr/tests/Makefile create mode 100644 lib/libthr/tests/dlopen/Makefile create mode 100644 lib/libthr/tests/dlopen/dso/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index ae377acedc16..68c015d82902 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -149,6 +149,10 @@ .. libproc .. + libthr + dlopen + .. + .. libutil .. .. diff --git a/lib/libthr/Makefile b/lib/libthr/Makefile index cfcc41efb997..5cbd0aa3144b 100644 --- a/lib/libthr/Makefile +++ b/lib/libthr/Makefile @@ -64,4 +64,6 @@ SYMLINKS+=lib${LIB}_p.a ${LIBDIR}/libpthread_p.a CFLAGS+=-DSYSCALL_COMPAT .endif +.include + .include diff --git a/lib/libthr/Makefile.amd64 b/lib/libthr/Makefile.amd64 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/libthr/Makefile.amd64 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/libthr/Makefile.i386 b/lib/libthr/Makefile.i386 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/libthr/Makefile.i386 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/libthr/tests/Makefile b/lib/libthr/tests/Makefile new file mode 100644 index 000000000000..50f07f07e008 --- /dev/null +++ b/lib/libthr/tests/Makefile @@ -0,0 +1,58 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H} +SRCTOP= ${.CURDIR:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread + +TESTSDIR= ${TESTSBASE}/lib/libthr + +# TODO: t_name (missing pthread_getname_np support in FreeBSD) +NETBSD_ATF_TESTS_C= barrier_test +NETBSD_ATF_TESTS_C+= cond_test +NETBSD_ATF_TESTS_C+= condwait_test +NETBSD_ATF_TESTS_C+= detach_test +NETBSD_ATF_TESTS_C+= equal_test +NETBSD_ATF_TESTS_C+= fork_test +NETBSD_ATF_TESTS_C+= fpu_test +NETBSD_ATF_TESTS_C+= join_test +NETBSD_ATF_TESTS_C+= kill_test +NETBSD_ATF_TESTS_C+= mutex_test +NETBSD_ATF_TESTS_C+= once_test +NETBSD_ATF_TESTS_C+= preempt_test +NETBSD_ATF_TESTS_C+= rwlock_test +NETBSD_ATF_TESTS_C+= sem_test +NETBSD_ATF_TESTS_C+= sigmask_test +NETBSD_ATF_TESTS_C+= sigsuspend_test +NETBSD_ATF_TESTS_C+= siglongjmp_test +NETBSD_ATF_TESTS_C+= sleep_test +NETBSD_ATF_TESTS_C+= swapcontext_test + +NETBSD_ATF_TESTS_SH= atexit_test +NETBSD_ATF_TESTS_SH+= cancel_test +NETBSD_ATF_TESTS_SH+= exit_test +NETBSD_ATF_TESTS_SH+= resolv_test + +DPADD+= ${LIBPTHREAD} +LDADD+= -lpthread +DPADD.fpu_test+= ${LIBM} +LDADD.fpu_test+= -lm +DPADD.sem_test+= ${LIBRT} +LDADD.sem_test+= -lrt + +BINDIR= ${TESTSDIR} + +PROGS= h_atexit +PROGS+= h_cancel +PROGS+= h_exit +PROGS+= h_resolv + +FILESDIR= ${TESTSDIR} +FILES= d_mach + +TESTS_SUBDIRS= dlopen + +.include + +CFLAGS.condwait_test+= -I${SRCTOP}/contrib/netbsd-tests/lib/libc/gen + +.include diff --git a/lib/libthr/tests/dlopen/Makefile b/lib/libthr/tests/dlopen/Makefile new file mode 100644 index 000000000000..0764bfa15936 --- /dev/null +++ b/lib/libthr/tests/dlopen/Makefile @@ -0,0 +1,30 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread/dlopen + +.include + +TESTSDIR= ${TESTSBASE}/lib/libthr/dlopen + +CFLAGS+= -DTESTDIR=\"${TESTSDIR:Q}/\" +LDFLAGS+= -L${.OBJDIR}/dso -Wl,-rpath=${TESTDIR} + +.if !defined(NO_PIC) +SUBDIR+= dso + +NETBSD_ATF_TESTS_C= dlopen_test +NETBSD_ATF_TESTS_C+= main_pthread_create_test +# XXX: this blocks running the testcase +#NETBSD_ATF_TESTS_C+= dso_pthread_create_test + +.for t in dlopen_test main_pthread_create_test +DPADD.$t+= ${LIBPTHREAD} +LDADD.$t+= -lpthread +.endfor +.endif + +.include + +.include diff --git a/lib/libthr/tests/dlopen/dso/Makefile b/lib/libthr/tests/dlopen/dso/Makefile new file mode 100644 index 000000000000..080dec941a8c --- /dev/null +++ b/lib/libthr/tests/dlopen/dso/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H:H:H} +SRCTOP= ${.CURDIR:H:H:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libpthread/dlopen/dso + +SHLIB= h_pthread_dlopen +SHLIB_MAJOR= 1 +SHLIB_NAME= h_pthread_dlopen.so.${SHLIB_MAJOR} +SRCS= h_pthread_dlopen.c + +DPADD+= ${LIBPTHREAD} +LDADD+= -lpthread + +LIBDIR= ${TESTSBASE}/lib/libthr/dlopen + +.include + +.include -- cgit v1.3 From 536b1b933ed25a91ae99dcfa99c4459eae04307e Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Sun, 16 Nov 2014 07:03:19 +0000 Subject: Add reachover Makefiles for contrib/netbsd-tests/lib/librt A variant of this code has been tested on amd64/i386 for some time by EMC/Isilon on 10-STABLE/11-CURRENT. It builds on other architectures, but the code will remain off until it's proven it works on virtual hardware or real hardware on other architectures Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ lib/librt/Makefile | 4 ++++ lib/librt/Makefile.amd64 | 6 ++++++ lib/librt/Makefile.i386 | 6 ++++++ lib/librt/tests/Makefile | 17 +++++++++++++++++ 5 files changed, 35 insertions(+) create mode 100644 lib/librt/Makefile.amd64 create mode 100644 lib/librt/Makefile.i386 create mode 100644 lib/librt/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 68c015d82902..ffa8bd72d472 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -149,6 +149,8 @@ .. libproc .. + librt + .. libthr dlopen .. diff --git a/lib/librt/Makefile b/lib/librt/Makefile index f624cf7b1d50..bd6ec0717d91 100644 --- a/lib/librt/Makefile +++ b/lib/librt/Makefile @@ -1,5 +1,7 @@ # $FreeBSD$ +.include + LIB=rt SHLIB_MAJOR= 1 CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR} @@ -18,4 +20,6 @@ PRECIOUSLIB= VERSION_MAP= ${.CURDIR}/Version.map +.include + .include diff --git a/lib/librt/Makefile.amd64 b/lib/librt/Makefile.amd64 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/librt/Makefile.amd64 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/librt/Makefile.i386 b/lib/librt/Makefile.i386 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/librt/Makefile.i386 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/librt/tests/Makefile b/lib/librt/tests/Makefile new file mode 100644 index 000000000000..224f52ea85aa --- /dev/null +++ b/lib/librt/tests/Makefile @@ -0,0 +1,17 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H} +SRCTOP= ${.CURDIR:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/librt + +TESTSDIR= ${TESTSBASE}/lib/librt + +DPADD+= ${LIBRT} +LDADD+= -lrt + +NETBSD_ATF_TESTS_C= sched_test +NETBSD_ATF_TESTS_C+= sem_test + +.include + +.include -- cgit v1.3 From 4cef7be5c3b8811011ee166f169cce3b48dae7f2 Mon Sep 17 00:00:00 2001 From: Enji Cooper Date: Mon, 17 Nov 2014 09:19:09 +0000 Subject: Add reachover Makefiles for contrib/netbsd-tests/lib/librt A variant of this code has been tested on amd64/i386 for some time by EMC/Isilon on 10-STABLE/11-CURRENT. It builds on other architectures, but the code will remain off until it's proven it works on virtual hardware or real hardware on other architectures Sponsored by: EMC / Isilon Storage Division --- etc/mtree/BSD.tests.dist | 2 ++ lib/msun/Makefile | 4 +++ lib/msun/Makefile.amd64 | 6 +++++ lib/msun/Makefile.i386 | 6 +++++ lib/msun/tests/Makefile | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 lib/msun/Makefile.amd64 create mode 100644 lib/msun/Makefile.i386 create mode 100644 lib/msun/tests/Makefile (limited to 'etc') diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index ffa8bd72d472..8604c55932b5 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -157,6 +157,8 @@ .. libutil .. + msun + .. .. libexec atf diff --git a/lib/msun/Makefile b/lib/msun/Makefile index e8277676818c..aee0f2d03315 100644 --- a/lib/msun/Makefile +++ b/lib/msun/Makefile @@ -219,4 +219,8 @@ MLINKS+=tan.3 tanf.3 tan.3 tanl.3 MLINKS+=tanh.3 tanhf.3 tanh.3 tanhl.3 MLINKS+=trunc.3 truncf.3 trunc.3 truncl.3 +.include + +.include + .include diff --git a/lib/msun/Makefile.amd64 b/lib/msun/Makefile.amd64 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/msun/Makefile.amd64 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/msun/Makefile.i386 b/lib/msun/Makefile.i386 new file mode 100644 index 000000000000..dd0f5b0cfb2d --- /dev/null +++ b/lib/msun/Makefile.i386 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +.if ${MK_TESTS} != "no" +SUBDIR+= tests +.endif + diff --git a/lib/msun/tests/Makefile b/lib/msun/tests/Makefile new file mode 100644 index 000000000000..4261e4865b52 --- /dev/null +++ b/lib/msun/tests/Makefile @@ -0,0 +1,63 @@ +# $FreeBSD$ + +OBJTOP= ${.OBJDIR:H:H:H} +SRCTOP= ${.CURDIR:H:H:H} +TESTSRC= ${SRCTOP}/contrib/netbsd-tests/lib/libm + +TESTSDIR= ${TESTSBASE}/lib/msun + +.if ${MACHINE} == "sparc" || ${MACHINE} == "i386" \ + || ${MACHINE} == "amd64" || ${MACHINE_CPU} == "arm" \ + || ${MACHINE} == "sparc64" +CFLAGS+= -DHAVE_FENV_H +.endif + +.if ${MACHINE} == "amd64" || ${MACHINE} == "i386" +CFLAGS+= -D__HAVE_LONG_DOUBLE +.endif + +NETBSD_ATF_TESTS_C= acos_test +NETBSD_ATF_TESTS_C+= asin_test +NETBSD_ATF_TESTS_C+= atan_test +NETBSD_ATF_TESTS_C+= cbrt_test +NETBSD_ATF_TESTS_C+= ceil_test +NETBSD_ATF_TESTS_C+= cos_test +NETBSD_ATF_TESTS_C+= cosh_test +NETBSD_ATF_TESTS_C+= erf_test +NETBSD_ATF_TESTS_C+= exp_test +NETBSD_ATF_TESTS_C+= fmod_test +NETBSD_ATF_TESTS_C+= infinity_test +NETBSD_ATF_TESTS_C+= ldexp_test +NETBSD_ATF_TESTS_C+= log_test +NETBSD_ATF_TESTS_C+= pow_test +NETBSD_ATF_TESTS_C+= precision_test +NETBSD_ATF_TESTS_C+= round_test +NETBSD_ATF_TESTS_C+= scalbn_test +NETBSD_ATF_TESTS_C+= sin_test +NETBSD_ATF_TESTS_C+= sinh_test +NETBSD_ATF_TESTS_C+= sqrt_test +NETBSD_ATF_TESTS_C+= tan_test +NETBSD_ATF_TESTS_C+= tanh_test + +CSTD= c99 + +LDADD+= -lm +DPADD+= ${LIBM} +#COPTS+= -Wfloat-equal + +# Copied from lib/msun/Makefile +.if ${MACHINE_CPUARCH} == "i386" +ARCH_SUBDIR= i387 +.else +ARCH_SUBDIR= ${MACHINE_CPUARCH} +.endif + +.include "../${ARCH_SUBDIR}/Makefile.inc" + +# XXX: for some odd reason float.h doesn't tell the full story about what the +# precision is. +CFLAGS+= -DLDBL_PREC=${LDBL_PREC} + +.include + +.include -- cgit v1.3 From c2384debfc94ca908f8c4903a7373cba74e8be50 Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Tue, 18 Nov 2014 16:31:00 +0000 Subject: Missed a terminating ';'. X-MFC-with: r273009 --- etc/devd/apple.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'etc') diff --git a/etc/devd/apple.conf b/etc/devd/apple.conf index 7f066cdf5ad7..9a84542d0905 100644 --- a/etc/devd/apple.conf +++ b/etc/devd/apple.conf @@ -77,4 +77,4 @@ notify 10 { match "subsystem" "POWER"; match "type" "ACLINE"; action "/etc/rc.d/power_profile $notify"; -} +}; -- cgit v1.3