[Pkg-shadow-commits] r3205 - in upstream/trunk: . lib libmisc src
Nicolas FRANÇOIS
nekral-guest at alioth.debian.org
Sun Apr 4 20:55:48 UTC 2010
Author: nekral-guest
Date: 2010-04-04 20:55:46 +0000 (Sun, 04 Apr 2010)
New Revision: 3205
Modified:
upstream/trunk/ChangeLog
upstream/trunk/lib/prototypes.h
upstream/trunk/libmisc/chowndir.c
upstream/trunk/libmisc/copydir.c
upstream/trunk/src/useradd.c
upstream/trunk/src/usermod.c
Log:
2010-04-04 Nicolas Fran?\195?\167ois <nicolas.francois at 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?\195?\167ois <nicolas.francois at 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?\195?\167ois <nicolas.francois at 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?\195?\167ois <nicolas.francois at 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.
Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/ChangeLog 2010-04-04 20:55:46 UTC (rev 3205)
@@ -1,3 +1,45 @@
+2010-04-04 Nicolas François <nicolas.francois at 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 at 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 at 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 at 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.
+
2010-04-03 Nicolas François <nicolas.francois at centraliens.net>
* man/hu/passwd.5: Fix formatting typo.
Modified: upstream/trunk/lib/prototypes.h
===================================================================
--- upstream/trunk/lib/prototypes.h 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/lib/prototypes.h 2010-04-04 20:55:46 UTC (rev 3205)
@@ -75,7 +75,9 @@
extern char *Basename (char *str);
/* chowndir.c */
-extern int chown_tree (const char *, uid_t, uid_t, gid_t, gid_t);
+extern int chown_tree (const char *root,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
/* chowntty.c */
extern void chown_tty (const struct passwd *);
@@ -116,8 +118,9 @@
/* copydir.c */
extern int copy_tree (const char *src_root, const char *dst_root,
- long int uid, long int gid);
-
+ bool copy_root,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
#ifdef WITH_SELINUX
extern int selinux_file_context (const char *dst_name);
#endif
Modified: upstream/trunk/libmisc/chowndir.c
===================================================================
--- upstream/trunk/libmisc/chowndir.c 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/libmisc/chowndir.c 2010-04-04 20:55:46 UTC (rev 3205)
@@ -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 @@
/*
* 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 @@
}
while ((ent = readdir (dir))) {
+ uid_t tmpuid = (uid_t) -1;
+ gid_t tmpgid = (gid_t) -1;
/*
* Skip the "." and ".." entries
@@ -96,12 +111,16 @@
* 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 @@
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;
}
Modified: upstream/trunk/libmisc/copydir.c
===================================================================
--- upstream/trunk/libmisc/copydir.c 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/libmisc/copydir.c 2010-04-04 20:55:46 UTC (rev 3205)
@@ -68,24 +68,38 @@
static /*@exposed@*/struct link_name *links;
static int copy_entry (const char *src, const char *dst,
- long int uid, long int gid);
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
static int copy_dir (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid);
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
#ifdef S_IFLNK
static char *readlink_malloc (const char *filename);
static int copy_symlink (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid);
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
#endif /* S_IFLNK */
-static int copy_hardlink (const char *src, const char *dst,
+static int copy_hardlink (const char *dst,
struct link_name *lp);
static int copy_special (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid);
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
static int copy_file (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid);
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
+static int chown_if_needed (const char *dst, const struct stat *statp,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
+static int lchown_if_needed (const char *dst, const struct stat *statp,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
+static int fchown_if_needed (int fdst, const struct stat *statp,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid);
#ifdef WITH_SELINUX
/*
@@ -130,7 +144,10 @@
#endif /* WITH_SELINUX */
#if defined(WITH_ACL) || defined(WITH_ATTR)
-void error (struct error_context *ctx, const char *fmt, ...)
+/*
+ * error - format the error messages for the ACL and EQ libraries.
+ */
+static void error (struct error_context *ctx, const char *fmt, ...)
{
va_list ap;
@@ -143,7 +160,7 @@
va_end (ap);
}
-struct error_context ctx = {
+static struct error_context ctx = {
error
};
#endif /* WITH_ACL || WITH_ATTR */
@@ -225,15 +242,46 @@
*
* copy_tree() walks a directory tree and copies ordinary files
* as it goes.
+ *
+ * old_uid and new_uid are used to set the ownership of the copied
+ * files. Unless old_uid is set to -1, only the files owned by
+ * old_uid have their ownership changed to new_uid. In addition, if
+ * new_uid is set to -1, no ownership will be changed.
+ *
+ * The same logic applies for the group-ownership and
+ * old_gid/new_gid.
*/
int copy_tree (const char *src_root, const char *dst_root,
- long int uid, long int gid)
+ bool copy_root,
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
int err = 0;
bool set_orig = false;
struct DIRECT *ent;
DIR *dir;
+ if (copy_root) {
+ struct stat sb;
+ if (access (dst_root, F_OK) == 0) {
+ return -1;
+ }
+
+ if (LSTAT (src_root, &sb) == -1) {
+ return -1;
+ }
+
+ if (!S_ISDIR (sb.st_mode)) {
+ fprintf (stderr,
+ "%s: %s is not a directory",
+ Prog, src_root);
+ return -1;
+ }
+
+ return copy_entry (src_root, dst_root,
+ old_uid, new_uid, old_gid, new_gid);
+ }
+
/*
* Make certain both directories exist. This routine is called
* after the home directory is created, or recursively after the
@@ -290,7 +338,9 @@
snprintf (dst_name, dst_len, "%s/%s",
dst_root, ent->d_name);
- err = copy_entry (src_name, dst_name, uid, gid);
+ err = copy_entry (src_name, dst_name,
+ old_uid, new_uid,
+ old_gid, new_gid);
}
if (NULL != src_name) {
free (src_name);
@@ -330,13 +380,18 @@
*
* The access and modification time will not be modified.
*
- * The permissions will be set to uid/gid.
+ * The permissions will be set to new_uid/new_gid.
*
- * If uid (resp. gid) is equal to -1, the user (resp. group) will
+ * If new_uid (resp. new_gid) is equal to -1, the user (resp. group) will
* not be modified.
+ *
+ * Only the files owned (resp. group-owned) by old_uid (resp.
+ * old_gid) will be modified, unless old_uid (resp. old_gid) is set
+ * to -1.
*/
static int copy_entry (const char *src, const char *dst,
- long int uid, long int gid)
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
int err = 0;
struct stat sb;
@@ -371,7 +426,8 @@
#endif /* !HAVE_STRUCT_STAT_ST_MTIM */
if (S_ISDIR (sb.st_mode)) {
- err = copy_dir (src, dst, &sb, mt, uid, gid);
+ err = copy_dir (src, dst, &sb, mt,
+ old_uid, new_uid, old_gid, new_gid);
}
#ifdef S_IFLNK
@@ -380,7 +436,8 @@
*/
else if (S_ISLNK (sb.st_mode)) {
- err = copy_symlink (src, dst, &sb, mt, uid, gid);
+ err = copy_symlink (src, dst, &sb, mt,
+ old_uid, new_uid, old_gid, new_gid);
}
#endif /* S_IFLNK */
@@ -389,7 +446,7 @@
*/
else if ((lp = check_link (src, &sb)) != NULL) {
- err = copy_hardlink (src, dst, lp);
+ err = copy_hardlink (dst, lp);
}
/*
@@ -399,7 +456,8 @@
*/
else if (!S_ISREG (sb.st_mode)) {
- err = copy_special (src, dst, &sb, mt, uid, gid);
+ err = copy_special (src, dst, &sb, mt,
+ old_uid, new_uid, old_gid, new_gid);
}
/*
@@ -408,7 +466,8 @@
*/
else {
- err = copy_file (src, dst, &sb, mt, uid, gid);
+ err = copy_file (src, dst, &sb, mt,
+ old_uid, new_uid, old_gid, new_gid);
}
}
@@ -420,14 +479,15 @@
*
* Copy a directory (recursively) from src to dst.
*
- * statp, mt, uid, gid are used to set the access and modification and the
- * access rights.
+ * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
+ * the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_dir (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid)
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
int err = 0;
@@ -440,9 +500,8 @@
selinux_file_context (dst);
#endif /* WITH_SELINUX */
if ( (mkdir (dst, statp->st_mode) != 0)
- || (chown (dst,
- (uid == - 1) ? statp->st_uid : (uid_t) uid,
- (gid == - 1) ? statp->st_gid : (gid_t) gid) != 0)
+ || (chown_if_needed (dst, statp,
+ old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| (perm_copy_file (src, dst, &ctx) != 0)
#else /* !WITH_ACL */
@@ -458,7 +517,8 @@
*/
|| (attr_copy_file (src, dst, NULL, &ctx) != 0)
#endif /* WITH_ATTR */
- || (copy_tree (src, dst, uid, gid) != 0)
+ || (copy_tree (src, dst, false,
+ old_uid, new_uid, old_gid, new_gid) != 0)
|| (utimes (dst, mt) != 0)) {
err = -1;
}
@@ -508,14 +568,15 @@
*
* Copy a symlink from src to dst.
*
- * statp, mt, uid, gid are used to set the access and modification and the
- * access rights.
+ * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
+ * the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_symlink (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid)
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
char *oldlink;
@@ -554,9 +615,8 @@
selinux_file_context (dst);
#endif /* WITH_SELINUX */
if ( (symlink (oldlink, dst) != 0)
- || (lchown (dst,
- (uid == -1) ? statp->st_uid : (uid_t) uid,
- (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
+ || (lchown_if_needed (dst, statp,
+ old_uid, new_uid, old_gid, new_gid) != 0)) {
/* FIXME: there are no modes on symlinks, right?
* ACL could be copied, but this would be much more
* complex than calling perm_copy_file.
@@ -589,7 +649,7 @@
*
* Return 0 on success, -1 on error.
*/
-static int copy_hardlink (const char *src, const char *dst,
+static int copy_hardlink (const char *dst,
struct link_name *lp)
{
/* FIXME: selinux, ACL, Extended Attributes needed? */
@@ -613,14 +673,15 @@
*
* Copy a special file from src to dst.
*
- * statp, mt, uid, gid are used to set the access and modification and the
- * access rights.
+ * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
+ * the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_special (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid)
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
int err = 0;
@@ -629,9 +690,8 @@
#endif /* WITH_SELINUX */
if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
- || (chown (dst,
- (uid == -1) ? statp->st_uid : (uid_t) uid,
- (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
+ || (chown_if_needed (dst, statp,
+ old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| (perm_copy_file (src, dst, &ctx) != 0)
#else /* !WITH_ACL */
@@ -659,14 +719,15 @@
*
* Copy a file from src to dst.
*
- * statp, mt, uid, gid are used to set the access and modification and the
- * access rights.
+ * statp, mt, old_uid, new_uid, old_gid, and new_gid are used to set
+ * the access and modification and the access rights.
*
* Return 0 on success, -1 on error.
*/
static int copy_file (const char *src, const char *dst,
const struct stat *statp, const struct timeval mt[],
- long int uid, long int gid)
+ uid_t old_uid, uid_t new_uid,
+ gid_t old_gid, gid_t new_gid)
{
int err = 0;
int ifd;
@@ -683,9 +744,8 @@
#endif /* WITH_SELINUX */
ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
if ( (ofd < 0)
- || (fchown (ofd,
- (uid == -1) ? statp->st_uid : (uid_t) uid,
- (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
+ || (fchown_if_needed (ofd, statp,
+ old_uid, new_uid, old_gid, new_gid) != 0)
#ifdef WITH_ACL
|| (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
#else /* !WITH_ACL */
@@ -734,3 +794,37 @@
return err;
}
+#define def_chown_if_needed(chown_function, type_dst) \
+static int chown_function ## _if_needed (type_dst dst, \
+ const struct stat *statp, \
+ uid_t old_uid, uid_t new_uid, \
+ gid_t old_gid, gid_t new_gid) \
+{ \
+ uid_t tmpuid = (uid_t) -1; \
+ gid_t tmpgid = (gid_t) -1; \
+ \
+ /* Use new_uid if old_uid is set to -1 or if the file was \
+ * owned by the user. */ \
+ if (((uid_t) -1 == old_uid) || (statp->st_uid == old_uid)) { \
+ tmpuid = new_uid; \
+ } \
+ /* Otherwise, or if new_uid was set to -1, we keep the same \
+ * owner. */ \
+ if ((uid_t) -1 == tmpuid) { \
+ tmpuid = statp->st_uid; \
+ } \
+ \
+ if (((gid_t) -1 == old_gid) || (statp->st_gid == old_gid)) { \
+ tmpgid = new_gid; \
+ } \
+ if ((gid_t) -1 == tmpgid) { \
+ tmpgid = statp->st_gid; \
+ } \
+ \
+ return chown_function (dst, tmpuid, tmpgid); \
+}
+
+def_chown_if_needed (chown, const char *)
+def_chown_if_needed (lchown, const char *)
+def_chown_if_needed (fchown, int)
+
Modified: upstream/trunk/src/useradd.c
===================================================================
--- upstream/trunk/src/useradd.c 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/src/useradd.c 2010-04-04 20:55:46 UTC (rev 3205)
@@ -2,7 +2,7 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2009, Nicolas François
+ * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1806,7 +1806,8 @@
static void create_mail (void)
{
if (strcasecmp (create_mail_spool, "yes") == 0) {
- char *spool, *file;
+ const char *spool;
+ char *file;
int fd;
struct group *gr;
gid_t gid;
@@ -2036,7 +2037,8 @@
if (mflg) {
create_home ();
if (home_added) {
- copy_tree (def_template, user_home, user_id, user_gid);
+ copy_tree (def_template, user_home, false,
+ (uid_t)-1, user_id, (gid_t)-1, user_gid);
} else {
fprintf (stderr,
_("%s: warning: the home directory already exists.\n"
Modified: upstream/trunk/src/usermod.c
===================================================================
--- upstream/trunk/src/usermod.c 2010-04-04 20:48:29 UTC (rev 3204)
+++ upstream/trunk/src/usermod.c 2010-04-04 20:55:46 UTC (rev 3205)
@@ -2,7 +2,7 @@
* Copyright (c) 1991 - 1994, Julianne Frances Haugh
* Copyright (c) 1996 - 2000, Marek Michałkiewicz
* Copyright (c) 2000 - 2006, Tomasz Kłoczko
- * Copyright (c) 2007 - 2009, Nicolas François
+ * Copyright (c) 2007 - 2010, Nicolas François
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1403,44 +1403,51 @@
{
struct stat sb;
- if (mflg && (stat (user_home, &sb) == 0)) {
+ if (stat (user_home, &sb) == 0) {
/*
+ * If the new home directory already exist, the user
+ * should not use -m.
+ */
+ if (access (user_newhome, F_OK) == 0) {
+ fprintf (stderr,
+ _("%s: directory %s exists\n"),
+ Prog, user_newhome);
+ fail_exit (E_HOMEDIR);
+ }
+
+ /*
* Don't try to move it if it is not a directory
* (but /dev/null for example). --marekm
*/
if (!S_ISDIR (sb.st_mode)) {
- return;
+ fprintf (stderr,
+ _("%s: The previous home directory (%s) was "
+ "not a directory. It is not removed and no "
+ "home directories are created.\n"),
+ Prog, user_home);
+ fail_exit (E_HOMEDIR);
}
- if (access (user_newhome, F_OK) == 0) {
- fprintf (stderr,
- _("%s: directory %s exists\n"),
- Prog, user_newhome);
- fail_exit (E_HOMEDIR);
- } else if (rename (user_home, user_newhome) != 0) {
- // FIXME: rename above may have broken symlinks
- // pointing to the user's home directory
- // with an absolute path.
- if (errno == EXDEV) {
- if (mkdir (user_newhome, sb.st_mode & 0777) != 0) {
- fprintf (stderr,
- _("%s: can't create %s\n"),
- Prog, user_newhome);
- }
- if (chown (user_newhome, sb.st_uid, sb.st_gid) != 0) {
- fprintf (stderr,
- _("%s: can't chown %s\n"),
- Prog, user_newhome);
- rmdir (user_newhome);
- fail_exit (E_HOMEDIR);
- }
- // FIXME: the current uid & gid should
- // also be provided so that only the files
- // owned by the user/group have their
- // ownership changed.
- if (copy_tree (user_home, user_newhome,
- uflg ? (long int)user_newid : -1,
- gflg ? (long int)user_newgid : -1) == 0) {
+ if (rename (user_home, user_newhome) == 0) {
+ /* FIXME: rename above may have broken symlinks
+ * pointing to the user's home directory
+ * with an absolute path. */
+ if (chown_tree (user_newhome,
+ user_id, uflg ? user_newid : (uid_t)-1,
+ user_gid, gflg ? user_newgid : (gid_t)-1) != 0) {
+ fprintf (stderr,
+ _("%s: Failed to change ownership of the home directory"),
+ Prog);
+ fail_exit (E_HOMEDIR);
+ }
+ return;
+ } else {
+ if (EXDEV == errno) {
+ if (copy_tree (user_home, user_newhome, true,
+ user_id,
+ uflg ? user_newid : (uid_t)-1,
+ user_gid,
+ gflg ? user_newgid : (gid_t)-1) == 0) {
if (remove_tree (user_home, true) != 0) {
fprintf (stderr,
_("%s: warning: failed to completely remove old home directory %s"),
@@ -1457,8 +1464,6 @@
return;
}
- /* TODO: do some cleanup if the copy
- * was started */
(void) remove_tree (user_newhome, true);
}
fprintf (stderr,
@@ -1472,16 +1477,6 @@
user_newname, (unsigned int) user_newid, 1);
#endif
}
- if (uflg || gflg) {
-#ifdef WITH_AUDIT
- audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
- "changing home directory owner",
- user_newname, (unsigned int) user_newid, 1);
-#endif
- chown (dflg ? user_newhome : user_home,
- uflg ? user_newid : user_id,
- gflg ? user_newgid : user_gid);
- }
}
/*
@@ -1819,17 +1814,28 @@
}
#endif
- if (uflg) { // FIXME: gflg also, except for faillog/lastlog
+ if (uflg) {
update_lastlog ();
update_faillog ();
+ }
+ if (!mflg && (uflg || gflg)) {
+ if (access (dflg ? user_newhome : user_home, F_OK) == 0) {
/*
* Change the UID on all of the files owned by `user_id' to
* `user_newid' in the user's home directory.
+ *
+ * move_home() already takes care of changing the ownership.
*/
- chown_tree (dflg ? user_newhome : user_home,
- user_id, user_newid,
- user_gid, gflg ? user_newgid : user_gid);
+ if (chown_tree (dflg ? user_newhome : user_home,
+ user_id, uflg ? user_newid : (uid_t)-1,
+ user_gid, gflg ? user_newgid : (gid_t)-1) != 0) {
+ fprintf (stderr,
+ _("%s: Failed to change ownership of the home directory"),
+ Prog);
+ fail_exit (E_HOMEDIR);
+ }
+ }
}
return E_SUCCESS;
More information about the Pkg-shadow-commits
mailing list