OK, I finally got correct versions of Konev's ported patches together with the annotations.
-- Don't say I didn't warn you.
$Id: 003b_xfs_fixes.diff 2151 2005-01-24 16:54:48Z branden $ This patch by Branden Robinson, Matthieu Herrb, and Nikita V. Youshchenko. os/utils.c: - Handle pid files the way most other Unix daemons do. Use Matthieu Herrb's version of StorePid(), which refuses to open pre-existing pid files, and is more careful with the type of Pid_t. - Allow the user to specify the pid filename on the command line with a "-pid" option (courtesy of Nikita V. Youshchenko). - Add RemovePid() function which removes the process ID file, and register it with atexit() so that it is automatically invoked when xfs exits. - Sort options in usage message alphabetically. - Refer to "user ID" and "process ID" in diagnostic messages, not "userid" and "process-id". - Remove duplicate unconditional #include of stdlib.h. - Wrap long lines. - Whitespace police. xfs.man: - Document the new "-pid" option (courtesy of Nikita V. Youshchenko). - Add "FUTURE DIRECTIONS" section. - Perform massive cleanup and reformatting. Not submitted upstream yet. Index: xc/programs/xfs/os/utils.c =================================================================== --- xc/programs/xfs/os/utils.c (revision 309) +++ xc/programs/xfs/os/utils.c (working copy) @@ -3,7 +3,7 @@ * misc os utilities */ /* - + Copyright 1990, 1991, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its @@ -27,7 +27,7 @@ in this Software without prior written authorization from The Open Group. * Copyright 1990, 1991 Network Computing Devices; - * Portions Copyright 1987 by Digital Equipment Corporation + * Portions Copyright 1987 by Digital Equipment Corporation * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -90,8 +90,6 @@ #define SIGNALS_RESET_WHEN_CAUGHT #endif -#include <stdlib.h> - extern char *configfilename; static Bool dropPriv = FALSE; /* whether or not to drop root privileges */ #ifdef DEFAULT_DAEMON @@ -116,7 +114,8 @@ static char *pidFile = XFSPIDDIR "/xfs.pid"; static int pidFd; static FILE *pidFilePtr; -static int StorePid (void); +static long StorePid (void); +static void RemovePid (void); /* ARGSUSED */ SIGVAL @@ -219,7 +218,9 @@ static void usage(void) { - fprintf(stderr, "usage: %s [-config config_file] [-port tcp_port] [-droppriv] [-daemon] [-nodaemon] [-user user_name] [-ls listen_socket]\n", + fprintf(stderr, "usage: %s [-config config_file] [-daemon] [-droppriv]" + " [-ls listen_socket] [-nodaemon] [-pid pid_file]" + " [-port tcp_port] [-user user_name]\n", progname); exit(1); } @@ -242,7 +243,7 @@ * * [] denotes optional and ... denotes repitition. * - * The string must be _exactly_ in the above format. + * The string must be _exactly_ in the above format. */ void @@ -260,7 +261,7 @@ count++; ptr++; } - + OldListenCount = count + 1; OldListen = (OldListenRec *) malloc ( OldListenCount * sizeof (OldListenRec)); @@ -349,6 +350,11 @@ configfilename = argv[++i]; else usage(); + } else if (!strcmp(argv[i], "-pid")) { + if (argv[i + 1]) + pidFile = argv[++i]; + else + usage(); } #ifdef MEMBUG else if ( strcmp( argv[i], "-alloc") == 0) @@ -392,7 +398,7 @@ FSalloc (unsigned long amount) { register pointer ptr; - + if ((long)amount < 0) return 0; if (amount == 0) @@ -462,21 +468,21 @@ FatalError("out of memory\n"); return 0; } - + /***************** * FSfree - * calls free - *****************/ + * calls free + *****************/ void FSfree(pointer ptr) { #ifdef MEMBUG if (ptr) - ffree((char *)ptr); + ffree((char *)ptr); #else if (ptr) - free((char *)ptr); + free((char *)ptr); #endif } @@ -511,11 +517,12 @@ } #endif /* QNX4 */ if (setuid(pwent->pw_uid)) { - FatalError("fatal: couldn't set userid to %s user\n", user); + FatalError("fatal: couldn't set user ID to %s user\n", user); } } } else if (dropPriv || userId) { - FatalError("fatal: -droppriv or -user flag specified, but xfs not run as root\n"); + FatalError("fatal: -droppriv or -user flag specified, but xfs not" + " invoked by root user\n"); } } @@ -523,48 +530,76 @@ void SetDaemonState(void) { - int oldpid; + long oldpid; if (becomeDaemon) { BecomeDaemon(); if ((oldpid = StorePid ())) { if (oldpid == -1) - ErrorF ("error opening process-id file %s\n", pidFile); + ErrorF ("error opening process ID file %s\n", pidFile); else ErrorF ("process-id file %s indicates another xfs is " - "running (pid %d); exiting\n", pidFile, oldpid); + "running (pid %ld); exiting\n", pidFile, oldpid); exit(1); } + if (atexit (RemovePid)) + ErrorF ("could not register RemovePid() with atexit()\n"); } } -static int +static long +/* + * Create and populate file storing process ID. + */ StorePid (void) { - int oldpid; + long oldpid; + char pidstr[11]; /* enough space for a 32-bit pid plus \0 */ + size_t pidstrlen; - if (pidFile[0] != '\0') { - pidFd = open (pidFile, O_RDWR); - if (pidFd == -1 && errno == ENOENT) - pidFd = open (pidFile, O_RDWR|O_CREAT, 0666); - if (pidFd == -1 || !(pidFilePtr = fdopen (pidFd, "r+"))) + if (pidFile[0] != '\0') + { + pidFd = open (pidFile, O_WRONLY|O_CREAT|O_EXCL, 0666); + if (pidFd == -1) { - ErrorF ("cannot open process-id file %s: %s\n", pidFile, - strerror (errno)); - return -1; + if (errno == EEXIST) + { + /* pidFile already exists; see if we can open it */ + pidFilePtr = fopen (pidFile, "r"); + if (pidFilePtr == NULL) + { + ErrorF ("cannot open process ID file %s for reading: " + "%s\n", pidFile, strerror (errno)); + return -1; + } + if (fscanf (pidFilePtr, "%ld\n", &oldpid) != 1) + { + ErrorF ("existing process ID file %s empty or contains " + "garbage\n", pidFile); + oldpid = -1; + } + fclose (pidFilePtr); + return oldpid; + } + else + { + ErrorF ("cannot fdopen process ID file %s for writing: " + "%s\n", pidFile, strerror (errno)); + return -1; + } } - if (fscanf (pidFilePtr, "%d\n", &oldpid) != 1) - oldpid = -1; - if (fseek (pidFilePtr, 0L, SEEK_SET) == -1) + if ((pidFilePtr = fdopen (pidFd, "w")) == NULL) { - ErrorF ("cannot seek process-id file %s: %s\n", pidFile, - strerror (errno)); - return -1; + ErrorF ("cannot open process ID file %s for writing: %s\n", + pidFile, strerror (errno)); + return -1; } - if (fprintf (pidFilePtr, "%5ld\n", (long) getpid ()) != 6) + (void) snprintf (pidstr, 11, "%ld", (long) getpid()); + pidstrlen = strlen (pidstr); + if (fprintf (pidFilePtr, "%s\n", pidstr) != ( pidstrlen + 1)) { - ErrorF ("cannot write to process-id file %s: %s\n", pidFile, + ErrorF ("cannot write to process ID file %s: %s\n", pidFile, strerror (errno)); return -1; } @@ -573,3 +608,19 @@ } return 0; } + + +/* + * Remove process ID file. This function should be registered with atexit(). + */ +static void +RemovePid (void) +{ +#ifdef DEBUG + fprintf (stderr, "unlinking process ID file %s\n", pidFile); +#endif + if (unlink (pidFile)) + if (errno != ENOENT) + ErrorF ("cannot remove process ID file %s: %s\n", pidFile, + strerror (errno)); +} Index: xc/programs/xfs/xfs.man =================================================================== --- xc/programs/xfs/xfs.man (revision 309) +++ xc/programs/xfs/xfs.man (working copy) @@ -37,206 +37,320 @@ .\" suitability of this software for any purpose. It is provided "as is" .\" without express or implied warranty. .\" $Xorg: xfs.man,v 1.4 2001/02/09 02:05:42 xorgcvs Exp $ -.TH XFS 1 __xorgversion__ +.TH xfs __mansuffix__ __xorgversion__ .SH NAME xfs \- X font server .SH SYNOPSIS -.B "xfs" -[\-config \fIconfiguration_file\fP] -[\-daemon] -[\-droppriv] -[\-ls \fIlisten_socket\fP] -[\-nodaemon] -[\-port \fItcp_port\fP] -[\-user \fIusername\fP] +.B xfs +[ +.BI "\-config " configuration_file +] +[ +.B \-daemon +] +[ +.B \-droppriv +] +[ +.BI "\-ls " listen_socket +] +[ +.B \-nodaemon +] +[ +.BI "\-pid " pid_file +] +[ +.BI "\-port " tcp_port +] +[ +.BI "\-user " username +] .SH DESCRIPTION +.B xfs +is the X Window System font server. +It supplies fonts to X Window System display servers. +The server is usually run by a system administrator, and started via +.BR init (__osadmmansuffix__). +Users may also wish to start private font servers for specific sets of +fonts. .PP -.I Xfs -is the X Window System font server. It supplies fonts to X Window -System display servers. -.SH "STARTING THE SERVER" -The server is usually run by a system administrator, and started via -boot files like \fI/etc/rc.local\fR. Users may also wish to start -private font servers for specific sets of fonts. -.SH "OPTIONS" -.TP 8 -.B \-config configuration_file -Specifies the configuration file the font server will use. If this -parameter is not specified, the default file, \fI/usr/X11R6/lib/X11/fs/config\fR +To connect to a font server, see the documentation for your X server; it +likely supports the syntax documented in the \(lqFONT SERVER NAMES\(rq +section of +.BR X (__miscmansuffix__). +.SH OPTIONS +.TP +.BI "\-config " configuration_file +specifies the configuration file +.B xfs +will use. +If this parameter is not specified, the default file, +.IR __projectroot__/lib/X11/fs/config , will be used. -.TP 8 -.B \-ls listen_socket -Specifies a file descriptor which is already set up to be used as the -listen socket. This option is only intended to be used by the font server -itself when automatically spawning another copy of itself to handle -additional connections. -.TP 8 -.B \-port tcp_port -Specifies the TCP port number on which the server will listen for connections. -The default port number is 7100. -.TP 8 +.TP .B \-daemon -Instructs xfs to fork and go into the background automatically at -startup If this option is not specified, xfs will run as a regular -process (unless xfs was built to daemonize by default). -.TP 8 +instructs +.B xfs +to fork and go into the background automatically at startup. +If this option is not specified, +.B xfs +will run as a regular process (unless it was built to daemonize by +default). +When running as a daemon, +.B xfs +will attempt to create a file in which it stores its process ID, and will +delete that file upon exit; see +.BR \-pid . +.TP .B \-droppriv -If specified, xfs will attempt to run as user and group \fIxfs\fR (unless -the +instructs +.B xfs +to attempt to run as user and group +.I xfs +(unless the .B \-user -option is used). This -has been implemented for security reasons, as xfs may have undiscovered -buffer overflows or other paths for possible exploit, both local and -remote. With this option, you may also wish to specify -"no-listen = tcp" -in the config file, which ensures that xfs will not to use a TCP port at all. -.TP 8 +option is used). +This has been implemented for security reasons, as +.B xfs +may have undiscovered buffer overflows or other paths for possible exploit, +both local and remote. +When using this option, you may also wish to specify \(oqno\-listen = +tcp\(cq in the config file, which ensures that +.B xfs +will not to use a TCP port at all. +By default, +.B xfs +runs with the user and group IDs of the user who invoked it. +.TP +.BI "\-ls " listen_socket +specifies a file descriptor which is already set up to be used as the +listen socket. +This option is only intended to be used by the font server itself when +automatically spawning another copy of itself to handle additional +connections. +.TP .B \-nodaemon -When xfs is built to daemonize (run in the background) by default, -this prevents that and starts xfs up as a regular process. -.TP 8 -.B \-user username -This is equivalent to +instructs +.B xfs +not to daemonize (fork and detach from its controlling terminal). +This option only has an effect if +.B xfs +is built to daemonize by default, which is not the stock configuration. +.TP +.BI "\-pid " pid_file +instructs +.B xfs +to save its process ID into +.IR pid_file , +instead of the default, +.IR /var/run/xfs.pid . +If +.B xfs +is not running as a daemon, this option has no effect. +.TP +.BI "\-port " tcp_port +specifies the TCP port number on which the server will listen for +connections. +The default port number is 7100. +This option is ignored if +.B xfs +is configured to not listen to TCP transports at all (see \(lqConfiguration +File Format\(rq below). +.TP +.BI "\-user " username +instructs +.B xfs +to run as the user +.IR username. +See .B \-droppriv -except that xfs will run as user \fIusername\fR. -.SH "SIGNALS" -.TP 8 -.I SIGTERM -This causes the font server to exit cleanly. -.TP 8 -.I SIGUSR1 -This signal is used to cause the server to re-read its configuration file. -.TP 8 -.I SIGUSR2 -This signal is used to cause the server to flush any cached data it -may have. -.TP 8 -.I SIGHUP -This signal is used to cause the server to reset, closing all active -connections and re-reading the configuration file. -.SH "CONFIGURATION" +for why this may be desired. +By default, +.B xfs +runs with the user and group IDs of the user who invoked it. +.SH "INPUT FILES" +.B xfs +reads and serves any font file format recognized by the X server itself. +It locates font files through the specification of a +.IR catalogue , +which is delcared in +.BR xfs 's +configuration file. +.SS "Configuration File Format" +.B xfs +reads its configuration from +.I __projectroot__/lib/X11/fs/config +by default (see the +.B \-config +option in the \(lqOPTIONS\(rq section above). The configuration language is a list of keyword and value pairs. -Each keyword is followed by an '=' and then the desired value. +Each keyword is followed by an equals sign (\(oq=\(cq) and then the desired +value. .PP Recognized keywords include: -.sp -.\" .IP "cache-size (cardinal)" -.\" Size in bytes of the font server cache. -.IP "catalogue (list of string)" -Ordered list of font path element names. -Use of the keyword "catalogue" is very misleading at present, -the current implementation only supports a single catalogue ("all"), +.TP +.BR alternate\-servers " (list of \fIstring\fPs)" +lists alternate servers for this font server. +See the \(lqFONT SERVER NAMES\(rq section of +.BR X (__miscmansuffix__) +for the syntax of the string. +.\" .TP +.\" .BR cache\-size " (\fIcardinal\fP)" +.\" determines the size (in bytes) of the font server cache. +.TP +.BR catalogue " (list of \fIstring\fPs)" +declares as ordered list of font path element names from which fonts will +be served. +Use of the keyword \(oqcatalogue\(cq is very misleading at present: the +current implementation only supports a single catalogue (\(oqall\(cq), containing all of the specified fonts. -.IP "alternate-servers (list of string)" -List of alternate servers for this font server. -.IP "client-limit (cardinal)" -Number of clients this font server will support -before refusing service. This is useful for tuning -the load on each individual font server. -.IP "clone-self (boolean)" -Whether this font server should attempt to clone itself -when it reachs the client-limit. -.IP "default-point-size (cardinal)" -The default pointsize (in decipoints) for fonts that -don't specify. The default is 120. -.IP "default-resolutions (list of resolutions)" -Resolutions the server supports by default. -This information may be used as a hint for -pre-rendering, and substituted for scaled fonts -which do not specify a resolution. -A resolution is a comma-separated pair of x and y resolutions in -pixels per inch. +.TP +.BR client\-limit " (\fIcardinal\fP)" +determines the number of clients this font server will support before +refusing service. +This is useful for tuning the load on each individual font server. +.TP +.BR clone\-self " (\fIboolean\fP)" +indicates whether this font server should attempt to clone itself when the +number of connected clients reaches the +.BR client\-limit . +.TP +.BR default\-point\-size " (\fIcardinal\fP)" +The default pointsize (in decipoints) for font requests that don't specify +a point size. +The default is 120. +.TP +.BR default\-resolutions " (list of \fIresolution\fPs)" +indicates the resolutions the server supports by default. +This information may be used as a hint for pre-rendering, and substituted +into requests for scaled fonts which do not specify a resolution. +A +.I resolution +is a comma-separated pair of horizontal and vertical resolutions in pixels +per inch. Multiple resolutions are separated by commas. -.IP "error-file (string)" -Filename of the error file. All warnings and errors -will be logged here. -.IP "no-listen (trans-type)" -Disable a transport type. For example, TCP/IP connections can -be disabled with no-listen tcp -.IP "port (cardinal)" -TCP port on which the server will listen for connections. -.IP "use-syslog (boolean)" -Whether syslog(3) (on supported systems) is to be used -for errors. -.IP "deferglyphs (string)" -Set the mode for delayed fetching and caching of glyphs. Value is -"none", meaning deferred glyphs is disabled, "all", meaning it is -enabled for all fonts, and "16", meaning it is enabled only for -16-bits fonts. -.\" .IP "trusted-clients (list of string)" -.\" Those clients the fontserver will talk to. Others -.\" will be refused for the initial connection. An empty -.\" list means the server will talk to any client. -.SH "EXAMPLE" +.TP +.BR deferglyphs " (\fIstring\fP)" +sets the mode for delayed fetching and caching of glyphs. +.I string +should be one of \(oqnone\(cq, meaning glyphs deferment is disabled, +\(oqall\(cq, meaning it is enabled for all fonts, and \(oq16\(cq, meaning +it is enabled only for 16-bit fonts. +.TP +.BR error\-file " (\fIstring\fP)" +indicates the filename of the error file. +All warnings and errors will be logged here, unless +.B use\-syslog +is set to a true value (see below). +.TP +.BR no\-listen " (\fItrans-type\fP)" +disables the specified transport type. +For example, TCP/IP connections can be disabled with \(oqno\-listen = +tcp\(cq. +.TP +.BR port " (\fIcardinal\fP)" +indicates the TCP port on which the server will listen for connections. +.\" .TP +.\" .BR trusted-clients " (list of \fIstring\fPs)" +.\" idefntifies the clients the font server will talk to. +.\" Others will be refused for the initial connection. +.\" An empty list means the server will talk to any client. +.TP +.BR use\-syslog " (\fIboolean\fP)" +determines whether errors and diagnostics should be reported via +.BR syslog (__oslibmansuffix__) +(on supported systems) instead of being written to the +.B error\-file +(see above). +.SS "Example Configuration File" .nf XCOMM XCOMM sample font server configuration file XCOMM -XCOMM allow a max of 10 clients to connect to this font server -client-limit = 10 +XCOMM allow a max of 10 clients to connect to this font server. +client\-limit = 10 -XCOMM when a font server reaches its limit, start up a new one -clone-self = on +XCOMM When a font server reaches the above limit, start up a new one. +clone\-self = on -XCOMM alternate font servers for clients to use -alternate-servers = hansen:7101,hansen:7102 +XCOMM Identify alternate font servers for clients to use. +alternate\-servers = hansen:7101,hansen:7102 -XCOMM where to look for fonts -XCOMM the first is a set of Speedo outlines, the second is a set of -XCOMM misc bitmaps and the last is a set of 100dpi bitmaps +XCOMM Look for fonts in the following directories. The first is a set of +XCOMM Speedo outlines, the second is a set of misc bitmaps (such as terminal +XCOMM and cursor fonts), and the last is a set of 100dpi bitmaps. XCOMM catalogue = /usr/X11R6/lib/X11/fonts/speedo, - /usr/X11R6/lib/X11/fonts/misc, - /usr/X11R6/lib/X11/fonts/100dpi/ + /usr/X11R6/lib/X11/fonts/misc, + /usr/X11R6/lib/X11/fonts/100dpi/ XCOMM in 12 points, decipoints -default-point-size = 120 +default\-point\-size = 120 XCOMM 100 x 100 and 75 x 75 -default-resolutions = 100,100,75,75 -use-syslog = off +default\-resolutions = 100,100,75,75 + +XCOMM Specify our log filename. +error\-file = /var/log/xfs.log + +XCOMM Direct diagnostics to our own log file instead of using syslog. +use\-syslog = off .fi -.sp -.SH "FONT SERVER NAMES" -One of the following forms can be used to name a font server that -accepts TCP connections: -.sp -.nf - tcp/\fIhostname\fP:\fIport\fP - tcp/\fIhostname\fP:\fIport\fP/\fIcataloguelist\fP -.fi -.PP -The \fIhostname\fP specifies the name (or decimal numeric address) -of the machine on which the font server is running. The \fIport\fP -is the decimal TCP port on which the font server is listening for connections. -The \fIcataloguelist\fP specifies a list of catalogue names, -with '+' as a separator. -.PP -Examples: \fItcp/fs.x.org:7100\fP, \fItcp/18.30.0.212:7101/all\fP. -.PP -One of the following forms can be used to name a font server that -accepts DECnet connections: -.sp -.nf - decnet/\fInodename\fP::font$\fIobjname\fP - decnet/\fInodename\fP::font$\fIobjname\fP/\fIcataloguelist\fP -.fi -.PP -The \fInodename\fP specifies the name (or decimal numeric address) -of the machine on which the font server is running. -The \fIobjname\fP is a normal, case-insensitive DECnet object name. -The \fIcataloguelist\fP specifies a list of catalogue names, -with '+' as a separator. -.PP -Examples: \fIDECnet/SRVNOD::FONT$DEFAULT\fP, \fIdecnet/44.70::font$special/symbols\fP. -.SH "SEE ALSO" -X(__miscmansuffix__), \fIThe X Font Service Protocol\fP, -.br -\fIFont server implementation overview\fP +.SH "OUTPUT FILES" +When operating in daemon mode, +.B xfs +sends diagnostic messages (errors and warnings) to the system log via the +.B syslog +C library function by default. +However, these messages can be sent to an alternate location via the +.B error\-file +and +.B use\-syslog +configuration variables; see \(lqConfiguration File Format\(rq, above. +.SH "ASYNCHRONOUS EVENTS" +.B xfs +handles the following signals specially: +.TP +.I SIGTERM +causes the font server to exit cleanly. +.TP +.I SIGUSR1 +causes +.B xfs +to re-read its configuration file. +.TP +.I SIGUSR2 +causes +.B xfs +to flush any cached data it may have. +.TP +.I SIGHUP +causes +.B xfs +to reset, closing all active connections and re-reading the configuration +file. .SH BUGS Multiple catalogues should be supported. +.SH "FUTURE DIRECTIONS" +Significant further development of +.B xfs +is unlikely. +One of the original motivations behind it was the single-threaded nature of +the X server \(em a user's X session could seem to \(oqfreeze up\(cq while +the X server took a moment to rasterize a font. +This problem with the X server, which remains single-threaded in all +popular implementations to this day, has been mitigated on two fronts: +machines have gotten much faster, and client-side font rendering +(particularly via the Xft library) is the norm in contemporary software. .SH AUTHORS Dave Lemke, Network Computing Devices, Inc .br Keith Packard, Massachusetts Institute of Technology +.SH "SEE ALSO" +.BR X (__miscmansuffix__), +.BR init (__osadmmansuffix__), +.BR syslog (__oslibmansuffix__), +.IR "The X Font Service Protocol" , +.I Font Server Implementation Overview
$Id: 099u_mkdirhier_rewrite.diff 2171 2005-02-08 07:13:50Z branden $ Reimplement mkdirhier; see Debian #141347 and #232357 for some reasons why. This shell script and manpage by Branden Robinson. Not submitted upstream to XFree86 or X.Org. Index: xc/config/util/mkdirhier.sh =================================================================== --- xc/config/util/mkdirhier.sh (revision 309) +++ xc/config/util/mkdirhier.sh (working copy) @@ -1,67 +1,94 @@ #!/bin/sh -# $Xorg: mkdirhier.sh,v 1.3 2000/08/17 19:41:53 cpqbld Exp $ -# Courtesy of Paul Eggert -newline=' -' -IFS=$newline +# Copyright 2005 Branden Robinson. -case ${1--} in --*) echo >&2 "mkdirhier: usage: mkdirhier directory ..."; exit 1 -esac +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following condition: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# SOFTWARE IN THE PUBLIC INTEREST, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. -status= +# I rewrote Paul Eggert's script in POSIX shell because it was a little +# odd, and did not confine itself to puritantical pre-POSIX conventions. +# For example, in one place it used: +# case ${1--} in +# -*) +# to test for $1 being null, presumably due to fears that test -n and -z +# will not be available. Yet later in the script, test -n was used. +# +# This seemed quite silly. I decided to rewrite it since I am arrgoant +# enough to think I know what I'm doing in POSIX shell. +# +# If someone needs a pre-POSIX version of mkdirhier, they'll probably need to +# turn to someone else, as I have no idea where such a thing is specified. -for directory -do - case $directory in - '') - echo >&2 "mkdirhier: empty directory name" - status=1 - continue;; - *"$newline"*) - echo >&2 "mkdirhier: directory name contains a newline: \`\`$directory''" - status=1 - continue;; - ///*) prefix=/;; # See Posix 2.3 "path". - //*) prefix=//;; - /*) prefix=/;; - -*) prefix=./;; - *) prefix= - esac +set -e - IFS=/ - set x $directory - case $2 in - */*) # IFS parsing is broken - IFS=' ' - set x `echo $directory | tr / ' '` - ;; - esac - IFS=$newline - shift +PROGNAME=${0##*/} +STATUS=0 - for filename - do - path=$prefix$filename - prefix=$path/ - shift +usage() { + cat <<EOF +usage: $PROGNAME DIRECTORY ... +Create each directory DIRECTORY, also creating intermediate directories in the +specified hierarchy as necessary. - test -d "$path" || { - paths=$path - for filename - do - if [ -n "$filename" -a "$filename" != "." ]; then - path=$path/$filename - paths=$paths$newline$path - fi - done +Note: Use "mkdir -p" instead of "$PROGNAME" if the system supports it. +EOF +} - mkdir $paths || status=$? +makedir () { + FUNC_STATUS=0 + # Does the desired directory already exist? + if ! [ -d "$1" ]; then + # Is a directory hierarchy specified (i.e., are any slashes in the + # argument)? + PARENT=${1%/*} + if [ -n "$PARENT" ] && [ "$PARENT" != "$1" ]; then + # Yes; does the desired directory's immediate parent exist? + if ! [ -d "$PARENT" ]; then + # No; push it onto the stack. If that fails, return + # immediately, as we know later calls will also fail. E.g., if + # we are asked to create /usr/bin/foo/bar/baz/quux and + # /usr/bin/foo fails, we don't have to even try anything deeper + # in the hierarchy. + if ! makedir "$PARENT"; then + return $FUNC_STATUS + fi + fi + fi + mkdir "$1" || FUNC_STATUS=$? + fi + return $FUNC_STATUS +} - break - } - done - done +if [ -z "$1" ]; then + usage >&2 + exit 64 +fi -exit $status +while [ -n "$1" ]; do + ARG="$1" + makedir "$ARG" || \ + { + STATUS=$? + echo "$PROGNAME: could not create directory \"$ARG\"" >&2 + } + shift +done + +exit $STATUS + +# vim:set ai et sts=4 sw=4 tw=80: Index: xc/config/util/mkdirhier.man =================================================================== --- xc/config/util/mkdirhier.man (revision 309) +++ xc/config/util/mkdirhier.man (working copy) @@ -1,42 +1,111 @@ -.\" $Xorg: mkdirhier.man,v 1.4 2001/02/09 02:03:17 xorgcvs Exp $ -.\" Copyright (c) 1993, 1994, 1998 The Open Group -.\" -.\" Permission to use, copy, modify, distribute, and sell this software and its -.\" documentation for any purpose is hereby granted without fee, provided that -.\" the above copyright notice appear in all copies and that both that -.\" copyright notice and this permission notice appear in supporting -.\" documentation. -.\" -.\" The above copyright notice and this permission notice shall be included in -.\" all copies or substantial portions of the Software. -.\" +.\" Copyright 2005 Branden Robinson. +.\" +.\" Permission is hereby granted, free of charge, to any person obtaining a +.\" copy of this software and associated documentation files (the "Software"), +.\" to deal in the Software without restriction, including without limitation +.\" the rights to use, copy, modify, merge, publish, distribute, sublicense, +.\" and/or sell copies of the Software, and to permit persons to whom the +.\" Software is furnished to do so, subject to the following condition: +.\" +.\" The above copyright notice and this permission notice shall be +.\" included in all copies or substantial portions of the Software. +.\" .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR .\" IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -.\" THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -.\" WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -.\" OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -.\" SOFTWARE. -.\" -.\" Except as contained in this notice, the name of The Open Group shall not -.\" be used in advertising or otherwise to promote the sale, use or other -.\" dealing in this Software without prior written authorization from The -.\" Open Group. -.\" -.\" $XFree86: xc/config/util/mkdirhier.man,v 1.2 2001/01/27 18:19:55 dawes Exp $ -.\" -.TH MKDIRHIER 1 __xorgversion__ +.\" FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +.\" SOFTWARE IN THE PUBLIC INTEREST, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR +.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +.\" DEALINGS IN THE SOFTWARE. +.TH mkdirhier __mansuffix__ __xorgversion__ .SH NAME -mkdirhier \- makes a directory hierarchy +mkdirhier \- create a directory hierarchy .SH SYNOPSIS .B mkdirhier -directory ... +.I directory +\&... .SH DESCRIPTION -The -.I mkdirhier -command creates the specified directories. Unlike -.I mkdir -if any of the parent directories of the specified directory -do not exist, it creates them as well. +.B mkdirhier +creates the specified directories. +Unlike some versions of +.BR mkdir , +if any of the parent directories of the specified directory do not exist, +.B mkdirhier +creates them as well. +.PP +.B mkdirhier +is a wrapper for +.BR mkdir ; +systems with +.BR mkdir (__osmansuffix__) +implementations conformant with the Single Unix Specification may simply +use +.B mkdir \-p +instead \(em this includes all systems using the GNU Core Utilities' +version of +.BR mkdir . +.SH DIAGNOSTICS +If +.B mkdirhier +is not supplied with any arguments, a usage message is printed. +.PP +.B mkdirhier +prefixes its diagnostic messages with the name under which it was invoked, +followed by a colon (\(oq:\(cq) so that its messages can be distingushed +from others. +.TP +.B could not create directory \(dq\fIdirectory\fP\(dq +indicates that there was a failure while creating +.IR directory . +This message will likely be preceded by a diagnostic message from +.BR mkdir . +.SH "EXIT STATUS" +.TP +.B 64 +.B mkdirhier +was not given any directory names to create. +.PP +.B mkdirhier +otherwise exits with the exit status of the last +.B mkdir +command that failed. +.SH BUGS +.B mkdirhier +does not create all the requested directories as an atomic operation; +therefore, it is is susceptible to race conditions. +For example, if +.B mkdirhier +is directed to create a hierarchy +.I a/b/c/d +and any of +.IR a/ , +.IR b/ , +or +.I c/ +do not yet exist, any of the newly-created directories can be removed +and/or replaced by a symbolic link to another location in the window of +time after +.B mkdirhier +creates a directory and the directory immediately below it. +This means that failures can be provoked (since +.B mkdir +will fail to create a directory in a directory that does not already +exist), +or directories may be created in unexpected locations. +The same limitation holds for multiple directory arguments to +.BR mkdirhier ; +given two arguments +.I a/b/c/d +and +.IR a/b/c/f , +it is possible for the directory hierarchy +.I a/b/c +to be disrupted in the time between the processing of the two arguments. +To avoid these problems, use +.B mkdir \-p +instead, or do not use +.B mkdirhier +to create directories in parts of the filesystem where untrusted users can +manipulate them. .SH "SEE ALSO" -mkdir(1) +.BR mkdir (__osmansuffix__)