chmod.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* 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
* 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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/* */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* chmod option mode files
* where
* mode is [ugoa][+-=][rwxXlstugo] or an octal number
* option is -R and -f
*/
/*
* Note that many convolutions are necessary
* due to the re-use of bits between locking
* and setgid
*/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <locale.h>
#include <string.h> /* strerror() */
#include <stdarg.h>
#include <limits.h>
#include <errno.h>
static int rflag;
static int fflag;
extern int optind;
extern int errno;
static int mac; /* Alternate to argc (for parseargs) */
static char **mav; /* Alternate to argv (for parseargs) */
static char *ms; /* Points to the mode argument */
extern mode_t
static int
static void
usage(void);
void
static void
int
{
int i, c;
int status = 0;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case 'R':
rflag++;
break;
case 'f':
fflag++;
break;
case '?':
usage();
exit(2);
}
}
/*
* Check for sufficient arguments
* or a usage error.
*/
if (mac < 2) {
usage();
exit(2);
}
for (i = 1; i < mac; i++)
}
static int
{
int linkflg = 0;
return (1);
}
linkflg = 1;
return (1);
}
}
/* Do not recurse if directory is object of symbolic link */
return (1);
}
/*
* If the group permissions of the file are being modified,
* make sure that the file's ACL (if it has one) is
* modified also, since chmod is supposed to apply group
* permissions changes to both the acl mask and the
* general group permissions.
*/
if (group_clear_bits || group_set_bits)
return (0);
}
static int
{
int ecode;
savedir);
/*
* Change what we are given before doing it's contents
*/
&group_clear_bits, &group_set_bits)) < 0) {
return (1);
}
/*
* If the group permissions of the file are being modified,
* make sure that the file's ACL (if it has one) is
* modified also, since chmod is supposed to apply group
* permissions changes to both the acl mask and the
* general group permissions.
*/
if (group_clear_bits || group_set_bits)
return (1);
}
return (1);
}
ecode = 0;
/*
* Save parent directory path before recursive chmod.
* We'll need this for error printing purposes. Add
* a trailing '/' to the path except in the case where
* the path is just '/'
*/
}
}
return (ecode ? 1 : 0);
}
/* PRINTFLIKE3 */
void
{
static char *msg[] = {
"",
"ERROR",
"WARNING",
""
};
/*
* Always print error message if this is a fatal error (code == 0);
* otherwise, print message if fflag == 0 (no -f option specified)
*/
}
if (code != 0)
}
static void
usage(void)
{
"usage:\tchmod [-fR] <absolute-mode> file ...\n"));
"\tchmod [-fR] <symbolic-mode-list> file ...\n"));
"where \t<symbolic-mode-list> is a comma-separated list of\n"));
"\t[ugoa]{+|-|=}[rwxXlstugo]\n"));
}
/*
* parseargs - generate getopt-friendly argument list for backwards
* compatibility with earlier Solaris usage (eg, chmod -w
* foo).
*
* assumes the existence of a static set of alternates to argc and argv,
* (namely, mac, and mav[]).
*
*/
static void
{
int i; /* current argument */
int fflag; /* arg list contains "--" */
/*
* We add an extra argument slot, in case we need to jam a "--"
* argument into the list.
*/
perror("chmod");
exit(2);
}
/* scan for the use of "--" in the argument list */
fflag = 1;
}
/* process the arguments */
for (i = mac = 0;
i++) {
/*
* If there is not already a "--" argument specified,
* and the argument starts with '-' but does not
* contain any of the official option letters, then it
* is probably a mode argument beginning with '-'.
* Force a "--" into the argument stream in front of
* it.
*/
}
}
}
}
/*
* This function is called whenever the group permissions of a file
* is being modified. According to the chmod(1) manpage, any
* change made to the group permissions must be applied to both
* the acl mask and the acl's GROUP_OBJ. The chmod(2) already
* set the mask, so this routine needs to make the same change
* to the GROUP_OBJ.
*/
static void
{
int aclcnt, n;
return; /* it's just a trivial acl; no need to change it */
== NULL) {
perror("chmod");
exit(2);
}
return;
}
if (group_clear_bits != 0)
newperm &= ~group_clear_bits;
if (group_set_bits != 0)
< 0) {
}
}
break;
}
}
}