Re: svn commit: r301024 - head/sbin/swapon

2016-05-31 Thread Chris Torek
> This change makes the code use the POSIX basename() function. It has the
> advantage that (if implemented correctly), it also imposes no restrict
> on the pathname length.

I'm not sure what the parenthetic remark "if implemented correctly"
means, but libc basename() has this in it:

char *
basename(const char *path)
{
static char *bname = NULL;

if (bname == NULL) {
bname = (char *)malloc(MAXPATHLEN);
if (bname == NULL)
return (NULL);
}
return (basename_r(path, bname));
}

which means that it is not only not thread-safe, it also
imposes restrictions on pathname length.

I recently wrote a pair of can-be-thread-safe yet can-be-
unlimited-path-length yet can-be-backwards-compatible basename
and dirname functions (I tested to see if they produced the same
errno's and oddball outputs like for dirname("///")).  I'll toss
them in here in case anyone has some enthusiasm for fixing the
mess.  Of course they are equally non-standard, unless we can
convince a future POSIX committee or something.

(I also wrote some halfway useable reentrant getpw* and getgr*
functions but they need more thought and do not play well with
nsswitch so I am not including them here.  NB: rfuncs.h just
contains declarations for these reentrant r_* functions.)

Chris

---

/*
 * Copyright 2016 Chris Torek 
 * All rights reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted providing that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *notice, this list of conditions and the following disclaimer in the
 *documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include 
#include 
#include 
#include 

#include "rfuncs.h"

/*
 * This is essentially a clone of the BSD basename_r function,
 * which is like POSIX basename() but puts the result in a user
 * supplied buffer.
 *
 * In BSD basename_r, the buffer must be least MAXPATHLEN bytes
 * long.  In our case we take the size of the buffer as an argument.
 *
 * Note that it's impossible in general to do this without
 * a temporary buffer since basename("foo/bar") is "bar",
 * but basename("foo/bar/") is still "bar" -- no trailing
 * slash is allowed.
 *
 * The return value is your supplied buffer , or NULL if
 * the length of the basename of the supplied  equals or
 * exceeds your indicated .
 *
 * As a special but useful case, if you supply NULL for the 
 * argument, we allocate the buffer dynamically to match the
 * basename, i.e., the result is basically strdup()ed for you.
 * In this case  is ignored (recommended: pass 0 here).
 */
char *
r_basename(const char *path, char *buf, size_t bufsize)
{
const char *endp, *comp;
size_t len;

/*
 * NULL or empty path means ".".  This is perhaps overly
 * forgiving but matches libc basename_r(), and avoids
 * breaking the code below.
 */
if (path == NULL || *path == '\0') {
comp = ".";
len = 1;
} else {
/*
 * Back up over any trailing slashes.  If we reach
 * the top of the path and it's still a trailing
 * slash, it's also a leading slash and the entire
 * path is just "/" (or "//", or "///", etc).
 */
endp = path + strlen(path) - 1;
while (*endp == '/' && endp > path)
endp--;
/* Invariant: *endp != '/' || endp == path */
if (*endp == '/') {
/* then endp==path and hence entire path is "/" */
comp = "/";
len = 1;
} else {
/*
 * We handled empty strings earlier, and
 * we just proved *endp != '/'.  

svn commit: r301024 - head/sbin/swapon

2016-05-31 Thread Ed Schouten
Author: ed
Date: Tue May 31 06:45:19 2016
New Revision: 301024
URL: https://svnweb.freebsd.org/changeset/base/301024

Log:
  Stop using the non-standard basename_r() function.
  
  This change makes the code use the POSIX basename() function. It has the
  advantage that (if implemented correctly), it also imposes no restrict
  on the pathname length.
  
  Notice that I haven't added any error handling to the strdup() call. It
  looks like none of the other calls to strdup() and malloc() performed by
  this utility do it either.
  
  Reviewed by:  hrs
  Differential Revision:https://reviews.freebsd.org/D6626

Modified:
  head/sbin/swapon/swapon.c

Modified: head/sbin/swapon/swapon.c
==
--- head/sbin/swapon/swapon.c   Tue May 31 06:24:09 2016(r301023)
+++ head/sbin/swapon/swapon.c   Tue May 31 06:45:19 2016(r301024)
@@ -216,7 +216,7 @@ main(int argc, char **argv)
 static const char *
 swap_on_off(const char *name, int doingall, char *mntops)
 {
-   char base[PATH_MAX];
+   char *base, *basebuf;
 
/* Swap on vnode-backed md(4) device. */
if (mntops != NULL &&
@@ -227,17 +227,23 @@ swap_on_off(const char *name, int doinga
 strncmp(MD_NAME, name, sizeof(MD_NAME)) == 0))
return (swap_on_off_md(name, mntops, doingall));
 
-   basename_r(name, base);
+   basebuf = strdup(name);
+   base = basename(basebuf);
 
/* Swap on encrypted device by GEOM_BDE. */
-   if (fnmatch("*.bde", base, 0) == 0)
+   if (fnmatch("*.bde", base, 0) == 0) {
+   free(basebuf);
return (swap_on_off_gbde(name, doingall));
+   }
 
/* Swap on encrypted device by GEOM_ELI. */
-   if (fnmatch("*.eli", base, 0) == 0)
+   if (fnmatch("*.eli", base, 0) == 0) {
+   free(basebuf);
return (swap_on_off_geli(name, mntops, doingall));
+   }
 
/* Swap on special file. */
+   free(basebuf);
return (swap_on_off_sfile(name, doingall));
 }
 
___
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"