* lib/commonio.c: Avoid PATH_MAX. On glibc, we can use realpath
with a NULL argument. * src/useradd.c: Replace PATH_MAX by a fixed constant. The buffer was not meant as a storage for a path. * src/useradd.c, src/newusers.c, src/chpasswd.c: Better detection of fgets errors. Lines shall end with a \n, unless we reached the end of file. * libmisc/copydir.c: Avoid PATH_MAX. Support file paths with any length. Added readlink_malloc().
This commit is contained in:
parent
a01499179f
commit
750093a3ed
12
ChangeLog
12
ChangeLog
@ -1,3 +1,15 @@
|
|||||||
|
2009-05-10 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* lib/commonio.c: Avoid PATH_MAX. On glibc, we can use realpath
|
||||||
|
with a NULL argument.
|
||||||
|
* src/useradd.c: Replace PATH_MAX by a fixed constant. The buffer
|
||||||
|
was not meant as a storage for a path.
|
||||||
|
* src/useradd.c, src/newusers.c, src/chpasswd.c: Better detection
|
||||||
|
of fgets errors. Lines shall end with a \n, unless we reached the
|
||||||
|
end of file.
|
||||||
|
* libmisc/copydir.c: Avoid PATH_MAX. Support file paths with any
|
||||||
|
length. Added readlink_malloc().
|
||||||
|
|
||||||
2009-05-09 Nicolas François <nicolas.francois@centraliens.net>
|
2009-05-09 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* src/pwck.c: Warn if an user has an entry in passwd and shadow,
|
* src/pwck.c: Warn if an user has an entry in passwd and shadow,
|
||||||
|
@ -83,21 +83,36 @@ static bool nscd_need_reload = false;
|
|||||||
*/
|
*/
|
||||||
int lrename (const char *old, const char *new)
|
int lrename (const char *old, const char *new)
|
||||||
{
|
{
|
||||||
|
|
||||||
char resolved_path[PATH_MAX];
|
|
||||||
int res;
|
int res;
|
||||||
|
char *r = NULL;
|
||||||
|
|
||||||
#if defined(S_ISLNK)
|
#if defined(S_ISLNK)
|
||||||
|
#ifndef __GLIBC__
|
||||||
|
char resolved_path[PATH_MAX];
|
||||||
|
#endif /* !__GLIBC__ */
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
|
if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
|
||||||
if (realpath (new, resolved_path) == NULL) {
|
#ifdef __GLIBC__ /* now a POSIX.1-2008 feature */
|
||||||
|
r = realpath (new, NULL);
|
||||||
|
#else /* !__GLIBC__ */
|
||||||
|
r = realpath (new, resolved_path);
|
||||||
|
#endif /* !__GLIBC__ */
|
||||||
|
if (NULL == r) {
|
||||||
perror ("realpath in lrename()");
|
perror ("realpath in lrename()");
|
||||||
} else {
|
} else {
|
||||||
new = resolved_path;
|
new = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* S_ISLNK */
|
||||||
|
|
||||||
res = rename (old, new);
|
res = rename (old, new);
|
||||||
|
|
||||||
|
#ifdef __GLIBC__
|
||||||
|
if (NULL != r) {
|
||||||
|
free (r);
|
||||||
|
}
|
||||||
|
#endif /* __GLIBC__ */
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,8 +199,6 @@ static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, c
|
|||||||
int copy_tree (const char *src_root, const char *dst_root,
|
int copy_tree (const char *src_root, const char *dst_root,
|
||||||
long int uid, long int gid)
|
long int uid, long int gid)
|
||||||
{
|
{
|
||||||
char src_name[PATH_MAX];
|
|
||||||
char dst_name[PATH_MAX];
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
bool set_orig = false;
|
bool set_orig = false;
|
||||||
struct DIRECT *ent;
|
struct DIRECT *ent;
|
||||||
@ -240,27 +238,36 @@ int copy_tree (const char *src_root, const char *dst_root,
|
|||||||
*/
|
*/
|
||||||
if ((strcmp (ent->d_name, ".") != 0) &&
|
if ((strcmp (ent->d_name, ".") != 0) &&
|
||||||
(strcmp (ent->d_name, "..") != 0)) {
|
(strcmp (ent->d_name, "..") != 0)) {
|
||||||
/*
|
char *src_name;
|
||||||
* Make sure the resulting source and destination
|
char *dst_name;
|
||||||
* filenames will fit in their buffers.
|
size_t src_len = strlen (ent->d_name) + 2;
|
||||||
*/
|
size_t dst_len = strlen (ent->d_name) + 2;
|
||||||
if ( (strlen (src_root) + strlen (ent->d_name) + 2 >
|
src_len += strlen (src_root);
|
||||||
sizeof src_name)
|
dst_len += strlen (dst_root);
|
||||||
|| (strlen (dst_root) + strlen (ent->d_name) + 2 >
|
|
||||||
sizeof dst_name)) {
|
src_name = (char *) malloc (src_len);
|
||||||
|
dst_name = (char *) malloc (dst_len);
|
||||||
|
|
||||||
|
if ((NULL == src_name) || (NULL == dst_name)) {
|
||||||
err = -1;
|
err = -1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Build the filename for both the source and
|
* Build the filename for both the source and
|
||||||
* the destination files.
|
* the destination files.
|
||||||
*/
|
*/
|
||||||
snprintf (src_name, sizeof src_name, "%s/%s",
|
snprintf (src_name, src_len, "%s/%s",
|
||||||
src_root, ent->d_name);
|
src_root, ent->d_name);
|
||||||
snprintf (dst_name, sizeof dst_name, "%s/%s",
|
snprintf (dst_name, dst_len, "%s/%s",
|
||||||
dst_root, ent->d_name);
|
dst_root, ent->d_name);
|
||||||
|
|
||||||
err = copy_entry (src_name, dst_name, uid, gid);
|
err = copy_entry (src_name, dst_name, uid, gid);
|
||||||
}
|
}
|
||||||
|
if (NULL != src_name) {
|
||||||
|
free (src_name);
|
||||||
|
}
|
||||||
|
if (NULL != dst_name) {
|
||||||
|
free (dst_name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void) closedir (dir);
|
(void) closedir (dir);
|
||||||
@ -415,6 +422,41 @@ static int copy_dir (const char *src, const char *dst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef S_IFLNK
|
#ifdef S_IFLNK
|
||||||
|
/*
|
||||||
|
* readlink_malloc - wrapper for readlink
|
||||||
|
*
|
||||||
|
* return NULL on error.
|
||||||
|
* The return string shall be freed by the caller.
|
||||||
|
*/
|
||||||
|
char *readlink_malloc (const char *filename)
|
||||||
|
{
|
||||||
|
size_t size = 1024;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
ssize_t nchars;
|
||||||
|
char *buffer = (char *) malloc (size);
|
||||||
|
if (NULL == buffer) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nchars = readlink (filename, buffer, size);
|
||||||
|
|
||||||
|
if (nchars < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (size_t) nchars < size) { /* The buffer was large enough */
|
||||||
|
/* readlink does not nul-terminate */
|
||||||
|
buffer[nchars] = '\0';
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try again with a bigger buffer */
|
||||||
|
free (buffer);
|
||||||
|
size *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* copy_symlink - copy a symlink
|
* copy_symlink - copy a symlink
|
||||||
*
|
*
|
||||||
@ -429,10 +471,7 @@ static int copy_symlink (const char *src, const char *dst,
|
|||||||
const struct stat *statp, const struct timeval mt[],
|
const struct stat *statp, const struct timeval mt[],
|
||||||
long int uid, long int gid)
|
long int uid, long int gid)
|
||||||
{
|
{
|
||||||
char oldlink[PATH_MAX];
|
char *oldlink;
|
||||||
char dummy[PATH_MAX];
|
|
||||||
int len;
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
/* copy_tree () must be the entry point */
|
/* copy_tree () must be the entry point */
|
||||||
assert (NULL != src_orig);
|
assert (NULL != src_orig);
|
||||||
@ -446,17 +485,25 @@ static int copy_symlink (const char *src, const char *dst,
|
|||||||
* destination directory name.
|
* destination directory name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
len = readlink (src, oldlink, sizeof (oldlink) - 1);
|
oldlink = readlink_malloc (src);
|
||||||
if (len < 0) {
|
if (NULL == oldlink) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
oldlink[len] = '\0'; /* readlink() does not NUL-terminate */
|
|
||||||
|
/* If src was a link to an entry of the src_orig directory itself,
|
||||||
|
* create a link to the corresponding entry in the dst_orig
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
|
if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
|
||||||
snprintf (dummy, sizeof dummy, "%s%s",
|
size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
|
||||||
|
char *dummy = (char *) malloc (len);
|
||||||
|
snprintf (dummy, len, "%s%s",
|
||||||
dst_orig,
|
dst_orig,
|
||||||
oldlink + strlen (src_orig));
|
oldlink + strlen (src_orig));
|
||||||
strcpy (oldlink, dummy);
|
free (oldlink);
|
||||||
|
oldlink = dummy;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WITH_SELINUX
|
#ifdef WITH_SELINUX
|
||||||
selinux_file_context (dst);
|
selinux_file_context (dst);
|
||||||
#endif
|
#endif
|
||||||
@ -464,8 +511,10 @@ static int copy_symlink (const char *src, const char *dst,
|
|||||||
|| (lchown (dst,
|
|| (lchown (dst,
|
||||||
(uid == -1) ? statp->st_uid : (uid_t) uid,
|
(uid == -1) ? statp->st_uid : (uid_t) uid,
|
||||||
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
|
(gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
|
||||||
|
free (oldlink);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
free (oldlink);
|
||||||
|
|
||||||
#ifdef HAVE_LUTIMES
|
#ifdef HAVE_LUTIMES
|
||||||
/* 2007-10-18: We don't care about
|
/* 2007-10-18: We don't care about
|
||||||
@ -476,7 +525,7 @@ static int copy_symlink (const char *src, const char *dst,
|
|||||||
lutimes (dst, mt);
|
lutimes (dst, mt);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return err;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -618,7 +667,7 @@ static int copy_file (const char *src, const char *dst,
|
|||||||
|
|
||||||
int remove_tree (const char *root)
|
int remove_tree (const char *root)
|
||||||
{
|
{
|
||||||
char new_name[PATH_MAX];
|
char *new_name = NULL;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
struct DIRECT *ent;
|
struct DIRECT *ent;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
@ -645,6 +694,7 @@ int remove_tree (const char *root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while ((ent = readdir (dir))) {
|
while ((ent = readdir (dir))) {
|
||||||
|
size_t new_len = strlen (root) + strlen (ent->d_name) + 2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip the "." and ".." entries
|
* Skip the "." and ".." entries
|
||||||
@ -659,12 +709,15 @@ int remove_tree (const char *root)
|
|||||||
* Make the filename for the current entry.
|
* Make the filename for the current entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name) {
|
if (NULL != new_name) {
|
||||||
|
free (new_name);
|
||||||
|
}
|
||||||
|
new_name = (char *) malloc (new_len);
|
||||||
|
if (NULL == new_name) {
|
||||||
err = -1;
|
err = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
snprintf (new_name, sizeof new_name, "%s/%s", root,
|
snprintf (new_name, new_len, "%s/%s", root, ent->d_name);
|
||||||
ent->d_name);
|
|
||||||
if (LSTAT (new_name, &sb) == -1) {
|
if (LSTAT (new_name, &sb) == -1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -687,6 +740,9 @@ int remove_tree (const char *root)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (NULL != new_name) {
|
||||||
|
free (new_name);
|
||||||
|
}
|
||||||
(void) closedir (dir);
|
(void) closedir (dir);
|
||||||
|
|
||||||
if (0 == err) {
|
if (0 == err) {
|
||||||
|
@ -434,11 +434,13 @@ int main (int argc, char **argv)
|
|||||||
if (NULL != cp) {
|
if (NULL != cp) {
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
} else {
|
} else {
|
||||||
fprintf (stderr,
|
if (feof (stdin) == 0) {
|
||||||
_("%s: line %d: line too long\n"),
|
fprintf (stderr,
|
||||||
Prog, line);
|
_("%s: line %d: line too long\n"),
|
||||||
errors++;
|
Prog, line);
|
||||||
continue;
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -863,10 +863,13 @@ int main (int argc, char **argv)
|
|||||||
if (NULL != cp) {
|
if (NULL != cp) {
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
} else {
|
} else {
|
||||||
fprintf (stderr, _("%s: line %d: line too long\n"),
|
if (feof (stdin) == 0) {
|
||||||
Prog, line);
|
fprintf (stderr,
|
||||||
errors++;
|
_("%s: line %d: line too long\n"),
|
||||||
continue;
|
Prog, line);
|
||||||
|
errors++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -421,7 +421,7 @@ static int set_defaults (void)
|
|||||||
{
|
{
|
||||||
FILE *ifp;
|
FILE *ifp;
|
||||||
FILE *ofp;
|
FILE *ofp;
|
||||||
char buf[PATH_MAX];
|
char buf[1024];
|
||||||
static char new_file[] = NEW_USER_FILE;
|
static char new_file[] = NEW_USER_FILE;
|
||||||
char *cp;
|
char *cp;
|
||||||
int ofd;
|
int ofd;
|
||||||
@ -468,6 +468,16 @@ static int set_defaults (void)
|
|||||||
cp = strrchr (buf, '\n');
|
cp = strrchr (buf, '\n');
|
||||||
if (NULL != cp) {
|
if (NULL != cp) {
|
||||||
*cp = '\0';
|
*cp = '\0';
|
||||||
|
} else {
|
||||||
|
/* A line which does not end with \n is only valid
|
||||||
|
* at the end of the file.
|
||||||
|
*/
|
||||||
|
if (feof (ifp) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: line too long in %s: %s..."),
|
||||||
|
Prog, def_file, buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!out_group && MATCH (buf, DGROUP)) {
|
if (!out_group && MATCH (buf, DGROUP)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user