mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
Compare commits
63
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54055718ff | ||
|
|
1f61e76b51 | ||
|
|
69a8884af1 | ||
|
|
510c6cf29a | ||
|
|
c998438538 | ||
|
|
3649c5caff | ||
|
|
76322dbacd | ||
|
|
f9a559a82d | ||
|
|
9070dd1518 | ||
|
|
a54b5e9264 | ||
|
|
38f33e47a0 | ||
|
|
e7b58bcd8d | ||
|
|
d35c52a536 | ||
|
|
bbee93cbf5 | ||
|
|
4679e4f9c4 | ||
|
|
5d7d08d44a | ||
|
|
2b6caead9d | ||
|
|
e8fb91fe8b | ||
|
|
03a76b348d | ||
|
|
575826f183 | ||
|
|
5b37f4de45 | ||
|
|
45e294f985 | ||
|
|
af51f9df3c | ||
|
|
daf0e2ac5e | ||
|
|
4304e5eb17 | ||
|
|
421bcceeb8 | ||
|
|
c1ff6d05f5 | ||
|
|
d550f5d3db | ||
|
|
52ab77523b | ||
|
|
59fbe89293 | ||
|
|
2cfb122f55 | ||
|
|
c4f7dce098 | ||
|
|
6df7da0052 | ||
|
|
b329f45a9a | ||
|
|
04260ee25f | ||
|
|
72f50b48c4 | ||
|
|
563a73f034 | ||
|
|
79c1c663cb | ||
|
|
8fcffe2145 | ||
|
|
6e5c517269 | ||
|
|
34e6868261 | ||
|
|
62309d46fc | ||
|
|
9f5a40581d | ||
|
|
f8cb494d51 | ||
|
|
4e7ac0d6fc | ||
|
|
6e043e1a60 | ||
|
|
23b937f516 | ||
|
|
da2a3ace37 | ||
|
|
1b5ec3f62e | ||
|
|
516148ef3e | ||
|
|
6759c92a8d | ||
|
|
9929416e83 | ||
|
|
7ff6b770c6 | ||
|
|
fec900bd04 | ||
|
|
1b65664c28 | ||
|
|
6794374441 | ||
|
|
2487bb6cb1 | ||
|
|
e175267715 | ||
|
|
98e57db40f | ||
|
|
2a72044563 | ||
|
|
77bbc16437 | ||
|
|
4c1e483f92 | ||
|
|
af333ae2db |
No files matched your search
@@ -4,7 +4,7 @@
|
||||
The compilation of software known as FreeBSD is distributed under the
|
||||
following terms:
|
||||
|
||||
Copyright (c) 1992-2013 The FreeBSD Project. All rights reserved.
|
||||
Copyright (c) 1992-2009 The FreeBSD Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
|
||||
+1
-2
@@ -3,7 +3,7 @@ $FreeBSD$
|
||||
Please note that the content of this file is strictly advisory.
|
||||
No locks listed here are valid. The only strict review requirements
|
||||
are granted by core. These are documented in src/LOCKS and enforced
|
||||
by svnadmin/conf/approvers.
|
||||
by CVSROOT/approvers.
|
||||
|
||||
The source tree is a community effort. However, some folks go to the
|
||||
trouble of looking after particular areas of the tree. In return for
|
||||
@@ -129,7 +129,6 @@ gnu/usr.bin/send-pr bugmaster Pre-commit review requested.
|
||||
BSD.{local,x11*}.dist portmgr Pre-commit review requested, since these files interface with ports.
|
||||
usb core Please contact core@ before any major changes
|
||||
ncurses rafan Heads-up appreciated, try not to break it.
|
||||
isci(4) jimharris Pre-commit review requested.
|
||||
|
||||
Following are the entries from the Makefiles, and a few other sources.
|
||||
Please remove stale entries from both their origin, and this file.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
# check-old-dirs - List obsolete directories.
|
||||
# check-old-files - List obsolete files.
|
||||
# check-old-libs - List obsolete libraries.
|
||||
# delete-old - Delete obsolete directories/files.
|
||||
# delete-old - Delete obsolete directories/files/libraries.
|
||||
# delete-old-dirs - Delete obsolete directories.
|
||||
# delete-old-files - Delete obsolete files.
|
||||
# delete-old-libs - Delete obsolete libraries.
|
||||
@@ -57,7 +57,7 @@
|
||||
# 6. `mergemaster -p'
|
||||
# 7. `make installworld'
|
||||
# 8. `make delete-old'
|
||||
# 9. `mergemaster' (you may wish to use -i, along with -U or -F).
|
||||
# 9. `mergemaster' (you may wish to use -U or -ai).
|
||||
# 10. `reboot'
|
||||
# 11. `make delete-old-libs' (in case no 3rd party program uses them anymore)
|
||||
#
|
||||
@@ -139,12 +139,10 @@ buildworld: upgrade_checks
|
||||
#
|
||||
# In the following, the first 'rm' in a series will usually remove all
|
||||
# files and directories. If it does not, then there are probably some
|
||||
# files with file flags set, so this unsets them and tries the 'rm' a
|
||||
# files with chflags set, so this unsets them and tries the 'rm' a
|
||||
# second time. There are situations where this target will be cleaning
|
||||
# some directories via more than one method, but that duplication is
|
||||
# needed to correctly handle all the possible situations. Removing all
|
||||
# files without file flags set in the first 'rm' instance saves time,
|
||||
# because 'chflags' will need to operate on fewer files afterwards.
|
||||
# needed to correctly handle all the possible situations.
|
||||
#
|
||||
BW_CANONICALOBJDIR:=${MAKEOBJDIRPREFIX}${.CURDIR}
|
||||
cleanworld:
|
||||
@@ -272,9 +270,9 @@ make: .PHONY
|
||||
# existing system is.
|
||||
#
|
||||
.if make(universe)
|
||||
TARGETS?=amd64 arm i386 ia64 pc98 powerpc sparc64
|
||||
TARGETS?=amd64 arm i386 ia64 pc98 powerpc sparc64 sun4v
|
||||
|
||||
universe: universe_prologue upgrade_checks
|
||||
universe: universe_prologue
|
||||
universe_prologue:
|
||||
@echo "--------------------------------------------------------------"
|
||||
@echo ">>> make universe started on ${STARTTIME}"
|
||||
@@ -285,7 +283,7 @@ KERNCONFS!= cd ${.CURDIR}/sys/${target}/conf && \
|
||||
! -name DEFAULTS ! -name LINT
|
||||
KERNCONFS:= ${KERNCONFS:S/^NOTES$/LINT/}
|
||||
universe: universe_${target}
|
||||
.ORDER: universe_prologue upgrade_checks universe_${target}_prologue universe_${target} universe_epilogue
|
||||
.ORDER: universe_prologue universe_${target} universe_epilogue
|
||||
universe_${target}:
|
||||
.if !defined(MAKE_JUST_KERNELS)
|
||||
@echo ">> ${target} started on `LC_ALL=C date`"
|
||||
@@ -297,7 +295,6 @@ universe_${target}:
|
||||
"check _.${target}.buildworld for details")
|
||||
@echo ">> ${target} buildworld completed on `LC_ALL=C date`"
|
||||
.endif
|
||||
.if !defined(MAKE_JUST_WORLDS)
|
||||
.if exists(${.CURDIR}/sys/${target}/conf/NOTES)
|
||||
@(cd ${.CURDIR}/sys/${target}/conf && env __MAKE_CONF=/dev/null \
|
||||
${MAKE} LINT > ${.CURDIR}/_.${target}.makeLINT 2>&1 || \
|
||||
@@ -313,7 +310,6 @@ universe_${target}:
|
||||
echo "${target} ${kernel} kernel failed," \
|
||||
"check _.${target}.${kernel} for details")
|
||||
.endfor
|
||||
.endif
|
||||
@echo ">> ${target} completed on `LC_ALL=C date`"
|
||||
.endfor
|
||||
universe: universe_epilogue
|
||||
|
||||
+4
-12
@@ -88,7 +88,7 @@ CLEANDIR= cleandir
|
||||
.endif
|
||||
|
||||
CVS?= cvs
|
||||
CVSFLAGS?= -r RELENG_7 -P -d -I!
|
||||
CVSFLAGS?= -r RELENG_7_2 -P -d -I!
|
||||
SUP?= /usr/bin/csup
|
||||
SUPFLAGS?= -g -L 2
|
||||
.if defined(SUPHOST)
|
||||
@@ -263,7 +263,6 @@ LIB32WMAKEENV= MAKEOBJDIRPREFIX=${OBJTREE}/lib32 \
|
||||
VERSION="${VERSION}" \
|
||||
MACHINE=i386 \
|
||||
MACHINE_ARCH=i386 \
|
||||
MACHINE_CPU="i686 mmx sse sse2" \
|
||||
INSTALL="sh ${.CURDIR}/tools/install.sh" \
|
||||
PATH=${TMPPATH} \
|
||||
CC="${CC} ${LIB32FLAGS}" \
|
||||
@@ -735,17 +734,15 @@ buildkernel:
|
||||
@echo ">>> stage 2.3: build tools"
|
||||
@echo "--------------------------------------------------------------"
|
||||
cd ${KRNLOBJDIR}/${_kernel}; \
|
||||
PATH=${BPATH}:${PATH} \
|
||||
MAKESRCPATH=${KERNSRCDIR}/dev/aic7xxx/aicasm \
|
||||
${MAKE} -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF \
|
||||
${MAKE} -DNO_CPU_CFLAGS -DNO_CTF \
|
||||
-f ${KERNSRCDIR}/dev/aic7xxx/aicasm/Makefile
|
||||
# XXX - Gratuitously builds aicasm in the ``makeoptions NO_MODULES'' case.
|
||||
.if !defined(MODULES_WITH_WORLD) && !defined(NO_MODULES) && exists(${KERNSRCDIR}/modules)
|
||||
.for target in obj depend all
|
||||
cd ${KERNSRCDIR}/modules/aic7xxx/aicasm; \
|
||||
PATH=${BPATH}:${PATH} \
|
||||
MAKEOBJDIRPREFIX=${KRNLOBJDIR}/${_kernel}/modules \
|
||||
${MAKE} -DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF ${target}
|
||||
${MAKE} -DNO_CPU_CFLAGS -DNO_CTF ${target}
|
||||
.endfor
|
||||
.endif
|
||||
.if !defined(NO_KERNELDEPEND)
|
||||
@@ -890,10 +887,6 @@ _colldef= usr.bin/colldef
|
||||
_gencat= usr.bin/gencat
|
||||
.endif
|
||||
|
||||
.if ${BOOTSTRAPPING} >= 1000013
|
||||
_yacc= usr.bin/yacc
|
||||
.endif
|
||||
|
||||
.if ${BOOTSTRAPPING} < 600016
|
||||
_mklocale= usr.bin/mklocale
|
||||
.endif
|
||||
@@ -928,7 +921,6 @@ bootstrap-tools:
|
||||
${_gencat} \
|
||||
usr.bin/lorder \
|
||||
usr.bin/makewhatis \
|
||||
${_yacc} \
|
||||
${_mklocale} \
|
||||
usr.bin/rpcgen \
|
||||
usr.bin/xinstall \
|
||||
@@ -993,7 +985,7 @@ build-tools:
|
||||
#
|
||||
# cross-tools: Build cross-building tools
|
||||
#
|
||||
.if ${TARGET_ARCH} != ${MACHINE_ARCH} || ${BOOTSTRAPPING} < 702104
|
||||
.if ${TARGET_ARCH} != ${MACHINE_ARCH}
|
||||
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386"
|
||||
_btxld= usr.sbin/btxld
|
||||
.endif
|
||||
|
||||
@@ -14,20 +14,6 @@
|
||||
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
|
||||
#
|
||||
|
||||
# 20110224: sticky.8 -> sticky.7
|
||||
OLD_FILES+=usr/share/man/man8/sticky.8.gz
|
||||
# 20101114: Remove long-obsolete MAKEDEV.8
|
||||
OLD_FILES+=usr/share/man/man8/MAKEDEV.8.gz
|
||||
# 20101112: vgonel(9) has gone to private API a while ago
|
||||
OLD_FILES+=usr/share/man/man9/vgonel.9.gz
|
||||
# 20101025: catch up with vm_page_sleep_if_busy rename
|
||||
OLD_FILES+=usr/share/man/man9/vm_page_sleep_busy.9.gz
|
||||
# 20100815: retired last traces of chooseproc(9)
|
||||
OLD_FILES+=usr/share/man/man9/chooseproc.9.gz
|
||||
# 20091129: pecoff image activator removed
|
||||
.if ${TARGET_ARCH} == "i386"
|
||||
OLD_FILES+=usr/include/machine/pecoff_machdep.h
|
||||
.endif
|
||||
# 20090203: adding_user.8 moved to adding_user.7
|
||||
OLD_FILES+=usr/share/man/man8/adding_user.8.gz
|
||||
# 20080407: pkg_sign has been removed
|
||||
|
||||
@@ -8,53 +8,16 @@ Items affecting the ports and packages system can be found in
|
||||
/usr/ports/UPDATING. Please read that file before running
|
||||
portupgrade.
|
||||
|
||||
20111101:
|
||||
The broken amd(4) driver has been replaced with esp(4) in the amd64,
|
||||
i386 and pc98 GENERIC kernel configuration files.
|
||||
|
||||
20110221:
|
||||
FreeBSD 7.4-RELEASE
|
||||
|
||||
20101126:
|
||||
New version of minidump format for amd64 architecture was
|
||||
introduced in r215874. To analyze vmcore files produced by
|
||||
kernels at or after this version you will need updated userland,
|
||||
libkvm actually, that is able to handle the new version.
|
||||
|
||||
20100323:
|
||||
FreeBSD 7.3-RELEASE
|
||||
|
||||
20091129:
|
||||
PECOFF image activator support removed.
|
||||
|
||||
20090831:
|
||||
The newly imported zic(8) produces a new format in the
|
||||
output. Please run tzsetup(8) to install the newly created
|
||||
data to /etc/localtime.
|
||||
|
||||
20090731:
|
||||
The ABI of various structures related to the SYSV IPC API have
|
||||
been changed. Bump __FreeBSD_version to 702105.
|
||||
|
||||
20090606:
|
||||
The components of PmcTools have been upgraded. Please
|
||||
update world and the kernel.
|
||||
|
||||
20090521:
|
||||
The k8temp(4) driver has been renamed to amdtemp(4) since
|
||||
support for K10 and K11 CPU families was added.
|
||||
|
||||
20090520:
|
||||
Update ZFS to version 13. ZFS users will need to re-build
|
||||
and install both kernel and world simultaneously in order
|
||||
for the ZFS tools to work. Existing pools will continue to work
|
||||
without upgrade. If a pool is upgraded it will no longer be
|
||||
usable by older kernel revs. ZFS send / recv between
|
||||
pool version 6 and pool version 13 is not supported.
|
||||
|
||||
20090504:
|
||||
FreeBSD 7.2-RELEASE
|
||||
|
||||
20090422: FreeBSD-SA-09:07.libc, FreeBSD-SA-09:08.openssl
|
||||
Don't leak information via uninitialized space in db(3) records.
|
||||
[09:07]
|
||||
|
||||
Sanity-check string lengths in order to stop OpenSSL crashing
|
||||
when printing corrupt BMPString or UniversalString objects. [09:08]
|
||||
|
||||
20090326:
|
||||
Following bug-fixes to TCP connection state flags, netstat, systat,
|
||||
and sockstat will need to be rebuilt in order to properly print
|
||||
@@ -171,13 +134,13 @@ portupgrade.
|
||||
|
||||
The important thing to note is that the 82575 adapters
|
||||
were supported in the em driver in 7.0, but now needed
|
||||
to be moved into igb, so if you have the affected cards
|
||||
to be moved into igb, so if you have the effected cards
|
||||
be sure and make any script changes to follow the name
|
||||
change.
|
||||
|
||||
There are only 3 PCI ID's affected in this change:
|
||||
There are only 3 PCI ID's effected in this change:
|
||||
0x10A7, 0x10A9, and 0x10D6
|
||||
So you can know ahead of time if they will be affected,
|
||||
So you can know ahead of time if they will be effected,
|
||||
these will now be supported in the igb driver. That
|
||||
driver will also support the new 82576 followon.
|
||||
|
||||
@@ -189,7 +152,7 @@ portupgrade.
|
||||
|
||||
20080724:
|
||||
I have MFC'd in code to support multiple routing tables.
|
||||
See the man pages setfib(1) and setfib(2).
|
||||
see the man pages setfib(1) and setfib(2).
|
||||
This is a backwards compatible version,
|
||||
but to make use of it you need to compile your kernel
|
||||
with options ROUTETABLES=2 (or more up to 16).
|
||||
@@ -992,8 +955,8 @@ COMMON ITEMS:
|
||||
<reboot in single user> [3]
|
||||
mergemaster -p [5]
|
||||
make installworld
|
||||
make delete-old
|
||||
mergemaster [4]
|
||||
make delete-old [6]
|
||||
<reboot>
|
||||
|
||||
|
||||
@@ -1030,8 +993,8 @@ COMMON ITEMS:
|
||||
<reboot in single user> [3]
|
||||
mergemaster -p [5]
|
||||
make installworld
|
||||
make delete-old
|
||||
mergemaster -i [4]
|
||||
make delete-old [6]
|
||||
<reboot>
|
||||
|
||||
Make sure that you've read the UPDATING file to understand the
|
||||
@@ -1073,10 +1036,6 @@ COMMON ITEMS:
|
||||
install) after the buildworld before this step if you last updated
|
||||
from current before 20020224 or from -stable before 20020408.
|
||||
|
||||
[6] This only deletes old files and directories. Old libraries
|
||||
can be deleted by "make delete-old-libs", but you have to make
|
||||
sure that no program is using those libraries anymore.
|
||||
|
||||
[8] In order to have a kernel that can run the 4.x binaries
|
||||
needed to do an installworld, you must include the COMPAT_FREEBSD4
|
||||
option in your kernel. Failure to do so may leave you with a system
|
||||
@@ -1099,10 +1058,9 @@ COMMON ITEMS:
|
||||
FORMAT:
|
||||
|
||||
This file contains a list, in reverse chronological order, of major
|
||||
breakages in tracking -current. It is not guaranteed to be a complete
|
||||
list of such breakages, and only contains entries since October 16, 2004.
|
||||
If you need to see UPDATING entries from before that date, you will need
|
||||
to fetch an UPDATING file from an older FreeBSD release.
|
||||
breakages in tracking -current. Not all things will be listed here,
|
||||
and it only starts on October 16, 2004. Updating files can found in
|
||||
previous releases if your system is older than this.
|
||||
|
||||
Copyright information:
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ SUBDIR= cat \
|
||||
mv \
|
||||
pax \
|
||||
ps \
|
||||
pwait \
|
||||
pwd \
|
||||
${_rcp} \
|
||||
realpath \
|
||||
|
||||
@@ -115,7 +115,7 @@ main(int argc, char *argv[])
|
||||
fts_options |= FTS_LOGICAL;
|
||||
}
|
||||
} else
|
||||
fts_options = hflag ? FTS_PHYSICAL : FTS_LOGICAL;
|
||||
fts_options = FTS_LOGICAL;
|
||||
|
||||
/* XXX: Why don't chflags and lchflags have compatible prototypes? */
|
||||
if (hflag)
|
||||
|
||||
@@ -1072,7 +1072,6 @@ find_element(char *voltag, uint16_t *et, uint16_t *eu)
|
||||
|
||||
/* Read in the changer slots */
|
||||
if (cp.cp_nslots > 0) {
|
||||
(void) memset(&cesr, 0, sizeof(cesr));
|
||||
cesr.cesr_element_type = CHET_ST;
|
||||
cesr.cesr_element_base = 0;
|
||||
cesr.cesr_element_count = cp.cp_nslots;
|
||||
|
||||
+2
-7
@@ -32,7 +32,7 @@
|
||||
.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 23, 2009
|
||||
.Dd December 22, 2006
|
||||
.Dt CHMOD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -281,10 +281,6 @@ Operations upon the other permissions only (specified by the symbol
|
||||
``o'' by itself), in combination with the
|
||||
.Ar perm
|
||||
symbols ``s'' or ``t'', are ignored.
|
||||
.Pp
|
||||
The ``w'' permission on directories will permit file creation, relocation,
|
||||
and copy into that directory.
|
||||
Files created within the directory itself will inherit its group ID.
|
||||
.Sh EXAMPLES
|
||||
.Bl -tag -width "u=rwx,go=u-w" -compact
|
||||
.It Li 644
|
||||
@@ -347,5 +343,4 @@ command appeared in
|
||||
.Sh BUGS
|
||||
There is no
|
||||
.Ar perm
|
||||
option for the naughty bits which are ``S'' and
|
||||
``T'' respectively.
|
||||
option for the naughty bits.
|
||||
+3
-5
@@ -32,7 +32,7 @@
|
||||
.\" @(#)cp.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 17, 2010
|
||||
.Dd October 27, 2006
|
||||
.Dt CP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -45,7 +45,7 @@
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Oc
|
||||
.Op Fl f | i | n
|
||||
.Op Fl alpvx
|
||||
.Op Fl alpv
|
||||
.Ar source_file target_file
|
||||
.Nm
|
||||
.Oo
|
||||
@@ -53,7 +53,7 @@
|
||||
.Op Fl H | Fl L | Fl P
|
||||
.Oc
|
||||
.Op Fl f | i | n
|
||||
.Op Fl alpvx
|
||||
.Op Fl alpv
|
||||
.Ar source_file ... target_directory
|
||||
.Sh DESCRIPTION
|
||||
In the first synopsis form, the
|
||||
@@ -183,8 +183,6 @@ permissions.
|
||||
Cause
|
||||
.Nm
|
||||
to be verbose, showing files as they are copied.
|
||||
.It Fl x
|
||||
File system mount points are not traversed.
|
||||
.El
|
||||
.Pp
|
||||
For each destination file that already exists, its contents are
|
||||
|
||||
+2
-5
@@ -101,9 +101,8 @@ main(int argc, char *argv[])
|
||||
int Hflag, Lflag, Pflag, ch, fts_options, r, have_trailing_slash;
|
||||
char *target;
|
||||
|
||||
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
|
||||
Hflag = Lflag = Pflag = 0;
|
||||
while ((ch = getopt(argc, argv, "HLPRafilnprvx")) != -1)
|
||||
while ((ch = getopt(argc, argv, "HLPRafilnprv")) != -1)
|
||||
switch (ch) {
|
||||
case 'H':
|
||||
Hflag = 1;
|
||||
@@ -151,9 +150,6 @@ main(int argc, char *argv[])
|
||||
case 'v':
|
||||
vflag = 1;
|
||||
break;
|
||||
case 'x':
|
||||
fts_options |= FTS_XDEV;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
@@ -164,6 +160,7 @@ main(int argc, char *argv[])
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
fts_options = FTS_NOCHDIR | FTS_PHYSICAL;
|
||||
if (Rflag && rflag)
|
||||
errx(1, "the -R and -r options may not be specified together");
|
||||
if (rflag)
|
||||
|
||||
+3
-3
@@ -339,7 +339,7 @@ setfile(struct stat *fs, int fd)
|
||||
if (!gotstat || fs->st_flags != ts.st_flags)
|
||||
if (fdval ?
|
||||
fchflags(fd, fs->st_flags) :
|
||||
(islink ? lchflags(to.p_path, fs->st_flags) :
|
||||
(islink ? (errno = ENOSYS) :
|
||||
chflags(to.p_path, fs->st_flags))) {
|
||||
warn("chflags: %s", to.p_path);
|
||||
rval = 1;
|
||||
@@ -429,8 +429,8 @@ usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file target_file",
|
||||
" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpvx] source_file ... "
|
||||
"usage: cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file target_file",
|
||||
" cp [-R [-H | -L | -P]] [-f | -i | -n] [-alpv] source_file ... "
|
||||
"target_directory");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
+3
-3
@@ -18,7 +18,7 @@ DFLAGS= -D_PATH_TCSHELL='"/rescue/${PROG}"'
|
||||
DFLAGS= -D_PATH_TCSHELL='"/bin/${PROG}"'
|
||||
.endif
|
||||
CFLAGS+= -I. -I${.CURDIR} -I${TCSHDIR} ${DFLAGS}
|
||||
WARNS?= 1
|
||||
WARNS?= 0
|
||||
SRCS= sh.c sh.dir.c sh.dol.c sh.err.c sh.exec.c sh.char.c \
|
||||
sh.exp.c sh.file.c sh.func.c sh.glob.c sh.hist.c sh.init.c \
|
||||
sh.lex.c sh.misc.c sh.parse.c sh.print.c sh.proc.c sh.sem.c \
|
||||
@@ -107,10 +107,10 @@ gethost: gethost.c sh.err.h tc.const.h sh.h
|
||||
@rm -f ${.TARGET}
|
||||
${CC} -o gethost ${LDFLAGS} ${CFLAGS} ${TCSHDIR}/gethost.c
|
||||
|
||||
tc.defs.c: gethost ${TCSHDIR}/host.defs
|
||||
tc.defs.c: gethost ${.CURDIR}/host.defs
|
||||
@rm -f ${.TARGET}
|
||||
@echo "/* Do not edit this file, make creates it */" > ${.TARGET}
|
||||
./gethost ${TCSHDIR}/host.defs >> ${.TARGET}
|
||||
./gethost ${.CURDIR}/host.defs >> ${.TARGET}
|
||||
|
||||
ed.defns.h: ed.defns.c
|
||||
@rm -f ${.TARGET}
|
||||
|
||||
+22
-57
@@ -1,5 +1,5 @@
|
||||
/* $FreeBSD$ */
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h. Generated by configure. */
|
||||
/* config.h.in. Generated from configure.in by autoheader. */
|
||||
|
||||
/* Define to the type of elements in the array set by `getgroups'. Usually
|
||||
@@ -12,6 +12,9 @@
|
||||
/* Define to 1 if you have the <auth.h> header file. */
|
||||
/* #undef HAVE_AUTH_H */
|
||||
|
||||
/* Define to 1 if you have the `catgets' function. */
|
||||
#define HAVE_CATGETS 1
|
||||
|
||||
/* Define to 1 if you have the <crypt.h> header file. */
|
||||
/* #undef HAVE_CRYPT_H */
|
||||
|
||||
@@ -38,9 +41,6 @@
|
||||
/* Define to 1 if you have the `dup2' function. */
|
||||
#define HAVE_DUP2 1
|
||||
|
||||
/* Define to 1 if you have the <features.h> header file. */
|
||||
/* #undef HAVE_FEATURES_H */
|
||||
|
||||
/* Define to 1 if you have the `getauthid' function. */
|
||||
/* #undef HAVE_GETAUTHID */
|
||||
|
||||
@@ -56,10 +56,7 @@
|
||||
/* Define to 1 if you have the `getutent' function. */
|
||||
/* #undef HAVE_GETUTENT */
|
||||
|
||||
/* Define to 1 if you have the `getutxent' function. */
|
||||
/* #undef HAVE_GETUTXENT */
|
||||
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
/* Define if you have the iconv() function. */
|
||||
/* #undef HAVE_ICONV */
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
@@ -68,9 +65,6 @@
|
||||
/* Define to 1 if the system has the type `long long'. */
|
||||
#define HAVE_LONG_LONG 1
|
||||
|
||||
/* Define to 1 if you have the `mallinfo' function. */
|
||||
/* #undef HAVE_MALLINFO */
|
||||
|
||||
/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
|
||||
#define HAVE_MBRTOWC 1
|
||||
|
||||
@@ -83,9 +77,6 @@
|
||||
/* Define to 1 if you have the `memset' function. */
|
||||
#define HAVE_MEMSET 1
|
||||
|
||||
/* Define to 1 if you have the `mkstemp' function. */
|
||||
#define HAVE_MKSTEMP 1
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
/* #undef HAVE_NDIR_H */
|
||||
|
||||
@@ -95,9 +86,6 @@
|
||||
/* Define to 1 if you have the `nl_langinfo' function. */
|
||||
#define HAVE_NL_LANGINFO 1
|
||||
|
||||
/* Define to 1 if you have the <paths.h> header file. */
|
||||
#define HAVE_PATHS_H 1
|
||||
|
||||
/* Define to 1 if you have the `sbrk' function. */
|
||||
#define HAVE_SBRK 1
|
||||
|
||||
@@ -132,34 +120,22 @@
|
||||
/* Define to 1 if you have the `strstr' function. */
|
||||
#define HAVE_STRSTR 1
|
||||
|
||||
/* Define to 1 if `d_ino' is a member of `struct dirent'. */
|
||||
/* Define to 1 if `d_ino' is member of `struct dirent'. */
|
||||
#define HAVE_STRUCT_DIRENT_D_INO 1
|
||||
|
||||
/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */
|
||||
/* Define to 1 if `ss_family' is member of `struct sockaddr_storage'. */
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmpx'. */
|
||||
/* #undef HAVE_STRUCT_UTMPX_UT_HOST */
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmpx'. */
|
||||
/* #undef HAVE_STRUCT_UTMPX_UT_TV */
|
||||
|
||||
/* Define to 1 if `ut_user' is a member of `struct utmpx'. */
|
||||
/* #undef HAVE_STRUCT_UTMPX_UT_USER */
|
||||
|
||||
/* Define to 1 if `ut_xtime' is a member of `struct utmpx'. */
|
||||
/* #undef HAVE_STRUCT_UTMPX_UT_XTIME */
|
||||
|
||||
/* Define to 1 if `ut_host' is a member of `struct utmp'. */
|
||||
/* Define to 1 if `ut_host' is member of `struct utmp'. */
|
||||
#define HAVE_STRUCT_UTMP_UT_HOST 1
|
||||
|
||||
/* Define to 1 if `ut_tv' is a member of `struct utmp'. */
|
||||
/* Define to 1 if `ut_tv' is member of `struct utmp'. */
|
||||
/* #undef HAVE_STRUCT_UTMP_UT_TV */
|
||||
|
||||
/* Define to 1 if `ut_user' is a member of `struct utmp'. */
|
||||
/* Define to 1 if `ut_user' is member of `struct utmp'. */
|
||||
/* #undef HAVE_STRUCT_UTMP_UT_USER */
|
||||
|
||||
/* Define to 1 if `ut_xtime' is a member of `struct utmp'. */
|
||||
/* Define to 1 if `ut_xtime' is member of `struct utmp'. */
|
||||
/* #undef HAVE_STRUCT_UTMP_UT_XTIME */
|
||||
|
||||
/* Define to 1 if you have the `sysconf' function. */
|
||||
@@ -203,31 +179,25 @@
|
||||
/* Support NLS. */
|
||||
#define NLS 1
|
||||
|
||||
/* Support NLS catalogs. */
|
||||
#define NLS_CATALOGS 1
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "http://bugs.gw.com/"
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "tcsh"
|
||||
#define PACKAGE_NAME ""
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "tcsh 6.18.01"
|
||||
#define PACKAGE_STRING ""
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "tcsh"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
#define PACKAGE_TARNAME ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "6.18.01"
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
/* Define to 1 if the `setpgrp' function takes no argument. */
|
||||
/* #undef SETPGRP_VOID */
|
||||
|
||||
/* The size of `wchar_t', as computed by sizeof. */
|
||||
/* The size of a `wchar_t', as computed by sizeof. */
|
||||
#define SIZEOF_WCHAR_T 4
|
||||
|
||||
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
|
||||
@@ -236,11 +206,6 @@
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
|
||||
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
|
||||
#define below would cause a syntax error. */
|
||||
/* #undef _UINT32_T */
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
/* #undef const */
|
||||
|
||||
@@ -250,7 +215,7 @@
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* #undef mode_t */
|
||||
|
||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||
/* Define to `unsigned' if <sys/types.h> does not define. */
|
||||
/* #undef size_t */
|
||||
|
||||
/* Define to `int' if neither <sys/types.h> nor <sys/socket.h> define. */
|
||||
@@ -262,10 +227,6 @@
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
/* #undef uid_t */
|
||||
|
||||
/* Define to the type of an unsigned integer type of width exactly 32 bits if
|
||||
such a type exists and the standard includes do not define it. */
|
||||
/* #undef uint32_t */
|
||||
|
||||
/* Define to empty if the keyword `volatile' does not work. Warning: valid
|
||||
code using `volatile' can become incorrect without. Disable with care. */
|
||||
/* #undef volatile */
|
||||
@@ -273,5 +234,9 @@
|
||||
#include "config_p.h"
|
||||
#include "config_f.h"
|
||||
|
||||
#ifndef NO_NLS_CATALOGS
|
||||
#define NLS_CATALOGS
|
||||
#endif
|
||||
|
||||
/* Work around a vendor issue where config_f.h is #undef'ing this setting */
|
||||
#define SYSMALLOC
|
||||
@@ -105,6 +105,9 @@
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
# define SYSMALLOC
|
||||
|
||||
#else
|
||||
# define NLS_CATALOGS
|
||||
#endif
|
||||
|
||||
#endif /* _h_config */
|
||||
+1140
File diff suppressed because it is too large.
Load diff
@@ -61,20 +61,9 @@ dl_iconv_open(const char *tocode, const char *fromcode)
|
||||
if (iconvlib == NULL)
|
||||
return (iconv_t)-1;
|
||||
iconv_open = (iconv_open_t *)dlfunc(iconvlib, ICONV_OPEN);
|
||||
if (iconv_open == NULL)
|
||||
goto dlfunc_err;
|
||||
dl_iconv = (dl_iconv_t *)dlfunc(iconvlib, ICONV_ENGINE);
|
||||
if (dl_iconv == NULL)
|
||||
goto dlfunc_err;
|
||||
dl_iconv_close = (dl_iconv_close_t *)dlfunc(iconvlib,
|
||||
ICONV_CLOSE);
|
||||
if (dl_iconv_close == NULL)
|
||||
goto dlfunc_err;
|
||||
}
|
||||
return iconv_open(tocode, fromcode);
|
||||
|
||||
dlfunc_err:
|
||||
dlclose(iconvlib);
|
||||
iconvlib = NULL;
|
||||
return (iconv_t)-1;
|
||||
}
|
||||
+2
-7
@@ -78,20 +78,15 @@ this overrides the
|
||||
.Ev BLOCKSIZE
|
||||
specification from the environment.
|
||||
.It Fl H
|
||||
.Dq Human-readable
|
||||
output.
|
||||
"Human-readable" output.
|
||||
Use unit suffixes: Byte, Kilobyte, Megabyte,
|
||||
Gigabyte, Terabyte and Petabyte in order to reduce the number of
|
||||
digits to four or fewer using base 10 for sizes.
|
||||
.It Fl h
|
||||
.Dq Human-readable
|
||||
output.
|
||||
"Human-readable" output.
|
||||
Use unit suffixes: Byte, Kilobyte, Megabyte,
|
||||
Gigabyte, Terabyte and Petabyte in order to reduce the number of
|
||||
digits to four or fewer using base 2 for sizes.
|
||||
Inodes statistics, if enabled with
|
||||
.Fl i ,
|
||||
are always printed in base 10.
|
||||
.It Fl i
|
||||
Include statistics on the number of free inodes.
|
||||
.It Fl k
|
||||
|
||||
+5
-31
@@ -124,7 +124,7 @@ main(int argc, char *argv[])
|
||||
/* FALLTHROUGH */
|
||||
case 'P':
|
||||
/*
|
||||
* POSIX specifically discusses the behavior of
|
||||
* POSIX specifically discusses the the behavior of
|
||||
* both -k and -P. It states that the blocksize should
|
||||
* be set to 1024. Thus, if this occurs, simply break
|
||||
* rather than clobbering the old blocksize.
|
||||
@@ -364,23 +364,6 @@ prthumanval(int64_t bytes)
|
||||
(void)printf(" %6s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an inode count in "human-readable" format.
|
||||
*/
|
||||
static void
|
||||
prthumanvalinode(int64_t bytes)
|
||||
{
|
||||
char buf[6];
|
||||
int flags;
|
||||
|
||||
flags = HN_NOSPACE | HN_DECIMAL | HN_DIVISOR_1000;
|
||||
|
||||
humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
|
||||
bytes, "", HN_AUTOSCALE, flags);
|
||||
|
||||
(void)printf(" %5s", buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert statfs returned file system size into BLOCKSIZE units.
|
||||
* Attempts to avoid overflow for large file systems.
|
||||
@@ -423,10 +406,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
|
||||
mwp->mntfrom, "Filesystem", mwp->total, header,
|
||||
mwp->used, "Used", mwp->avail, "Avail");
|
||||
if (iflag) {
|
||||
mwp->iused = imax(hflag ? 0 : mwp->iused,
|
||||
(int)strlen(" iused"));
|
||||
mwp->ifree = imax(hflag ? 0 : mwp->ifree,
|
||||
(int)strlen("ifree"));
|
||||
mwp->iused = imax(mwp->iused, (int)strlen(" iused"));
|
||||
mwp->ifree = imax(mwp->ifree, (int)strlen("ifree"));
|
||||
(void)printf(" %*s %*s %%iused",
|
||||
mwp->iused - 2, "iused", mwp->ifree, "ifree");
|
||||
}
|
||||
@@ -450,15 +431,8 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
|
||||
if (iflag) {
|
||||
inodes = sfsp->f_files;
|
||||
used = inodes - sfsp->f_ffree;
|
||||
if (hflag) {
|
||||
(void)printf(" ");
|
||||
prthumanvalinode(used);
|
||||
prthumanvalinode(sfsp->f_ffree);
|
||||
} else {
|
||||
(void)printf(" %*jd %*jd", mwp->iused, (intmax_t)used,
|
||||
mwp->ifree, (intmax_t)sfsp->f_ffree);
|
||||
}
|
||||
(void)printf(" %4.0f%% ", inodes == 0 ? 100.0 :
|
||||
(void)printf(" %*jd %*jd %4.0f%% ", mwp->iused, (intmax_t)used,
|
||||
mwp->ifree, (intmax_t)sfsp->f_ffree, inodes == 0 ? 100.0 :
|
||||
(double)used / (double)inodes * 100.0);
|
||||
} else
|
||||
(void)printf(" ");
|
||||
|
||||
+9
-22
@@ -32,7 +32,7 @@
|
||||
.\" @(#)echo.1 8.1 (Berkeley) 7/22/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 12, 2010
|
||||
.Dd April 12, 2003
|
||||
.Dt ECHO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -56,37 +56,24 @@ The following option is available:
|
||||
.Bl -tag -width flag
|
||||
.It Fl n
|
||||
Do not print the trailing newline character.
|
||||
.El
|
||||
.Pp
|
||||
The end-of-options marker
|
||||
.Fl Fl
|
||||
is not recognized and written literally.
|
||||
.Pp
|
||||
The newline may also be suppressed by appending
|
||||
This may also be achieved by appending
|
||||
.Ql \ec
|
||||
to the end of the string, as is done
|
||||
by iBCS2 compatible systems.
|
||||
Note that the
|
||||
.Fl n
|
||||
option as well as the effect of
|
||||
Note that this option as well as the effect of
|
||||
.Ql \ec
|
||||
are implementation-defined in
|
||||
.St -p1003.1-2001
|
||||
as amended by Cor.\& 1-2002.
|
||||
For portability,
|
||||
.Nm
|
||||
should only be used if the first argument does not start with a hyphen
|
||||
.Pq Ql "-"
|
||||
and does not contain any backslashes
|
||||
.Pq Ql "\e" .
|
||||
If this is not sufficient,
|
||||
Applications aiming for maximum
|
||||
portability are strongly encouraged to use
|
||||
.Xr printf 1
|
||||
should be used.
|
||||
to suppress the newline character.
|
||||
.El
|
||||
.Pp
|
||||
Most shells provide a builtin
|
||||
Some shells may provide a builtin
|
||||
.Nm
|
||||
command which tends to differ from this utility
|
||||
in the treatment of options and backslashes.
|
||||
command which is similar or identical to this utility.
|
||||
Consult the
|
||||
.Xr builtin 1
|
||||
manual page.
|
||||
|
||||
@@ -94,7 +94,6 @@ put_sbuf_line(const char *cs)
|
||||
;
|
||||
if (s - cs >= LINECHARS) {
|
||||
errmsg = "line too long";
|
||||
free(lp);
|
||||
return NULL;
|
||||
}
|
||||
len = s - cs;
|
||||
@@ -103,7 +102,6 @@ put_sbuf_line(const char *cs)
|
||||
if (fseeko(sfp, (off_t)0, SEEK_END) < 0) {
|
||||
fprintf(stderr, "%s\n", strerror(errno));
|
||||
errmsg = "cannot seek temp file";
|
||||
free(lp);
|
||||
return NULL;
|
||||
}
|
||||
sfseek = ftello(sfp);
|
||||
@@ -114,7 +112,6 @@ put_sbuf_line(const char *cs)
|
||||
sfseek = -1;
|
||||
fprintf(stderr, "%s\n", strerror(errno));
|
||||
errmsg = "cannot write temp file";
|
||||
free(lp);
|
||||
return NULL;
|
||||
}
|
||||
lp->len = len;
|
||||
|
||||
+2
-2
@@ -231,7 +231,7 @@ The current line (address) in the buffer.
|
||||
The last line in the buffer.
|
||||
.It n
|
||||
The
|
||||
.Em n Ns th
|
||||
.Em n Ns th,
|
||||
line in the buffer
|
||||
where
|
||||
.Em n
|
||||
@@ -649,7 +649,7 @@ The mark is not cleared until the line is
|
||||
deleted or otherwise modified.
|
||||
.It (.,.)l
|
||||
Print the addressed lines unambiguously.
|
||||
If a single line fills more than one screen (as might be the case
|
||||
If a single line fills for than one screen (as might be the case
|
||||
when viewing a binary file, for instance), a
|
||||
.Dq Li --More--
|
||||
prompt is printed on the last line.
|
||||
|
||||
+10
-21
@@ -30,7 +30,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 9, 2010
|
||||
.Dd July 12, 2004
|
||||
.Dt EXPR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -217,9 +217,6 @@ command, one might rearrange the expression:
|
||||
More generally, parenthesize possibly-negative values:
|
||||
.Dl "a=$(expr \e( $a \e) + 1)"
|
||||
.It
|
||||
With shell arithmetic, no escaping is required:
|
||||
.Dl "a=$((a + 1))"
|
||||
.It
|
||||
This example prints the filename portion of a pathname stored
|
||||
in variable
|
||||
.Va a .
|
||||
@@ -232,12 +229,6 @@ The
|
||||
.Li //
|
||||
characters resolve this ambiguity.
|
||||
.Dl "expr \*q//$a\*q \&: '.*/\e(.*\e)'"
|
||||
.It
|
||||
With modern
|
||||
.Xr sh 1
|
||||
syntax,
|
||||
.Dl "\*q${a##*/}\*q"
|
||||
expands to the same value.
|
||||
.El
|
||||
.Pp
|
||||
The following examples output the number of characters in variable
|
||||
@@ -246,21 +237,19 @@ Again, if
|
||||
.Va a
|
||||
might begin with a hyphen, it is necessary to prevent it from being
|
||||
interpreted as an option to
|
||||
.Nm ,
|
||||
and
|
||||
.Va a
|
||||
might be interpreted as an operator.
|
||||
.Nm .
|
||||
.Bl -bullet
|
||||
.It
|
||||
To deal with all of this, a complicated command
|
||||
If the
|
||||
.Nm
|
||||
command conforms to
|
||||
.St -p1003.1-2001 ,
|
||||
this is simple:
|
||||
.Dl "expr -- \*q$a\*q \&: \*q.*\*q"
|
||||
.It
|
||||
For portability to older systems, however, a more complicated command
|
||||
is required:
|
||||
.Dl "expr \e( \*qX$a\*q \&: \*q.*\*q \e) - 1"
|
||||
.It
|
||||
With modern
|
||||
.Xr sh 1
|
||||
syntax, this can be done much more easily:
|
||||
.Dl "${#a}"
|
||||
expands to the required number.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sh 1 ,
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ main(int argc, char *argv[])
|
||||
numsig = strtol(*argv, &ep, 10);
|
||||
if (!**argv || *ep)
|
||||
errx(1, "illegal signal number: %s", *argv);
|
||||
if (numsig < 0)
|
||||
if (numsig < 0 || numsig >= sys_nsig)
|
||||
nosig(*argv);
|
||||
} else
|
||||
nosig(*argv);
|
||||
|
||||
+3
-3
@@ -29,7 +29,7 @@
|
||||
.\" @(#)symlink.7 8.3 (Berkeley) 3/31/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 25, 2010
|
||||
.Dd March 31, 1994
|
||||
.Dt SYMLINK 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -138,8 +138,8 @@ an existing symbolic link can be changed by means of the
|
||||
and
|
||||
.Xr lutimes 2
|
||||
system calls, respectively.
|
||||
Of these, only the flags and ownership are used by the system;
|
||||
the access permissions are ignored.
|
||||
Of these, only the flags are used by the system;
|
||||
the access permissions and ownership are ignored.
|
||||
.Pp
|
||||
The
|
||||
.Bx 4.4
|
||||
|
||||
+1
-1
@@ -504,7 +504,7 @@ traverse(int argc, char *argv[], int options)
|
||||
break;
|
||||
case FTS_DNR:
|
||||
case FTS_ERR:
|
||||
warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
|
||||
warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
|
||||
rval = 1;
|
||||
break;
|
||||
case FTS_D:
|
||||
|
||||
+1
-1
@@ -183,7 +183,7 @@ do_move(char *from, char *to)
|
||||
} else if (iflg) {
|
||||
(void)fprintf(stderr, "overwrite %s? %s", to, YESNO);
|
||||
ask = 1;
|
||||
} else if (access(to, W_OK) && !stat(to, &sb) && isatty(STDIN_FILENO)) {
|
||||
} else if (access(to, W_OK) && !stat(to, &sb)) {
|
||||
strmode(sb.st_mode, modep);
|
||||
(void)fprintf(stderr, "override %s%s%s/%s for %s? %s",
|
||||
modep + 1, modep[9] == ' ' ? "" : " ",
|
||||
|
||||
@@ -29,6 +29,9 @@ PROG= pax
|
||||
SRCS= ar_io.c ar_subs.c buf_subs.c cache.c cpio.c file_subs.c ftree.c \
|
||||
gen_subs.c getoldopt.c options.c pat_rep.c pax.c sel_subs.c \
|
||||
tables.c tar.c tty_subs.c
|
||||
#XXX NOTYET
|
||||
#MAN= pax.1 tar.1 cpio.1
|
||||
#LINKS= ${BINDIR}/pax ${BINDIR}/tar ${BINDIR}/pax ${BINDIR}/cpio
|
||||
|
||||
.if ${MACHINE_ARCH} == "arm"
|
||||
WARNS?= 3
|
||||
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1997 SigmaSoft, Th. Lockert
|
||||
.\" 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. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by SigmaSoft, Th. Lockert.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $OpenBSD: cpio.1,v 1.16 2001/05/01 17:58:01 aaron Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 16, 1997
|
||||
.Dt CPIO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm cpio
|
||||
.Nd copy file archives in and out
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Fl o
|
||||
.Op Fl aABcLvzZ
|
||||
.Op Fl C Ar bytes
|
||||
.Op Fl F Ar archive
|
||||
.Op Fl H Ar format
|
||||
.Op Fl O Ar archive
|
||||
.No < Ar name-list
|
||||
.Op No > Ar archive
|
||||
.Nm
|
||||
.Fl i
|
||||
.Op Fl bBcdfmrsStuvzZ6
|
||||
.Op Fl C Ar bytes
|
||||
.Op Fl E Ar file
|
||||
.Op Fl F Ar archive
|
||||
.Op Fl H Ar format
|
||||
.Op Fl I Ar archive
|
||||
.Op Ar pattern ...
|
||||
.Op No < Ar archive
|
||||
.Nm
|
||||
.Fl p
|
||||
.Op Fl adlLmuv
|
||||
.Ar destination-directory
|
||||
.No < Ar name-list
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command copies files to and from a
|
||||
.Nm
|
||||
archive.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl o
|
||||
Create an archive.
|
||||
Reads the list of files to store in the
|
||||
archive from standard input, and writes the archive on standard
|
||||
output.
|
||||
.Bl -tag -width indent
|
||||
.It Fl a
|
||||
Reset the access times on files that have been copied to the
|
||||
archive.
|
||||
.It Fl A
|
||||
Append to the specified archive.
|
||||
.It Fl B
|
||||
Set block size of output to 5120 bytes.
|
||||
.It Fl c
|
||||
Use
|
||||
.Tn ASCII
|
||||
format for
|
||||
.Nm
|
||||
header for portability.
|
||||
.It Fl C Ar bytes
|
||||
Set the block size of output to
|
||||
.Ar bytes .
|
||||
.It Fl F Ar archive
|
||||
.It Fl O Ar archive
|
||||
Use the specified file name as the archive to write to.
|
||||
.It Fl H Ar format
|
||||
Write the archive in the specified format.
|
||||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Cm bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Cm cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Cm sv4cpio
|
||||
.Tn SVR4
|
||||
hex
|
||||
.Nm
|
||||
format.
|
||||
.It Cm tar
|
||||
Old tar format.
|
||||
.It Cm ustar
|
||||
.Tn POSIX
|
||||
ustar format.
|
||||
.El
|
||||
.It Fl L
|
||||
Follow symbolic links.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are written to the archive.
|
||||
.It Fl z
|
||||
Compress archive using
|
||||
.Xr gzip 1
|
||||
format.
|
||||
.It Fl Z
|
||||
Compress archive using
|
||||
.Xr compress 1
|
||||
format.
|
||||
.El
|
||||
.It Fl i
|
||||
Restore files from an archive.
|
||||
Reads the archive file from
|
||||
standard input and extracts files matching the
|
||||
.Ar patterns
|
||||
that were specified on the command line.
|
||||
.Bl -tag -width indent
|
||||
.It Fl b
|
||||
Do byte and word swapping after reading in data from the
|
||||
archive, for restoring archives created on systems with
|
||||
a different byte order.
|
||||
.It Fl B
|
||||
Set the block size of the archive being read to 5120 bytes.
|
||||
.It Fl c
|
||||
Expect the archive headers to be in
|
||||
.Tn ASCII
|
||||
format.
|
||||
.It Fl C Ar bytes
|
||||
Read archive written with a block size of
|
||||
.Ar bytes .
|
||||
.It Fl d
|
||||
Create any intermediate directories as needed during
|
||||
restore.
|
||||
.It Fl E Ar file
|
||||
Read list of file name patterns to extract or list from
|
||||
.Ar file .
|
||||
.It Fl f
|
||||
Restore all files except those matching the
|
||||
.Ar patterns
|
||||
given on the command line.
|
||||
.It Fl F Ar archive , Fl I Ar archive
|
||||
Use the specified file as the input for the archive.
|
||||
.It Fl H Ar format
|
||||
Read an archive of the specified format.
|
||||
Recognized formats are:
|
||||
.Pp
|
||||
.Bl -tag -width sv4cpio -compact
|
||||
.It Cm bcpio
|
||||
Old binary
|
||||
.Nm
|
||||
format.
|
||||
.It Cm cpio
|
||||
Old octal character
|
||||
.Nm
|
||||
format.
|
||||
.It Cm sv4cpio
|
||||
.Tn SVR4
|
||||
hex
|
||||
.Nm
|
||||
format.
|
||||
.It Cm tar
|
||||
Old tar format.
|
||||
.It Cm ustar
|
||||
.Tn POSIX
|
||||
ustar format.
|
||||
.El
|
||||
.It Fl m
|
||||
Restore modification times on files.
|
||||
.It Fl r
|
||||
Rename restored files interactively.
|
||||
.It Fl s
|
||||
Swap bytes after reading data from the archive.
|
||||
.It Fl S
|
||||
Swap words after reading data from the archive.
|
||||
.It Fl t
|
||||
Only list the contents of the archive, no files or
|
||||
directories will be created.
|
||||
.It Fl u
|
||||
Overwrite files even when the file in the archive is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied in from the archive.
|
||||
.It Fl z
|
||||
Uncompress archive using
|
||||
.Xr gzip 1
|
||||
format.
|
||||
.It Fl Z
|
||||
Uncompress archive using
|
||||
.Xr compress 1
|
||||
format.
|
||||
.It Fl 6
|
||||
Process old-style
|
||||
.Nm
|
||||
format archives.
|
||||
.El
|
||||
.It Fl p
|
||||
Copy files from one location to another in a single pass.
|
||||
The list of files to copy are read from standard input and
|
||||
written out to a directory relative to the specified
|
||||
.Ar directory
|
||||
argument.
|
||||
.Bl -tag -width indent
|
||||
.It Fl a
|
||||
Reset the access times on files that have been copied.
|
||||
.It Fl d
|
||||
Create any intermediate directories as needed to write
|
||||
the files at the new location.
|
||||
.It Fl l
|
||||
When possible, link files rather than creating an
|
||||
extra copy.
|
||||
.It Fl L
|
||||
Follow symbolic links.
|
||||
.It Fl m
|
||||
Restore modification times on files.
|
||||
.It Fl u
|
||||
Overwrite files even when the original file being copied is
|
||||
older than the one that will be overwritten.
|
||||
.It Fl v
|
||||
Be verbose about operations.
|
||||
List filenames as they are copied.
|
||||
.El
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width TMPDIR
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility will exit with one of the following values:
|
||||
.Bl -tag -width 2n
|
||||
.It 0
|
||||
All files were processed successfully.
|
||||
.It 1
|
||||
An error occurred.
|
||||
.El
|
||||
.Pp
|
||||
Whenever
|
||||
.Nm
|
||||
cannot create a file or a link when extracting an archive or cannot
|
||||
find a file while writing an archive, or cannot preserve the user
|
||||
ID, group ID, file mode, or access and modification times when the
|
||||
.Fl p
|
||||
option is specified, a diagnostic message is written to standard
|
||||
error and a non-zero exit value will be returned, but processing
|
||||
will continue.
|
||||
In the case where
|
||||
.Nm
|
||||
cannot create a link to a file,
|
||||
.Nm
|
||||
will not create a second copy of the file.
|
||||
.Pp
|
||||
If the extraction of a file from an archive is prematurely terminated
|
||||
by a signal or error,
|
||||
.Nm
|
||||
may have only partially extracted the file the user wanted.
|
||||
Additionally, the file modes of extracted files and directories may
|
||||
have incorrect file bits, and the modification and access times may
|
||||
be wrong.
|
||||
.Pp
|
||||
If the creation of an archive is prematurely terminated by a signal
|
||||
or error,
|
||||
.Nm
|
||||
may have only partially created the archive which may violate the
|
||||
specific archive format specification.
|
||||
.Sh SEE ALSO
|
||||
.Xr pax 1 ,
|
||||
.Xr tar 1
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego.
|
||||
.Sh BUGS
|
||||
The
|
||||
.Fl s
|
||||
and
|
||||
.Fl S
|
||||
options are currently not implemented.
|
||||
+2
-4
@@ -33,7 +33,7 @@
|
||||
.\" @(#)pax.1 8.4 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 29, 2010
|
||||
.Dd July 3, 2004
|
||||
.Dt PAX 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -748,9 +748,7 @@ The extended tar interchange format specified in the
|
||||
.St -p1003.2
|
||||
standard.
|
||||
The default blocksize for this format is 10240 bytes.
|
||||
Pathnames stored by this format must be 255 characters or less in length.
|
||||
The directory part may be at most 155 characters and each path component
|
||||
must be less than 100 characters.
|
||||
Pathnames stored by this format must be 250 characters or less in length.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
|
||||
@@ -396,7 +396,6 @@ trng_add(char *str)
|
||||
default:
|
||||
paxwarn(1, "Bad option %c with time range %s",
|
||||
*flgpt, str);
|
||||
free(pt);
|
||||
goto out;
|
||||
}
|
||||
++flgpt;
|
||||
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1996 SigmaSoft, Th. Lockert
|
||||
.\" 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. All advertising materials mentioning features or use of this software
|
||||
.\" must display the following acknowledgement:
|
||||
.\" This product includes software developed by SigmaSoft, Th. Lockert.
|
||||
.\" 4. The name of the author may not be used to endorse or promote products
|
||||
.\" derived from this software without specific prior written permission
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" $OpenBSD: tar.1,v 1.33 2001/05/01 17:58:01 aaron Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd February 7, 2001
|
||||
.Dt TAR 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm tar
|
||||
.Nd tape archiver
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Sm off
|
||||
.Op Fl
|
||||
.Brq Cm crtux
|
||||
.Op Cm befhjmopqsvwyzHLOPXZ014578
|
||||
.Sm on
|
||||
.Op Ar blocksize
|
||||
.Op Ar archive
|
||||
.Op Ar replstr
|
||||
.\" XXX how to do this right?
|
||||
.Op Fl C Ar directory
|
||||
.Op Fl I Ar file
|
||||
.Op Ar
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command creates, adds files to, or extracts files from an
|
||||
archive file in
|
||||
.Nm
|
||||
format.
|
||||
A
|
||||
.Nm
|
||||
archive is often stored on a magnetic tape, but can be
|
||||
stored equally well on a floppy, CD-ROM, or in a regular disk file.
|
||||
.Pp
|
||||
One of the following flags must be present:
|
||||
.Bl -tag -width indent
|
||||
.It Fl c
|
||||
Create new archive, or overwrite an existing archive,
|
||||
adding the specified files to it.
|
||||
.It Fl r
|
||||
Append the named new files to existing archive.
|
||||
Note that this will only work on media on which an end-of-file mark
|
||||
can be overwritten.
|
||||
.It Fl t
|
||||
List contents of archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be listed.
|
||||
.It Fl u
|
||||
Alias for
|
||||
.Fl r .
|
||||
.It Fl x
|
||||
Extract files from archive.
|
||||
If any files are named on the
|
||||
command line, only those files will be extracted from the
|
||||
archive.
|
||||
If more than one copy of a file exists in the
|
||||
archive, later copies will overwrite earlier copies during
|
||||
extraction.
|
||||
The file mode and modification time are preserved
|
||||
if possible.
|
||||
The file mode is subject to modification by the
|
||||
.Xr umask 2 .
|
||||
.El
|
||||
.Pp
|
||||
In addition to the flags mentioned above, any of the following
|
||||
flags may be used:
|
||||
.Bl -tag -width indent
|
||||
.It Fl b Ar "blocking factor"
|
||||
Set blocking factor to use for the archive, with 512 byte blocks.
|
||||
The default is 20, the maximum is 126.
|
||||
Archives with a blocking factor larger 63 violate the
|
||||
.Tn POSIX
|
||||
standard and will not be portable to all systems.
|
||||
.It Fl e
|
||||
Stop after first error.
|
||||
.It Fl f Ar archive
|
||||
Filename where the archive is stored.
|
||||
Defaults to
|
||||
.Pa /dev/sa0 .
|
||||
.It Fl h
|
||||
Follow symbolic links as if they were normal files
|
||||
or directories.
|
||||
.It Fl j
|
||||
Compress archives using
|
||||
.Xr bzip2 1 .
|
||||
.It Fl m
|
||||
Do not preserve modification time.
|
||||
.It Fl O
|
||||
Write old-style
|
||||
.Pq non- Ns Tn POSIX
|
||||
archives.
|
||||
.It Fl o
|
||||
Do not write directory information that the older (V7) style
|
||||
.Nm
|
||||
is unable to decode.
|
||||
This implies the
|
||||
.Fl O
|
||||
flag.
|
||||
.It Fl p
|
||||
Preserve user and group ID as well as file mode regardless of
|
||||
the current
|
||||
.Xr umask 2 .
|
||||
The setuid and setgid bits are only preserved if the user is
|
||||
the superuser.
|
||||
Only meaningful in conjunction with the
|
||||
.Fl x
|
||||
flag.
|
||||
.It Fl q
|
||||
Select the first archive member that matches each
|
||||
.Ar pattern
|
||||
operand.
|
||||
No more than one archive member is matched for each
|
||||
.Ar pattern .
|
||||
When members of type directory are matched, the file hierarchy rooted at that
|
||||
directory is also matched.
|
||||
.It Fl s Ar replstr
|
||||
Modify the file or archive member names specified by the
|
||||
.Ar pattern
|
||||
or
|
||||
.Ar file
|
||||
operands according to the substitution expression
|
||||
.Ar replstr ,
|
||||
using the syntax of the
|
||||
.Xr ed 1
|
||||
utility regular expressions.
|
||||
The format of these regular expressions are:
|
||||
.Dl /old/new/[gp]
|
||||
As in
|
||||
.Xr ed 1 ,
|
||||
.Cm old
|
||||
is a basic regular expression and
|
||||
.Cm new
|
||||
can contain an ampersand
|
||||
.Pq Ql & ,
|
||||
.Li \e Ns Ar n
|
||||
(where
|
||||
.Ar n
|
||||
is a digit) back-references,
|
||||
or subexpression matching.
|
||||
The
|
||||
.Cm old
|
||||
string may also contain newline characters.
|
||||
Any non-null character can be used as a delimiter
|
||||
.Ql ( /
|
||||
is shown here).
|
||||
Multiple
|
||||
.Fl s
|
||||
expressions can be specified.
|
||||
The expressions are applied in the order they are specified on the
|
||||
command line, terminating with the first successful substitution.
|
||||
The optional trailing
|
||||
.Cm g
|
||||
continues to apply the substitution expression to the pathname substring
|
||||
which starts with the first character following the end of the last successful
|
||||
substitution.
|
||||
The first unsuccessful substitution stops the operation of the
|
||||
.Cm g
|
||||
option.
|
||||
The optional trailing
|
||||
.Cm p
|
||||
will cause the final result of a successful substitution to be written to
|
||||
standard error
|
||||
in the following format:
|
||||
.Pp
|
||||
.Dl <original pathname> >> <new pathname>
|
||||
.Pp
|
||||
File or archive member names that substitute to the empty string
|
||||
are not selected and will be skipped.
|
||||
.It Fl v
|
||||
Verbose operation mode.
|
||||
.It Fl w
|
||||
Interactively rename files.
|
||||
This option causes
|
||||
.Nm
|
||||
to prompt the user for the filename to use when storing or
|
||||
extracting files in an archive.
|
||||
.It Fl y
|
||||
Compress archives using
|
||||
.Xr bzip2 1 .
|
||||
.It Fl z
|
||||
Compress archive using
|
||||
.Xr gzip 1 .
|
||||
.It Fl C Ar directory
|
||||
This is a positional argument which sets the working directory for the
|
||||
following files.
|
||||
When extracting, files will be extracted into
|
||||
the specified directory; when creating, the specified files will be matched
|
||||
from the directory.
|
||||
.It Fl H
|
||||
Follow symlinks given on command line only.
|
||||
.It Fl L
|
||||
Follow all symlinks.
|
||||
.It Fl P
|
||||
Do not strip leading slashes
|
||||
.Pq Ql /
|
||||
from pathnames.
|
||||
The default is to strip leading slashes.
|
||||
.It Fl I Ar file
|
||||
This is a positional argument which reads the names of files to
|
||||
archive or extract from the given file, one per line.
|
||||
.It Fl X
|
||||
Do not cross mount points in the file system.
|
||||
.It Fl Z
|
||||
Compress archive using
|
||||
.Xr compress 1 .
|
||||
.El
|
||||
.Pp
|
||||
The options
|
||||
.Op Fl 014578
|
||||
can be used to select one of the compiled-in backup devices,
|
||||
.Pa /dev/rst Ns Ar N .
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width TMPDIR
|
||||
.It Ev TMPDIR
|
||||
Path in which to store temporary files.
|
||||
.It Ev TAPE
|
||||
Default tape device to use instead of
|
||||
.Pa /dev/sa0 .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/dev/sa0"
|
||||
.It Pa /dev/sa0
|
||||
default archive name
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
utility will exit with one of the following values:
|
||||
.Bl -tag -width 2n
|
||||
.It 0
|
||||
All files were processed successfully.
|
||||
.It 1
|
||||
An error occurred.
|
||||
.El
|
||||
.Pp
|
||||
Whenever
|
||||
.Nm
|
||||
cannot create a file or a link when extracting an archive or cannot
|
||||
find a file while writing an archive, or cannot preserve the user
|
||||
ID, group ID, file mode, or access and modification times when the
|
||||
.Fl p
|
||||
option is specified, a diagnostic message is written to standard
|
||||
error and a non-zero exit value will be returned, but processing
|
||||
will continue.
|
||||
In the case where
|
||||
.Nm
|
||||
cannot create a link to a file,
|
||||
.Nm
|
||||
will not create a second copy of the file.
|
||||
.Pp
|
||||
If the extraction of a file from an archive is prematurely terminated
|
||||
by a signal or error,
|
||||
.Nm
|
||||
may have only partially extracted the file the user wanted.
|
||||
Additionally, the file modes of extracted files and directories may
|
||||
have incorrect file bits, and the modification and access times may
|
||||
be wrong.
|
||||
.Pp
|
||||
If the creation of an archive is prematurely terminated by a signal
|
||||
or error,
|
||||
.Nm
|
||||
may have only partially created the archive which may violate the
|
||||
specific archive format specification.
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Fl L
|
||||
flag is not portable to other versions of
|
||||
.Nm
|
||||
where it may have a different meaning.
|
||||
.Sh SEE ALSO
|
||||
.Xr cpio 1 ,
|
||||
.Xr pax 1
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command first appeared in
|
||||
.At v7 .
|
||||
.Sh AUTHORS
|
||||
.An Keith Muller
|
||||
at the University of California, San Diego.
|
||||
+2
-2
@@ -1086,7 +1086,7 @@ name_split(char *name, int len)
|
||||
*/
|
||||
if (len <= TNMSZ)
|
||||
return(name);
|
||||
if (len > TPFSZ + TNMSZ)
|
||||
if (len > (TPFSZ + TNMSZ + 1))
|
||||
return(NULL);
|
||||
|
||||
/*
|
||||
@@ -1095,7 +1095,7 @@ name_split(char *name, int len)
|
||||
* to find the biggest piece to fit in the name field (or the smallest
|
||||
* prefix we can find)
|
||||
*/
|
||||
start = name + len - TNMSZ;
|
||||
start = name + len - TNMSZ - 1;
|
||||
while ((*start != '\0') && (*start != '/'))
|
||||
++start;
|
||||
|
||||
|
||||
+1
-2
@@ -39,7 +39,7 @@ extern fixpt_t ccpu;
|
||||
extern int cflag, eval, fscale, nlistread, rawcpu;
|
||||
extern unsigned long mempages;
|
||||
extern time_t now;
|
||||
extern int showthreads, sumrusage, termwidth, totwidth;
|
||||
extern int sumrusage, termwidth, totwidth;
|
||||
extern STAILQ_HEAD(velisthead, varent) varlist;
|
||||
|
||||
__BEGIN_DECLS
|
||||
@@ -71,7 +71,6 @@ void priorityr(KINFO *, VARENT *);
|
||||
void rgroupname(KINFO *, VARENT *);
|
||||
void runame(KINFO *, VARENT *);
|
||||
void rvar(KINFO *, VARENT *);
|
||||
int s_comm(KINFO *);
|
||||
int s_label(KINFO *);
|
||||
int s_rgroupname(KINFO *);
|
||||
int s_runame(KINFO *);
|
||||
|
||||
+9
-12
@@ -79,8 +79,8 @@ static VAR var[] = {
|
||||
CHAR, NULL, 0},
|
||||
{"blocked", "", "sigmask", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"caught", "", "sigcatch", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"comm", "COMMAND", NULL, LJUST|DSIZ, ucomm, s_comm,
|
||||
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
|
||||
{"comm", "COMMAND", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR,
|
||||
NULL, 0},
|
||||
{"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16, 0,
|
||||
CHAR, NULL, 0},
|
||||
{"cpu", "CPU", NULL, 0, kvar, NULL, 3, KOFF(ki_estcpu), UINT, "d",
|
||||
@@ -135,13 +135,12 @@ static VAR var[] = {
|
||||
LONG, "ld", 0},
|
||||
{"nvcsw", "NVCSW", NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw),
|
||||
LONG, "ld", 0},
|
||||
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, sizeof(void *) * 2, 0,
|
||||
CHAR, NULL, 0},
|
||||
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, 8, 0, CHAR, NULL, 0},
|
||||
{"oublk", "OUBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_oublock),
|
||||
LONG, "ld", 0},
|
||||
{"oublock", "", "oublk", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"paddr", "PADDR", NULL, 0, kvar, NULL, sizeof(void *) * 2,
|
||||
KOFF(ki_paddr), KPTR, "lx", 0},
|
||||
{"paddr", "PADDR", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
|
||||
"lx", 0},
|
||||
{"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6, 0, CHAR, NULL, 0},
|
||||
{"pcpu", "", "%cpu", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
{"pending", "", "sig", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
@@ -195,13 +194,13 @@ static VAR var[] = {
|
||||
{"tsiz", "TSIZ", NULL, 0, kvar, NULL, 4, KOFF(ki_tsize), PGTOK, "ld", 0},
|
||||
{"tt", "TT ", NULL, 0, tname, NULL, 4, 0, CHAR, NULL, 0},
|
||||
{"tty", "TTY", NULL, LJUST, longtname, NULL, 8, 0, CHAR, NULL, 0},
|
||||
{"ucomm", "UCOMM", NULL, LJUST|DSIZ, ucomm, s_comm,
|
||||
COMMLEN + OCOMMLEN + 1, 0, CHAR, NULL, 0},
|
||||
{"ucomm", "UCOMM", NULL, LJUST, ucomm, NULL, MAXCOMLEN, 0, CHAR, NULL,
|
||||
0},
|
||||
{"uid", "UID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_uid), UINT,
|
||||
UIDFMT, 0},
|
||||
{"upr", "UPR", NULL, 0, upr, NULL, 3, 0, CHAR, NULL, 0},
|
||||
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, sizeof(void *) * 2,
|
||||
KOFF(ki_paddr), KPTR, "lx", 0},
|
||||
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, 8, KOFF(ki_paddr), KPTR,
|
||||
"lx", 0},
|
||||
{"user", "USER", NULL, LJUST|DSIZ, uname, s_uname, USERLEN, 0, CHAR,
|
||||
NULL, 0},
|
||||
{"usrpri", "", "upr", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
|
||||
@@ -325,8 +324,6 @@ findvar(char *p, int user, char **header)
|
||||
*/
|
||||
rflen = strlen(v->alias) + strlen(hp) + 2;
|
||||
realfmt = malloc(rflen);
|
||||
if (realfmt == NULL)
|
||||
errx(1, "malloc failed");
|
||||
snprintf(realfmt, rflen, "%s=%s", v->alias, hp);
|
||||
parsefmt(realfmt, user);
|
||||
}
|
||||
|
||||
+14
-53
@@ -129,33 +129,25 @@ command(KINFO *k, VARENT *ve)
|
||||
v = ve->var;
|
||||
if (cflag) {
|
||||
/* If it is the last field, then don't pad */
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) {
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL)
|
||||
(void)printf("%s", k->ki_p->ki_comm);
|
||||
} else
|
||||
else
|
||||
(void)printf("%-*s", v->width, k->ki_p->ki_comm);
|
||||
return;
|
||||
}
|
||||
if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
if (k->ki_env) {
|
||||
if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
} else
|
||||
vis_env = NULL;
|
||||
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) {
|
||||
/* last field */
|
||||
|
||||
if (k->ki_env) {
|
||||
if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
|
||||
== NULL)
|
||||
errx(1, "malloc failed");
|
||||
strvis(vis_env, k->ki_env,
|
||||
VIS_TAB | VIS_NL | VIS_NOSLASH);
|
||||
} else
|
||||
vis_env = NULL;
|
||||
|
||||
if (termwidth == UNLIMITED) {
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (vis_env)
|
||||
(void)printf("%s ", vis_env);
|
||||
(void)printf("%s", vis_args);
|
||||
@@ -163,9 +155,6 @@ command(KINFO *k, VARENT *ve)
|
||||
left = termwidth - (totwidth - v->width);
|
||||
if (left < 1) /* already wrapped, just use std width */
|
||||
left = v->width;
|
||||
if ((cp = k->ki_d.prefix) != NULL)
|
||||
while (--left >= 0 && *cp)
|
||||
(void)putchar(*cp++);
|
||||
if ((cp = vis_env) != NULL) {
|
||||
while (--left >= 0 && *cp)
|
||||
(void)putchar(*cp++);
|
||||
@@ -175,34 +164,24 @@ command(KINFO *k, VARENT *ve)
|
||||
for (cp = vis_args; --left >= 0 && *cp != '\0';)
|
||||
(void)putchar(*cp++);
|
||||
}
|
||||
if (vis_env != NULL)
|
||||
free(vis_env);
|
||||
} else
|
||||
/* ki_d.prefix & ki_env aren't shown for interim fields */
|
||||
/* XXX env? */
|
||||
(void)printf("%-*.*s", v->width, v->width, vis_args);
|
||||
free(vis_args);
|
||||
if (vis_env != NULL)
|
||||
free(vis_env);
|
||||
}
|
||||
|
||||
void
|
||||
ucomm(KINFO *k, VARENT *ve)
|
||||
{
|
||||
char tmpbuff[COMMLEN + OCOMMLEN + 2];
|
||||
VAR *v;
|
||||
|
||||
v = ve->var;
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) { /* last field, don't pad */
|
||||
if (k->ki_d.prefix)
|
||||
(void)printf("%s", k->ki_d.prefix);
|
||||
if (STAILQ_NEXT(ve, next_ve) == NULL) /* last field, don't pad */
|
||||
(void)printf("%s", k->ki_p->ki_comm);
|
||||
} else {
|
||||
bzero(tmpbuff, sizeof(tmpbuff));
|
||||
if (showthreads && k->ki_p->ki_numthreads > 1)
|
||||
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
|
||||
k->ki_p->ki_ocomm);
|
||||
else
|
||||
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
|
||||
(void)printf("%-*s", v->width, tmpbuff);
|
||||
}
|
||||
else
|
||||
(void)printf("%-*s", v->width, k->ki_p->ki_comm);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -580,10 +559,6 @@ elapsed(KINFO *k, VARENT *ve)
|
||||
char obuff[128];
|
||||
|
||||
v = ve->var;
|
||||
if (!k->ki_valid) {
|
||||
(void)printf("%-*s", v->width, "-");
|
||||
return;
|
||||
}
|
||||
val = now - k->ki_p->ki_start.tv_sec;
|
||||
days = val / (24 * 60 * 60);
|
||||
val %= 24 * 60 * 60;
|
||||
@@ -829,20 +804,6 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
s_comm(KINFO *k)
|
||||
{
|
||||
char tmpbuff[COMMLEN + OCOMMLEN + 2];
|
||||
|
||||
bzero(tmpbuff, sizeof(tmpbuff));
|
||||
if (showthreads && k->ki_p->ki_numthreads > 1)
|
||||
sprintf(tmpbuff, "%s/%s", k->ki_p->ki_comm,
|
||||
k->ki_p->ki_ocomm);
|
||||
else
|
||||
sprintf(tmpbuff, "%s", k->ki_p->ki_comm);
|
||||
return (strlen(tmpbuff));
|
||||
}
|
||||
|
||||
int
|
||||
s_label(KINFO *k)
|
||||
{
|
||||
|
||||
+12
-28
@@ -29,7 +29,7 @@
|
||||
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 1, 2011
|
||||
.Dd August 21, 2006
|
||||
.Dt PS 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -37,7 +37,7 @@
|
||||
.Nd process status
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl aCcdefHhjlmrSTuvwXxZ
|
||||
.Op Fl aCcefHhjlmrSTuvwXxZ
|
||||
.Op Fl O Ar fmt | Fl o Ar fmt
|
||||
.Op Fl G Ar gid Ns Op , Ns Ar gid Ns Ar ...
|
||||
.Op Fl M Ar core
|
||||
@@ -54,11 +54,6 @@ utility
|
||||
displays a header line, followed by lines containing information about
|
||||
all of your
|
||||
processes that have controlling terminals.
|
||||
If the
|
||||
.Fl x
|
||||
options is specified,
|
||||
.Nm
|
||||
will also display processes that do not have controlling terminals.
|
||||
.Pp
|
||||
A different set of processes can be selected for display by using any
|
||||
combination of the
|
||||
@@ -95,8 +90,8 @@ and
|
||||
.Fl o
|
||||
options).
|
||||
The default output format includes, for each process, the process' ID,
|
||||
controlling terminal, state, CPU time (including both user and system time)
|
||||
and associated command.
|
||||
controlling terminal, CPU time (including both user and system time),
|
||||
state, and associated command.
|
||||
.Pp
|
||||
The process file system (see
|
||||
.Xr procfs 5 )
|
||||
@@ -108,9 +103,13 @@ The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl a
|
||||
Display information about other users' processes as well as your own.
|
||||
If the
|
||||
This will skip any processes which do not have a controlling terminal,
|
||||
unless the
|
||||
.Fl x
|
||||
option is also specified.
|
||||
This can be disabled by setting the
|
||||
.Va security.bsd.see_other_uids
|
||||
sysctl is set to zero, this option is honored only if the UID of the user is 0.
|
||||
sysctl to zero.
|
||||
.It Fl c
|
||||
Change the
|
||||
.Dq command
|
||||
@@ -123,15 +122,6 @@ CPU calculation that ignores
|
||||
.Dq resident
|
||||
time (this normally has
|
||||
no effect).
|
||||
.It Fl d
|
||||
Arrange processes into descendancy order and prefix each command with
|
||||
indentation text showing sibling and parent/child relationships.
|
||||
If either of the
|
||||
.Fl m
|
||||
and
|
||||
.Fl r
|
||||
options are also used, they control how sibling processes are sorted
|
||||
relative to eachother.
|
||||
.It Fl e
|
||||
Display the environment as well.
|
||||
.It Fl f
|
||||
@@ -214,9 +204,6 @@ with the standard input.
|
||||
.It Fl t
|
||||
Display information about processes attached to the specified terminal
|
||||
devices.
|
||||
Full pathnames, as well as abbreviations (see explanation of the
|
||||
.Cm tt
|
||||
keyword) can be specified.
|
||||
.It Fl U
|
||||
Display the processes belonging to the specified usernames.
|
||||
.It Fl u
|
||||
@@ -415,15 +402,12 @@ The process is being traced or debugged.
|
||||
An abbreviation for the pathname of the controlling terminal, if any.
|
||||
The abbreviation consists of the three letters following
|
||||
.Pa /dev/tty ,
|
||||
or, for pseudo-terminals, the corresponding entry in
|
||||
.Pa /dev/pts .
|
||||
or, for the console,
|
||||
.Dq Li con .
|
||||
This is followed by a
|
||||
.Ql -
|
||||
if the process can no longer reach that
|
||||
controlling terminal (i.e., it has been revoked).
|
||||
The full pathname of the controlling terminal is available via the
|
||||
.Cm tty
|
||||
keyword.
|
||||
.It Cm wchan
|
||||
The event (an address in the system) on which a process waits.
|
||||
When printed numerically, the initial part of the address is
|
||||
|
||||
+6
-134
@@ -100,7 +100,6 @@ int rawcpu; /* -C */
|
||||
int sumrusage; /* -S */
|
||||
int termwidth; /* Width of the screen (0 == infinity). */
|
||||
int totwidth; /* Calculated-width of requested variables. */
|
||||
int showthreads; /* will threads be shown? */
|
||||
|
||||
struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist);
|
||||
|
||||
@@ -138,7 +137,6 @@ static int addelem_pid(struct listinfo *, const char *);
|
||||
static int addelem_tty(struct listinfo *, const char *);
|
||||
static int addelem_uid(struct listinfo *, const char *);
|
||||
static void add_list(struct listinfo *, const char *);
|
||||
static void descendant_sort(KINFO *, int);
|
||||
static void dynsizevars(KINFO *);
|
||||
static void *expand_list(struct listinfo *);
|
||||
static const char *
|
||||
@@ -164,7 +162,7 @@ static char vfmt[] = "pid,state,time,sl,re,pagein,vsz,rss,lim,tsiz,"
|
||||
"%cpu,%mem,command";
|
||||
static char Zfmt[] = "label";
|
||||
|
||||
#define PS_ARGS "AaCcde" OPT_LAZY_f "G:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||
#define PS_ARGS "AaCce" OPT_LAZY_f "G:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -178,8 +176,8 @@ main(int argc, char *argv[])
|
||||
const char *nlistf, *memf;
|
||||
char *cols;
|
||||
int all, ch, elem, flag, _fmt, i, lineno;
|
||||
int descendancy, nentries, nkept, nselectors;
|
||||
int prtheader, wflag, what, xkeep, xkeep_implied;
|
||||
int nentries, nkept, nselectors;
|
||||
int prtheader, showthreads, wflag, what, xkeep, xkeep_implied;
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
(void) setlocale(LC_ALL, "");
|
||||
@@ -202,7 +200,7 @@ main(int argc, char *argv[])
|
||||
if (argc > 1)
|
||||
argv[1] = kludge_oldps_options(PS_ARGS, argv[1], argv[2]);
|
||||
|
||||
all = descendancy = _fmt = nselectors = optfatal = 0;
|
||||
all = _fmt = nselectors = optfatal = 0;
|
||||
prtheader = showthreads = wflag = xkeep_implied = 0;
|
||||
xkeep = -1; /* Neither -x nor -X. */
|
||||
init_list(&gidlist, addelem_gid, sizeof(gid_t), "group");
|
||||
@@ -212,8 +210,7 @@ main(int argc, char *argv[])
|
||||
init_list(&sesslist, addelem_pid, sizeof(pid_t), "session id");
|
||||
init_list(&ttylist, addelem_tty, sizeof(dev_t), "tty");
|
||||
init_list(&uidlist, addelem_uid, sizeof(uid_t), "user");
|
||||
memf = _PATH_DEVNULL;
|
||||
nlistf = NULL;
|
||||
memf = nlistf = _PATH_DEVNULL;
|
||||
while ((ch = getopt(argc, argv, PS_ARGS)) != -1)
|
||||
switch ((char)ch) {
|
||||
case 'A':
|
||||
@@ -235,9 +232,6 @@ main(int argc, char *argv[])
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
descendancy = 1;
|
||||
break;
|
||||
case 'e': /* XXX set ufmt */
|
||||
needenv = 1;
|
||||
break;
|
||||
@@ -580,8 +574,6 @@ main(int argc, char *argv[])
|
||||
keepit:
|
||||
next_KINFO = &kinfo[nkept];
|
||||
next_KINFO->ki_p = kp;
|
||||
next_KINFO->ki_d.level = 0;
|
||||
next_KINFO->ki_d.prefix = NULL;
|
||||
next_KINFO->ki_pcpu = getpcpu(next_KINFO);
|
||||
if (sortby == SORTMEM)
|
||||
next_KINFO->ki_memsize = kp->ki_tsize +
|
||||
@@ -606,13 +598,6 @@ main(int argc, char *argv[])
|
||||
* sort proc list
|
||||
*/
|
||||
qsort(kinfo, nkept, sizeof(KINFO), pscomp);
|
||||
|
||||
/*
|
||||
* We want things in descendant order
|
||||
*/
|
||||
if (descendancy)
|
||||
descendant_sort(kinfo, nkept);
|
||||
|
||||
/*
|
||||
* For each process, call each variable output function.
|
||||
*/
|
||||
@@ -636,9 +621,6 @@ main(int argc, char *argv[])
|
||||
free_list(&sesslist);
|
||||
free_list(&ttylist);
|
||||
free_list(&uidlist);
|
||||
for (i = 0; i < nkept; i++)
|
||||
free(kinfo[i].ki_d.prefix);
|
||||
free(kinfo);
|
||||
|
||||
exit(eval);
|
||||
}
|
||||
@@ -907,116 +889,6 @@ add_list(struct listinfo *inf, const char *argp)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
descendant_sort(KINFO *ki, int items)
|
||||
{
|
||||
int dst, lvl, maxlvl, n, ndst, nsrc, siblings, src;
|
||||
unsigned char *path;
|
||||
KINFO kn;
|
||||
|
||||
/*
|
||||
* First, sort the entries by descendancy, tracking the descendancy
|
||||
* depth in the ki_d.level field.
|
||||
*/
|
||||
src = 0;
|
||||
maxlvl = 0;
|
||||
while (src < items) {
|
||||
if (ki[src].ki_d.level) {
|
||||
src++;
|
||||
continue;
|
||||
}
|
||||
for (nsrc = 1; src + nsrc < items; nsrc++)
|
||||
if (!ki[src + nsrc].ki_d.level)
|
||||
break;
|
||||
|
||||
for (dst = 0; dst < items; dst++) {
|
||||
if (ki[dst].ki_p->ki_pid == ki[src].ki_p->ki_pid)
|
||||
continue;
|
||||
if (ki[dst].ki_p->ki_pid == ki[src].ki_p->ki_ppid)
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst == items) {
|
||||
src += nsrc;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ndst = 1; dst + ndst < items; ndst++)
|
||||
if (ki[dst + ndst].ki_d.level <= ki[dst].ki_d.level)
|
||||
break;
|
||||
|
||||
for (n = src; n < src + nsrc; n++) {
|
||||
ki[n].ki_d.level += ki[dst].ki_d.level + 1;
|
||||
if (maxlvl < ki[n].ki_d.level)
|
||||
maxlvl = ki[n].ki_d.level;
|
||||
}
|
||||
|
||||
while (nsrc) {
|
||||
if (src < dst) {
|
||||
kn = ki[src];
|
||||
memmove(ki + src, ki + src + 1,
|
||||
(dst - src + ndst - 1) * sizeof *ki);
|
||||
ki[dst + ndst - 1] = kn;
|
||||
nsrc--;
|
||||
dst--;
|
||||
ndst++;
|
||||
} else if (src != dst + ndst) {
|
||||
kn = ki[src];
|
||||
memmove(ki + dst + ndst + 1, ki + dst + ndst,
|
||||
(src - dst - ndst) * sizeof *ki);
|
||||
ki[dst + ndst] = kn;
|
||||
ndst++;
|
||||
nsrc--;
|
||||
src++;
|
||||
} else {
|
||||
ndst += nsrc;
|
||||
src += nsrc;
|
||||
nsrc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now populate ki_d.prefix (instead of ki_d.level) with the command
|
||||
* prefix used to show descendancies.
|
||||
*/
|
||||
path = malloc((maxlvl + 7) / 8);
|
||||
memset(path, '\0', (maxlvl + 7) / 8);
|
||||
for (src = 0; src < items; src++) {
|
||||
if ((lvl = ki[src].ki_d.level) == 0) {
|
||||
ki[src].ki_d.prefix = NULL;
|
||||
continue;
|
||||
}
|
||||
if ((ki[src].ki_d.prefix = malloc(lvl * 2 + 1)) == NULL)
|
||||
errx(1, "malloc failed");
|
||||
for (n = 0; n < lvl - 2; n++) {
|
||||
ki[src].ki_d.prefix[n * 2] =
|
||||
path[n / 8] & 1 << (n % 8) ? '|' : ' ';
|
||||
ki[src].ki_d.prefix[n * 2 + 1] = ' ';
|
||||
|
||||
}
|
||||
if (n == lvl - 2) {
|
||||
/* Have I any more siblings? */
|
||||
for (siblings = 0, dst = src + 1; dst < items; dst++) {
|
||||
if (ki[dst].ki_d.level > lvl)
|
||||
continue;
|
||||
if (ki[dst].ki_d.level == lvl)
|
||||
siblings = 1;
|
||||
break;
|
||||
}
|
||||
if (siblings)
|
||||
path[n / 8] |= 1 << (n % 8);
|
||||
else
|
||||
path[n / 8] &= ~(1 << (n % 8));
|
||||
ki[src].ki_d.prefix[n * 2] = siblings ? '|' : '`';
|
||||
ki[src].ki_d.prefix[n * 2 + 1] = '-';
|
||||
n++;
|
||||
}
|
||||
strcpy(ki[src].ki_d.prefix + n * 2, "- ");
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void *
|
||||
expand_list(struct listinfo *inf)
|
||||
{
|
||||
@@ -1333,7 +1205,7 @@ check_procfs(void)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
#define SINGLE_OPTS "[-aCcde" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
|
||||
#define SINGLE_OPTS "[-aCce" OPT_LAZY_f "HhjlmrSTuvwXxZ]"
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||
"usage: ps " SINGLE_OPTS " [-O fmt | -o fmt] [-G gid[,gid...]]",
|
||||
|
||||
@@ -42,10 +42,6 @@ typedef struct kinfo {
|
||||
int ki_valid; /* 1 => uarea stuff valid */
|
||||
double ki_pcpu; /* calculated in main() */
|
||||
segsz_t ki_memsize; /* calculated in main() */
|
||||
union {
|
||||
int level; /* used in decendant_sort() */
|
||||
char *prefix; /* calculated in decendant_sort() */
|
||||
} ki_d;
|
||||
} KINFO;
|
||||
|
||||
/* Variables. */
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= pwait
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,78 +0,0 @@
|
||||
.\"
|
||||
.\" Copyright (c) 2004-2009, Jilles Tjoelker
|
||||
.\" 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 COPYRIGHT HOLDERS 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
|
||||
.\" COPYRIGHT OWNER 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, 2009
|
||||
.Os
|
||||
.Dt PWAIT 1
|
||||
.Sh NAME
|
||||
.Nm pwait
|
||||
.Nd wait for processes to terminate
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl v
|
||||
.Ar pid
|
||||
\&...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility will wait until each of the given processes has terminated.
|
||||
.Pp
|
||||
The following option is available:
|
||||
.Bl -tag -width indent
|
||||
.It Fl v
|
||||
Print the exit status when each process terminates.
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
utility returns 0 on success, and >0 if an error occurs.
|
||||
.Pp
|
||||
Invalid pids elicit a warning message but are otherwise ignored.
|
||||
.Sh SEE ALSO
|
||||
.Xr kill 1 ,
|
||||
.Xr pkill 1 ,
|
||||
.Xr ps 1 ,
|
||||
.Xr wait 1 ,
|
||||
.Xr kqueue 2
|
||||
.Sh NOTES
|
||||
.Nm
|
||||
is not a substitute for the
|
||||
.Xr wait 1
|
||||
builtin
|
||||
as it will not clean up any zombies or state in the parent process.
|
||||
.Sh HISTORY
|
||||
A
|
||||
.Nm
|
||||
command first appeared in SunOS 5.8.
|
||||
@@ -1,145 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2004-2009, Jilles Tjoelker
|
||||
* 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 COPYRIGHT HOLDERS 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
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: pwait [-v] pid ...\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
/*
|
||||
* pwait - wait for processes to terminate
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int kq;
|
||||
struct kevent *e;
|
||||
int verbose = 0;
|
||||
int opt, nleft, n, i, duplicate, status;
|
||||
long pid;
|
||||
char *s, *end;
|
||||
|
||||
while ((opt = getopt(argc, argv, "v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
kq = kqueue();
|
||||
if (kq == -1)
|
||||
err(1, "kqueue");
|
||||
|
||||
e = malloc(argc * sizeof(struct kevent));
|
||||
if (e == NULL)
|
||||
err(1, "malloc");
|
||||
nleft = 0;
|
||||
for (n = 0; n < argc; n++) {
|
||||
s = argv[n];
|
||||
if (!strncmp(s, "/proc/", 6)) /* Undocumented Solaris compat */
|
||||
s += 6;
|
||||
errno = 0;
|
||||
pid = strtol(s, &end, 10);
|
||||
if (pid < 0 || *end != '\0' || errno != 0) {
|
||||
warnx("%s: bad process id", s);
|
||||
continue;
|
||||
}
|
||||
duplicate = 0;
|
||||
for (i = 0; i < nleft; i++)
|
||||
if (e[i].ident == (uintptr_t)pid)
|
||||
duplicate = 1;
|
||||
if (!duplicate) {
|
||||
EV_SET(e + nleft, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT,
|
||||
0, NULL);
|
||||
if (kevent(kq, e + nleft, 1, NULL, 0, NULL) == -1)
|
||||
warn("%ld", pid);
|
||||
else
|
||||
nleft++;
|
||||
}
|
||||
}
|
||||
|
||||
while (nleft > 0) {
|
||||
n = kevent(kq, NULL, 0, e, nleft, NULL);
|
||||
if (n == -1)
|
||||
err(1, "kevent");
|
||||
if (verbose)
|
||||
for (i = 0; i < n; i++) {
|
||||
status = e[i].data;
|
||||
if (WIFEXITED(status))
|
||||
printf("%ld: exited with status %d.\n",
|
||||
(long)e[i].ident,
|
||||
WEXITSTATUS(status));
|
||||
else if (WIFSIGNALED(status))
|
||||
printf("%ld: killed by signal %d.\n",
|
||||
(long)e[i].ident,
|
||||
WTERMSIG(status));
|
||||
else
|
||||
printf("%ld: terminated.\n",
|
||||
(long)e[i].ident);
|
||||
}
|
||||
nleft -= n;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
+8
-21
@@ -231,7 +231,7 @@ rm_tree(char **argv)
|
||||
else if (!uid &&
|
||||
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)) &&
|
||||
lchflags(p->fts_accpath,
|
||||
chflags(p->fts_accpath,
|
||||
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE)) < 0)
|
||||
goto err;
|
||||
continue;
|
||||
@@ -250,7 +250,7 @@ rm_tree(char **argv)
|
||||
if (!uid &&
|
||||
(p->fts_statp->st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(p->fts_statp->st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||
rval = lchflags(p->fts_accpath,
|
||||
rval = chflags(p->fts_accpath,
|
||||
p->fts_statp->st_flags &= ~(UF_APPEND|UF_IMMUTABLE));
|
||||
if (rval == 0) {
|
||||
/*
|
||||
@@ -288,16 +288,10 @@ rm_tree(char **argv)
|
||||
if (fflag)
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case FTS_F:
|
||||
case FTS_NSOK:
|
||||
if (Pflag)
|
||||
if (!rm_overwrite(p->fts_accpath, p->fts_info ==
|
||||
FTS_NSOK ? NULL : p->fts_statp))
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
|
||||
default:
|
||||
if (Pflag)
|
||||
if (!rm_overwrite(p->fts_accpath, NULL))
|
||||
continue;
|
||||
rval = unlink(p->fts_accpath);
|
||||
if (rval == 0 || (fflag && errno == ENOENT)) {
|
||||
if (rval == 0 && vflag)
|
||||
@@ -356,7 +350,7 @@ rm_file(char **argv)
|
||||
if (!uid && !S_ISWHT(sb.st_mode) &&
|
||||
(sb.st_flags & (UF_APPEND|UF_IMMUTABLE)) &&
|
||||
!(sb.st_flags & (SF_APPEND|SF_IMMUTABLE)))
|
||||
rval = lchflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
|
||||
rval = chflags(f, sb.st_flags & ~(UF_APPEND|UF_IMMUTABLE));
|
||||
if (rval == 0) {
|
||||
if (S_ISWHT(sb.st_mode))
|
||||
rval = undelete(f);
|
||||
@@ -392,7 +386,7 @@ rm_file(char **argv)
|
||||
int
|
||||
rm_overwrite(char *file, struct stat *sbp)
|
||||
{
|
||||
struct stat sb, sb2;
|
||||
struct stat sb;
|
||||
struct statfs fsb;
|
||||
off_t len;
|
||||
int bsize, fd, wlen;
|
||||
@@ -411,15 +405,8 @@ rm_overwrite(char *file, struct stat *sbp)
|
||||
file, sbp->st_ino);
|
||||
return (0);
|
||||
}
|
||||
if ((fd = open(file, O_WRONLY|O_NONBLOCK|O_NOFOLLOW, 0)) == -1)
|
||||
if ((fd = open(file, O_WRONLY, 0)) == -1)
|
||||
goto err;
|
||||
if (fstat(fd, &sb2))
|
||||
goto err;
|
||||
if (sb2.st_dev != sbp->st_dev || sb2.st_ino != sbp->st_ino ||
|
||||
!S_ISREG(sb2.st_mode)) {
|
||||
errno = EPERM;
|
||||
goto err;
|
||||
}
|
||||
if (fstatfs(fd, &fsb) == -1)
|
||||
goto err;
|
||||
bsize = MAX(fsb.f_iosize, 1024);
|
||||
|
||||
+3
-6
@@ -21,12 +21,12 @@ LDADD= -ll -ledit -ltermcap
|
||||
LFLAGS= -8 # 8-bit lex scanner for arithmetic
|
||||
CFLAGS+=-DSHELL -I. -I${.CURDIR}
|
||||
# for debug:
|
||||
# DEBUG_FLAGS+= -g -DDEBUG=2 -fno-inline
|
||||
WARNS?= 2
|
||||
# CFLAGS+= -g -DDEBUG=2
|
||||
WARNS?= 3
|
||||
WFORMAT=0
|
||||
|
||||
.PATH: ${.CURDIR}/bltin \
|
||||
${.CURDIR}/../test
|
||||
${.CURDIR}/../../bin/test
|
||||
|
||||
CLEANFILES+= mkinit mkinit.o mknodes mknodes.o \
|
||||
mksyntax mksyntax.o
|
||||
@@ -62,7 +62,4 @@ syntax.c syntax.h: mksyntax
|
||||
token.h: mktokens
|
||||
sh ${.CURDIR}/mktokens
|
||||
|
||||
regress:
|
||||
cd ${.CURDIR}/../../tools/regression/bin/sh && ${MAKE} SH=${.OBJDIR}/sh
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
+3
-23
@@ -51,13 +51,6 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
int yylex(void);
|
||||
|
||||
struct varname
|
||||
{
|
||||
struct varname *next;
|
||||
char name[1];
|
||||
};
|
||||
static struct varname *varnames;
|
||||
|
||||
#undef YY_INPUT
|
||||
#define YY_INPUT(buf,result,max) \
|
||||
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
|
||||
@@ -87,14 +80,11 @@ static struct varname *varnames;
|
||||
* If variable doesn't exist, we should initialize
|
||||
* it to zero.
|
||||
*/
|
||||
struct varname *temp;
|
||||
char *temp;
|
||||
if (lookupvar(yytext) == NULL)
|
||||
setvarsafe(yytext, "0", 0);
|
||||
temp = ckmalloc(sizeof(struct varname) +
|
||||
strlen(yytext));
|
||||
temp->next = varnames;
|
||||
varnames = temp;
|
||||
yylval.s_value = strcpy(temp->name, yytext);
|
||||
temp = (char *)ckmalloc(strlen(yytext) + 1);
|
||||
yylval.s_value = strcpy(temp, yytext);
|
||||
|
||||
return ARITH_VAR;
|
||||
}
|
||||
@@ -140,15 +130,5 @@ static struct varname *varnames;
|
||||
void
|
||||
arith_lex_reset(void)
|
||||
{
|
||||
struct varname *name, *next;
|
||||
|
||||
YY_NEW_FILE;
|
||||
|
||||
name = varnames;
|
||||
while (name != NULL) {
|
||||
next = name->next;
|
||||
ckfree(name);
|
||||
name = next;
|
||||
}
|
||||
varnames = NULL;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
.\"-
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Kenneth Almquist.
|
||||
.\" Copyright 1989 by Kenneth Almquist
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)echo.1 8.2 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 4, 1995
|
||||
.Dt ECHO 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm echo
|
||||
.Nd produce message in a shell script
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl n | Fl e
|
||||
.Ar args...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility prints its arguments on the standard output, separated by spaces.
|
||||
Unless the
|
||||
.Fl n
|
||||
option is present, a newline is output following the arguments.
|
||||
The
|
||||
.Fl e
|
||||
option causes
|
||||
.Nm
|
||||
to treat the escape sequences specially, as described in the following
|
||||
paragraph.
|
||||
The
|
||||
.Fl e
|
||||
option is the default, and is provided solely for compatibility with
|
||||
other systems.
|
||||
Only one of the options
|
||||
.Fl n
|
||||
and
|
||||
.Fl e
|
||||
may be given.
|
||||
.Pp
|
||||
If any of the following sequences of characters is encountered during
|
||||
output, the sequence is not output.
|
||||
Instead, the specified action is
|
||||
performed:
|
||||
.Bl -tag -width indent
|
||||
.It Li \eb
|
||||
A backspace character is output.
|
||||
.It Li \ec
|
||||
Subsequent output is suppressed.
|
||||
This is normally used at the end of the
|
||||
last argument to suppress the trailing newline that
|
||||
.Nm
|
||||
would otherwise output.
|
||||
.It Li \ef
|
||||
Output a form feed.
|
||||
.It Li \en
|
||||
Output a newline character.
|
||||
.It Li \er
|
||||
Output a carriage return.
|
||||
.It Li \et
|
||||
Output a (horizontal) tab character.
|
||||
.It Li \ev
|
||||
Output a vertical tab.
|
||||
.It Li \e0 Ns Ar digits
|
||||
Output the character whose value is given by zero to three digits.
|
||||
If there are zero digits, a
|
||||
.Dv NUL
|
||||
character is output.
|
||||
.It Li \e\e
|
||||
Output a backslash.
|
||||
.El
|
||||
.Sh HINTS
|
||||
Remember that backslash is special to the shell and needs to be escaped.
|
||||
To output a message to standard error, say
|
||||
.Pp
|
||||
.D1 echo message >&2
|
||||
.Sh BUGS
|
||||
The octal character escape mechanism
|
||||
.Pq Li \e0 Ns Ar digits
|
||||
differs from the
|
||||
C language mechanism.
|
||||
.Pp
|
||||
There is no way to force
|
||||
.Nm
|
||||
to treat its arguments literally, rather than interpreting them as
|
||||
options and escape sequences.
|
||||
+21
-28
@@ -70,7 +70,7 @@ STATIC int docd(char *, int, int);
|
||||
STATIC char *getcomponent(void);
|
||||
STATIC char *findcwd(char *);
|
||||
STATIC void updatepwd(char *);
|
||||
STATIC char *getpwd2(void);
|
||||
STATIC char *getpwd2(char *, size_t);
|
||||
|
||||
STATIC char *curdir = NULL; /* current working directory */
|
||||
STATIC char *prevdir; /* previous working directory */
|
||||
@@ -263,8 +263,10 @@ findcwd(char *dir)
|
||||
* any more because we traversed a symbolic link or something
|
||||
* we couldn't stat().
|
||||
*/
|
||||
if (dir == NULL || curdir == NULL)
|
||||
return getpwd2();
|
||||
if (dir == NULL || curdir == NULL) {
|
||||
p = stalloc(PATH_MAX);
|
||||
return getpwd2(p, PATH_MAX);
|
||||
}
|
||||
cdcomppath = stalloc(strlen(dir) + 1);
|
||||
scopy(dir, cdcomppath);
|
||||
STARTSTACKSTR(new);
|
||||
@@ -311,7 +313,7 @@ updatepwd(char *dir)
|
||||
int
|
||||
pwdcmd(int argc, char **argv)
|
||||
{
|
||||
char *p;
|
||||
char buf[PATH_MAX];
|
||||
int ch, phys;
|
||||
|
||||
optreset = 1; optind = 1; opterr = 0; /* initialize getopt */
|
||||
@@ -339,9 +341,9 @@ pwdcmd(int argc, char **argv)
|
||||
out1str(curdir);
|
||||
out1c('\n');
|
||||
} else {
|
||||
if ((p = getpwd2()) == NULL)
|
||||
if (getcwd(buf, sizeof(buf)) == NULL)
|
||||
error(".: %s", strerror(errno));
|
||||
out1str(p);
|
||||
out1str(buf);
|
||||
out1c('\n');
|
||||
}
|
||||
|
||||
@@ -354,45 +356,36 @@ pwdcmd(int argc, char **argv)
|
||||
char *
|
||||
getpwd(void)
|
||||
{
|
||||
char buf[PATH_MAX];
|
||||
char *p;
|
||||
|
||||
if (curdir)
|
||||
return curdir;
|
||||
|
||||
p = getpwd2();
|
||||
p = getpwd2(buf, sizeof(buf));
|
||||
if (p != NULL)
|
||||
curdir = savestr(p);
|
||||
|
||||
return curdir;
|
||||
}
|
||||
|
||||
#define MAXPWD 256
|
||||
|
||||
/*
|
||||
* Return the current directory.
|
||||
*/
|
||||
STATIC char *
|
||||
getpwd2(void)
|
||||
getpwd2(char *buf, size_t size)
|
||||
{
|
||||
struct stat stdot, stpwd;
|
||||
char *pwd;
|
||||
int i;
|
||||
if (getcwd(buf, size) == NULL) {
|
||||
char *pwd = getenv("PWD");
|
||||
struct stat stdot, stpwd;
|
||||
|
||||
for (i = MAXPWD;; i *= 2) {
|
||||
pwd = stalloc(i);
|
||||
if (getcwd(pwd, i) != NULL)
|
||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||
stat(pwd, &stpwd) != -1 &&
|
||||
stdot.st_dev == stpwd.st_dev &&
|
||||
stdot.st_ino == stpwd.st_ino) {
|
||||
return pwd;
|
||||
stunalloc(pwd);
|
||||
if (errno != ERANGE)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pwd = getenv("PWD");
|
||||
if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
|
||||
stat(pwd, &stpwd) != -1 &&
|
||||
stdot.st_dev == stpwd.st_dev &&
|
||||
stdot.st_ino == stpwd.st_ino) {
|
||||
return pwd;
|
||||
}
|
||||
return NULL;
|
||||
return buf;
|
||||
}
|
||||
+5
-11
@@ -83,7 +83,6 @@ MKINIT int evalskip; /* set if we are skipping commands */
|
||||
STATIC int skipcount; /* number of levels to skip */
|
||||
MKINIT int loopnest; /* current loop nesting level */
|
||||
int funcnest; /* depth of function calls */
|
||||
STATIC int builtin_flags; /* evalcommand flags for builtins */
|
||||
|
||||
|
||||
char *commandname;
|
||||
@@ -148,7 +147,7 @@ evalcmd(int argc, char **argv)
|
||||
STPUTC('\0', concat);
|
||||
p = grabstackstr(concat);
|
||||
}
|
||||
evalstring(p, builtin_flags & EV_TESTED);
|
||||
evalstring(p);
|
||||
}
|
||||
return exitstatus;
|
||||
}
|
||||
@@ -159,7 +158,7 @@ evalcmd(int argc, char **argv)
|
||||
*/
|
||||
|
||||
void
|
||||
evalstring(char *s, int flags)
|
||||
evalstring(char *s)
|
||||
{
|
||||
union node *n;
|
||||
struct stackmark smark;
|
||||
@@ -167,8 +166,7 @@ evalstring(char *s, int flags)
|
||||
setstackmark(&smark);
|
||||
setinputstring(s, 1);
|
||||
while ((n = parsecmd(0)) != NEOF) {
|
||||
if (n != NULL)
|
||||
evaltree(n, flags);
|
||||
evaltree(n, 0);
|
||||
popstackmark(&smark);
|
||||
}
|
||||
popfile();
|
||||
@@ -775,7 +773,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
INTOFF;
|
||||
savelocalvars = localvars;
|
||||
localvars = NULL;
|
||||
reffunc(cmdentry.u.func);
|
||||
INTON;
|
||||
if (setjmp(jmploc.loc)) {
|
||||
if (exception == EXSHELLPROC)
|
||||
@@ -784,7 +781,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
freeparam(&shellparam);
|
||||
shellparam = saveparam;
|
||||
}
|
||||
unreffunc(cmdentry.u.func);
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
handler = savehandler;
|
||||
@@ -796,12 +792,11 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
mklocal(sp->text);
|
||||
funcnest++;
|
||||
if (flags & EV_TESTED)
|
||||
evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
|
||||
evaltree(cmdentry.u.func, EV_TESTED);
|
||||
else
|
||||
evaltree(getfuncnode(cmdentry.u.func), 0);
|
||||
evaltree(cmdentry.u.func, 0);
|
||||
funcnest--;
|
||||
INTOFF;
|
||||
unreffunc(cmdentry.u.func);
|
||||
poplocalvars();
|
||||
localvars = savelocalvars;
|
||||
freeparam(&shellparam);
|
||||
@@ -842,7 +837,6 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
commandname = argv[0];
|
||||
argptr = argv + 1;
|
||||
optptr = NULL; /* initialize nextopt */
|
||||
builtin_flags = flags;
|
||||
exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv);
|
||||
flushall();
|
||||
cmddone:
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ struct backcmd { /* result of evalbackcmd */
|
||||
};
|
||||
|
||||
int evalcmd(int, char **);
|
||||
void evalstring(char *, int);
|
||||
void evalstring(char *);
|
||||
union node; /* BLETCH for ansi C */
|
||||
void evaltree(union node *, int);
|
||||
void evalbackcmd(union node *, struct backcmd *);
|
||||
|
||||
+4
-4
@@ -285,7 +285,7 @@ printentry(struct tblentry *cmdp, int verbose)
|
||||
out1fmt("function %s", cmdp->cmdname);
|
||||
if (verbose) {
|
||||
INTOFF;
|
||||
name = commandtext(getfuncnode(cmdp->param.func));
|
||||
name = commandtext(cmdp->param.func);
|
||||
out1c(' ');
|
||||
out1str(name);
|
||||
ckfree(name);
|
||||
@@ -582,7 +582,7 @@ deletefuncs(void)
|
||||
while ((cmdp = *pp) != NULL) {
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
*pp = cmdp->next;
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
ckfree(cmdp);
|
||||
} else {
|
||||
pp = &cmdp->next;
|
||||
@@ -669,7 +669,7 @@ addcmdentry(char *name, struct cmdentry *entry)
|
||||
INTOFF;
|
||||
cmdp = cmdlookup(name, 1);
|
||||
if (cmdp->cmdtype == CMDFUNCTION) {
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
}
|
||||
cmdp->cmdtype = entry->cmdtype;
|
||||
cmdp->param = entry->u;
|
||||
@@ -704,7 +704,7 @@ unsetfunc(char *name)
|
||||
struct tblentry *cmdp;
|
||||
|
||||
if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
|
||||
unreffunc(cmdp->param.func);
|
||||
freefunc(cmdp->param.func);
|
||||
delete_cmd_entry();
|
||||
return (0);
|
||||
}
|
||||
|
||||
+1
-2
@@ -46,12 +46,11 @@ enum {
|
||||
TYPECMD_TYPE /* type */
|
||||
};
|
||||
|
||||
union node;
|
||||
struct cmdentry {
|
||||
int cmdtype;
|
||||
union param {
|
||||
int index;
|
||||
struct funcdef *func;
|
||||
union node *func;
|
||||
} u;
|
||||
int special;
|
||||
};
|
||||
|
||||
+45
-66
@@ -1,8 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
* Copyright (c) 1997-2005
|
||||
* Herbert Xu <herbert@gondor.apana.org.au>. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Kenneth Almquist.
|
||||
@@ -139,18 +137,12 @@ expandhere(union node *arg, int fd)
|
||||
|
||||
|
||||
/*
|
||||
* Perform expansions on an argument, placing the resulting list of arguments
|
||||
* in arglist. Parameter expansion, command substitution and arithmetic
|
||||
* expansion are always performed; additional expansions can be requested
|
||||
* via flag (EXP_*).
|
||||
* The result is left in the stack string.
|
||||
* When arglist is NULL, perform here document expansion. A partial result
|
||||
* may be written to herefd, which is then not included in the stack string.
|
||||
*
|
||||
* Caution: this function uses global state and is not reentrant.
|
||||
* However, a new invocation after an interrupted invocation is safe
|
||||
* and will reset the global state for the new call.
|
||||
* Perform variable substitution and command substitution on an argument,
|
||||
* placing the resulting list of arguments in arglist. If EXP_FULL is true,
|
||||
* perform splitting and file name expansion. When arglist is NULL, perform
|
||||
* here document expansion.
|
||||
*/
|
||||
|
||||
void
|
||||
expandarg(union node *arg, struct arglist *arglist, int flag)
|
||||
{
|
||||
@@ -202,14 +194,11 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
|
||||
|
||||
|
||||
/*
|
||||
* Perform parameter expansion, command substitution and arithmetic
|
||||
* expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
|
||||
* Processing ends at a CTLENDVAR character as well as '\0'.
|
||||
* This is used to expand word in ${var+word} etc.
|
||||
* If EXP_FULL, EXP_CASE or EXP_REDIR are set, keep and/or generate CTLESC
|
||||
* characters to allow for further processing.
|
||||
* If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
|
||||
* Perform variable and command substitution. If EXP_FULL is set, output CTLESC
|
||||
* characters to allow for further processing. Otherwise treat
|
||||
* $@ like $* since no splitting will be performed.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
argstr(char *p, int flag)
|
||||
{
|
||||
@@ -222,7 +211,7 @@ argstr(char *p, int flag)
|
||||
for (;;) {
|
||||
switch (c = *p++) {
|
||||
case '\0':
|
||||
case CTLENDVAR:
|
||||
case CTLENDVAR: /* ??? */
|
||||
goto breakloop;
|
||||
case CTLQUOTEMARK:
|
||||
/* "$@" syntax adherence hack */
|
||||
@@ -272,10 +261,6 @@ argstr(char *p, int flag)
|
||||
breakloop:;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform tilde expansion, placing the result in the stack string and
|
||||
* returning the next position in the input string to process.
|
||||
*/
|
||||
STATIC char *
|
||||
exptilde(char *p, int flag)
|
||||
{
|
||||
@@ -376,11 +361,12 @@ expari(int flag)
|
||||
int quotes = flag & (EXP_FULL | EXP_CASE | EXP_REDIR);
|
||||
int quoted;
|
||||
|
||||
|
||||
/*
|
||||
* This routine is slightly over-complicated for
|
||||
* efficiency. First we make sure there is
|
||||
* enough space for the result, which may be bigger
|
||||
* than the expression. Next we
|
||||
* than the expression if we add exponentiation. Next we
|
||||
* scan backwards looking for the start of arithmetic. If the
|
||||
* next previous character is a CTLESC character, then we
|
||||
* have to rescan starting from the beginning since CTLESC
|
||||
@@ -419,8 +405,9 @@ expari(int flag)
|
||||
|
||||
|
||||
/*
|
||||
* Perform command substitution.
|
||||
* Expand stuff in backwards quotes.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
expbackq(union node *cmd, int quoted, int flag)
|
||||
{
|
||||
@@ -944,7 +931,7 @@ numvar:
|
||||
|
||||
|
||||
/*
|
||||
* Record the fact that we have to scan this region of the
|
||||
* Record the the fact that we have to scan this region of the
|
||||
* string for IFS characters.
|
||||
*/
|
||||
|
||||
@@ -972,12 +959,6 @@ recordregion(int start, int end, int nulonly)
|
||||
* Break the argument string into pieces based upon IFS and add the
|
||||
* strings to the argument list. The regions of the string to be
|
||||
* searched for IFS characters have been stored by recordregion.
|
||||
* CTLESC characters are preserved but have little effect in this pass
|
||||
* other than escaping CTL* characters. In particular, they do not escape
|
||||
* IFS characters: that should be done with the ifsregion mechanism.
|
||||
* CTLQUOTEMARK characters are used to preserve empty quoted strings.
|
||||
* This pass treats them as a regular character, making the string non-empty.
|
||||
* Later, they are removed along with the other CTL* characters.
|
||||
*/
|
||||
STATIC void
|
||||
ifsbreakup(char *string, struct arglist *arglist)
|
||||
@@ -1065,14 +1046,15 @@ ifsbreakup(char *string, struct arglist *arglist)
|
||||
}
|
||||
|
||||
|
||||
STATIC char expdir[PATH_MAX];
|
||||
#define expdir_end (expdir + sizeof(expdir))
|
||||
|
||||
/*
|
||||
* Perform pathname generation and remove control characters.
|
||||
* At this point, the only control characters should be CTLESC and CTLQUOTEMARK.
|
||||
* The results are stored in the list exparg.
|
||||
* Expand shell metacharacters. At this point, the only control characters
|
||||
* should be escapes. The results are stored in the list exparg.
|
||||
*/
|
||||
|
||||
STATIC char *expdir;
|
||||
|
||||
|
||||
STATIC void
|
||||
expandmeta(struct strlist *str, int flag __unused)
|
||||
{
|
||||
@@ -1094,7 +1076,14 @@ expandmeta(struct strlist *str, int flag __unused)
|
||||
}
|
||||
savelastp = exparg.lastp;
|
||||
INTOFF;
|
||||
if (expdir == NULL) {
|
||||
int i = strlen(str->text);
|
||||
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
|
||||
}
|
||||
|
||||
expmeta(expdir, str->text);
|
||||
ckfree(expdir);
|
||||
expdir = NULL;
|
||||
INTON;
|
||||
if (exparg.lastp == savelastp) {
|
||||
/*
|
||||
@@ -1133,11 +1122,10 @@ expmeta(char *enddir, char *name)
|
||||
struct dirent *dp;
|
||||
int atend;
|
||||
int matchdot;
|
||||
int esc;
|
||||
|
||||
metaflag = 0;
|
||||
start = name;
|
||||
for (p = name; esc = 0, *p; p += esc + 1) {
|
||||
for (p = name ; ; p++) {
|
||||
if (*p == '*' || *p == '?')
|
||||
metaflag = 1;
|
||||
else if (*p == '[') {
|
||||
@@ -1162,14 +1150,12 @@ expmeta(char *enddir, char *name)
|
||||
break;
|
||||
else if (*p == CTLQUOTEMARK)
|
||||
continue;
|
||||
else {
|
||||
if (*p == CTLESC)
|
||||
esc++;
|
||||
if (p[esc] == '/') {
|
||||
if (metaflag)
|
||||
break;
|
||||
start = p + esc + 1;
|
||||
}
|
||||
else if (*p == CTLESC)
|
||||
p++;
|
||||
if (*p == '/') {
|
||||
if (metaflag)
|
||||
break;
|
||||
start = p + 1;
|
||||
}
|
||||
}
|
||||
if (metaflag == 0) { /* we've reached the end of the file name */
|
||||
@@ -1183,8 +1169,6 @@ expmeta(char *enddir, char *name)
|
||||
*enddir++ = *p;
|
||||
if (*p == '\0')
|
||||
break;
|
||||
if (enddir == expdir_end)
|
||||
return;
|
||||
}
|
||||
if (metaflag == 0 || lstat(expdir, &statb) >= 0)
|
||||
addfname(expdir);
|
||||
@@ -1199,8 +1183,6 @@ expmeta(char *enddir, char *name)
|
||||
if (*p == CTLESC)
|
||||
p++;
|
||||
*enddir++ = *p++;
|
||||
if (enddir == expdir_end)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (enddir == expdir) {
|
||||
@@ -1219,8 +1201,7 @@ expmeta(char *enddir, char *name)
|
||||
atend = 1;
|
||||
} else {
|
||||
atend = 0;
|
||||
*endname = '\0';
|
||||
endname += esc + 1;
|
||||
*endname++ = '\0';
|
||||
}
|
||||
matchdot = 0;
|
||||
p = start;
|
||||
@@ -1234,23 +1215,21 @@ expmeta(char *enddir, char *name)
|
||||
if (dp->d_name[0] == '.' && ! matchdot)
|
||||
continue;
|
||||
if (patmatch(start, dp->d_name, 0)) {
|
||||
if (enddir + dp->d_namlen + 1 > expdir_end)
|
||||
continue;
|
||||
memcpy(enddir, dp->d_name, dp->d_namlen + 1);
|
||||
if (atend)
|
||||
if (atend) {
|
||||
scopy(dp->d_name, enddir);
|
||||
addfname(expdir);
|
||||
else {
|
||||
if (enddir + dp->d_namlen + 2 > expdir_end)
|
||||
} else {
|
||||
for (p = enddir, q = dp->d_name;
|
||||
(*p++ = *q++) != '\0';)
|
||||
continue;
|
||||
enddir[dp->d_namlen] = '/';
|
||||
enddir[dp->d_namlen + 1] = '\0';
|
||||
expmeta(enddir + dp->d_namlen + 1, endname);
|
||||
p[-1] = '/';
|
||||
expmeta(p, endname);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dirp);
|
||||
if (! atend)
|
||||
endname[-esc - 1] = esc ? CTLESC : '/';
|
||||
endname[-1] = '/';
|
||||
}
|
||||
|
||||
|
||||
@@ -1472,7 +1451,7 @@ breakloop:
|
||||
|
||||
|
||||
/*
|
||||
* Remove any CTLESC and CTLQUOTEMARK characters from a string.
|
||||
* Remove any CTLESC characters from a string.
|
||||
*/
|
||||
|
||||
void
|
||||
|
||||
+3
-3
@@ -350,7 +350,7 @@ histcmd(int argc, char **argv)
|
||||
if (displayhist) {
|
||||
out2str(s);
|
||||
}
|
||||
evalstring(s, 0);
|
||||
evalstring(s);
|
||||
if (displayhist && hist) {
|
||||
/*
|
||||
* XXX what about recursive and
|
||||
@@ -382,7 +382,7 @@ histcmd(int argc, char **argv)
|
||||
fclose(efp);
|
||||
editcmd = stalloc(strlen(editor) + strlen(editfile) + 2);
|
||||
sprintf(editcmd, "%s %s", editor, editfile);
|
||||
evalstring(editcmd, 0); /* XXX - should use no JC command */
|
||||
evalstring(editcmd); /* XXX - should use no JC command */
|
||||
INTON;
|
||||
readcmdfile(editfile); /* XXX - should read back - quick tst */
|
||||
unlink(editfile);
|
||||
@@ -411,7 +411,7 @@ fc_replace(const char *s, char *p, char *r)
|
||||
} else
|
||||
STPUTC(*s++, dest);
|
||||
}
|
||||
STPUTC('\0', dest);
|
||||
STACKSTRNUL(dest);
|
||||
dest = grabstackstr(dest);
|
||||
|
||||
return (dest);
|
||||
|
||||
+1
-1
@@ -178,7 +178,7 @@ state2:
|
||||
state3:
|
||||
state = 4;
|
||||
if (minusc) {
|
||||
evalstring(minusc, 0);
|
||||
evalstring(minusc);
|
||||
}
|
||||
if (sflag || minusc == NULL) {
|
||||
state4: /* XXX ??? - why isn't this before the "if" statement */
|
||||
|
||||
+7
-10
@@ -295,13 +295,6 @@ grabstackblock(int len)
|
||||
* is space for at least one character.
|
||||
*/
|
||||
|
||||
static char *
|
||||
growstrstackblock(int n)
|
||||
{
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - n;
|
||||
return stackblock() + n;
|
||||
}
|
||||
|
||||
char *
|
||||
growstackstr(void)
|
||||
@@ -311,10 +304,12 @@ growstackstr(void)
|
||||
len = stackblocksize();
|
||||
if (herefd >= 0 && len >= 1024) {
|
||||
xwrite(herefd, stackblock(), len);
|
||||
sstrnleft = len;
|
||||
sstrnleft = len - 1;
|
||||
return stackblock();
|
||||
}
|
||||
return growstrstackblock(len);
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len - 1;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +323,9 @@ makestrspace(void)
|
||||
int len;
|
||||
|
||||
len = stackblocksize() - sstrnleft;
|
||||
return growstrstackblock(len);
|
||||
growstackblock();
|
||||
sstrnleft = stackblocksize() - len;
|
||||
return stackblock() + len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-8
@@ -65,16 +65,9 @@ void ungrabstackstr(char *, char *);
|
||||
#define stackblock() stacknxt
|
||||
#define stackblocksize() stacknleft
|
||||
#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
|
||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), --sstrnleft, *p++ = (c)))
|
||||
#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
|
||||
#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); }
|
||||
#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
|
||||
/*
|
||||
* STACKSTRNUL's use is where we want to be able to turn a stack
|
||||
* (non-sentinel, character counting string) into a C string,
|
||||
* and later pretend the NUL is not there.
|
||||
* Note: Because of STACKSTRNUL's semantics, STACKSTRNUL cannot be used
|
||||
* on a stack that will grabstackstr()ed.
|
||||
*/
|
||||
#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
|
||||
#define STUNPUTC(p) (++sstrnleft, --p)
|
||||
#define STTOPC(p) p[-1]
|
||||
|
||||
+2
-5
@@ -248,11 +248,8 @@ output(char *file)
|
||||
fputs("\tstruct nodelist *next;\n", hfile);
|
||||
fputs("\tunion node *n;\n", hfile);
|
||||
fputs("};\n\n\n", hfile);
|
||||
fputs("struct funcdef;\n", hfile);
|
||||
fputs("struct funcdef *copyfunc(union node *);\n", hfile);
|
||||
fputs("union node *getfuncnode(struct funcdef *);\n", hfile);
|
||||
fputs("void reffunc(struct funcdef *);\n", hfile);
|
||||
fputs("void unreffunc(struct funcdef *);\n", hfile);
|
||||
fputs("union node *copyfunc(union node *);\n", hfile);
|
||||
fputs("void freefunc(union node *);\n", hfile);
|
||||
|
||||
fputs(writer, cfile);
|
||||
while (fgets(line, sizeof line, patfile) != NULL) {
|
||||
|
||||
+9
-37
@@ -35,7 +35,6 @@
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
/*
|
||||
* Routine for dealing with parsed shell commands.
|
||||
*/
|
||||
@@ -61,40 +60,25 @@ STATIC struct nodelist *copynodelist(struct nodelist *);
|
||||
STATIC char *nodesavestr(char *);
|
||||
|
||||
|
||||
struct funcdef {
|
||||
unsigned int refcount;
|
||||
union node n;
|
||||
};
|
||||
|
||||
/*
|
||||
* Make a copy of a parse tree.
|
||||
*/
|
||||
|
||||
struct funcdef *
|
||||
union node *
|
||||
copyfunc(union node *n)
|
||||
{
|
||||
struct funcdef *fn;
|
||||
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
funcblocksize = offsetof(struct funcdef, n);
|
||||
funcblocksize = 0;
|
||||
funcstringsize = 0;
|
||||
calcsize(n);
|
||||
fn = ckmalloc(funcblocksize + funcstringsize);
|
||||
fn->refcount = 1;
|
||||
funcblock = (char *)fn + offsetof(struct funcdef, n);
|
||||
funcstring = (char *)fn + funcblocksize;
|
||||
copynode(n);
|
||||
return fn;
|
||||
funcblock = ckmalloc(funcblocksize + funcstringsize);
|
||||
funcstring = (char *)funcblock + funcblocksize;
|
||||
return copynode(n);
|
||||
}
|
||||
|
||||
|
||||
union node *
|
||||
getfuncnode(struct funcdef *fn)
|
||||
{
|
||||
return fn == NULL ? NULL : &fn->n;
|
||||
}
|
||||
|
||||
|
||||
STATIC void
|
||||
calcsize(union node *n)
|
||||
@@ -160,26 +144,14 @@ nodesavestr(char *s)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
reffunc(struct funcdef *fn)
|
||||
{
|
||||
if (fn)
|
||||
fn->refcount++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Decrement the reference count of a function definition, freeing it
|
||||
* if it falls to 0.
|
||||
* Free a parse tree.
|
||||
*/
|
||||
|
||||
void
|
||||
unreffunc(struct funcdef *fn)
|
||||
freefunc(union node *n)
|
||||
{
|
||||
if (fn) {
|
||||
fn->refcount--;
|
||||
if (fn->refcount > 0)
|
||||
return;
|
||||
ckfree(fn);
|
||||
}
|
||||
if (n)
|
||||
ckfree(n);
|
||||
}
|
||||
@@ -250,7 +250,6 @@ pipeline(void)
|
||||
int negate;
|
||||
|
||||
negate = 0;
|
||||
checkkwd = 2;
|
||||
TRACE(("pipeline: entered\n"));
|
||||
while (readtoken() == TNOT)
|
||||
negate = !negate;
|
||||
|
||||
+29
-83
@@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 31, 2010
|
||||
.Dd October 7, 2006
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -40,24 +40,9 @@
|
||||
.Nd command interpreter (shell)
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl /+abCEefIimnPpTuVvx
|
||||
.Op Fl /+abCEefIimnPpsTuVvx
|
||||
.Op Fl /+o Ar longname
|
||||
.Oo
|
||||
.Ar script
|
||||
.Op Ar arg ...
|
||||
.Oc
|
||||
.Nm
|
||||
.Op Fl /+abCEefIimnPpTuVvx
|
||||
.Op Fl /+o Ar longname
|
||||
.Fl c Ar string
|
||||
.Oo
|
||||
.Ar name
|
||||
.Op Ar arg ...
|
||||
.Oc
|
||||
.Nm
|
||||
.Op Fl /+abCEefIimnPpTuVvx
|
||||
.Op Fl /+o Ar longname
|
||||
.Fl s
|
||||
.Op Fl c Ar string
|
||||
.Op Ar arg ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
@@ -390,10 +375,6 @@ introduces a comment if used at the beginning of a word.
|
||||
The word starting with
|
||||
.Ql #
|
||||
and the rest of the line are ignored.
|
||||
.Pp
|
||||
.Tn ASCII
|
||||
.Dv NUL
|
||||
characters (character code 0) are not allowed in shell input.
|
||||
.Ss Quoting
|
||||
Quoting is used to remove the special meaning of certain characters
|
||||
or words to the shell, such as operators, whitespace, keywords,
|
||||
@@ -426,11 +407,11 @@ character, with the exception of the newline character
|
||||
.Pq Ql \en .
|
||||
A backslash preceding a newline is treated as a line continuation.
|
||||
.El
|
||||
.Ss Keywords
|
||||
Keywords or reserved words are words that have special meaning to the
|
||||
.Ss Reserved Words
|
||||
Reserved words are words that have special meaning to the
|
||||
shell and are recognized at the beginning of a line and
|
||||
after a control operator.
|
||||
The following are keywords:
|
||||
The following are reserved words:
|
||||
.Bl -column "doneXX" "elifXX" "elseXX" "untilXX" "whileX" -offset center
|
||||
.It Li \&! Ta { Ta } Ta Ic case Ta Ic do
|
||||
.It Ic done Ta Ic elif Ta Ic else Ta Ic esac Ta Ic fi
|
||||
@@ -440,8 +421,8 @@ The following are keywords:
|
||||
An alias is a name and corresponding value set using the
|
||||
.Ic alias
|
||||
built-in command.
|
||||
Whenever a keyword may occur (see above),
|
||||
and after checking for keywords, the shell
|
||||
Whenever a reserved word may occur (see above),
|
||||
and after checking for reserved words, the shell
|
||||
checks the word to see if it matches an alias.
|
||||
If it does, it replaces it in the input stream with its value.
|
||||
For example, if there is an alias called
|
||||
@@ -480,7 +461,7 @@ of this man page (refer to the BNF in the
|
||||
document).
|
||||
Essentially though, a line is read and if
|
||||
the first word of the line (or after a control operator)
|
||||
is not a keyword, then the shell has recognized a
|
||||
is not a reserved word, then the shell has recognized a
|
||||
simple command.
|
||||
Otherwise, a complex command or some
|
||||
other special construct may have been recognized.
|
||||
@@ -700,7 +681,7 @@ Signal numbers are defined in the header file
|
||||
.In sys/signal.h .
|
||||
.Ss Complex Commands
|
||||
Complex commands are combinations of simple commands
|
||||
with control operators or keywords, together creating a larger complex
|
||||
with control operators or reserved words, together creating a larger complex
|
||||
command.
|
||||
More generally, a command is one of the following:
|
||||
.Bl -item -offset indent
|
||||
@@ -741,17 +722,10 @@ both of a command is considered to be assigned by the
|
||||
pipeline before any redirection specified by redirection
|
||||
operators that are part of the command.
|
||||
.Pp
|
||||
Note that unlike some other shells,
|
||||
.Nm
|
||||
executes each process in a pipeline with more than one command
|
||||
in a subshell environment and as a child of the
|
||||
.Nm
|
||||
process.
|
||||
.Pp
|
||||
If the pipeline is not in the background (discussed later),
|
||||
the shell waits for all commands to complete.
|
||||
.Pp
|
||||
If the keyword
|
||||
If the reserved word
|
||||
.Ic !\&
|
||||
does not precede the pipeline, the
|
||||
exit status is the exit status of the last command specified
|
||||
@@ -785,6 +759,15 @@ to be executed sequentially;
|
||||
an
|
||||
.Ql &
|
||||
causes asynchronous execution of the preceding AND-OR-list.
|
||||
.Pp
|
||||
Note that unlike some other shells,
|
||||
.Nm
|
||||
executes each process in the pipeline as a child of the
|
||||
.Nm
|
||||
process.
|
||||
Shell built-in commands are the exception to this rule.
|
||||
They are executed in the current shell, although they do not affect its
|
||||
environment when used in pipelines.
|
||||
.Ss Background Commands (&)
|
||||
If a command is terminated by the control operator ampersand
|
||||
.Pq Ql & ,
|
||||
@@ -869,7 +852,7 @@ command is:
|
||||
If
|
||||
.Ic in
|
||||
and the following words are omitted,
|
||||
.Ic in Li \&"$@\&"
|
||||
.Ic in Li $@
|
||||
is used instead.
|
||||
The words are expanded, and then the list is executed
|
||||
repeatedly with the variable set to each word in turn.
|
||||
@@ -1084,7 +1067,7 @@ and
|
||||
is
|
||||
.Dq Li "def ghi" ,
|
||||
then
|
||||
.Li \&"$@\&"
|
||||
.Dq Li $@
|
||||
expands to
|
||||
the two arguments:
|
||||
.Bd -literal -offset indent
|
||||
@@ -1114,12 +1097,7 @@ For a
|
||||
pipeline, the process ID is that of the last command in the
|
||||
pipeline.
|
||||
.It Li $0
|
||||
(zero) Expands to the name of the shell script if passed on the command line,
|
||||
the
|
||||
.Ar name
|
||||
operand if given (with
|
||||
.Fl c )
|
||||
or otherwise argument 0 passed to the shell.
|
||||
(zero) Expands to the name of the shell or shell script.
|
||||
.El
|
||||
.Ss Word Expansions
|
||||
This clause describes the various expansions that are
|
||||
@@ -1160,7 +1138,7 @@ Quote Removal.
|
||||
The
|
||||
.Ql $
|
||||
character is used to introduce parameter expansion, command
|
||||
substitution, or arithmetic expansion.
|
||||
substitution, or arithmetic evaluation.
|
||||
.Ss Tilde Expansion (substituting a user's home directory)
|
||||
A word beginning with an unquoted tilde character
|
||||
.Pq Ql ~
|
||||
@@ -1239,9 +1217,6 @@ In all cases, the
|
||||
final value of
|
||||
.Ar parameter
|
||||
is substituted.
|
||||
Quoting inside
|
||||
.Ar word
|
||||
does not prevent field splitting or pathname expansion.
|
||||
Only variables, not positional
|
||||
parameters or special parameters, can be
|
||||
assigned in this way.
|
||||
@@ -1375,41 +1350,10 @@ The
|
||||
shell expands all tokens in the
|
||||
.Ar expression
|
||||
for parameter expansion,
|
||||
command substitution,
|
||||
arithmetic expansion
|
||||
and quote removal.
|
||||
command substitution, and quote removal.
|
||||
.Pp
|
||||
The allowed expressions are a subset of C expressions,
|
||||
summarized below.
|
||||
.Bl -tag -width "Variables" -offset indent
|
||||
.It Values
|
||||
All values are of type
|
||||
.Ft intmax_t .
|
||||
.It Constants
|
||||
Decimal, octal (starting with
|
||||
.Li 0 )
|
||||
and hexadecimal (starting with
|
||||
.Li 0x )
|
||||
integer constants.
|
||||
.It Variables
|
||||
Shell variables can be read and written
|
||||
and contain integer constants.
|
||||
.It Unary operators
|
||||
.Li "! ~ + -"
|
||||
.It Binary operators
|
||||
.Li "* / % + - << >> < <= > >= == != & ^ | && ||"
|
||||
.It Assignment operators
|
||||
.Li "= += -= *= /= %= <<= >>= &= ^= |="
|
||||
.It Short-circuit evaluation
|
||||
The
|
||||
.Li &&
|
||||
and
|
||||
.Li ||
|
||||
operators always evaluate both sides.
|
||||
This is a bug.
|
||||
.El
|
||||
.Pp
|
||||
The result of the expression is substituted in decimal.
|
||||
Next, the shell treats this as an arithmetic expression and
|
||||
substitutes the value of the expression.
|
||||
.Ss White Space Splitting (Field Splitting)
|
||||
After parameter expansion, command substitution, and
|
||||
arithmetic expansion the shell scans the results of
|
||||
@@ -2404,6 +2348,8 @@ will return the argument.
|
||||
.Xr echo 1 ,
|
||||
.Xr ed 1 ,
|
||||
.Xr emacs 1 ,
|
||||
.Xr expr 1 ,
|
||||
.Xr getopt 1 ,
|
||||
.Xr pwd 1 ,
|
||||
.Xr test 1 ,
|
||||
.Xr vi 1 ,
|
||||
|
||||
+2
-2
@@ -416,7 +416,7 @@ dotrap(void)
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld++;
|
||||
savestatus = exitstatus;
|
||||
evalstring(trap[i], 0);
|
||||
evalstring(trap[i]);
|
||||
exitstatus = savestatus;
|
||||
if (i == SIGCHLD)
|
||||
ignore_sigchld--;
|
||||
@@ -471,7 +471,7 @@ exitshell(int status)
|
||||
handler = &loc1;
|
||||
if ((p = trap[0]) != NULL && *p != '\0') {
|
||||
trap[0] = NULL;
|
||||
evalstring(p, 0);
|
||||
evalstring(p);
|
||||
}
|
||||
l1: handler = &loc2; /* probably unnecessary */
|
||||
flushall();
|
||||
|
||||
+6
-3
@@ -523,8 +523,9 @@ var_compare(const void *a, const void *b)
|
||||
|
||||
|
||||
/*
|
||||
* Command to list all variables which are set. This is invoked from the
|
||||
* set command when it is called without any options or operands.
|
||||
* Command to list all variables which are set. Currently this command
|
||||
* is invoked from the set command when the set command is called without
|
||||
* any variables.
|
||||
*/
|
||||
|
||||
int
|
||||
@@ -759,7 +760,9 @@ setvarcmd(int argc, char **argv)
|
||||
|
||||
|
||||
/*
|
||||
* The unset builtin command.
|
||||
* The unset builtin command. We unset the function before we unset the
|
||||
* variable to allow a function to be unset when there is a readonly variable
|
||||
* with the same name.
|
||||
*/
|
||||
|
||||
int
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# $FreeBSD$
|
||||
|
||||
OS/shell syntax error failed
|
||||
--------------------------------------------------------------------
|
||||
bash 1.14.5 3 0
|
||||
pdksh 5.2.5 7 0
|
||||
zsh 2.6-beta17 6 4
|
||||
FreeBSD 2.1 /bin/test 8 0
|
||||
IRIX 5.3 ksh 3 0
|
||||
IRIX 5.3 sh 3 0
|
||||
IRIX 5.3 /usr/bin/test 11 3
|
||||
SunOS 5.4 ksh 3 0
|
||||
SunOS 5.4 sh 3 0
|
||||
SunOS 5.4 /usr/ucb/test 3 0
|
||||
SunOS 5.5 ksh 0 0
|
||||
SunOS 5.5 sh 3 0
|
||||
SunOS 5.5 /usr/ucb/test 3 0
|
||||
SunOS 4.1.3_U1 sh 3 0
|
||||
SunOS 4.1.3_U1 /usr/bin/test 3 0
|
||||
ULTRIX 4.2 /bin/test 9 0
|
||||
ULTRIX 4.2 ksh 1 0
|
||||
ULTRIX 4.2 sh5 4 0
|
||||
|
||||
96/06/16
|
||||
@@ -0,0 +1,152 @@
|
||||
# @(#)TEST.csh 5.2 (Berkeley) 4/30/93
|
||||
# $FreeBSD$
|
||||
|
||||
#alias t '/usr/src/bin/test/obj/test \!*; echo $status'
|
||||
alias t '/bin/test \!*; echo $status'
|
||||
|
||||
echo 't -b /dev/ttyp2'
|
||||
t -b /dev/ttyp2
|
||||
echo 't -b /dev/jb1a'
|
||||
t -b /dev/jb1a
|
||||
|
||||
echo 't -c test.c'
|
||||
t -c test.c
|
||||
echo 't -c /dev/tty'
|
||||
t -c /dev/tty
|
||||
|
||||
echo 't -d test.c'
|
||||
t -d test.c
|
||||
echo 't -d /etc'
|
||||
t -d /etc
|
||||
|
||||
echo 't -e noexist'
|
||||
t -e noexist
|
||||
echo 't -e test.c'
|
||||
t -e test.c
|
||||
|
||||
echo 't -f noexist'
|
||||
t -f noexist
|
||||
echo 't -f /dev/tty'
|
||||
t -f /dev/tty
|
||||
echo 't -f test.c'
|
||||
t -f test.c
|
||||
|
||||
echo 't -g test.c'
|
||||
t -g test.c
|
||||
echo 't -g /bin/ps'
|
||||
t -g /bin/ps
|
||||
|
||||
echo 't -n ""'
|
||||
t -n ""
|
||||
echo 't -n "hello"'
|
||||
t -n "hello"
|
||||
|
||||
echo 't -p test.c'
|
||||
t -p test.c
|
||||
|
||||
echo 't -r noexist'
|
||||
t -r noexist
|
||||
echo 't -r /etc/master.passwd'
|
||||
t -r /etc/master.passwd
|
||||
echo 't -r test.c'
|
||||
t -r test.c
|
||||
|
||||
echo 't -s noexist'
|
||||
t -s noexist
|
||||
echo 't -s /dev/null'
|
||||
t -s /dev/null
|
||||
echo 't -s test.c'
|
||||
t -s test.c
|
||||
|
||||
echo 't -t 20'
|
||||
t -t 20
|
||||
echo 't -t 0'
|
||||
t -t 0
|
||||
|
||||
echo 't -u test.c'
|
||||
t -u test.c
|
||||
echo 't -u /bin/rcp'
|
||||
t -u /bin/rcp
|
||||
|
||||
echo 't -w noexist'
|
||||
t -w noexist
|
||||
echo 't -w /etc/master.passwd'
|
||||
t -w /etc/master.passwd
|
||||
echo 't -w /dev/null'
|
||||
t -w /dev/null
|
||||
|
||||
echo 't -x noexist'
|
||||
t -x noexist
|
||||
echo 't -x /bin/ps'
|
||||
t -x /bin/ps
|
||||
echo 't -x /etc/motd'
|
||||
t -x /etc/motd
|
||||
|
||||
echo 't -z ""'
|
||||
t -z ""
|
||||
echo 't -z "foo"'
|
||||
t -z "foo"
|
||||
|
||||
echo 't "foo"'
|
||||
t "foo"
|
||||
echo 't ""'
|
||||
t ""
|
||||
|
||||
echo 't "hello" = "hello"'
|
||||
t "hello" = "hello"
|
||||
echo 't "hello" = "goodbye"'
|
||||
t "hello" = "goodbye"
|
||||
|
||||
echo 't "hello" != "hello"'
|
||||
t "hello" != "hello"
|
||||
echo 't "hello" != "goodbye"'
|
||||
t "hello" != "goodbye"
|
||||
|
||||
echo 't 200 -eq 200'
|
||||
t 200 -eq 200
|
||||
echo 't 34 -eq 222'
|
||||
t 34 -eq 222
|
||||
|
||||
echo 't 200 -ne 200'
|
||||
t 200 -ne 200
|
||||
echo 't 34 -ne 222'
|
||||
t 34 -ne 222
|
||||
|
||||
echo 't 200 -gt 200'
|
||||
t 200 -gt 200
|
||||
echo 't 340 -gt 222'
|
||||
t 340 -gt 222
|
||||
|
||||
echo 't 200 -ge 200'
|
||||
t 200 -ge 200
|
||||
echo 't 34 -ge 222'
|
||||
t 34 -ge 222
|
||||
|
||||
echo 't 200 -lt 200'
|
||||
t 200 -lt 200
|
||||
echo 't 34 -lt 222'
|
||||
t 34 -lt 222
|
||||
|
||||
echo 't 200 -le 200'
|
||||
t 200 -le 200
|
||||
echo 't 340 -le 222'
|
||||
t 340 -le 222
|
||||
|
||||
echo 't 700 -le 1000 -a -n "1" -a "20" = "20"'
|
||||
t 700 -le 1000 -a -n "1" -a "20" = "20"
|
||||
echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)'
|
||||
t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)
|
||||
|
||||
echo 't -5 -eq 5'
|
||||
t -5 -eq 5
|
||||
|
||||
|
||||
echo 't foo -a ""'
|
||||
t foo -a ""
|
||||
echo 't "" -a foo'
|
||||
t "" -a foo
|
||||
echo 't "" -a ""'
|
||||
t "" -a ""
|
||||
echo 't "" -o ""'
|
||||
t "" -o ""
|
||||
|
||||
@@ -30,29 +30,44 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
# force a specified test program, e.g. `env test=/bin/test sh regress.sh'
|
||||
# force a specified test program, e.g. `env test=/bin/test sh TEST.sh'
|
||||
: ${test=test}
|
||||
|
||||
ERROR=0 FAILED=0
|
||||
|
||||
t ()
|
||||
{
|
||||
# $1 -> exit code
|
||||
# $2 -> $test expression
|
||||
|
||||
count=$((count+1))
|
||||
echo -n "$1: $test $2 "
|
||||
|
||||
# check for syntax errors
|
||||
syntax="`eval $test $2 2>&1`"
|
||||
ret=$?
|
||||
if test -n "$syntax"; then
|
||||
printf "not ok %s - (syntax error)\n" "$count $2"
|
||||
elif [ "$ret" != "$1" ]; then
|
||||
printf "not ok %s - (got $ret, expected $1)\n" "$count $2"
|
||||
if test -z "$syntax"; then
|
||||
|
||||
case $1 in
|
||||
0) if eval $test $2; then echo " OK"; else failed;fi;;
|
||||
1) if eval $test $2; then failed; else echo " OK";fi;;
|
||||
esac
|
||||
|
||||
else
|
||||
printf "ok %s\n" "$count $2"
|
||||
error
|
||||
fi
|
||||
}
|
||||
|
||||
count=0
|
||||
echo "1..94"
|
||||
error ()
|
||||
{
|
||||
echo ""; echo " $syntax"
|
||||
ERROR=`expr $ERROR + 1`
|
||||
}
|
||||
|
||||
failed ()
|
||||
{
|
||||
echo ""; echo " failed"
|
||||
FAILED=`expr $FAILED + 1`
|
||||
}
|
||||
|
||||
|
||||
t 0 'b = b'
|
||||
t 1 'b != b'
|
||||
@@ -118,42 +133,5 @@ t 0 '"a" -a ! ""'
|
||||
t 1 '""'
|
||||
t 0 '! ""'
|
||||
|
||||
t 0 '!'
|
||||
t 0 '\('
|
||||
t 0 '\)'
|
||||
|
||||
t 1 '\( = \)'
|
||||
t 0 '\( != \)'
|
||||
t 0 '\( ! \)'
|
||||
t 0 '\( \( \)'
|
||||
t 0 '\( \) \)'
|
||||
t 0 '! = !'
|
||||
t 1 '! != !'
|
||||
t 1 '-n = \)'
|
||||
t 0 '! != \)'
|
||||
t 1 '! = a'
|
||||
t 0 '! != -n'
|
||||
t 0 '! -c /etc/passwd'
|
||||
|
||||
t 0 '! \( = \)'
|
||||
t 1 '! \( != \)'
|
||||
t 1 '! = = ='
|
||||
t 0 '! = = \)'
|
||||
t 0 '! "" -o ""'
|
||||
t 1 '! "x" -o ""'
|
||||
t 1 '! "" -o "x"'
|
||||
t 1 '! "x" -o "x"'
|
||||
t 0 '\( -f /etc/passwd \)'
|
||||
t 1 '\( ! = \)'
|
||||
t 0 '\( ! "" \)'
|
||||
t 1 '\( ! -e \)'
|
||||
|
||||
t 0 '0 -eq 0 -a -d /'
|
||||
t 0 '-s = "" -o "" = ""'
|
||||
t 0 '"" = "" -o -s = ""'
|
||||
t 1 '-s = "" -o -s = ""'
|
||||
t 0 '-z x -o x = "#" -o x = x'
|
||||
t 1 '-z y -o y = "#" -o y = x'
|
||||
t 0 '0 -ne 0 -o ! -f /'
|
||||
t 0 '1 -ne 0 -o ! -f /etc/passwd'
|
||||
t 1 '0 -ne 0 -o ! -f /etc/passwd'
|
||||
echo ""
|
||||
echo "Syntax errors: $ERROR Failed: $FAILED"
|
||||
+6
-13
@@ -32,7 +32,7 @@
|
||||
.\" @(#)test.1 8.1 (Berkeley) 5/31/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 10, 2010
|
||||
.Dd July 31, 2006
|
||||
.Dt TEST 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -282,7 +282,7 @@ True if either
|
||||
or
|
||||
.Ar expression2
|
||||
are true.
|
||||
.It Cm \&( Ar expression Cm \&)
|
||||
.It Cm \&( Ns Ar expression Ns Cm \&)
|
||||
True if expression is true.
|
||||
.El
|
||||
.Pp
|
||||
@@ -310,14 +310,6 @@ are evaluated consistently according to the rules specified in the
|
||||
standards document.
|
||||
All other cases are subject to the ambiguity in the
|
||||
command semantics.
|
||||
.Pp
|
||||
In particular, only expressions containing
|
||||
.Fl a ,
|
||||
.Fl o ,
|
||||
.Cm \&(
|
||||
or
|
||||
.Cm \&)
|
||||
can be ambiguous.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
@@ -346,11 +338,12 @@ specification.
|
||||
Both sides are always evaluated in
|
||||
.Fl a
|
||||
and
|
||||
.Fl o .
|
||||
.Fl o ,
|
||||
unlike in the logical operators of
|
||||
.Xr sh 1 .
|
||||
For instance, the writable status of
|
||||
.Pa file
|
||||
will be tested by the following command even though the former expression
|
||||
indicated false, which results in a gratuitous access to the file system:
|
||||
.Pp
|
||||
.Dl "[ -z abc -a -w file ]"
|
||||
To avoid this, write
|
||||
.Dl "[ -z abc ] && [ -w file ]"
|
||||
+9
-63
@@ -9,10 +9,6 @@
|
||||
*
|
||||
* This program is in the Public Domain.
|
||||
*/
|
||||
/*
|
||||
* Important: This file is used both as a standalone program /bin/test and
|
||||
* as a builtin for /bin/sh (#define SHELL).
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
@@ -167,7 +163,6 @@ struct t_op {
|
||||
struct t_op const *t_wp_op;
|
||||
int nargc;
|
||||
char **t_wp;
|
||||
int parenlevel;
|
||||
|
||||
static int aexpr(enum token);
|
||||
static int binop(void);
|
||||
@@ -176,9 +171,7 @@ static int filstat(char *, enum token);
|
||||
static int getn(const char *);
|
||||
static intmax_t getq(const char *);
|
||||
static int intcmp(const char *, const char *);
|
||||
static int isunopoperand(void);
|
||||
static int islparenoperand(void);
|
||||
static int isrparenoperand(void);
|
||||
static int isoperand(void);
|
||||
static int newerf(const char *, const char *);
|
||||
static int nexpr(enum token);
|
||||
static int oexpr(enum token);
|
||||
@@ -212,14 +205,7 @@ main(int argc, char **argv)
|
||||
#endif
|
||||
nargc = argc;
|
||||
t_wp = &argv[1];
|
||||
parenlevel = 0;
|
||||
if (nargc == 4 && strcmp(*t_wp, "!") == 0) {
|
||||
/* Things like ! "" -o x do not fit in the normal grammar. */
|
||||
--nargc;
|
||||
++t_wp;
|
||||
res = oexpr(t_lex(*t_wp));
|
||||
} else
|
||||
res = !oexpr(t_lex(*t_wp));
|
||||
res = !oexpr(t_lex(*t_wp));
|
||||
|
||||
if (--nargc > 0)
|
||||
syntax(*t_wp, "unexpected operator");
|
||||
@@ -282,16 +268,12 @@ primary(enum token n)
|
||||
if (n == EOI)
|
||||
return 0; /* missing expression */
|
||||
if (n == LPAREN) {
|
||||
parenlevel++;
|
||||
if ((nn = t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL)) ==
|
||||
RPAREN) {
|
||||
parenlevel--;
|
||||
RPAREN)
|
||||
return 0; /* missing expression */
|
||||
}
|
||||
res = oexpr(nn);
|
||||
if (t_lex(nargc > 0 ? (--nargc, *++t_wp) : NULL) != RPAREN)
|
||||
syntax(NULL, "closing paren expected");
|
||||
parenlevel--;
|
||||
return res;
|
||||
}
|
||||
if (t_wp_op && t_wp_op->op_type == UNOP) {
|
||||
@@ -428,10 +410,8 @@ t_lex(char *s)
|
||||
}
|
||||
while (op->op_text) {
|
||||
if (strcmp(s, op->op_text) == 0) {
|
||||
if (((op->op_type == UNOP || op->op_type == BUNOP)
|
||||
&& isunopoperand()) ||
|
||||
(op->op_num == LPAREN && islparenoperand()) ||
|
||||
(op->op_num == RPAREN && isrparenoperand()))
|
||||
if ((op->op_type == UNOP && isoperand()) ||
|
||||
(op->op_num == LPAREN && nargc == 1))
|
||||
break;
|
||||
t_wp_op = op;
|
||||
return op->op_num;
|
||||
@@ -443,7 +423,7 @@ t_lex(char *s)
|
||||
}
|
||||
|
||||
static int
|
||||
isunopoperand(void)
|
||||
isoperand(void)
|
||||
{
|
||||
struct t_op const *op = ops;
|
||||
char *s;
|
||||
@@ -451,53 +431,19 @@ isunopoperand(void)
|
||||
|
||||
if (nargc == 1)
|
||||
return 1;
|
||||
s = *(t_wp + 1);
|
||||
if (nargc == 2)
|
||||
return parenlevel == 1 && strcmp(s, ")") == 0;
|
||||
return 0;
|
||||
s = *(t_wp + 1);
|
||||
t = *(t_wp + 2);
|
||||
while (op->op_text) {
|
||||
if (strcmp(s, op->op_text) == 0)
|
||||
return op->op_type == BINOP &&
|
||||
(parenlevel == 0 || t[0] != ')' || t[1] != '\0');
|
||||
(t[0] != ')' || t[1] != '\0');
|
||||
op++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
islparenoperand(void)
|
||||
{
|
||||
struct t_op const *op = ops;
|
||||
char *s;
|
||||
|
||||
if (nargc == 1)
|
||||
return 1;
|
||||
s = *(t_wp + 1);
|
||||
if (nargc == 2)
|
||||
return parenlevel == 1 && strcmp(s, ")") == 0;
|
||||
if (nargc != 3)
|
||||
return 0;
|
||||
while (op->op_text) {
|
||||
if (strcmp(s, op->op_text) == 0)
|
||||
return op->op_type == BINOP;
|
||||
op++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
isrparenoperand(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (nargc == 1)
|
||||
return 0;
|
||||
s = *(t_wp + 1);
|
||||
if (nargc == 2)
|
||||
return parenlevel == 1 && strcmp(s, ")") == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* atoi with error detection */
|
||||
static int
|
||||
getn(const char *s)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 23, 2012
|
||||
.Dd September 7, 2005
|
||||
.Dt UUIDGEN 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -52,11 +52,8 @@ instructs
|
||||
to not generate them in batch, but one at a time.
|
||||
.It Fl n
|
||||
This option controls the number of identifiers generated.
|
||||
By default, multiple identifiers are generated in batch.
|
||||
The upper hard limit is 2048
|
||||
.Po see
|
||||
.Xr uuidgen 2
|
||||
.Pc .
|
||||
By default, multiple
|
||||
identifiers are generated in batch.
|
||||
.It Fl o
|
||||
Redirect output to
|
||||
.Ar filename
|
||||
|
||||
@@ -6,5 +6,3 @@ OPENSOLARIS_SYS_DISTDIR= ${.CURDIR}/../../../sys/cddl/contrib/opensolaris
|
||||
IGNORE_PRAGMA= YES
|
||||
|
||||
CFLAGS+= -DNEED_SOLARIS_BOOLEAN
|
||||
|
||||
CSTD?= gnu89
|
||||
@@ -1,36 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||
* 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 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$
|
||||
*/
|
||||
|
||||
#ifndef _OPENSOLARIS_LIBSHARE_H_
|
||||
#define _OPENSOLARIS_LIBSHARE_H_
|
||||
|
||||
#define SA_OK 0
|
||||
|
||||
#define SA_INIT_CONTROL_API 0
|
||||
|
||||
#endif /* !_OPENSOLARIS_LIBSHARE_H_ */
|
||||
@@ -9,8 +9,6 @@
|
||||
#define MNTTAB _PATH_DEVNULL
|
||||
#define MNT_LINE_MAX 1024
|
||||
|
||||
#define umount2(p, f) unmount(p, f)
|
||||
|
||||
struct mnttab {
|
||||
char *mnt_special;
|
||||
char *mnt_mountp;
|
||||
|
||||
@@ -94,7 +94,11 @@ int
|
||||
devid_get(int fd, ddi_devid_t *retdevid)
|
||||
{
|
||||
|
||||
return (ENOENT);
|
||||
if (ioctl(fd, DIOCGIDENT, retdevid->devid) == -1)
|
||||
return (errno);
|
||||
if (retdevid->devid[0] == '\0')
|
||||
return (ENOENT);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -37,8 +37,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *
|
||||
mntopt(char **p)
|
||||
|
||||
@@ -35,10 +35,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/mount.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void
|
||||
build_iovec(struct iovec **iov, int *iovlen, const char *name, void *val,
|
||||
@@ -87,7 +86,7 @@ zmount(const char *spec, const char *dir, int mflag, char *fstype,
|
||||
assert(optlen > 0);
|
||||
|
||||
optstr = strdup(optptr);
|
||||
assert(optstr != NULL);
|
||||
assert(optptr != NULL);
|
||||
|
||||
iov = NULL;
|
||||
iovlen = 0;
|
||||
@@ -95,10 +94,8 @@ zmount(const char *spec, const char *dir, int mflag, char *fstype,
|
||||
build_iovec(&iov, &iovlen, "fspath", __DECONST(char *, dir),
|
||||
(size_t)-1);
|
||||
build_iovec(&iov, &iovlen, "from", __DECONST(char *, spec), (size_t)-1);
|
||||
for (p = optstr; p != NULL; strsep(&p, ",/ ")) {
|
||||
if (*p != '\0')
|
||||
build_iovec(&iov, &iovlen, p, NULL, (size_t)-1);
|
||||
}
|
||||
for (p = optstr; p != NULL; strsep(&p, ",/ "))
|
||||
build_iovec(&iov, &iovlen, p, NULL, (size_t)-1);
|
||||
rv = nmount(iov, iovlen, 0);
|
||||
free(optstr);
|
||||
return (rv);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/zone.h>
|
||||
|
||||
zoneid_t
|
||||
int
|
||||
getzoneid(void)
|
||||
{
|
||||
size_t size;
|
||||
@@ -42,5 +42,5 @@ getzoneid(void)
|
||||
size = sizeof(jailid);
|
||||
if (sysctlbyname("security.jail.jailed", &jailid, &size, NULL, 0) == -1)
|
||||
assert(!"No security.jail.jailed sysctl!");
|
||||
return ((zoneid_t)jailid);
|
||||
return (jailid);
|
||||
}
|
||||
@@ -28,18 +28,13 @@ zdb \- ZFS debugger
|
||||
.fi
|
||||
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
.LP
|
||||
The \fBzdb\fR command is used by support engineers to diagnose failures and gather statistics. Since the \fBZFS\fR file system is always consistent on disk and is self-repairing, \fBzdb\fR should only be run under the direction by a support engineer.
|
||||
.sp
|
||||
.LP
|
||||
If no arguments are specified, \fBzdb\fR, performs basic consistency checks on the pool and associated datasets, and report any problems detected.
|
||||
.sp
|
||||
.LP
|
||||
Any options supported by this command are internal to Sun and subject to change at any time.
|
||||
.SH EXIT STATUS
|
||||
|
||||
.sp
|
||||
.LP
|
||||
The following exit values are returned:
|
||||
.sp
|
||||
@@ -76,9 +71,6 @@ Invalid command line options were specified.
|
||||
.RE
|
||||
|
||||
.SH ATTRIBUTES
|
||||
|
||||
.sp
|
||||
|
||||
.LP
|
||||
See \fBattributes\fR(5) for descriptions of the following attributes:
|
||||
.sp
|
||||
@@ -97,6 +89,5 @@ Interface StabilityUnstable
|
||||
.TE
|
||||
|
||||
.SH SEE ALSO
|
||||
.sp
|
||||
.LP
|
||||
\fBzfs\fR(1M), \fBzpool\fR(1M), \fBattributes\fR(5)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -233,26 +233,19 @@ typedef struct zil_rec_info {
|
||||
} zil_rec_info_t;
|
||||
|
||||
static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = {
|
||||
{ NULL, "Total " },
|
||||
{ zil_prt_rec_create, "TX_CREATE " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR " },
|
||||
{ zil_prt_rec_create, "TX_MKXATTR " },
|
||||
{ zil_prt_rec_create, "TX_SYMLINK " },
|
||||
{ zil_prt_rec_remove, "TX_REMOVE " },
|
||||
{ zil_prt_rec_remove, "TX_RMDIR " },
|
||||
{ zil_prt_rec_link, "TX_LINK " },
|
||||
{ zil_prt_rec_rename, "TX_RENAME " },
|
||||
{ zil_prt_rec_write, "TX_WRITE " },
|
||||
{ zil_prt_rec_truncate, "TX_TRUNCATE " },
|
||||
{ zil_prt_rec_setattr, "TX_SETATTR " },
|
||||
{ zil_prt_rec_acl, "TX_ACL_V0 " },
|
||||
{ zil_prt_rec_acl, "TX_ACL_ACL " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ACL " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_CREATE_ACL_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ACL " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ATTR " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR_ACL_ATTR " },
|
||||
{ NULL, "Total " },
|
||||
{ zil_prt_rec_create, "TX_CREATE " },
|
||||
{ zil_prt_rec_create, "TX_MKDIR " },
|
||||
{ zil_prt_rec_create, "TX_MKXATTR " },
|
||||
{ zil_prt_rec_create, "TX_SYMLINK " },
|
||||
{ zil_prt_rec_remove, "TX_REMOVE " },
|
||||
{ zil_prt_rec_remove, "TX_RMDIR " },
|
||||
{ zil_prt_rec_link, "TX_LINK " },
|
||||
{ zil_prt_rec_rename, "TX_RENAME " },
|
||||
{ zil_prt_rec_write, "TX_WRITE " },
|
||||
{ zil_prt_rec_truncate, "TX_TRUNCATE" },
|
||||
{ zil_prt_rec_setattr, "TX_SETATTR " },
|
||||
{ zil_prt_rec_acl, "TX_ACL " },
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -262,14 +255,12 @@ print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t claim_txg)
|
||||
int txtype;
|
||||
int verbose = MAX(dump_opt['d'], dump_opt['i']);
|
||||
|
||||
/* reduce size of txtype to strip off TX_CI bit */
|
||||
txtype = lr->lrc_txtype;
|
||||
|
||||
ASSERT(txtype != 0 && (uint_t)txtype < TX_MAX_TYPE);
|
||||
ASSERT(lr->lrc_txg);
|
||||
|
||||
(void) printf("\t\t%s%s len %6llu, txg %llu, seq %llu\n",
|
||||
(lr->lrc_txtype & TX_CI) ? "CI-" : "",
|
||||
(void) printf("\t\t%s len %6llu, txg %llu, seq %llu\n",
|
||||
zil_rec_info[txtype].zri_name,
|
||||
(u_longlong_t)lr->lrc_reclen,
|
||||
(u_longlong_t)lr->lrc_txg,
|
||||
|
||||
+367
-1154
File diff suppressed because it is too large.
Load diff
@@ -19,10 +19,12 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libintl.h>
|
||||
#include <libuutil.h>
|
||||
#include <stddef.h>
|
||||
@@ -54,43 +56,28 @@ typedef struct zfs_node {
|
||||
|
||||
typedef struct callback_data {
|
||||
uu_avl_t *cb_avl;
|
||||
int cb_flags;
|
||||
int cb_recurse;
|
||||
zfs_type_t cb_types;
|
||||
zfs_sort_column_t *cb_sortcol;
|
||||
zprop_list_t **cb_proplist;
|
||||
zfs_proplist_t **cb_proplist;
|
||||
} callback_data_t;
|
||||
|
||||
uu_avl_pool_t *avl_pool;
|
||||
|
||||
/*
|
||||
* Include snaps if they were requested or if this a zfs list where types
|
||||
* were not specified and the "listsnapshots" property is set on this pool.
|
||||
*/
|
||||
static int
|
||||
zfs_include_snapshots(zfs_handle_t *zhp, callback_data_t *cb)
|
||||
{
|
||||
zpool_handle_t *zph;
|
||||
|
||||
if ((cb->cb_flags & ZFS_ITER_PROP_LISTSNAPS) == 0)
|
||||
return (cb->cb_types & ZFS_TYPE_SNAPSHOT);
|
||||
|
||||
zph = zfs_get_pool_handle(zhp);
|
||||
return (zpool_get_prop_int(zph, ZPOOL_PROP_LISTSNAPS, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
* Called for each dataset. If the object is of an appropriate type,
|
||||
* Called for each dataset. If the object the object is of an appropriate type,
|
||||
* add it to the avl tree and recurse over any children as necessary.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
{
|
||||
callback_data_t *cb = data;
|
||||
int dontclose = 0;
|
||||
int include_snaps = zfs_include_snapshots(zhp, cb);
|
||||
|
||||
if ((zfs_get_type(zhp) & cb->cb_types) ||
|
||||
((zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT) && include_snaps)) {
|
||||
/*
|
||||
* If this object is of the appropriate type, add it to the AVL tree.
|
||||
*/
|
||||
if (zfs_get_type(zhp) & cb->cb_types) {
|
||||
uu_avl_index_t idx;
|
||||
zfs_node_t *node = safe_malloc(sizeof (zfs_node_t));
|
||||
|
||||
@@ -113,12 +100,10 @@ zfs_callback(zfs_handle_t *zhp, void *data)
|
||||
/*
|
||||
* Recurse if necessary.
|
||||
*/
|
||||
if (cb->cb_flags & ZFS_ITER_RECURSE) {
|
||||
if (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM)
|
||||
(void) zfs_iter_filesystems(zhp, zfs_callback, data);
|
||||
if ((zfs_get_type(zhp) != ZFS_TYPE_SNAPSHOT) && include_snaps)
|
||||
(void) zfs_iter_snapshots(zhp, zfs_callback, data);
|
||||
}
|
||||
if (cb->cb_recurse && (zfs_get_type(zhp) == ZFS_TYPE_FILESYSTEM ||
|
||||
(zfs_get_type(zhp) == ZFS_TYPE_VOLUME && (cb->cb_types &
|
||||
ZFS_TYPE_SNAPSHOT))))
|
||||
(void) zfs_iter_children(zhp, zfs_callback, data);
|
||||
|
||||
if (!dontclose)
|
||||
zfs_close(zhp);
|
||||
@@ -133,7 +118,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
||||
zfs_sort_column_t *col;
|
||||
zfs_prop_t prop;
|
||||
|
||||
if ((prop = zfs_name_to_prop(name)) == ZPROP_INVAL &&
|
||||
if ((prop = zfs_name_to_prop(name)) == ZFS_PROP_INVAL &&
|
||||
!zfs_prop_user(name))
|
||||
return (-1);
|
||||
|
||||
@@ -141,7 +126,7 @@ zfs_add_sort_column(zfs_sort_column_t **sc, const char *name,
|
||||
|
||||
col->sc_prop = prop;
|
||||
col->sc_reverse = reverse;
|
||||
if (prop == ZPROP_INVAL) {
|
||||
if (prop == ZFS_PROP_INVAL) {
|
||||
col->sc_user_prop = safe_malloc(strlen(name) + 1);
|
||||
(void) strcpy(col->sc_user_prop, name);
|
||||
}
|
||||
@@ -258,7 +243,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
* Otherwise, we compare 'lnum' and 'rnum'.
|
||||
*/
|
||||
lstr = rstr = NULL;
|
||||
if (psc->sc_prop == ZPROP_INVAL) {
|
||||
if (psc->sc_prop == ZFS_PROP_INVAL) {
|
||||
nvlist_t *luser, *ruser;
|
||||
nvlist_t *lval, *rval;
|
||||
|
||||
@@ -272,10 +257,10 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
|
||||
if (lvalid)
|
||||
verify(nvlist_lookup_string(lval,
|
||||
ZPROP_VALUE, &lstr) == 0);
|
||||
ZFS_PROP_VALUE, &lstr) == 0);
|
||||
if (rvalid)
|
||||
verify(nvlist_lookup_string(rval,
|
||||
ZPROP_VALUE, &rstr) == 0);
|
||||
ZFS_PROP_VALUE, &rstr) == 0);
|
||||
|
||||
} else if (zfs_prop_is_string(psc->sc_prop)) {
|
||||
lvalid = (zfs_prop_get(l, psc->sc_prop, lbuf,
|
||||
@@ -308,7 +293,7 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
|
||||
if (lstr)
|
||||
ret = strcmp(lstr, rstr);
|
||||
else if (lnum < rnum)
|
||||
if (lnum < rnum)
|
||||
ret = -1;
|
||||
else if (lnum > rnum)
|
||||
ret = 1;
|
||||
@@ -324,9 +309,9 @@ zfs_sort(const void *larg, const void *rarg, void *data)
|
||||
}
|
||||
|
||||
int
|
||||
zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
zfs_sort_column_t *sortcol, zprop_list_t **proplist,
|
||||
zfs_iter_f callback, void *data)
|
||||
zfs_for_each(int argc, char **argv, boolean_t recurse, zfs_type_t types,
|
||||
zfs_sort_column_t *sortcol, zfs_proplist_t **proplist, zfs_iter_f callback,
|
||||
void *data, boolean_t args_can_be_paths)
|
||||
{
|
||||
callback_data_t cb;
|
||||
int ret = 0;
|
||||
@@ -343,7 +328,7 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
}
|
||||
|
||||
cb.cb_sortcol = sortcol;
|
||||
cb.cb_flags = flags;
|
||||
cb.cb_recurse = recurse;
|
||||
cb.cb_proplist = proplist;
|
||||
cb.cb_types = types;
|
||||
if ((cb.cb_avl = uu_avl_create(avl_pool, NULL, UU_DEFAULT)) == NULL) {
|
||||
@@ -356,7 +341,7 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
/*
|
||||
* If given no arguments, iterate over all datasets.
|
||||
*/
|
||||
cb.cb_flags |= ZFS_ITER_RECURSE;
|
||||
cb.cb_recurse = 1;
|
||||
ret = zfs_iter_root(g_zfs, zfs_callback, &cb);
|
||||
} else {
|
||||
int i;
|
||||
@@ -369,14 +354,14 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types,
|
||||
* can take volumes as well.
|
||||
*/
|
||||
argtype = types;
|
||||
if (flags & ZFS_ITER_RECURSE) {
|
||||
if (recurse) {
|
||||
argtype |= ZFS_TYPE_FILESYSTEM;
|
||||
if (types & ZFS_TYPE_SNAPSHOT)
|
||||
argtype |= ZFS_TYPE_VOLUME;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (flags & ZFS_ITER_ARGS_CAN_BE_PATHS) {
|
||||
if (args_can_be_paths) {
|
||||
zhp = zfs_path_to_zhandle(g_zfs, argv[i],
|
||||
argtype);
|
||||
} else {
|
||||
|
||||
@@ -19,13 +19,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef ZFS_ITER_H
|
||||
#define ZFS_ITER_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -38,12 +40,8 @@ typedef struct zfs_sort_column {
|
||||
boolean_t sc_reverse;
|
||||
} zfs_sort_column_t;
|
||||
|
||||
#define ZFS_ITER_RECURSE (1 << 0)
|
||||
#define ZFS_ITER_ARGS_CAN_BE_PATHS (1 << 1)
|
||||
#define ZFS_ITER_PROP_LISTSNAPS (1 << 2)
|
||||
|
||||
int zfs_for_each(int, char **, int options, zfs_type_t,
|
||||
zfs_sort_column_t *, zprop_list_t **, zfs_iter_f, void *);
|
||||
int zfs_for_each(int, char **, boolean_t, zfs_type_t, zfs_sort_column_t *,
|
||||
zfs_proplist_t **, zfs_iter_f, void *, boolean_t);
|
||||
int zfs_add_sort_column(zfs_sort_column_t **, const char *, boolean_t);
|
||||
void zfs_free_sort_columns(zfs_sort_column_t *);
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,460 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* 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]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#undef verify /* both libzfs.h and zfs_context.h want to define this */
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/mntent.h>
|
||||
#include <sys/mnttab.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <sys/dmu.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dnode.h>
|
||||
#include <sys/vdev_impl.h>
|
||||
|
||||
#include "zinject.h"
|
||||
|
||||
#include <assert.h>
|
||||
#define verify assert
|
||||
|
||||
extern void kernel_init(int);
|
||||
extern void kernel_fini(void);
|
||||
|
||||
static int debug;
|
||||
|
||||
static void
|
||||
ziprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (!debug)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
(void) vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a full path to a file, translate into a dataset name and a relative
|
||||
* path within the dataset. 'dataset' must be at least MAXNAMELEN characters,
|
||||
* and 'relpath' must be at least MAXPATHLEN characters. We also pass a stat64
|
||||
* buffer, which we need later to get the object ID.
|
||||
*/
|
||||
static int
|
||||
parse_pathname(const char *fullpath, char *dataset, char *relpath,
|
||||
struct stat64 *statbuf)
|
||||
{
|
||||
struct statfs sfs;
|
||||
const char *rel;
|
||||
|
||||
if (fullpath[0] != '/') {
|
||||
(void) fprintf(stderr, "invalid object '%s': must be full "
|
||||
"path\n", fullpath);
|
||||
usage();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strlen(fullpath) >= MAXPATHLEN) {
|
||||
(void) fprintf(stderr, "invalid object; pathname too long\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (stat64(fullpath, statbuf) != 0) {
|
||||
(void) fprintf(stderr, "cannot open '%s': %s\n",
|
||||
fullpath, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (statfs(fullpath, &sfs) == -1) {
|
||||
(void) fprintf(stderr, "cannot find mountpoint for '%s': %s\n",
|
||||
fullpath, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strcmp(sfs.f_fstypename, MNTTYPE_ZFS) != 0) {
|
||||
(void) fprintf(stderr, "invalid path '%s': not a ZFS "
|
||||
"filesystem\n", fullpath);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (strncmp(fullpath, sfs.f_mntonname, strlen(sfs.f_mntonname)) != 0) {
|
||||
(void) fprintf(stderr, "invalid path '%s': mountpoint "
|
||||
"doesn't match path\n", fullpath);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
(void) strcpy(dataset, sfs.f_mntfromname);
|
||||
|
||||
rel = fullpath + strlen(sfs.f_mntonname);
|
||||
if (rel[0] == '/')
|
||||
rel++;
|
||||
(void) strcpy(relpath, rel);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from a (dataset, path) pair into a (objset, object) pair. Note that
|
||||
* we grab the object number from the inode number, since looking this up via
|
||||
* libzpool is a real pain.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
object_from_path(const char *dataset, const char *path, struct stat64 *statbuf,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
objset_t *os;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Before doing any libzpool operations, call sync() to ensure that the
|
||||
* on-disk state is consistent with the in-core state.
|
||||
*/
|
||||
sync();
|
||||
|
||||
if ((err = dmu_objset_open(dataset, DMU_OST_ZFS,
|
||||
DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
record->zi_objset = dmu_objset_id(os);
|
||||
record->zi_object = statbuf->st_ino;
|
||||
|
||||
dmu_objset_close(os);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the real range based on the type, level, and range given.
|
||||
*/
|
||||
static int
|
||||
calculate_range(const char *dataset, err_type_t type, int level, char *range,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
objset_t *os = NULL;
|
||||
dnode_t *dn = NULL;
|
||||
int err;
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
* Determine the numeric range from the string.
|
||||
*/
|
||||
if (range == NULL) {
|
||||
/*
|
||||
* If range is unspecified, set the range to [0,-1], which
|
||||
* indicates that the whole object should be treated as an
|
||||
* error.
|
||||
*/
|
||||
record->zi_start = 0;
|
||||
record->zi_end = -1ULL;
|
||||
} else {
|
||||
char *end;
|
||||
|
||||
/* XXX add support for suffixes */
|
||||
record->zi_start = strtoull(range, &end, 10);
|
||||
|
||||
|
||||
if (*end == '\0')
|
||||
record->zi_end = record->zi_start + 1;
|
||||
else if (*end == ',')
|
||||
record->zi_end = strtoull(end + 1, &end, 10);
|
||||
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid range '%s': must be "
|
||||
"a numeric range of the form 'start[,end]'\n",
|
||||
range);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case TYPE_DATA:
|
||||
break;
|
||||
|
||||
case TYPE_DNODE:
|
||||
/*
|
||||
* If this is a request to inject faults into the dnode, then we
|
||||
* must translate the current (objset,object) pair into an
|
||||
* offset within the metadnode for the objset. Specifying any
|
||||
* kind of range with type 'dnode' is illegal.
|
||||
*/
|
||||
if (range != NULL) {
|
||||
(void) fprintf(stderr, "range cannot be specified when "
|
||||
"type is 'dnode'\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
record->zi_start = record->zi_object * sizeof (dnode_phys_t);
|
||||
record->zi_end = record->zi_start + sizeof (dnode_phys_t);
|
||||
record->zi_object = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the dnode associated with object, so we can calculate the block
|
||||
* size.
|
||||
*/
|
||||
if ((err = dmu_objset_open(dataset, DMU_OST_ANY,
|
||||
DS_MODE_USER | DS_MODE_READONLY, &os)) != 0) {
|
||||
(void) fprintf(stderr, "cannot open dataset '%s': %s\n",
|
||||
dataset, strerror(err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (record->zi_object == 0) {
|
||||
dn = os->os->os_meta_dnode;
|
||||
} else {
|
||||
err = dnode_hold(os->os, record->zi_object, FTAG, &dn);
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr, "failed to hold dnode "
|
||||
"for object %llu\n",
|
||||
(u_longlong_t)record->zi_object);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ziprintf("data shift: %d\n", (int)dn->dn_datablkshift);
|
||||
ziprintf(" ind shift: %d\n", (int)dn->dn_indblkshift);
|
||||
|
||||
/*
|
||||
* Translate range into block IDs.
|
||||
*/
|
||||
if (record->zi_start != 0 || record->zi_end != -1ULL) {
|
||||
record->zi_start >>= dn->dn_datablkshift;
|
||||
record->zi_end >>= dn->dn_datablkshift;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check level, and then translate level 0 blkids into ranges
|
||||
* appropriate for level of indirection.
|
||||
*/
|
||||
record->zi_level = level;
|
||||
if (level > 0) {
|
||||
ziprintf("level 0 blkid range: [%llu, %llu]\n",
|
||||
record->zi_start, record->zi_end);
|
||||
|
||||
if (level >= dn->dn_nlevels) {
|
||||
(void) fprintf(stderr, "level %d exceeds max level "
|
||||
"of object (%d)\n", level, dn->dn_nlevels - 1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (record->zi_start != 0 || record->zi_end != 0) {
|
||||
int shift = dn->dn_indblkshift - SPA_BLKPTRSHIFT;
|
||||
|
||||
for (; level > 0; level--) {
|
||||
record->zi_start >>= shift;
|
||||
record->zi_end >>= shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
if (dn) {
|
||||
if (dn != os->os->os_meta_dnode)
|
||||
dnode_rele(dn, FTAG);
|
||||
}
|
||||
if (os)
|
||||
dmu_objset_close(os);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
translate_record(err_type_t type, const char *object, const char *range,
|
||||
int level, zinject_record_t *record, char *poolname, char *dataset)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
char *slash;
|
||||
struct stat64 statbuf;
|
||||
int ret = -1;
|
||||
|
||||
kernel_init(FREAD);
|
||||
|
||||
debug = (getenv("ZINJECT_DEBUG") != NULL);
|
||||
|
||||
ziprintf("translating: %s\n", object);
|
||||
|
||||
if (MOS_TYPE(type)) {
|
||||
/*
|
||||
* MOS objects are treated specially.
|
||||
*/
|
||||
switch (type) {
|
||||
case TYPE_MOS:
|
||||
record->zi_type = 0;
|
||||
break;
|
||||
case TYPE_MOSDIR:
|
||||
record->zi_type = DMU_OT_OBJECT_DIRECTORY;
|
||||
break;
|
||||
case TYPE_METASLAB:
|
||||
record->zi_type = DMU_OT_OBJECT_ARRAY;
|
||||
break;
|
||||
case TYPE_CONFIG:
|
||||
record->zi_type = DMU_OT_PACKED_NVLIST;
|
||||
break;
|
||||
case TYPE_BPLIST:
|
||||
record->zi_type = DMU_OT_BPLIST;
|
||||
break;
|
||||
case TYPE_SPACEMAP:
|
||||
record->zi_type = DMU_OT_SPACE_MAP;
|
||||
break;
|
||||
case TYPE_ERRLOG:
|
||||
record->zi_type = DMU_OT_ERROR_LOG;
|
||||
break;
|
||||
}
|
||||
|
||||
dataset[0] = '\0';
|
||||
(void) strcpy(poolname, object);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a full path into a (dataset, file) pair.
|
||||
*/
|
||||
if (parse_pathname(object, dataset, path, &statbuf) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf(" dataset: %s\n", dataset);
|
||||
ziprintf(" path: %s\n", path);
|
||||
|
||||
/*
|
||||
* Convert (dataset, file) into (objset, object)
|
||||
*/
|
||||
if (object_from_path(dataset, path, &statbuf, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf("raw objset: %llu\n", record->zi_objset);
|
||||
ziprintf("raw object: %llu\n", record->zi_object);
|
||||
|
||||
/*
|
||||
* For the given object, calculate the real (type, level, range)
|
||||
*/
|
||||
if (calculate_range(dataset, type, level, (char *)range, record) != 0)
|
||||
goto err;
|
||||
|
||||
ziprintf(" objset: %llu\n", record->zi_objset);
|
||||
ziprintf(" object: %llu\n", record->zi_object);
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
ziprintf(" range: all\n");
|
||||
else
|
||||
ziprintf(" range: [%llu, %llu]\n", record->zi_start,
|
||||
record->zi_end);
|
||||
|
||||
/*
|
||||
* Copy the pool name
|
||||
*/
|
||||
(void) strcpy(poolname, dataset);
|
||||
if ((slash = strchr(poolname, '/')) != NULL)
|
||||
*slash = '\0';
|
||||
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
kernel_fini();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
translate_raw(const char *str, zinject_record_t *record)
|
||||
{
|
||||
/*
|
||||
* A raw bookmark of the form objset:object:level:blkid, where each
|
||||
* number is a hexidecimal value.
|
||||
*/
|
||||
if (sscanf(str, "%llx:%llx:%x:%llx", (u_longlong_t *)&record->zi_objset,
|
||||
(u_longlong_t *)&record->zi_object, &record->zi_level,
|
||||
(u_longlong_t *)&record->zi_start) != 4) {
|
||||
(void) fprintf(stderr, "bad raw spec '%s': must be of the form "
|
||||
"'objset:object:level:blkid'\n", str);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
record->zi_end = record->zi_start;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
translate_device(const char *pool, const char *device, err_type_t label_type,
|
||||
zinject_record_t *record)
|
||||
{
|
||||
char *end;
|
||||
zpool_handle_t *zhp;
|
||||
nvlist_t *tgt;
|
||||
boolean_t isspare, iscache;
|
||||
|
||||
/*
|
||||
* Given a device name or GUID, create an appropriate injection record
|
||||
* with zi_guid set.
|
||||
*/
|
||||
if ((zhp = zpool_open(g_zfs, pool)) == NULL)
|
||||
return (-1);
|
||||
|
||||
record->zi_guid = strtoull(device, &end, 16);
|
||||
if (record->zi_guid == 0 || *end != '\0') {
|
||||
tgt = zpool_find_vdev(zhp, device, &isspare, &iscache, NULL);
|
||||
|
||||
if (tgt == NULL) {
|
||||
(void) fprintf(stderr, "cannot find device '%s' in "
|
||||
"pool '%s'\n", device, pool);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
verify(nvlist_lookup_uint64(tgt, ZPOOL_CONFIG_GUID,
|
||||
&record->zi_guid) == 0);
|
||||
}
|
||||
|
||||
switch (label_type) {
|
||||
case TYPE_LABEL_UBERBLOCK:
|
||||
record->zi_start = offsetof(vdev_label_t, vl_uberblock[0]);
|
||||
record->zi_end = record->zi_start + VDEV_UBERBLOCK_RING - 1;
|
||||
break;
|
||||
case TYPE_LABEL_NVLIST:
|
||||
record->zi_start = offsetof(vdev_label_t, vl_vdev_phys);
|
||||
record->zi_end = record->zi_start + VDEV_PHYS_SIZE - 1;
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -1,771 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* 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]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* ZFS Fault Injector
|
||||
*
|
||||
* This userland component takes a set of options and uses libzpool to translate
|
||||
* from a user-visible object type and name to an internal representation.
|
||||
* There are two basic types of faults: device faults and data faults.
|
||||
*
|
||||
*
|
||||
* DEVICE FAULTS
|
||||
*
|
||||
* Errors can be injected into a particular vdev using the '-d' option. This
|
||||
* option takes a path or vdev GUID to uniquely identify the device within a
|
||||
* pool. There are two types of errors that can be injected, EIO and ENXIO,
|
||||
* that can be controlled through the '-e' option. The default is ENXIO. For
|
||||
* EIO failures, any attempt to read data from the device will return EIO, but
|
||||
* subsequent attempt to reopen the device will succeed. For ENXIO failures,
|
||||
* any attempt to read from the device will return EIO, but any attempt to
|
||||
* reopen the device will also return ENXIO.
|
||||
* For label faults, the -L option must be specified. This allows faults
|
||||
* to be injected into either the nvlist or uberblock region of all the labels
|
||||
* for the specified device.
|
||||
*
|
||||
* This form of the command looks like:
|
||||
*
|
||||
* zinject -d device [-e errno] [-L <uber | nvlist>] pool
|
||||
*
|
||||
*
|
||||
* DATA FAULTS
|
||||
*
|
||||
* We begin with a tuple of the form:
|
||||
*
|
||||
* <type,level,range,object>
|
||||
*
|
||||
* type A string describing the type of data to target. Each type
|
||||
* implicitly describes how to interpret 'object'. Currently,
|
||||
* the following values are supported:
|
||||
*
|
||||
* data User data for a file
|
||||
* dnode Dnode for a file or directory
|
||||
*
|
||||
* The following MOS objects are special. Instead of injecting
|
||||
* errors on a particular object or blkid, we inject errors across
|
||||
* all objects of the given type.
|
||||
*
|
||||
* mos Any data in the MOS
|
||||
* mosdir object directory
|
||||
* config pool configuration
|
||||
* bplist blkptr list
|
||||
* spacemap spacemap
|
||||
* metaslab metaslab
|
||||
* errlog persistent error log
|
||||
*
|
||||
* level Object level. Defaults to '0', not applicable to all types. If
|
||||
* a range is given, this corresponds to the indirect block
|
||||
* corresponding to the specific range.
|
||||
*
|
||||
* range A numerical range [start,end) within the object. Defaults to
|
||||
* the full size of the file.
|
||||
*
|
||||
* object A string describing the logical location of the object. For
|
||||
* files and directories (currently the only supported types),
|
||||
* this is the path of the object on disk.
|
||||
*
|
||||
* This is translated, via libzpool, into the following internal representation:
|
||||
*
|
||||
* <type,objset,object,level,range>
|
||||
*
|
||||
* These types should be self-explanatory. This tuple is then passed to the
|
||||
* kernel via a special ioctl() to initiate fault injection for the given
|
||||
* object. Note that 'type' is not strictly necessary for fault injection, but
|
||||
* is used when translating existing faults into a human-readable string.
|
||||
*
|
||||
*
|
||||
* The command itself takes one of the forms:
|
||||
*
|
||||
* zinject
|
||||
* zinject <-a | -u pool>
|
||||
* zinject -c <id|all>
|
||||
* zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
|
||||
* [-r range] <object>
|
||||
* zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
|
||||
*
|
||||
* With no arguments, the command prints all currently registered injection
|
||||
* handlers, with their numeric identifiers.
|
||||
*
|
||||
* The '-c' option will clear the given handler, or all handlers if 'all' is
|
||||
* specified.
|
||||
*
|
||||
* The '-e' option takes a string describing the errno to simulate. This must
|
||||
* be either 'io' or 'checksum'. In most cases this will result in the same
|
||||
* behavior, but RAID-Z will produce a different set of ereports for this
|
||||
* situation.
|
||||
*
|
||||
* The '-a', '-u', and '-m' flags toggle internal flush behavior. If '-a' is
|
||||
* specified, then the ARC cache is flushed appropriately. If '-u' is
|
||||
* specified, then the underlying SPA is unloaded. Either of these flags can be
|
||||
* specified independently of any other handlers. The '-m' flag automatically
|
||||
* does an unmount and remount of the underlying dataset to aid in flushing the
|
||||
* cache.
|
||||
*
|
||||
* The '-f' flag controls the frequency of errors injected, expressed as a
|
||||
* integer percentage between 1 and 100. The default is 100.
|
||||
*
|
||||
* The this form is responsible for actually injecting the handler into the
|
||||
* framework. It takes the arguments described above, translates them to the
|
||||
* internal tuple using libzpool, and then issues an ioctl() to register the
|
||||
* handler.
|
||||
*
|
||||
* The final form can target a specific bookmark, regardless of whether a
|
||||
* human-readable interface has been designed. It allows developers to specify
|
||||
* a particular block by number.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#undef verify /* both libzfs.h and zfs_context.h want to define this */
|
||||
|
||||
#include "zinject.h"
|
||||
|
||||
libzfs_handle_t *g_zfs;
|
||||
int zfs_fd;
|
||||
|
||||
#ifndef ECKSUM
|
||||
#define ECKSUM EBADE
|
||||
#endif
|
||||
|
||||
static const char *errtable[TYPE_INVAL] = {
|
||||
"data",
|
||||
"dnode",
|
||||
"mos",
|
||||
"mosdir",
|
||||
"metaslab",
|
||||
"config",
|
||||
"bplist",
|
||||
"spacemap",
|
||||
"errlog",
|
||||
"uber",
|
||||
"nvlist"
|
||||
};
|
||||
|
||||
static err_type_t
|
||||
name_to_type(const char *arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TYPE_INVAL; i++)
|
||||
if (strcmp(errtable[i], arg) == 0)
|
||||
return (i);
|
||||
|
||||
return (TYPE_INVAL);
|
||||
}
|
||||
|
||||
static const char *
|
||||
type_to_name(uint64_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case DMU_OT_OBJECT_DIRECTORY:
|
||||
return ("mosdir");
|
||||
case DMU_OT_OBJECT_ARRAY:
|
||||
return ("metaslab");
|
||||
case DMU_OT_PACKED_NVLIST:
|
||||
return ("config");
|
||||
case DMU_OT_BPLIST:
|
||||
return ("bplist");
|
||||
case DMU_OT_SPACE_MAP:
|
||||
return ("spacemap");
|
||||
case DMU_OT_ERROR_LOG:
|
||||
return ("errlog");
|
||||
default:
|
||||
return ("-");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print usage message.
|
||||
*/
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
(void) printf(
|
||||
"usage:\n"
|
||||
"\n"
|
||||
"\tzinject\n"
|
||||
"\n"
|
||||
"\t\tList all active injection records.\n"
|
||||
"\n"
|
||||
"\tzinject -c <id|all>\n"
|
||||
"\n"
|
||||
"\t\tClear the particular record (if given a numeric ID), or\n"
|
||||
"\t\tall records if 'all' is specificed.\n"
|
||||
"\n"
|
||||
"\tzinject -d device [-e errno] [-L <nvlist|uber>] pool\n"
|
||||
"\t\tInject a fault into a particular device or the device's\n"
|
||||
"\t\tlabel. Label injection can either be 'nvlist' or 'uber'.\n"
|
||||
"\t\t'errno' can either be 'nxio' (the default) or 'io'.\n"
|
||||
"\n"
|
||||
"\tzinject -b objset:object:level:blkid pool\n"
|
||||
"\n"
|
||||
"\t\tInject an error into pool 'pool' with the numeric bookmark\n"
|
||||
"\t\tspecified by the remaining tuple. Each number is in\n"
|
||||
"\t\thexidecimal, and only one block can be specified.\n"
|
||||
"\n"
|
||||
"\tzinject [-q] <-t type> [-e errno] [-l level] [-r range]\n"
|
||||
"\t [-a] [-m] [-u] [-f freq] <object>\n"
|
||||
"\n"
|
||||
"\t\tInject an error into the object specified by the '-t' option\n"
|
||||
"\t\tand the object descriptor. The 'object' parameter is\n"
|
||||
"\t\tinterperted depending on the '-t' option.\n"
|
||||
"\n"
|
||||
"\t\t-q\tQuiet mode. Only print out the handler number added.\n"
|
||||
"\t\t-e\tInject a specific error. Must be either 'io' or\n"
|
||||
"\t\t\t'checksum'. Default is 'io'.\n"
|
||||
"\t\t-l\tInject error at a particular block level. Default is "
|
||||
"0.\n"
|
||||
"\t\t-m\tAutomatically remount underlying filesystem.\n"
|
||||
"\t\t-r\tInject error over a particular logical range of an\n"
|
||||
"\t\t\tobject. Will be translated to the appropriate blkid\n"
|
||||
"\t\t\trange according to the object's properties.\n"
|
||||
"\t\t-a\tFlush the ARC cache. Can be specified without any\n"
|
||||
"\t\t\tassociated object.\n"
|
||||
"\t\t-u\tUnload the associated pool. Can be specified with only\n"
|
||||
"\t\t\ta pool object.\n"
|
||||
"\t\t-f\tOnly inject errors a fraction of the time. Expressed as\n"
|
||||
"\t\t\ta percentage between 1 and 100.\n"
|
||||
"\n"
|
||||
"\t-t data\t\tInject an error into the plain file contents of a\n"
|
||||
"\t\t\tfile. The object must be specified as a complete path\n"
|
||||
"\t\t\tto a file on a ZFS filesystem.\n"
|
||||
"\n"
|
||||
"\t-t dnode\tInject an error into the metadnode in the block\n"
|
||||
"\t\t\tcorresponding to the dnode for a file or directory. The\n"
|
||||
"\t\t\t'-r' option is incompatible with this mode. The object\n"
|
||||
"\t\t\tis specified as a complete path to a file or directory\n"
|
||||
"\t\t\ton a ZFS filesystem.\n"
|
||||
"\n"
|
||||
"\t-t <mos>\tInject errors into the MOS for objects of the given\n"
|
||||
"\t\t\ttype. Valid types are: mos, mosdir, config, bplist,\n"
|
||||
"\t\t\tspacemap, metaslab, errlog. The only valid <object> is\n"
|
||||
"\t\t\tthe poolname.\n");
|
||||
}
|
||||
|
||||
static int
|
||||
iter_handlers(int (*func)(int, const char *, zinject_record_t *, void *),
|
||||
void *data)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
int ret;
|
||||
|
||||
zc.zc_guid = 0;
|
||||
|
||||
while (ioctl(zfs_fd, ZFS_IOC_INJECT_LIST_NEXT, &zc) == 0)
|
||||
if ((ret = func((int)zc.zc_guid, zc.zc_name,
|
||||
&zc.zc_inject_record, data)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
print_data_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
int *count = data;
|
||||
|
||||
if (record->zi_guid != 0)
|
||||
return (0);
|
||||
|
||||
if (*count == 0) {
|
||||
(void) printf("%3s %-15s %-6s %-6s %-8s %3s %-15s\n",
|
||||
"ID", "POOL", "OBJSET", "OBJECT", "TYPE", "LVL", "RANGE");
|
||||
(void) printf("--- --------------- ------ "
|
||||
"------ -------- --- ---------------\n");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
|
||||
(void) printf("%3d %-15s %-6llu %-6llu %-8s %3d ", id, pool,
|
||||
(u_longlong_t)record->zi_objset, (u_longlong_t)record->zi_object,
|
||||
type_to_name(record->zi_type), record->zi_level);
|
||||
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
(void) printf("all\n");
|
||||
else
|
||||
(void) printf("[%llu, %llu]\n", (u_longlong_t)record->zi_start,
|
||||
(u_longlong_t)record->zi_end);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
print_device_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
int *count = data;
|
||||
|
||||
if (record->zi_guid == 0)
|
||||
return (0);
|
||||
|
||||
if (*count == 0) {
|
||||
(void) printf("%3s %-15s %s\n", "ID", "POOL", "GUID");
|
||||
(void) printf("--- --------------- ----------------\n");
|
||||
}
|
||||
|
||||
*count += 1;
|
||||
|
||||
(void) printf("%3d %-15s %llx\n", id, pool,
|
||||
(u_longlong_t)record->zi_guid);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print all registered error handlers. Returns the number of handlers
|
||||
* registered.
|
||||
*/
|
||||
static int
|
||||
print_all_handlers(void)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
(void) iter_handlers(print_device_handler, &count);
|
||||
(void) printf("\n");
|
||||
count = 0;
|
||||
(void) iter_handlers(print_data_handler, &count);
|
||||
|
||||
return (count);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int
|
||||
cancel_one_handler(int id, const char *pool, zinject_record_t *record,
|
||||
void *data)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all fault injection handlers.
|
||||
*/
|
||||
static int
|
||||
cancel_all_handlers(void)
|
||||
{
|
||||
int ret = iter_handlers(cancel_one_handler, NULL);
|
||||
|
||||
(void) printf("removed all registered handlers\n");
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a specific fault injection handler.
|
||||
*/
|
||||
static int
|
||||
cancel_handler(int id)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
zc.zc_guid = (uint64_t)id;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_CLEAR_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to remove handler %d: %s\n",
|
||||
id, strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
(void) printf("removed handler %d\n", id);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a new fault injection handler.
|
||||
*/
|
||||
static int
|
||||
register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
int quiet)
|
||||
{
|
||||
zfs_cmd_t zc;
|
||||
|
||||
(void) strcpy(zc.zc_name, pool);
|
||||
zc.zc_inject_record = *record;
|
||||
zc.zc_guid = flags;
|
||||
|
||||
if (ioctl(zfs_fd, ZFS_IOC_INJECT_FAULT, &zc) != 0) {
|
||||
(void) fprintf(stderr, "failed to add handler: %s\n",
|
||||
strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (flags & ZINJECT_NULL)
|
||||
return (0);
|
||||
|
||||
if (quiet) {
|
||||
(void) printf("%llu\n", (u_longlong_t)zc.zc_guid);
|
||||
} else {
|
||||
(void) printf("Added handler %llu with the following "
|
||||
"properties:\n", (u_longlong_t)zc.zc_guid);
|
||||
(void) printf(" pool: %s\n", pool);
|
||||
if (record->zi_guid) {
|
||||
(void) printf(" vdev: %llx\n",
|
||||
(u_longlong_t)record->zi_guid);
|
||||
} else {
|
||||
(void) printf("objset: %llu\n",
|
||||
(u_longlong_t)record->zi_objset);
|
||||
(void) printf("object: %llu\n",
|
||||
(u_longlong_t)record->zi_object);
|
||||
(void) printf(" type: %llu\n",
|
||||
(u_longlong_t)record->zi_type);
|
||||
(void) printf(" level: %d\n", record->zi_level);
|
||||
if (record->zi_start == 0 &&
|
||||
record->zi_end == -1ULL)
|
||||
(void) printf(" range: all\n");
|
||||
else
|
||||
(void) printf(" range: [%llu, %llu)\n",
|
||||
(u_longlong_t)record->zi_start,
|
||||
(u_longlong_t)record->zi_end);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
char *range = NULL;
|
||||
char *cancel = NULL;
|
||||
char *end;
|
||||
char *raw = NULL;
|
||||
char *device = NULL;
|
||||
int level = 0;
|
||||
int quiet = 0;
|
||||
int error = 0;
|
||||
int domount = 0;
|
||||
err_type_t type = TYPE_INVAL;
|
||||
err_type_t label = TYPE_INVAL;
|
||||
zinject_record_t record = { 0 };
|
||||
char pool[MAXNAMELEN];
|
||||
char dataset[MAXNAMELEN];
|
||||
zfs_handle_t *zhp;
|
||||
int ret;
|
||||
int flags = 0;
|
||||
|
||||
if ((g_zfs = libzfs_init()) == NULL) {
|
||||
(void) fprintf(stderr, "internal error: failed to "
|
||||
"initialize ZFS library\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
libzfs_print_on_error(g_zfs, B_TRUE);
|
||||
|
||||
if ((zfs_fd = open(ZFS_DEV, O_RDWR)) < 0) {
|
||||
(void) fprintf(stderr, "failed to open ZFS device\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
/*
|
||||
* No arguments. Print the available handlers. If there are no
|
||||
* available handlers, direct the user to '-h' for help
|
||||
* information.
|
||||
*/
|
||||
if (print_all_handlers() == 0) {
|
||||
(void) printf("No handlers registered.\n");
|
||||
(void) printf("Run 'zinject -h' for usage "
|
||||
"information.\n");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv, ":ab:d:f:qhc:t:l:mr:e:uL:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
flags |= ZINJECT_FLUSH_ARC;
|
||||
break;
|
||||
case 'b':
|
||||
raw = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
cancel = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
device = optarg;
|
||||
break;
|
||||
case 'e':
|
||||
if (strcasecmp(optarg, "io") == 0) {
|
||||
error = EIO;
|
||||
} else if (strcasecmp(optarg, "checksum") == 0) {
|
||||
error = ECKSUM;
|
||||
} else if (strcasecmp(optarg, "nxio") == 0) {
|
||||
error = ENXIO;
|
||||
} else {
|
||||
(void) fprintf(stderr, "invalid error type "
|
||||
"'%s': must be 'io', 'checksum' or "
|
||||
"'nxio'\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
record.zi_freq = atoi(optarg);
|
||||
if (record.zi_freq < 1 || record.zi_freq > 100) {
|
||||
(void) fprintf(stderr, "frequency range must "
|
||||
"be in the range (0, 100]\n");
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return (0);
|
||||
case 'l':
|
||||
level = (int)strtol(optarg, &end, 10);
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid level '%s': "
|
||||
"must be an integer\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
domount = 1;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case 'r':
|
||||
range = optarg;
|
||||
break;
|
||||
case 't':
|
||||
if ((type = name_to_type(optarg)) == TYPE_INVAL &&
|
||||
!MOS_TYPE(type)) {
|
||||
(void) fprintf(stderr, "invalid type '%s'\n",
|
||||
optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
flags |= ZINJECT_UNLOAD_SPA;
|
||||
break;
|
||||
case 'L':
|
||||
if ((label = name_to_type(optarg)) == TYPE_INVAL &&
|
||||
!LABEL_TYPE(type)) {
|
||||
(void) fprintf(stderr, "invalid label type "
|
||||
"'%s'\n", optarg);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
(void) fprintf(stderr, "option -%c requires an "
|
||||
"operand\n", optopt);
|
||||
usage();
|
||||
return (1);
|
||||
case '?':
|
||||
(void) fprintf(stderr, "invalid option '%c'\n",
|
||||
optopt);
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (cancel != NULL) {
|
||||
/*
|
||||
* '-c' is invalid with any other options.
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0) {
|
||||
(void) fprintf(stderr, "cancel (-c) incompatible with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
if (argc != 0) {
|
||||
(void) fprintf(stderr, "extraneous argument to '-c'\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (strcmp(cancel, "all") == 0) {
|
||||
return (cancel_all_handlers());
|
||||
} else {
|
||||
int id = (int)strtol(cancel, &end, 10);
|
||||
if (*end != '\0') {
|
||||
(void) fprintf(stderr, "invalid handle id '%s':"
|
||||
" must be an integer or 'all'\n", cancel);
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
return (cancel_handler(id));
|
||||
}
|
||||
}
|
||||
|
||||
if (device != NULL) {
|
||||
/*
|
||||
* Device (-d) injection uses a completely different mechanism
|
||||
* for doing injection, so handle it separately here.
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0) {
|
||||
(void) fprintf(stderr, "device (-d) incompatible with "
|
||||
"data error injection\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "device (-d) injection requires "
|
||||
"a single pool name\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
|
||||
if (error == ECKSUM) {
|
||||
(void) fprintf(stderr, "device error type must be "
|
||||
"'io' or 'nxio'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_device(pool, device, label, &record) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = ENXIO;
|
||||
} else if (raw != NULL) {
|
||||
if (range != NULL || type != TYPE_INVAL || level != 0) {
|
||||
(void) fprintf(stderr, "raw (-b) format with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "raw (-b) format expects a "
|
||||
"single pool name\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
|
||||
if (error == ENXIO) {
|
||||
(void) fprintf(stderr, "data error type must be "
|
||||
"'checksum' or 'io'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_raw(raw, &record) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = EIO;
|
||||
} else if (type == TYPE_INVAL) {
|
||||
if (flags == 0) {
|
||||
(void) fprintf(stderr, "at least one of '-b', '-d', "
|
||||
"'-t', '-a', or '-u' must be specified\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (argc == 1 && (flags & ZINJECT_UNLOAD_SPA)) {
|
||||
(void) strcpy(pool, argv[0]);
|
||||
dataset[0] = '\0';
|
||||
} else if (argc != 0) {
|
||||
(void) fprintf(stderr, "extraneous argument for "
|
||||
"'-f'\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
flags |= ZINJECT_NULL;
|
||||
} else {
|
||||
if (argc != 1) {
|
||||
(void) fprintf(stderr, "missing object\n");
|
||||
usage();
|
||||
return (2);
|
||||
}
|
||||
|
||||
if (error == ENXIO) {
|
||||
(void) fprintf(stderr, "data error type must be "
|
||||
"'checksum' or 'io'\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (translate_record(type, argv[0], range, level, &record, pool,
|
||||
dataset) != 0)
|
||||
return (1);
|
||||
if (!error)
|
||||
error = EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is pool-wide metadata, unmount everything. The ioctl() will
|
||||
* unload the pool, so that we trigger spa-wide reopen of metadata next
|
||||
* time we access the pool.
|
||||
*/
|
||||
if (dataset[0] != '\0' && domount) {
|
||||
if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
|
||||
return (1);
|
||||
|
||||
if (zfs_unmount(zhp, NULL, 0) != 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
record.zi_error = error;
|
||||
|
||||
ret = register_handler(pool, flags, &record, quiet);
|
||||
|
||||
if (dataset[0] != '\0' && domount)
|
||||
ret = (zfs_mount(zhp, NULL, 0) != 0);
|
||||
|
||||
libzfs_fini(g_zfs);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* 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]
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef _ZINJECT_H
|
||||
#define _ZINJECT_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <sys/zfs_ioctl.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TYPE_DATA, /* plain file contents */
|
||||
TYPE_DNODE, /* metadnode contents */
|
||||
TYPE_MOS, /* all MOS data */
|
||||
TYPE_MOSDIR, /* MOS object directory */
|
||||
TYPE_METASLAB, /* metaslab objects */
|
||||
TYPE_CONFIG, /* MOS config */
|
||||
TYPE_BPLIST, /* block pointer list */
|
||||
TYPE_SPACEMAP, /* space map objects */
|
||||
TYPE_ERRLOG, /* persistent error log */
|
||||
TYPE_LABEL_UBERBLOCK, /* label specific uberblock */
|
||||
TYPE_LABEL_NVLIST, /* label specific nvlist */
|
||||
TYPE_INVAL
|
||||
} err_type_t;
|
||||
|
||||
#define MOS_TYPE(t) \
|
||||
((t) >= TYPE_MOS && (t) < TYPE_LABEL_UBERBLOCK)
|
||||
|
||||
#define LABEL_TYPE(t) \
|
||||
((t) >= TYPE_LABEL_UBERBLOCK && (t) < TYPE_INVAL)
|
||||
|
||||
int translate_record(err_type_t type, const char *object, const char *range,
|
||||
int level, zinject_record_t *record, char *poolname, char *dataset);
|
||||
int translate_raw(const char *raw, zinject_record_t *record);
|
||||
int translate_device(const char *pool, const char *device,
|
||||
err_type_t label_type, zinject_record_t *record);
|
||||
void usage(void);
|
||||
|
||||
extern libzfs_handle_t *g_zfs;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ZINJECT_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -53,7 +53,6 @@ struct zpool_list {
|
||||
boolean_t zl_findall;
|
||||
uu_avl_t *zl_avl;
|
||||
uu_avl_pool_t *zl_pool;
|
||||
zprop_list_t **zl_proplist;
|
||||
};
|
||||
|
||||
/* ARGSUSED */
|
||||
@@ -82,12 +81,6 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
node->zn_handle = zhp;
|
||||
uu_avl_node_init(node, &node->zn_avlnode, zlp->zl_pool);
|
||||
if (uu_avl_find(zlp->zl_avl, node, NULL, &idx) == NULL) {
|
||||
if (zlp->zl_proplist &&
|
||||
zpool_expand_proplist(zhp, zlp->zl_proplist) != 0) {
|
||||
zpool_close(zhp);
|
||||
free(node);
|
||||
return (-1);
|
||||
}
|
||||
uu_avl_insert(zlp->zl_avl, node, idx);
|
||||
} else {
|
||||
zpool_close(zhp);
|
||||
@@ -105,7 +98,7 @@ add_pool(zpool_handle_t *zhp, void *data)
|
||||
* line.
|
||||
*/
|
||||
zpool_list_t *
|
||||
pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
pool_list_get(int argc, char **argv, zpool_proplist_t **proplist, int *err)
|
||||
{
|
||||
zpool_list_t *zlp;
|
||||
|
||||
@@ -121,8 +114,6 @@ pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
UU_DEFAULT)) == NULL)
|
||||
zpool_no_memory();
|
||||
|
||||
zlp->zl_proplist = proplist;
|
||||
|
||||
if (argc == 0) {
|
||||
(void) zpool_iter(g_zfs, add_pool, zlp);
|
||||
zlp->zl_findall = B_TRUE;
|
||||
@@ -132,12 +123,13 @@ pool_list_get(int argc, char **argv, zprop_list_t **proplist, int *err)
|
||||
for (i = 0; i < argc; i++) {
|
||||
zpool_handle_t *zhp;
|
||||
|
||||
if (zhp = zpool_open_canfail(g_zfs, argv[i])) {
|
||||
if (add_pool(zhp, zlp) != 0)
|
||||
if ((zhp = zpool_open_canfail(g_zfs,
|
||||
argv[i])) != NULL && add_pool(zhp, zlp) == 0) {
|
||||
if (proplist &&
|
||||
zpool_expand_proplist(zhp, proplist) != 0)
|
||||
*err = B_TRUE;
|
||||
} else {
|
||||
} else
|
||||
*err = B_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +228,7 @@ pool_list_count(zpool_list_t *zlp)
|
||||
*/
|
||||
int
|
||||
for_each_pool(int argc, char **argv, boolean_t unavail,
|
||||
zprop_list_t **proplist, zpool_iter_f func, void *data)
|
||||
zpool_proplist_t **proplist, zpool_iter_f func, void *data)
|
||||
{
|
||||
zpool_list_t *list;
|
||||
int ret = 0;
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -19,7 +19,7 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -77,28 +77,3 @@ zpool_no_memory(void)
|
||||
gettext("internal error: out of memory\n"));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of logs in supplied nvlist
|
||||
*/
|
||||
uint_t
|
||||
num_logs(nvlist_t *nv)
|
||||
{
|
||||
uint_t nlogs = 0;
|
||||
uint_t c, children;
|
||||
nvlist_t **child;
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0)
|
||||
return (0);
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
uint64_t is_log = B_FALSE;
|
||||
|
||||
(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
|
||||
&is_log);
|
||||
if (is_log)
|
||||
nlogs++;
|
||||
}
|
||||
return (nlogs);
|
||||
}
|
||||
@@ -19,13 +19,15 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#ifndef ZPOOL_UTIL_H
|
||||
#define ZPOOL_UTIL_H
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <libnvpair.h>
|
||||
#include <libzfs.h>
|
||||
|
||||
@@ -39,24 +41,22 @@ extern "C" {
|
||||
void *safe_malloc(size_t);
|
||||
char *safe_strdup(const char *);
|
||||
void zpool_no_memory(void);
|
||||
uint_t num_logs(nvlist_t *nv);
|
||||
|
||||
/*
|
||||
* Virtual device functions
|
||||
*/
|
||||
|
||||
nvlist_t *make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
boolean_t isreplace, boolean_t dryrun, int argc, char **argv);
|
||||
nvlist_t *make_root_vdev(nvlist_t *poolconfig, int force, int check_rep,
|
||||
boolean_t isreplace, int argc, char **argv);
|
||||
|
||||
/*
|
||||
* Pool list functions
|
||||
*/
|
||||
int for_each_pool(int, char **, boolean_t unavail, zprop_list_t **,
|
||||
int for_each_pool(int, char **, boolean_t unavail, zpool_proplist_t **,
|
||||
zpool_iter_f, void *);
|
||||
|
||||
typedef struct zpool_list zpool_list_t;
|
||||
|
||||
zpool_list_t *pool_list_get(int, char **, zprop_list_t **, int *);
|
||||
zpool_list_t *pool_list_get(int, char **, zpool_proplist_t **, int *);
|
||||
void pool_list_update(zpool_list_t *);
|
||||
int pool_list_iter(zpool_list_t *, int unavail, zpool_iter_f, void *);
|
||||
void pool_list_free(zpool_list_t *);
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
/*
|
||||
* Functions to convert between a list of vdevs and an nvlist representing the
|
||||
* configuration. Each entry in the list can be one of:
|
||||
@@ -46,8 +48,8 @@
|
||||
* Hot spares are a special case, and passed down as an array of disk vdevs, at
|
||||
* the same level as the root of the vdev tree.
|
||||
*
|
||||
* The only function exported by this file is 'make_root_vdev'. The
|
||||
* function performs several passes:
|
||||
* The only function exported by this file is 'get_vdev_spec'. The function
|
||||
* performs several passes:
|
||||
*
|
||||
* 1. Construct the vdev specification. Performs syntax validation and
|
||||
* makes sure each device is valid.
|
||||
@@ -57,7 +59,6 @@
|
||||
* 3. Check for replication errors if the 'force' flag is not specified.
|
||||
* validates that the replication level is consistent across the
|
||||
* entire pool.
|
||||
* 4. Call libzfs to label any whole disks with an EFI label.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@@ -75,6 +76,8 @@
|
||||
#include <sys/mntent.h>
|
||||
#include <libgeom.h>
|
||||
|
||||
#include <libzfs.h>
|
||||
|
||||
#include "zpool_util.h"
|
||||
|
||||
/*
|
||||
@@ -108,105 +111,53 @@ vdev_error(const char *fmt, ...)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that a file is valid. All we can do in this case is check that it's
|
||||
* not in use by another pool, and not in use by swap.
|
||||
* Validate a GEOM provider.
|
||||
*/
|
||||
static int
|
||||
check_file(const char *file, boolean_t force, boolean_t isspare)
|
||||
{
|
||||
char *name;
|
||||
int fd;
|
||||
int ret = 0;
|
||||
int err;
|
||||
pool_state_t state;
|
||||
boolean_t inuse;
|
||||
|
||||
#if 0
|
||||
if (dm_inuse_swap(file, &err)) {
|
||||
if (err)
|
||||
libdiskmgt_error(err);
|
||||
else
|
||||
vdev_error(gettext("%s is currently used by swap. "
|
||||
"Please see swap(1M).\n"), file);
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((fd = open(file, O_RDONLY)) < 0)
|
||||
return (0);
|
||||
|
||||
if (zpool_in_use(g_zfs, fd, &state, &name, &inuse) == 0 && inuse) {
|
||||
const char *desc;
|
||||
|
||||
switch (state) {
|
||||
case POOL_STATE_ACTIVE:
|
||||
desc = gettext("active");
|
||||
break;
|
||||
|
||||
case POOL_STATE_EXPORTED:
|
||||
desc = gettext("exported");
|
||||
break;
|
||||
|
||||
case POOL_STATE_POTENTIALLY_ACTIVE:
|
||||
desc = gettext("potentially active");
|
||||
break;
|
||||
|
||||
default:
|
||||
desc = gettext("unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow hot spares to be shared between pools.
|
||||
*/
|
||||
if (state == POOL_STATE_SPARE && isspare)
|
||||
return (0);
|
||||
|
||||
if (state == POOL_STATE_ACTIVE ||
|
||||
state == POOL_STATE_SPARE || !force) {
|
||||
switch (state) {
|
||||
case POOL_STATE_SPARE:
|
||||
vdev_error(gettext("%s is reserved as a hot "
|
||||
"spare for pool %s\n"), file, name);
|
||||
break;
|
||||
default:
|
||||
vdev_error(gettext("%s is part of %s pool "
|
||||
"'%s'\n"), file, desc, name);
|
||||
break;
|
||||
}
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(name);
|
||||
}
|
||||
|
||||
(void) close(fd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
check_provider(const char *name, boolean_t force, boolean_t isspare)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
struct gmesh mesh;
|
||||
struct gclass *mp;
|
||||
struct ggeom *gp;
|
||||
struct gprovider *pp;
|
||||
int rv;
|
||||
|
||||
if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) != 0)
|
||||
snprintf(path, sizeof(path), "%s%s", _PATH_DEV, name);
|
||||
else
|
||||
strlcpy(path, name, sizeof(path));
|
||||
/* XXX: What to do with isspare? */
|
||||
|
||||
return (check_file(path, force, isspare));
|
||||
if (strncmp(name, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
name += sizeof(_PATH_DEV) - 1;
|
||||
|
||||
rv = geom_gettree(&mesh);
|
||||
assert(rv == 0);
|
||||
|
||||
pp = NULL;
|
||||
LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
|
||||
LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
|
||||
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
|
||||
if (strcmp(pp->lg_name, name) == 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
rv = -1;
|
||||
if (pp == NULL)
|
||||
vdev_error("no such provider %s\n", name);
|
||||
else {
|
||||
int acr, acw, ace;
|
||||
|
||||
VERIFY(sscanf(pp->lg_mode, "r%dw%de%d", &acr, &acw, &ace) == 3);
|
||||
if (acw == 0 && ace == 0)
|
||||
rv = 0;
|
||||
else
|
||||
vdev_error("%s is in use (%s)\n", name, pp->lg_mode);
|
||||
}
|
||||
geom_deletetree(&mesh);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
/*
|
||||
* By "whole disk" we mean an entire physical disk (something we can
|
||||
* label, toggle the write cache on, etc.) as opposed to the full
|
||||
* capacity of a pseudo-device such as lofi or did. We act as if we
|
||||
* are labeling the disk, which should be a pretty good test of whether
|
||||
* it's a viable device or not. Returns B_TRUE if it is and B_FALSE if
|
||||
* it isn't.
|
||||
*/
|
||||
static boolean_t
|
||||
is_whole_disk(const char *name)
|
||||
is_provider(const char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
@@ -216,8 +167,8 @@ is_whole_disk(const char *name)
|
||||
return (B_TRUE);
|
||||
}
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* Create a leaf vdev. Determine if this is a GEOM provider.
|
||||
* Valid forms for a leaf vdev are:
|
||||
@@ -225,8 +176,8 @@ is_whole_disk(const char *name)
|
||||
* /dev/xxx Complete path to a GEOM provider
|
||||
* xxx Shorthand for /dev/xxx
|
||||
*/
|
||||
static nvlist_t *
|
||||
make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
nvlist_t *
|
||||
make_leaf_vdev(const char *arg)
|
||||
{
|
||||
char ident[DISK_IDENT_SIZE], path[MAXPATHLEN];
|
||||
struct stat64 statbuf;
|
||||
@@ -234,72 +185,16 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
char *type = NULL;
|
||||
boolean_t wholedisk = B_FALSE;
|
||||
|
||||
/*
|
||||
* Determine what type of vdev this is, and put the full path into
|
||||
* 'path'. We detect whether this is a device of file afterwards by
|
||||
* checking the st_mode of the file.
|
||||
*/
|
||||
if (arg[0] == '/') {
|
||||
/*
|
||||
* Complete device or file path. Exact type is determined by
|
||||
* examining the file descriptor afterwards.
|
||||
*/
|
||||
wholedisk = is_whole_disk(arg);
|
||||
if (!wholedisk && (stat64(arg, &statbuf) != 0)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
arg, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
strlcpy(path, arg, sizeof (path));
|
||||
else
|
||||
snprintf(path, sizeof (path), "%s%s", _PATH_DEV, arg);
|
||||
|
||||
(void) strlcpy(path, arg, sizeof (path));
|
||||
} else {
|
||||
/*
|
||||
* This may be a short path for a device, or it could be total
|
||||
* gibberish. Check to see if it's a known device in
|
||||
* /dev/dsk/. As part of this check, see if we've been given a
|
||||
* an entire disk (minus the slice number).
|
||||
*/
|
||||
if (strncmp(arg, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
|
||||
strlcpy(path, arg, sizeof (path));
|
||||
else
|
||||
snprintf(path, sizeof (path), "%s%s", _PATH_DEV, arg);
|
||||
wholedisk = is_whole_disk(path);
|
||||
if (!wholedisk && (stat64(path, &statbuf) != 0)) {
|
||||
/*
|
||||
* If we got ENOENT, then the user gave us
|
||||
* gibberish, so try to direct them with a
|
||||
* reasonable error message. Otherwise,
|
||||
* regurgitate strerror() since it's the best we
|
||||
* can do.
|
||||
*/
|
||||
if (errno == ENOENT) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': no such "
|
||||
"GEOM provider\n"), arg);
|
||||
(void) fprintf(stderr,
|
||||
gettext("must be a full path or "
|
||||
"shorthand device name\n"));
|
||||
return (NULL);
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
gettext("cannot open '%s': %s\n"),
|
||||
path, strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether this is a device or a file.
|
||||
*/
|
||||
if (wholedisk) {
|
||||
if (is_provider(path))
|
||||
type = VDEV_TYPE_DISK;
|
||||
} else if (S_ISREG(statbuf.st_mode)) {
|
||||
type = VDEV_TYPE_FILE;
|
||||
} else {
|
||||
else {
|
||||
(void) fprintf(stderr, gettext("cannot use '%s': must be a "
|
||||
"GEOM provider or regular file\n"), path);
|
||||
"GEOM provider\n"), path);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -311,7 +206,6 @@ make_leaf_vdev(const char *arg, uint64_t is_log)
|
||||
verify(nvlist_alloc(&vdev, NV_UNIQUE_NAME, 0) == 0);
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_PATH, path) == 0);
|
||||
verify(nvlist_add_string(vdev, ZPOOL_CONFIG_TYPE, type) == 0);
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0)
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
(uint64_t)B_FALSE) == 0);
|
||||
@@ -373,14 +267,12 @@ typedef struct replication_level {
|
||||
uint64_t zprl_parity;
|
||||
} replication_level_t;
|
||||
|
||||
#define ZPOOL_FUZZ (16 * 1024 * 1024)
|
||||
|
||||
/*
|
||||
* Given a list of toplevel vdevs, return the current replication level. If
|
||||
* the config is inconsistent, then NULL is returned. If 'fatal' is set, then
|
||||
* an error message will be displayed for each self-inconsistent vdev.
|
||||
*/
|
||||
static replication_level_t *
|
||||
replication_level_t *
|
||||
get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
{
|
||||
nvlist_t **top;
|
||||
@@ -399,20 +291,10 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
|
||||
lastrep.zprl_type = NULL;
|
||||
for (t = 0; t < toplevels; t++) {
|
||||
uint64_t is_log = B_FALSE;
|
||||
|
||||
nv = top[t];
|
||||
|
||||
/*
|
||||
* For separate logs we ignore the top level vdev replication
|
||||
* constraints.
|
||||
*/
|
||||
(void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_LOG, &is_log);
|
||||
if (is_log)
|
||||
continue;
|
||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
|
||||
|
||||
verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE,
|
||||
&type) == 0);
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0) {
|
||||
/*
|
||||
@@ -446,7 +328,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
}
|
||||
|
||||
/*
|
||||
* The 'dontreport' variable indicates that we've
|
||||
* The 'dontreport' variable indicatest that we've
|
||||
* already reported an error for this spec, so don't
|
||||
* bother doing it again.
|
||||
*/
|
||||
@@ -467,7 +349,7 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
ZPOOL_CONFIG_TYPE, &childtype) == 0);
|
||||
|
||||
/*
|
||||
* If this is a replacing or spare vdev, then
|
||||
* If this is a a replacing or spare vdev, then
|
||||
* get the real first child of the vdev.
|
||||
*/
|
||||
if (strcmp(childtype,
|
||||
@@ -527,30 +409,22 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
*/
|
||||
if ((fd = open(path, O_RDONLY)) >= 0) {
|
||||
err = fstat64(fd, &statbuf);
|
||||
if (err == 0 &&
|
||||
S_ISCHR(statbuf.st_mode)) {
|
||||
err = ioctl(fd, DIOCGMEDIASIZE,
|
||||
&statbuf.st_size);
|
||||
}
|
||||
(void) close(fd);
|
||||
} else {
|
||||
err = stat64(path, &statbuf);
|
||||
}
|
||||
|
||||
if (err != 0 || statbuf.st_size == 0)
|
||||
continue;
|
||||
|
||||
size = statbuf.st_size;
|
||||
|
||||
/*
|
||||
* Also make sure that devices and
|
||||
* slices have a consistent size. If
|
||||
* they differ by a significant amount
|
||||
* (~16MB) then report an error.
|
||||
* Also check the size of each device. If they
|
||||
* differ, then report an error.
|
||||
*/
|
||||
if (!dontreport &&
|
||||
(vdev_size != -1ULL &&
|
||||
(labs(size - vdev_size) >
|
||||
ZPOOL_FUZZ))) {
|
||||
if (!dontreport && vdev_size != -1ULL &&
|
||||
size != vdev_size) {
|
||||
if (ret != NULL)
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
@@ -632,11 +506,9 @@ get_replication(nvlist_t *nvroot, boolean_t fatal)
|
||||
* has a consistent replication level, then we ignore any errors. Otherwise,
|
||||
* report any difference between the two.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
check_replication(nvlist_t *config, nvlist_t *newroot)
|
||||
{
|
||||
nvlist_t **child;
|
||||
uint_t children;
|
||||
replication_level_t *current = NULL, *new;
|
||||
int ret;
|
||||
|
||||
@@ -652,23 +524,6 @@ check_replication(nvlist_t *config, nvlist_t *newroot)
|
||||
if ((current = get_replication(nvroot, B_FALSE)) == NULL)
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* for spares there may be no children, and therefore no
|
||||
* replication level to check
|
||||
*/
|
||||
if ((nvlist_lookup_nvlist_array(newroot, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0) || (children == 0)) {
|
||||
free(current);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* If all we have is logs then there's no replication level to check.
|
||||
*/
|
||||
if (num_logs(newroot) == children) {
|
||||
free(current);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the replication level of the new vdev spec, reporting any
|
||||
@@ -766,7 +621,7 @@ is_spare(nvlist_t *config, const char *path)
|
||||
* Go through and find any devices that are in use. We rely on libdiskmgt for
|
||||
* the majority of this task.
|
||||
*/
|
||||
static int
|
||||
int
|
||||
check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
int isspare)
|
||||
{
|
||||
@@ -798,9 +653,6 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
if (strcmp(type, VDEV_TYPE_DISK) == 0)
|
||||
ret = check_provider(path, force, isspare);
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_FILE) == 0)
|
||||
ret = check_file(path, force, isspare);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
@@ -816,17 +668,10 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing,
|
||||
isreplacing, B_TRUE)) != 0)
|
||||
return (ret);
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0)
|
||||
for (c = 0; c < children; c++)
|
||||
if ((ret = check_in_use(config, child[c], force,
|
||||
isreplacing, B_FALSE)) != 0)
|
||||
return (ret);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
const char *
|
||||
is_grouping(const char *type, int *mindev)
|
||||
{
|
||||
if (strcmp(type, "raidz") == 0 || strcmp(type, "raidz1") == 0) {
|
||||
@@ -853,18 +698,6 @@ is_grouping(const char *type, int *mindev)
|
||||
return (VDEV_TYPE_SPARE);
|
||||
}
|
||||
|
||||
if (strcmp(type, "log") == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
return (VDEV_TYPE_LOG);
|
||||
}
|
||||
|
||||
if (strcmp(type, "cache") == 0) {
|
||||
if (mindev != NULL)
|
||||
*mindev = 1;
|
||||
return (VDEV_TYPE_L2CACHE);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
@@ -877,21 +710,14 @@ is_grouping(const char *type, int *mindev)
|
||||
nvlist_t *
|
||||
construct_spec(int argc, char **argv)
|
||||
{
|
||||
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
|
||||
int t, toplevels, mindev, nspares, nlogs, nl2cache;
|
||||
nvlist_t *nvroot, *nv, **top, **spares;
|
||||
int t, toplevels, mindev, nspares;
|
||||
const char *type;
|
||||
uint64_t is_log;
|
||||
boolean_t seen_logs;
|
||||
|
||||
top = NULL;
|
||||
toplevels = 0;
|
||||
spares = NULL;
|
||||
l2cache = NULL;
|
||||
nspares = 0;
|
||||
nlogs = 0;
|
||||
nl2cache = 0;
|
||||
is_log = B_FALSE;
|
||||
seen_logs = B_FALSE;
|
||||
|
||||
while (argc > 0) {
|
||||
nv = NULL;
|
||||
@@ -904,56 +730,12 @@ construct_spec(int argc, char **argv)
|
||||
nvlist_t **child = NULL;
|
||||
int c, children = 0;
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_SPARE) == 0) {
|
||||
if (spares != NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'spare' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_LOG) == 0) {
|
||||
if (seen_logs) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'log' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
seen_logs = B_TRUE;
|
||||
is_log = B_TRUE;
|
||||
argc--;
|
||||
argv++;
|
||||
/*
|
||||
* A log is not a real grouping device.
|
||||
* We just set is_log and continue.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
|
||||
if (l2cache != NULL) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: 'cache' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
is_log = B_FALSE;
|
||||
}
|
||||
|
||||
if (is_log) {
|
||||
if (strcmp(type, VDEV_TYPE_MIRROR) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid vdev "
|
||||
"specification: unsupported 'log' "
|
||||
"device: %s\n"), type);
|
||||
return (NULL);
|
||||
}
|
||||
nlogs++;
|
||||
if (strcmp(type, VDEV_TYPE_SPARE) == 0 &&
|
||||
spares != NULL) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev "
|
||||
"specification: 'spare' can be "
|
||||
"specified only once\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
for (c = 1; c < argc; c++) {
|
||||
@@ -964,8 +746,7 @@ construct_spec(int argc, char **argv)
|
||||
children * sizeof (nvlist_t *));
|
||||
if (child == NULL)
|
||||
zpool_no_memory();
|
||||
if ((nv = make_leaf_vdev(argv[c], B_FALSE))
|
||||
== NULL)
|
||||
if ((nv = make_leaf_vdev(argv[c])) == NULL)
|
||||
return (NULL);
|
||||
child[children - 1] = nv;
|
||||
}
|
||||
@@ -984,17 +765,11 @@ construct_spec(int argc, char **argv)
|
||||
spares = child;
|
||||
nspares = children;
|
||||
continue;
|
||||
} else if (strcmp(type, VDEV_TYPE_L2CACHE) == 0) {
|
||||
l2cache = child;
|
||||
nl2cache = children;
|
||||
continue;
|
||||
} else {
|
||||
verify(nvlist_alloc(&nv, NV_UNIQUE_NAME,
|
||||
0) == 0);
|
||||
verify(nvlist_add_string(nv, ZPOOL_CONFIG_TYPE,
|
||||
type) == 0);
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_IS_LOG, is_log) == 0);
|
||||
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_NPARITY,
|
||||
@@ -1013,10 +788,8 @@ construct_spec(int argc, char **argv)
|
||||
* We have a device. Pass off to make_leaf_vdev() to
|
||||
* construct the appropriate nvlist describing the vdev.
|
||||
*/
|
||||
if ((nv = make_leaf_vdev(argv[0], is_log)) == NULL)
|
||||
if ((nv = make_leaf_vdev(argv[0])) == NULL)
|
||||
return (NULL);
|
||||
if (is_log)
|
||||
nlogs++;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
@@ -1028,19 +801,13 @@ construct_spec(int argc, char **argv)
|
||||
top[toplevels - 1] = nv;
|
||||
}
|
||||
|
||||
if (toplevels == 0 && nspares == 0 && nl2cache == 0) {
|
||||
if (toplevels == 0 && nspares == 0) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev "
|
||||
"specification: at least one toplevel vdev must be "
|
||||
"specified\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (seen_logs && nlogs == 0) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev specification: "
|
||||
"log requires at least 1 device\n"));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally, create nvroot and add all top-level vdevs to it.
|
||||
*/
|
||||
@@ -1052,26 +819,18 @@ construct_spec(int argc, char **argv)
|
||||
if (nspares != 0)
|
||||
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
|
||||
spares, nspares) == 0);
|
||||
if (nl2cache != 0)
|
||||
verify(nvlist_add_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|
||||
l2cache, nl2cache) == 0);
|
||||
|
||||
for (t = 0; t < toplevels; t++)
|
||||
nvlist_free(top[t]);
|
||||
for (t = 0; t < nspares; t++)
|
||||
nvlist_free(spares[t]);
|
||||
for (t = 0; t < nl2cache; t++)
|
||||
nvlist_free(l2cache[t]);
|
||||
if (spares)
|
||||
free(spares);
|
||||
if (l2cache)
|
||||
free(l2cache);
|
||||
free(top);
|
||||
|
||||
return (nvroot);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get and validate the contents of the given vdev specification. This ensures
|
||||
* that the nvlist returned is well-formed, that all the devices exist, and that
|
||||
@@ -1083,11 +842,11 @@ construct_spec(int argc, char **argv)
|
||||
* added, even if they appear in use.
|
||||
*/
|
||||
nvlist_t *
|
||||
make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
boolean_t isreplacing, boolean_t dryrun, int argc, char **argv)
|
||||
make_root_vdev(nvlist_t *poolconfig, int force, int check_rep,
|
||||
boolean_t isreplacing, int argc, char **argv)
|
||||
{
|
||||
nvlist_t *newroot;
|
||||
nvlist_t *poolconfig = NULL;
|
||||
|
||||
is_force = force;
|
||||
|
||||
/*
|
||||
@@ -1098,9 +857,6 @@ make_root_vdev(zpool_handle_t *zhp, int force, int check_rep,
|
||||
if ((newroot = construct_spec(argc, argv)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (zhp && ((poolconfig = zpool_get_config(zhp, NULL)) == NULL))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Validate each device to make sure that its not shared with another
|
||||
* subsystem. We do this even if 'force' is set, because there are some
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
#if defined(__STDC__)
|
||||
#if __STDC_VERSION__ - 0 >= 199901L
|
||||
extern void __assert(const char *, const char *, int);
|
||||
extern void __assert_c99(const char *, const char *, int, const char *);
|
||||
#else
|
||||
extern void __assert(const char *, const char *, int);
|
||||
#endif /* __STDC_VERSION__ - 0 >= 199901L */
|
||||
@@ -70,7 +70,8 @@ extern void _assert();
|
||||
|
||||
#if defined(__STDC__)
|
||||
#if __STDC_VERSION__ - 0 >= 199901L
|
||||
#define assert(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#define assert(EX) (void)((EX) || \
|
||||
(__assert_c99(#EX, __FILE__, __LINE__, __func__), 0))
|
||||
#else
|
||||
#define assert(EX) (void)((EX) || (__assert(#EX, __FILE__, __LINE__), 0))
|
||||
#endif /* __STDC_VERSION__ - 0 >= 199901L */
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* 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.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (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.
|
||||
@@ -19,10 +20,11 @@
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
/* Libintl is a library of advanced internationalization functions. */
|
||||
|
||||
#ifndef _LIBINTL_H
|
||||
#define _LIBINTL_H
|
||||
@@ -61,9 +63,6 @@ typedef long wchar_t;
|
||||
|
||||
#define TEXTDOMAINMAX 256
|
||||
|
||||
#define __GNU_GETTEXT_SUPPORTED_REVISION(m) \
|
||||
((((m) == 0) || ((m) == 1)) ? 1 : -1)
|
||||
|
||||
#ifdef __STDC__
|
||||
extern char *dcgettext(const char *, const char *, const int);
|
||||
extern char *dgettext(const char *, const char *);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
* CDDL HEADER START
|
||||
*
|
||||
* 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.
|
||||
* Common Development and Distribution License, Version 1.0 only
|
||||
* (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.
|
||||
@@ -18,9 +19,8 @@
|
||||
*
|
||||
* CDDL HEADER END
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
||||
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
@@ -81,12 +81,12 @@ typedef lwp_cond_t cond_t;
|
||||
* Because we have to deal with C++, we cannot redefine this one as that one.
|
||||
*/
|
||||
typedef struct _rwlock {
|
||||
int32_t readers; /* rwstate word */
|
||||
int32_t readers; /* -1 == writer else # of readers */
|
||||
uint16_t type;
|
||||
uint16_t magic;
|
||||
mutex_t mutex; /* used with process-shared rwlocks */
|
||||
cond_t readercv; /* used only to indicate ownership */
|
||||
cond_t writercv; /* used only to indicate ownership */
|
||||
mutex_t mutex; /* used to indicate ownership */
|
||||
cond_t readercv; /* unused */
|
||||
cond_t writercv; /* unused */
|
||||
} rwlock_t;
|
||||
|
||||
#ifdef __STDC__
|
||||
@@ -111,7 +111,6 @@ int cond_signal(cond_t *);
|
||||
int cond_broadcast(cond_t *);
|
||||
int mutex_init(mutex_t *, int, void *);
|
||||
int mutex_destroy(mutex_t *);
|
||||
int mutex_consistent(mutex_t *);
|
||||
int mutex_lock(mutex_t *);
|
||||
int mutex_trylock(mutex_t *);
|
||||
int mutex_unlock(mutex_t *);
|
||||
@@ -153,7 +152,6 @@ int cond_signal();
|
||||
int cond_broadcast();
|
||||
int mutex_init();
|
||||
int mutex_destroy();
|
||||
int mutex_consistent();
|
||||
int mutex_lock();
|
||||
int mutex_trylock();
|
||||
int mutex_unlock();
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#pragma ident "%Z%%M% %I% %E% SMI"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <pthread_np.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
@@ -53,7 +52,6 @@ typedef pthread_rwlock_t rwlock_t;
|
||||
#define mutex_lock(l) pthread_mutex_lock(l)
|
||||
#define mutex_trylock(l) pthread_mutex_trylock(l)
|
||||
#define mutex_unlock(l) pthread_mutex_unlock(l)
|
||||
#define mutex_owned(l) pthread_mutex_isowned_np(l)
|
||||
#define rwlock_init(l,f,a) pthread_rwlock_init(l,NULL)
|
||||
#define rwlock_destroy(l) pthread_rwlock_destroy(l)
|
||||
#define rw_rdlock(l) pthread_rwlock_rdlock(l)
|
||||
|
||||
@@ -137,7 +137,6 @@ typedef struct dt_module {
|
||||
dt_idhash_t *dm_extern; /* external symbol definitions */
|
||||
#if !defined(sun)
|
||||
caddr_t dm_reloc_offset; /* Symbol relocation offset. */
|
||||
uintptr_t *dm_sec_offsets;
|
||||
#endif
|
||||
} dt_module_t;
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#undef input
|
||||
#undef unput
|
||||
#else
|
||||
/*
|
||||
/*
|
||||
* Define YY_INPUT for flex since input() can't be re-defined.
|
||||
*/
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
@@ -60,19 +60,6 @@
|
||||
buf[n] = *yypcb->pcb_strptr++; \
|
||||
result = n; \
|
||||
}
|
||||
/*
|
||||
* Do not EOF let tokens to be put back. This does not work with flex.
|
||||
* On the other hand, leaving current buffer in same state it was when
|
||||
* last EOF was received guarantees that input() will keep returning EOF
|
||||
* for all subsequent invocations, which is the effect desired.
|
||||
*/
|
||||
#undef unput
|
||||
#define unput(c) \
|
||||
do { \
|
||||
int _c = c; \
|
||||
if (_c != EOF) \
|
||||
yyunput(_c, yytext_ptr); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
static int id_or_type(const char *);
|
||||
|
||||
@@ -83,14 +83,6 @@ dt_module_syminit32(dt_module_t *dmp)
|
||||
uint_t i, n = dmp->dm_nsymelems;
|
||||
uint_t asrsv = 0;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
GElf_Ehdr ehdr;
|
||||
int is_elf_obj;
|
||||
|
||||
gelf_getehdr(dmp->dm_elf, &ehdr);
|
||||
is_elf_obj = (ehdr.e_type == ET_REL);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < n; i++, sym++) {
|
||||
const char *name = base + sym->st_name;
|
||||
uchar_t type = ELF32_ST_TYPE(sym->st_info);
|
||||
@@ -105,12 +97,8 @@ dt_module_syminit32(dt_module_t *dmp)
|
||||
(ELF32_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
|
||||
asrsv++; /* reserve space in the address map */
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if !defined(sun)
|
||||
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
|
||||
if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
|
||||
sym->st_shndx < ehdr.e_shnum)
|
||||
sym->st_value +=
|
||||
dmp->dm_sec_offsets[sym->st_shndx];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -129,14 +117,6 @@ dt_module_syminit64(dt_module_t *dmp)
|
||||
uint_t i, n = dmp->dm_nsymelems;
|
||||
uint_t asrsv = 0;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
GElf_Ehdr ehdr;
|
||||
int is_elf_obj;
|
||||
|
||||
gelf_getehdr(dmp->dm_elf, &ehdr);
|
||||
is_elf_obj = (ehdr.e_type == ET_REL);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < n; i++, sym++) {
|
||||
const char *name = base + sym->st_name;
|
||||
uchar_t type = ELF64_ST_TYPE(sym->st_info);
|
||||
@@ -150,12 +130,9 @@ dt_module_syminit64(dt_module_t *dmp)
|
||||
if (sym->st_value != 0 &&
|
||||
(ELF64_ST_BIND(sym->st_info) != STB_LOCAL || sym->st_size)) {
|
||||
asrsv++; /* reserve space in the address map */
|
||||
#if defined(__FreeBSD__)
|
||||
|
||||
#if !defined(sun)
|
||||
sym->st_value += (Elf_Addr) dmp->dm_reloc_offset;
|
||||
if (is_elf_obj && sym->st_shndx != SHN_UNDEF &&
|
||||
sym->st_shndx < ehdr.e_shnum)
|
||||
sym->st_value +=
|
||||
dmp->dm_sec_offsets[sym->st_shndx];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -745,12 +722,7 @@ dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
|
||||
free(dmp->dm_asmap);
|
||||
dmp->dm_asmap = NULL;
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
if (dmp->dm_sec_offsets != NULL) {
|
||||
free(dmp->dm_sec_offsets);
|
||||
dmp->dm_sec_offsets = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
dmp->dm_symfree = 0;
|
||||
dmp->dm_nsymbuckets = 0;
|
||||
dmp->dm_nsymelems = 0;
|
||||
@@ -874,12 +846,9 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
||||
(void) snprintf(fname, sizeof (fname),
|
||||
"%s/%s/object", OBJFS_ROOT, name);
|
||||
#else
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Phdr ph;
|
||||
char name[MAXPATHLEN];
|
||||
uintptr_t mapbase, alignmask;
|
||||
int i = 0;
|
||||
int is_elf_obj;
|
||||
|
||||
(void) strlcpy(name, k_stat->name, sizeof(name));
|
||||
(void) strlcpy(fname, k_stat->pathname, sizeof(fname));
|
||||
@@ -924,20 +893,7 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
||||
dt_module_destroy(dtp, dmp);
|
||||
return;
|
||||
}
|
||||
#if defined(__FreeBSD__)
|
||||
mapbase = (uintptr_t)k_stat->address;
|
||||
gelf_getehdr(dmp->dm_elf, &ehdr);
|
||||
is_elf_obj = (ehdr.e_type == ET_REL);
|
||||
if (is_elf_obj) {
|
||||
dmp->dm_sec_offsets =
|
||||
malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets));
|
||||
if (dmp->dm_sec_offsets == NULL) {
|
||||
dt_dprintf("failed to allocate memory\n");
|
||||
dt_module_destroy(dtp, dmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Iterate over the section headers locating various sections of
|
||||
* interest and use their attributes to flesh out the dt_module_t.
|
||||
@@ -946,19 +902,7 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
||||
if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL ||
|
||||
(s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL)
|
||||
continue; /* skip any malformed sections */
|
||||
#if defined(__FreeBSD__)
|
||||
if (sh.sh_size == 0)
|
||||
continue;
|
||||
if (is_elf_obj && (sh.sh_type == SHT_PROGBITS ||
|
||||
sh.sh_type == SHT_NOBITS)) {
|
||||
alignmask = sh.sh_addralign - 1;
|
||||
mapbase += alignmask;
|
||||
mapbase &= ~alignmask;
|
||||
sh.sh_addr = mapbase;
|
||||
dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr;
|
||||
mapbase += sh.sh_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(s, ".text") == 0) {
|
||||
dmp->dm_text_size = sh.sh_size;
|
||||
dmp->dm_text_va = sh.sh_addr;
|
||||
@@ -983,13 +927,6 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
||||
#if defined(sun)
|
||||
dmp->dm_modid = (int)OBJFS_MODID(st.st_ino);
|
||||
#else
|
||||
/*
|
||||
* Include .rodata and special sections into .text.
|
||||
* This depends on default section layout produced by GNU ld
|
||||
* for ELF objects and libraries:
|
||||
* [Text][R/O data][R/W data][Dynamic][BSS][Non loadable]
|
||||
*/
|
||||
dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va;
|
||||
#if defined(__i386__)
|
||||
/*
|
||||
* Find the first load section and figure out the relocation
|
||||
|
||||
Loaded 100 of 7780 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user