diff options
author | Alexander Eremin <a.eremin@nexenta.com> | 2018-12-17 08:42:40 +0000 |
---|---|---|
committer | Andy Fiddaman <omnios@citrus-it.co.uk> | 2019-02-11 17:20:31 +0000 |
commit | 2b987d42b0ad07d74e39b18a2498709e5195d7e3 (patch) | |
tree | f8de9dddd4498d866eea68b04328ce9622f8b96e /usr/src | |
parent | 7d732bb0c50cbe80dedb2fdedd5ecfa51b90c302 (diff) | |
download | illumos-gate-2b987d42b0ad07d74e39b18a2498709e5195d7e3.tar.gz |
9696 add /etc/system.d support
Portions contributed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/Targetdirs | 3 | ||||
-rw-r--r-- | usr/src/cmd/boot/bootadm/bootadm.c | 151 | ||||
-rw-r--r-- | usr/src/cmd/boot/filelist/i386/filelist.ramdisk | 1 | ||||
-rw-r--r-- | usr/src/cmd/nsadmin/system | 15 | ||||
-rw-r--r-- | usr/src/man/man4/system.4 | 28 | ||||
-rw-r--r-- | usr/src/pkg/manifests/SUNWcs.mf | 3 | ||||
-rw-r--r-- | usr/src/uts/common/os/modctl.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/os/modsysfile.c | 122 | ||||
-rw-r--r-- | usr/src/uts/common/sys/modctl.h | 1 |
9 files changed, 264 insertions, 67 deletions
diff --git a/usr/src/Targetdirs b/usr/src/Targetdirs index d17f120783..25ee9bc38a 100644 --- a/usr/src/Targetdirs +++ b/usr/src/Targetdirs @@ -26,7 +26,7 @@ # Copyright 2012 OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2014 Garrett D'Amore <garrett@damore.org> # Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> -# Copyright 2016 Nexenta Systems, Inc. +# Copyright 2017 Nexenta Systems, Inc. # Copyright 2017 RackTop Systems. # Copyright 2019 OmniOS Community Edition (OmniOSce) Association. # @@ -178,6 +178,7 @@ DIRS= \ /etc/svc/profile \ /etc/svc/profile/site \ /etc/svc/volatile \ + /etc/system.d \ /etc/tm \ /etc/usb \ /etc/user_attr.d \ diff --git a/usr/src/cmd/boot/bootadm/bootadm.c b/usr/src/cmd/boot/bootadm/bootadm.c index 36d167fafb..f0de13c1ed 100644 --- a/usr/src/cmd/boot/bootadm/bootadm.c +++ b/usr/src/cmd/boot/bootadm/bootadm.c @@ -24,7 +24,7 @@ * Copyright 2012 Milan Jurik. All rights reserved. * Copyright (c) 2015 by Delphix. All rights reserved. * Copyright 2016 Toomas Soome <tsoome@me.com> - * Copyright 2016 Nexenta Systems, Inc. + * Copyright 2017 Nexenta Systems, Inc. * Copyright 2018 OmniOS Community Edition (OmniOSce) Association. */ @@ -160,6 +160,9 @@ typedef enum { #define STAGE1 "/boot/grub/stage1" #define STAGE2 "/boot/grub/stage2" +#define ETC_SYSTEM_DIR "etc/system.d" +#define SELF_ASSEMBLY "etc/system.d/.self-assembly" + /* * Default file attributes */ @@ -245,6 +248,7 @@ static int bam_lock_fd = -1; static int bam_zfs; static int bam_mbr; char rootbuf[PATH_MAX] = "/"; +static char self_assembly[PATH_MAX]; static int bam_update_all; static int bam_alt_platform; static char *bam_platform; @@ -283,6 +287,7 @@ static error_t read_list(char *, filelist_t *); static error_t set_option(menu_t *, char *, char *); static error_t set_kernel(menu_t *, menu_cmd_t, char *, char *, size_t); static error_t get_kernel(menu_t *, menu_cmd_t, char *, size_t); +static error_t build_etc_system_dir(char *); static char *expand_path(const char *); static long s_strtol(char *); @@ -2459,6 +2464,19 @@ cmpstat( } } + /* + * Update self-assembly file if there are changes in + * /etc/system.d directory + */ + if (strstr(file, ETC_SYSTEM_DIR)) { + ret = update_dircache(self_assembly, flags); + if (ret == BAM_ERROR) { + bam_error(_("directory cache update failed " + "for %s\n"), file); + return (-1); + } + } + if (bam_verbose) { if (bam_smf_check) bam_print(" %s\n", file); @@ -3791,6 +3809,131 @@ out_path_err: return (BAM_ERROR); } +static int +assemble_systemfile(char *infilename, char *outfilename) +{ + char buf[BUFSIZ]; + FILE *infile, *outfile; + size_t n; + + if ((infile = fopen(infilename, "r")) == NULL) { + bam_error(_("failed to open file: %s: %s\n"), infilename, + strerror(errno)); + return (BAM_ERROR); + } + + if ((outfile = fopen(outfilename, "a")) == NULL) { + bam_error(_("failed to open file: %s: %s\n"), outfilename, + strerror(errno)); + (void) fclose(infile); + return (BAM_ERROR); + } + + while ((n = fread(buf, 1, sizeof (buf), infile)) > 0) { + if (fwrite(buf, 1, n, outfile) != n) { + bam_error(_("failed to write file: %s: %s\n"), + outfilename, strerror(errno)); + (void) fclose(infile); + (void) fclose(outfile); + return (BAM_ERROR); + } + } + + (void) fclose(infile); + (void) fclose(outfile); + + return (BAM_SUCCESS); +} + +/* + * Concatenate all files (except those starting with a dot) + * from /etc/system.d directory into a single /etc/system.d/.self-assembly + * file. The kernel reads it before /etc/system file. + */ +static error_t +build_etc_system_dir(char *root) +{ + struct dirent **filelist; + char path[PATH_MAX], tmpfile[PATH_MAX]; + int i, files, sysfiles = 0; + int ret = BAM_SUCCESS; + struct stat st; + timespec_t times[2]; + + (void) snprintf(path, sizeof (path), "%s/%s", root, ETC_SYSTEM_DIR); + (void) snprintf(self_assembly, sizeof (self_assembly), + "%s%s", root, SELF_ASSEMBLY); + (void) snprintf(tmpfile, sizeof (tmpfile), "%s.%ld", + self_assembly, (long)getpid()); + + if (stat(self_assembly, &st) >= 0 && (st.st_mode & S_IFMT) == S_IFREG) { + times[0] = times[1] = st.st_mtim; + } else { + times[1].tv_nsec = 0; + } + + if ((files = scandir(path, &filelist, NULL, alphasort)) < 0) { + /* Don't fail the update if <ROOT>/etc/system.d doesn't exist */ + if (errno == ENOENT) + return (BAM_SUCCESS); + bam_error(_("can't read %s: %s\n"), path, strerror(errno)); + return (BAM_ERROR); + } + + (void) unlink(tmpfile); + + for (i = 0; i < files; i++) { + char filepath[PATH_MAX]; + char *fname; + + fname = filelist[i]->d_name; + + /* skip anything that starts with a dot */ + if (strncmp(fname, ".", 1) == 0) { + free(filelist[i]); + continue; + } + + if (bam_verbose) + bam_print(_("/etc/system.d adding %s/%s\n"), + path, fname); + + (void) snprintf(filepath, sizeof (filepath), "%s/%s", + path, fname); + + if ((assemble_systemfile(filepath, tmpfile)) < 0) { + bam_error(_("failed to append file: %s: %s\n"), + filepath, strerror(errno)); + ret = BAM_ERROR; + break; + } + sysfiles++; + } + + if (sysfiles > 0) { + if (rename(tmpfile, self_assembly) < 0) { + bam_error(_("failed to rename file: %s: %s\n"), tmpfile, + strerror(errno)); + return (BAM_ERROR); + } + + /* + * Use previous attribute times to avoid + * boot archive recreation. + */ + if (times[1].tv_nsec != 0 && + utimensat(AT_FDCWD, self_assembly, times, 0) != 0) { + bam_error(_("failed to change times: %s\n"), + strerror(errno)); + return (BAM_ERROR); + } + } else { + (void) unlink(tmpfile); + (void) unlink(self_assembly); + } + return (ret); +} + static error_t create_ramdisk(char *root) { @@ -4155,6 +4298,12 @@ update_archive(char *root, char *opt) } /* + * Process the /etc/system.d/.self-assembly file. + */ + if (build_etc_system_dir(bam_root) == BAM_ERROR) + return (BAM_ERROR); + + /* * Now check if an update is really needed. */ ret = update_required(root); diff --git a/usr/src/cmd/boot/filelist/i386/filelist.ramdisk b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk index 4483167ed3..70059bb5f3 100644 --- a/usr/src/cmd/boot/filelist/i386/filelist.ramdisk +++ b/usr/src/cmd/boot/filelist/i386/filelist.ramdisk @@ -16,6 +16,7 @@ etc/name_to_sysnum etc/path_to_inst etc/rtc_config etc/system +etc/system.d etc/hostid kernel platform/i86hvm/kernel diff --git a/usr/src/cmd/nsadmin/system b/usr/src/cmd/nsadmin/system index f4b74d6168..29da0b787c 100644 --- a/usr/src/cmd/nsadmin/system +++ b/usr/src/cmd/nsadmin/system @@ -1,4 +1,3 @@ -*ident "%Z%%M% %I% %E% SMI" /* SVR4 1.5 */ * * CDDL HEADER START * @@ -24,6 +23,18 @@ * SYSTEM SPECIFICATION FILE * +* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +* +* It is not recommended to edit this file directly but rather +* to deliver configuration fragments into files under /etc/system.d; +* files in /etc/system.d are combined in alphabetical order and read by +* the kernel before this file (/etc/system) is processed. +* +* Refer to the system(4) manual page for more information and +* recommendations on naming fragment files. +* +* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * moddir: * * Set the search path for modules. This has a format similar to the @@ -72,7 +83,7 @@ * * Cause these modules to be loaded at boot time, (just before mounting * the root filesystem) rather than at first reference. Note that -* forceload expects a filename which includes the directory. Also +* forceload expects a filename which includes the directory. Also * note that loading a module does not necessarily imply that it will * be installed. * diff --git a/usr/src/man/man4/system.4 b/usr/src/man/man4/system.4 index ebd0d96faa..1b42fc3a75 100644 --- a/usr/src/man/man4/system.4 +++ b/usr/src/man/man4/system.4 @@ -1,11 +1,12 @@ '\" te .\" Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. .\" Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> +.\" Copyright 2019 OmniOS Community Edition (OmniOSce) Association. .\" Copyright 1989 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH SYSTEM 4 "Jan 25, 2016" +.TH SYSTEM 4 "Jan 29, 2019" .SH NAME system \- system configuration information file .SH DESCRIPTION @@ -15,6 +16,23 @@ system kernel. The recommended procedure is to preserve the original \fBsystem\fR file before modifying it. .sp .LP +It is not recommended to edit the \fB/etc/system\fR file directly but rather +to deliver configuration fragments into files under \fB/etc/system.d\fR; +files in this directory are combined in alphabetical order and read by the +kernel before \fB/etc/system\fR is processed. Directives in \fB/etc/system\fR +therefore take precedence over any settings delivered in fragment files. +.sp +.LP +The recommended naming schema for the fragment files is to use the name of +the package which is delivering the file with '\fB/\fR' characters replaced +by '\fB:\fR'; file names that start with a dot (\fB.\fR) will be ignored. +.sp +.LP +If \fB/etc/system.d/\fR exists and contains any fragment files, +then the directory must also be writable or it will not be possible to +create or update the system boot archive. +.sp +.LP The \fBsystem\fR file contains commands which are read by the kernel during initialization and used to customize the operation of your system. These commands are useful for modifying the system's treatment of its loadable kernel @@ -286,9 +304,9 @@ escape sequences are supported within the quoted string: .sp .in +2 .nf -\en (newline) -\et (tab) -\eb (backspace) +\en (newline) +\et (tab) +\eb (backspace) .fi .in -2 .sp @@ -360,4 +378,4 @@ file that will work, you may specify \fB/dev/null\fR. This acts as an empty settings. .SH NOTES .LP -The \fB/etc/system\fR file is read only once, at boot time. +The \fBsystem\fR files are read only once, at boot time. diff --git a/usr/src/pkg/manifests/SUNWcs.mf b/usr/src/pkg/manifests/SUNWcs.mf index e186427aa0..a2db071aef 100644 --- a/usr/src/pkg/manifests/SUNWcs.mf +++ b/usr/src/pkg/manifests/SUNWcs.mf @@ -23,7 +23,7 @@ # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2013 Gary Mills # Copyright 2014 Garrett D'Amore <garrett@damore.org> -# Copyright 2015 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. # Copyright 2017 Toomas Soome <tsoome@me.com> # Copyright 2019 Peter Tribble. # @@ -90,6 +90,7 @@ dir path=etc/svc/profile/site group=sys dir path=etc/svc/volatile group=sys dir path=etc/sysevent group=sys dir path=etc/sysevent/config group=sys +dir path=etc/system.d group=sys dir path=etc/tm group=sys dir path=etc/user_attr.d group=sys dir path=export group=sys diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c index 35162eb558..a6392a5273 100644 --- a/usr/src/uts/common/os/modctl.c +++ b/usr/src/uts/common/os/modctl.c @@ -1234,7 +1234,7 @@ modctl_get_devid(dev_t dev, uint_t len, ddi_devid_t udevid) /*ARGSUSED*/ static int modctl_devid2paths(ddi_devid_t udevid, char *uminor_name, uint_t flag, - size_t *ulensp, char *upaths) + size_t *ulensp, char *upaths) { ddi_devid_t devid = NULL; int devid_len; @@ -3351,7 +3351,7 @@ mod_askparams() if ((fd = kobj_open(systemfile)) != -1L) kobj_close(fd); else - systemfile = NULL; + systemfile = self_assembly = NULL; /*CONSTANTCONDITION*/ while (1) { @@ -3363,12 +3363,13 @@ mod_askparams() if (s0[0] == '\0') break; else if (strcmp(s0, "/dev/null") == 0) { - systemfile = NULL; + systemfile = self_assembly = NULL; break; } else { if ((fd = kobj_open(s0)) != -1L) { kobj_close(fd); systemfile = s0; + self_assembly = NULL; break; } } diff --git a/usr/src/uts/common/os/modsysfile.c b/usr/src/uts/common/os/modsysfile.c index 8dca86880f..7d8580c334 100644 --- a/usr/src/uts/common/os/modsysfile.c +++ b/usr/src/uts/common/os/modsysfile.c @@ -22,7 +22,7 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. - * Copyright 2016 Nexenta Systems, Inc. + * Copyright 2017 Nexenta Systems, Inc. */ #include <sys/types.h> @@ -64,6 +64,7 @@ static char class_file[] = CLASSFILE; static char dafile[] = DAFILE; static char dacffile[] = DACFFILE; +char *self_assembly = "/etc/system.d/.self-assembly"; char *systemfile = "/etc/system"; /* name of ascii system file */ static struct sysparam *sysparam_hd; /* head of parameters list */ @@ -751,67 +752,80 @@ bad: return (NULL); } -void -mod_read_system_file(int ask) +static void +read_system_file(char *name) { register struct sysparam *sp; register struct _buf *file; register token_t token, last_tok; char tokval[MAXLINESIZE]; - mod_sysfile_arena = vmem_create("mod_sysfile", NULL, 0, 8, - segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP); - - if (ask) - mod_askparams(); - - if (systemfile != NULL) { - - if ((file = kobj_open_file(systemfile)) == - (struct _buf *)-1) { + if ((file = kobj_open_file(name)) == + (struct _buf *)-1) { + if (strcmp(name, systemfile) == 0) cmn_err(CE_WARN, "cannot open system file: %s", - systemfile); - } else { + name); + } else { + if (sysparam_tl == NULL) sysparam_tl = (struct sysparam *)&sysparam_hd; - last_tok = NEWLINE; - while ((token = kobj_lex(file, tokval, - sizeof (tokval))) != EOF) { - switch (token) { - case STAR: - case POUND: - /* - * Skip comments. - */ - kobj_find_eol(file); - break; - case NEWLINE: - kobj_newline(file); - last_tok = NEWLINE; - break; - case NAME: - if (last_tok != NEWLINE) { - kobj_file_err(CE_WARN, file, - extra_err, tokval); - kobj_find_eol(file); - } else if ((sp = do_sysfile_cmd(file, - tokval)) != NULL) { - sp->sys_next = NULL; - sysparam_tl->sys_next = sp; - sysparam_tl = sp; - } - last_tok = NAME; - break; - default: - kobj_file_err(CE_WARN, - file, tok_err, tokval); + last_tok = NEWLINE; + while ((token = kobj_lex(file, tokval, + sizeof (tokval))) != EOF) { + switch (token) { + case STAR: + case POUND: + /* + * Skip comments. + */ + kobj_find_eol(file); + break; + case NEWLINE: + kobj_newline(file); + last_tok = NEWLINE; + break; + case NAME: + if (last_tok != NEWLINE) { + kobj_file_err(CE_WARN, file, + extra_err, tokval); kobj_find_eol(file); - break; + } else if ((sp = do_sysfile_cmd(file, + tokval)) != NULL) { + sp->sys_next = NULL; + sysparam_tl->sys_next = sp; + sysparam_tl = sp; } + last_tok = NAME; + break; + default: + kobj_file_err(CE_WARN, + file, tok_err, tokval); + kobj_find_eol(file); + break; } - kobj_close_file(file); } + kobj_close_file(file); } +} + +void +mod_read_system_file(int ask) +{ + mod_sysfile_arena = vmem_create("mod_sysfile", NULL, 0, 8, + segkmem_alloc, segkmem_free, heap_arena, 0, VM_SLEEP); + + if (ask) + mod_askparams(); + + /* + * Read the user self-assembly file first + * to preserve existing system settings. + */ + if (self_assembly != NULL) + read_system_file(self_assembly); + + if (systemfile != NULL) + read_system_file(systemfile); /* * Sanity check of /etc/system. @@ -2384,16 +2398,16 @@ read_binding_file(char *bindfile, struct bind **hashtab, /* * read_dacf_binding_file() - * Read the /etc/dacf.conf file and build the dacf_rule_t database from it. + * Read the /etc/dacf.conf file and build the dacf_rule_t database from it. * * The syntax of a line in the dacf.conf file is: - * dev-spec [module:]op-set operation options [config-args]; + * dev-spec [module:]op-set operation options [config-args]; * * Where: - * 1. dev-spec is of the format: name="data" - * 2. operation is the operation that this rule matches. (i.e. pre-detach) - * 3. options is a comma delimited list of options (i.e. debug,foobar) - * 4. config-data is a whitespace delimited list of the format: name="data" + * 1. dev-spec is of the format: name="data" + * 2. operation is the operation that this rule matches. (i.e. pre-detach) + * 3. options is a comma delimited list of options (i.e. debug,foobar) + * 4. config-data is a whitespace delimited list of the format: name="data" */ int read_dacf_binding_file(char *filename) diff --git a/usr/src/uts/common/sys/modctl.h b/usr/src/uts/common/sys/modctl.h index fe7f812358..80982e28f7 100644 --- a/usr/src/uts/common/sys/modctl.h +++ b/usr/src/uts/common/sys/modctl.h @@ -546,6 +546,7 @@ typedef int modid_t; extern kmutex_t mod_lock; extern char *systemfile; +extern char *self_assembly; extern char **syscallnames; extern int moddebug; |