2010-04-04 Nicolas François <nicolas.francois@centraliens.net>
* src/useradd.c: spool is a constant string. * src/useradd.c: Set the new copy_tree's paramater 'copy_root' to false 2010-04-04 Nicolas François <nicolas.francois@centraliens.net> * src/usermod.c: move_home() is only called if mflg is set. * src/usermod.c: Fail is -m is provided but the old home directory is not a directory. * src/usermod.c: Use the previous improvement of copy_tree to provide better error diagnosis. * src/usermod.c: When rename() is used, also change the ownership. * src/usermod.c: Do not change the ownership of the root directory twice. * src/usermod.c: When -u is provided, only change the ownership of the home directory if it is a directory. * src/usermod.c: Also change ownerships when -g is used. 2010-04-04 Nicolas François <nicolas.francois@centraliens.net> * lib/prototypes.h, libmisc/copydir.c: Add the old UID and GID to copy_tree to detect when ownership shall be changed. * libmisc/copydir.c: Document the behavior when the IDs are set to -1. * lib/prototypes.h, libmisc/copydir.c (copy_tree): Add parameter copy_root. * libmisc/copydir.c: error() and ctx can be static. * libmisc/copydir.c (copy_hardlink): Remove parameter src. 2010-04-04 Nicolas François <nicolas.francois@centraliens.net> * libmisc/chowndir.c: Dynamically allocate memory to support path longer than 1024 characters. * libmisc/chowndir.c: Fix typos in documentation. * libmisc/chowndir.c: Support and document the behavior when a old or new ID is set to -1. * libmisc/chowndir.c: Improved error detection when chown fails. * libmisc/chowndir.c: Harmonize error handling strategy when an error occurs: stop changing ownership as soon as an error was detected.
This commit is contained in:
+69
-21
@@ -45,23 +45,36 @@
|
||||
*
|
||||
* chown_dir() walks a directory tree and changes the ownership
|
||||
* of all files owned by the provided user ID.
|
||||
*
|
||||
* Only files owned (resp. group-owned) by old_uid (resp. by old_gid)
|
||||
* will have their ownership (resp. group-ownership) modified, unless
|
||||
* old_uid (resp. old_gid) is set to -1.
|
||||
*
|
||||
* new_uid and new_gid can be set to -1 to indicate that no owner or
|
||||
* group-owner shall be changed.
|
||||
*/
|
||||
int
|
||||
chown_tree (const char *root,
|
||||
uid_t old_uid,
|
||||
uid_t new_uid,
|
||||
gid_t old_gid,
|
||||
gid_t new_gid)
|
||||
int chown_tree (const char *root,
|
||||
uid_t old_uid,
|
||||
uid_t new_uid,
|
||||
gid_t old_gid,
|
||||
gid_t new_gid)
|
||||
{
|
||||
char new_name[1024];
|
||||
char *new_name;
|
||||
size_t new_name_len;
|
||||
int rc = 0;
|
||||
struct DIRECT *ent;
|
||||
struct stat sb;
|
||||
DIR *dir;
|
||||
|
||||
new_name = malloc (1024);
|
||||
if (NULL == new_name) {
|
||||
return -1;
|
||||
}
|
||||
new_name_len = 1024;
|
||||
|
||||
/*
|
||||
* Make certain the directory exists. This routine is called
|
||||
* directory by the invoker, or recursively.
|
||||
* directly by the invoker, or recursively.
|
||||
*/
|
||||
|
||||
if (access (root, F_OK) != 0) {
|
||||
@@ -71,8 +84,8 @@ chown_tree (const char *root,
|
||||
/*
|
||||
* Open the directory and read each entry. Every entry is tested
|
||||
* to see if it is a directory, and if so this routine is called
|
||||
* recursively. If not, it is checked to see if it is owned by
|
||||
* old user ID.
|
||||
* recursively. If not, it is checked to see if an ownership
|
||||
* shall be changed.
|
||||
*/
|
||||
|
||||
dir = opendir (root);
|
||||
@@ -81,6 +94,8 @@ chown_tree (const char *root,
|
||||
}
|
||||
|
||||
while ((ent = readdir (dir))) {
|
||||
uid_t tmpuid = (uid_t) -1;
|
||||
gid_t tmpgid = (gid_t) -1;
|
||||
|
||||
/*
|
||||
* Skip the "." and ".." entries
|
||||
@@ -96,12 +111,16 @@ chown_tree (const char *root,
|
||||
* destination files.
|
||||
*/
|
||||
|
||||
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) {
|
||||
break;
|
||||
if (strlen (root) + strlen (ent->d_name) + 2 > new_name_len) {
|
||||
new_name = realloc (new_name, new_name_len + 1024);
|
||||
if (NULL == new_name) {
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
new_name_len += 1024;
|
||||
}
|
||||
|
||||
snprintf (new_name, sizeof new_name, "%s/%s", root,
|
||||
ent->d_name);
|
||||
snprintf (new_name, new_name_len, "%s/%s", root, ent->d_name);
|
||||
|
||||
/* Don't follow symbolic links! */
|
||||
if (LSTAT (new_name, &sb) == -1) {
|
||||
@@ -126,23 +145,52 @@ chown_tree (const char *root,
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (sb.st_uid == old_uid) {
|
||||
LCHOWN (new_name, new_uid,
|
||||
(sb.st_gid == old_gid) ? new_gid : sb.st_gid);
|
||||
/*
|
||||
* By default, the IDs are not changed (-1).
|
||||
*
|
||||
* If the file is not owned by the user, the owner is not
|
||||
* changed.
|
||||
*
|
||||
* If the file is not group-owned by the group, the
|
||||
* group-owner is not changed.
|
||||
*/
|
||||
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
|
||||
tmpuid = new_uid;
|
||||
}
|
||||
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
|
||||
tmpgid = new_gid;
|
||||
}
|
||||
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
||||
rc = LCHOWN (new_name, tmpuid, tmpgid);
|
||||
if (0 != rc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (new_name);
|
||||
(void) closedir (dir);
|
||||
|
||||
/*
|
||||
* Now do the root of the tree
|
||||
*/
|
||||
|
||||
if (stat (root, &sb) == 0) {
|
||||
if (sb.st_uid == old_uid) {
|
||||
LCHOWN (root, new_uid,
|
||||
sb.st_gid == old_gid ? new_gid : sb.st_gid);
|
||||
if ((0 == rc) && (stat (root, &sb) == 0)) {
|
||||
uid_t tmpuid = (uid_t) -1;
|
||||
gid_t tmpgid = (gid_t) -1;
|
||||
if (((uid_t) -1 == old_uid) || (sb.st_uid == old_uid)) {
|
||||
tmpuid = new_uid;
|
||||
}
|
||||
if (((gid_t) -1 == old_gid) || (sb.st_gid == old_gid)) {
|
||||
tmpgid = new_gid;
|
||||
}
|
||||
if (((uid_t) -1 != tmpuid) || ((gid_t) -1 != tmpgid)) {
|
||||
rc = LCHOWN (root, tmpuid, tmpgid);
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user