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 .\" Copyright (c) 1989, 1991, 1993
.\" The Regents of the University of California. All rights reserved. .\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\" .\"
.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95 .\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
.\" .\"
.Dd May 17, 2005 .Dd October 1, 2005
.Dt SETMODE 3 .Dt SETMODE 3
.Os .Os
.Sh NAME .Sh NAME
@ -95,6 +95,17 @@ for any of the errors specified for the library routines
.Xr malloc 3 .Xr malloc 3
or or
.Xr strtol 3 . .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 .Sh SEE ALSO
.Xr chmod 1 , .Xr chmod 1 ,
.Xr stat 2 , .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 * Copyright (c) 1989, 1993, 1994
@ -37,7 +37,7 @@
#if 0 #if 0
static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94"; static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
#else #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
#endif /* LIBC_SCCS and not lint */ #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 <errno.h>
#include <signal.h> #include <signal.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h>
#include <unistd.h> #include <unistd.h>
#ifdef SETMODE_DEBUG #ifdef SETMODE_DEBUG
@ -76,7 +77,7 @@ typedef struct bitcmd {
#define CMD2_OBITS 0x08 #define CMD2_OBITS 0x08
#define CMD2_UBITS 0x10 #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 *)); static void compress_mode __P((BITCMD *));
#ifdef SETMODE_DEBUG #ifdef SETMODE_DEBUG
static void dumpmode __P((BITCMD *)); static void dumpmode __P((BITCMD *));
@ -165,15 +166,13 @@ common: if (set->cmd2 & CMD2_CLR) {
BITCMD *newset; \ BITCMD *newset; \
setlen += SET_LEN_INCR; \ setlen += SET_LEN_INCR; \
newset = realloc(saveset, sizeof(BITCMD) * setlen); \ newset = realloc(saveset, sizeof(BITCMD) * setlen); \
if (newset == NULL) { \ if (newset == NULL) \
free(saveset); \ goto out; \
return (NULL); \
} \
set = newset + (set - saveset); \ set = newset + (set - saveset); \
saveset = newset; \ saveset = newset; \
endset = newset + (setlen - 2); \ 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) } while (/*CONSTCOND*/0)
#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
@ -182,16 +181,19 @@ void *
setmode(p) setmode(p)
const char *p; const char *p;
{ {
int perm, who; int serrno;
char op, *ep; char op, *ep;
BITCMD *set, *saveset, *endset; BITCMD *set, *saveset, *endset;
sigset_t signset, sigoset; sigset_t signset, sigoset;
mode_t mask; mode_t mask, perm, permXbits, who;
long lval;
int equalopdone = 0; /* pacify gcc */ int equalopdone = 0; /* pacify gcc */
int permXbits, setlen; int setlen;
if (!*p) if (!*p) {
return (NULL); errno = EINVAL;
return NULL;
}
/* /*
* Get a copy of the mask for the permissions that are mask relative. * Get a copy of the mask for the permissions that are mask relative.
@ -217,11 +219,19 @@ setmode(p)
* or illegal bits. * or illegal bits.
*/ */
if (isdigit((unsigned char)*p)) { if (isdigit((unsigned char)*p)) {
perm = (mode_t)strtol(p, &ep, 8); errno = 0;
if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) { lval = strtol(p, &ep, 8);
free(saveset); if (*ep) {
return (NULL); 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); ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
set->cmd = 0; set->cmd = 0;
return (saveset); return (saveset);
@ -253,8 +263,8 @@ setmode(p)
} }
getop: if ((op = *p++) != '+' && op != '-' && op != '=') { getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
free(saveset); errno = EINVAL;
return (NULL); goto out;
} }
if (op == '=') if (op == '=')
equalopdone = 0; equalopdone = 0;
@ -349,14 +359,17 @@ apply: if (!*p)
dumpmode(saveset); dumpmode(saveset);
#endif #endif
return (saveset); return (saveset);
out:
serrno = errno;
free(saveset);
errno = serrno;
return NULL;
} }
static BITCMD * static BITCMD *
addcmd(set, op, who, oparg, mask) addcmd(set, op, who, oparg, mask)
BITCMD *set; BITCMD *set;
int oparg, who; mode_t oparg, who, op, mask;
int op;
u_int mask;
{ {
_DIAGASSERT(set != NULL); _DIAGASSERT(set != NULL);