Make sure that setmode sets errno on failure (it used to return a random

errno) and document it.
This commit is contained in:
christos 2005-10-01 20:08:01 +00:00
parent d15fb24907
commit fbd01002b3
2 changed files with 48 additions and 24 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: setmode.3,v 1.17 2005/06/04 00:39:26 wiz Exp $
.\" $NetBSD: setmode.3,v 1.18 2005/10/01 20:08:01 christos Exp $
.\"
.\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
.\"
.Dd May 17, 2005
.Dd October 1, 2005
.Dt SETMODE 3
.Os
.Sh NAME
@ -95,6 +95,17 @@ for any of the errors specified for the library routines
.Xr malloc 3
or
.Xr strtol 3 .
In addition,
.Fn setmode
will fail and set
.Va errno
to:
.Bl -tag -width Er
.It Bq Er EINVAL
The
.Fa mode
argument does not represent a valid mode.
.El
.Sh SEE ALSO
.Xr chmod 1 ,
.Xr stat 2 ,

View File

@ -1,4 +1,4 @@
/* $NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $ */
/* $NetBSD: setmode.c,v 1.31 2005/10/01 20:08:01 christos Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
#else
__RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $");
__RCSID("$NetBSD: setmode.c,v 1.31 2005/10/01 20:08:01 christos Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@ -50,6 +50,7 @@ __RCSID("$NetBSD: setmode.c,v 1.30 2003/08/07 16:42:56 agc Exp $");
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#ifdef SETMODE_DEBUG
@ -76,7 +77,7 @@ typedef struct bitcmd {
#define CMD2_OBITS 0x08
#define CMD2_UBITS 0x10
static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int));
static BITCMD *addcmd __P((BITCMD *, mode_t, mode_t, mode_t, mode_t));
static void compress_mode __P((BITCMD *));
#ifdef SETMODE_DEBUG
static void dumpmode __P((BITCMD *));
@ -165,15 +166,13 @@ common: if (set->cmd2 & CMD2_CLR) {
BITCMD *newset; \
setlen += SET_LEN_INCR; \
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
if (newset == NULL) { \
free(saveset); \
return (NULL); \
} \
if (newset == NULL) \
goto out; \
set = newset + (set - saveset); \
saveset = newset; \
endset = newset + (setlen - 2); \
} \
set = addcmd(set, (a), (b), (c), (d)); \
set = addcmd(set, (mode_t)(a), (mode_t)(b), (mode_t)(c), (d)); \
} while (/*CONSTCOND*/0)
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
@ -182,16 +181,19 @@ void *
setmode(p)
const char *p;
{
int perm, who;
int serrno;
char op, *ep;
BITCMD *set, *saveset, *endset;
sigset_t signset, sigoset;
mode_t mask;
mode_t mask, perm, permXbits, who;
long lval;
int equalopdone = 0; /* pacify gcc */
int permXbits, setlen;
int setlen;
if (!*p)
return (NULL);
if (!*p) {
errno = EINVAL;
return NULL;
}
/*
* Get a copy of the mask for the permissions that are mask relative.
@ -217,11 +219,19 @@ setmode(p)
* or illegal bits.
*/
if (isdigit((unsigned char)*p)) {
perm = (mode_t)strtol(p, &ep, 8);
if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
free(saveset);
return (NULL);
errno = 0;
lval = strtol(p, &ep, 8);
if (*ep) {
errno = EINVAL;
goto out;
}
if (errno == ERANGE && (lval == LONG_MAX || lval == LONG_MIN))
goto out;
if (lval & ~(STANDARD_BITS|S_ISTXT)) {
errno = EINVAL;
goto out;
}
perm = (mode_t)lval;
ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
set->cmd = 0;
return (saveset);
@ -253,8 +263,8 @@ setmode(p)
}
getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
free(saveset);
return (NULL);
errno = EINVAL;
goto out;
}
if (op == '=')
equalopdone = 0;
@ -349,14 +359,17 @@ apply: if (!*p)
dumpmode(saveset);
#endif
return (saveset);
out:
serrno = errno;
free(saveset);
errno = serrno;
return NULL;
}
static BITCMD *
addcmd(set, op, who, oparg, mask)
BITCMD *set;
int oparg, who;
int op;
u_int mask;
mode_t oparg, who, op, mask;
{
_DIAGASSERT(set != NULL);