2008-04-27 06:10:09 +05:30
|
|
|
/*
|
|
|
|
* Copyright (c) 1990 - 1994, Julianne Frances Haugh
|
|
|
|
* Copyright (c) 1996 - 2001, Marek Michałkiewicz
|
|
|
|
* Copyright (c) 2001 - 2006, Tomasz Kłoczko
|
2011-07-28 20:49:40 +05:30
|
|
|
* Copyright (c) 2007 - 2011, Nicolas François
|
2008-04-27 06:10:09 +05:30
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of the copyright holders or contributors may not be used to
|
|
|
|
* endorse or promote products derived from this software without
|
|
|
|
* specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
2007-11-11 05:16:11 +05:30
|
|
|
#ident "$Id$"
|
2007-10-07 17:17:01 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
#include "defines.h"
|
2009-04-28 01:48:00 +05:30
|
|
|
#include <assert.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <sys/stat.h>
|
2007-10-07 17:17:33 +05:30
|
|
|
#include <stdlib.h>
|
|
|
|
#include <limits.h>
|
2007-10-07 17:14:02 +05:30
|
|
|
#include <utime.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <signal.h>
|
2008-01-05 22:03:43 +05:30
|
|
|
#include "nscd.h"
|
Flush sssd caches in addition to nscd caches
Some distributions, notably Fedora, have the following order of nsswitch
modules by default:
passwd: sss files
group: sss files
The advantage of serving local users through SSSD is that the nss_sss
module has a fast mmapped-cache that speeds up NSS lookups compared to
accessing the disk an opening the files on each NSS request.
Traditionally, this has been done with the help of nscd, but using nscd
in parallel with sssd is cumbersome, as both SSSD and nscd use their own
independent caching, so using nscd in setups where sssd is also serving
users from some remote domain (LDAP, AD, ...) can result in a bit of
unpredictability.
More details about why Fedora chose to use sss before files can be found
on e.g.:
https://fedoraproject.org//wiki/Changes/SSSDCacheForLocalUsers
or:
https://docs.pagure.org/SSSD.sssd/design_pages/files_provider.html
Now, even though sssd watches the passwd and group files with the help
of inotify, there can still be a small window where someone requests a
user or a group, finds that it doesn't exist, adds the entry and checks
again. Without some support in shadow-utils that would explicitly drop
the sssd caches, the inotify watch can fire a little late, so a
combination of commands like this:
getent passwd user || useradd user; getent passwd user
can result in the second getent passwd not finding the newly added user
as the racy behaviour might still return the cached negative hit from
the first getent passwd.
This patch more or less copies the already existing support that
shadow-utils had for dropping nscd caches, except using the "sss_cache"
tool that sssd ships.
2018-09-12 17:52:11 +05:30
|
|
|
#include "sssd.h"
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
#ifdef WITH_TCB
|
|
|
|
#include <tcb.h>
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* WITH_TCB */
|
2009-04-25 05:05:01 +05:30
|
|
|
#include "prototypes.h"
|
2007-10-07 17:14:02 +05:30
|
|
|
#include "commonio.h"
|
|
|
|
|
|
|
|
/* local function prototypes */
|
2007-10-07 17:17:33 +05:30
|
|
|
static int lrename (const char *, const char *);
|
2008-05-26 06:16:25 +05:30
|
|
|
static int check_link_count (const char *file);
|
2011-07-14 19:28:17 +05:30
|
|
|
static int do_lock_file (const char *file, const char *lock, bool log);
|
2009-04-25 18:13:27 +05:30
|
|
|
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
|
|
|
const char *name,
|
|
|
|
const char *mode,
|
|
|
|
const struct stat *sb);
|
2007-10-07 17:16:07 +05:30
|
|
|
static int create_backup (const char *, FILE *);
|
|
|
|
static void free_linked_list (struct commonio_db *);
|
2009-04-25 20:48:49 +05:30
|
|
|
static void add_one_entry (
|
|
|
|
struct commonio_db *db,
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@owned@*/struct commonio_entry *p);
|
2008-05-26 06:16:25 +05:30
|
|
|
static bool name_is_nis (const char *name);
|
2007-10-07 17:16:07 +05:30
|
|
|
static int write_all (const struct commonio_db *);
|
2009-04-25 19:11:52 +05:30
|
|
|
static /*@dependent@*/ /*@null@*/struct commonio_entry *find_entry_by_name (
|
|
|
|
struct commonio_db *,
|
|
|
|
const char *);
|
|
|
|
static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
|
|
|
|
struct commonio_db *,
|
2009-04-25 19:46:22 +05:30
|
|
|
/*@null@*/struct commonio_entry *pos,
|
2009-04-25 19:11:52 +05:30
|
|
|
const char *);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
static int lock_count = 0;
|
2008-05-26 06:16:25 +05:30
|
|
|
static bool nscd_need_reload = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:17:33 +05:30
|
|
|
/*
|
|
|
|
* Simple rename(P) alternative that attempts to rename to symlink
|
|
|
|
* target.
|
|
|
|
*/
|
|
|
|
int lrename (const char *old, const char *new)
|
|
|
|
{
|
|
|
|
int res;
|
2009-05-10 19:19:03 +05:30
|
|
|
char *r = NULL;
|
2007-10-07 17:17:33 +05:30
|
|
|
|
|
|
|
#if defined(S_ISLNK)
|
2009-05-10 19:19:03 +05:30
|
|
|
#ifndef __GLIBC__
|
|
|
|
char resolved_path[PATH_MAX];
|
|
|
|
#endif /* !__GLIBC__ */
|
2007-11-20 01:55:36 +05:30
|
|
|
struct stat sb;
|
2007-10-07 17:17:33 +05:30
|
|
|
if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
|
2009-05-10 19:19:03 +05:30
|
|
|
#ifdef __GLIBC__ /* now a POSIX.1-2008 feature */
|
|
|
|
r = realpath (new, NULL);
|
|
|
|
#else /* !__GLIBC__ */
|
|
|
|
r = realpath (new, resolved_path);
|
|
|
|
#endif /* !__GLIBC__ */
|
|
|
|
if (NULL == r) {
|
2007-10-07 17:17:33 +05:30
|
|
|
perror ("realpath in lrename()");
|
|
|
|
} else {
|
2009-05-10 19:19:03 +05:30
|
|
|
new = r;
|
2007-10-07 17:17:33 +05:30
|
|
|
}
|
|
|
|
}
|
2009-05-10 19:19:03 +05:30
|
|
|
#endif /* S_ISLNK */
|
|
|
|
|
2007-10-07 17:17:33 +05:30
|
|
|
res = rename (old, new);
|
2009-05-10 19:19:03 +05:30
|
|
|
|
|
|
|
#ifdef __GLIBC__
|
|
|
|
if (NULL != r) {
|
|
|
|
free (r);
|
|
|
|
}
|
|
|
|
#endif /* __GLIBC__ */
|
|
|
|
|
2007-10-07 17:17:33 +05:30
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
static int check_link_count (const char *file)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (stat (file, &sb) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (sb.st_nlink != 2) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-14 19:28:17 +05:30
|
|
|
static int do_lock_file (const char *file, const char *lock, bool log)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
int fd;
|
2008-05-26 06:16:25 +05:30
|
|
|
pid_t pid;
|
2008-06-14 03:23:41 +05:30
|
|
|
ssize_t len;
|
2007-10-07 17:14:02 +05:30
|
|
|
int retval;
|
|
|
|
char buf[32];
|
|
|
|
|
2019-05-02 18:09:01 +05:30
|
|
|
fd = open (file, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (-1 == fd) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: %s: %s\n",
|
|
|
|
Prog, file, strerror (errno));
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
pid = getpid ();
|
2008-05-26 06:16:25 +05:30
|
|
|
snprintf (buf, sizeof buf, "%lu", (unsigned long) pid);
|
2008-06-14 03:23:41 +05:30
|
|
|
len = (ssize_t) strlen (buf) + 1;
|
|
|
|
if (write (fd, buf, (size_t) len) != len) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
2020-11-02 21:38:55 +05:30
|
|
|
"%s: %s file write error: %s\n",
|
|
|
|
Prog, file, strerror (errno));
|
|
|
|
}
|
|
|
|
(void) close (fd);
|
|
|
|
unlink (file);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (fdatasync (fd) == -1) {
|
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: %s file sync error: %s\n",
|
2011-07-14 19:28:17 +05:30
|
|
|
Prog, file, strerror (errno));
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
(void) close (fd);
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
close (fd);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
if (link (file, lock) == 0) {
|
|
|
|
retval = check_link_count (file);
|
2011-07-14 19:28:17 +05:30
|
|
|
if ((0==retval) && log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: %s: lock file already used\n",
|
|
|
|
Prog, file);
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
fd = open (lock, O_RDWR);
|
|
|
|
if (-1 == fd) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: %s: %s\n",
|
|
|
|
Prog, lock, strerror (errno));
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
len = read (fd, buf, sizeof (buf) - 1);
|
|
|
|
close (fd);
|
2007-10-07 17:14:02 +05:30
|
|
|
if (len <= 0) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: existing lock file %s without a PID\n",
|
|
|
|
Prog, lock);
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
buf[len] = '\0';
|
2009-04-25 05:05:01 +05:30
|
|
|
if (get_pid (buf, &pid) == 0) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: existing lock file %s with an invalid PID '%s'\n",
|
|
|
|
Prog, lock, buf);
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
if (kill (pid, 0) == 0) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
2011-07-30 07:18:42 +05:30
|
|
|
"%s: lock %s already used by PID %lu\n",
|
|
|
|
Prog, lock, (unsigned long) pid);
|
2011-07-14 19:28:17 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = EEXIST;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
if (unlink (lock) != 0) {
|
2011-07-14 19:28:17 +05:30
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: cannot get lock %s: %s\n",
|
|
|
|
Prog, lock, strerror (errno));
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
retval = 0;
|
2011-07-14 19:28:17 +05:30
|
|
|
if (link (file, lock) == 0) {
|
|
|
|
retval = check_link_count (file);
|
|
|
|
if ((0==retval) && log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: %s: lock file already used\n",
|
|
|
|
Prog, file);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (log) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: cannot get lock %s: %s\n",
|
|
|
|
Prog, lock, strerror (errno));
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (file);
|
2007-10-07 17:14:02 +05:30
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-25 18:13:27 +05:30
|
|
|
static /*@null@*/ /*@dependent@*/FILE *fopen_set_perms (
|
|
|
|
const char *name,
|
|
|
|
const char *mode,
|
|
|
|
const struct stat *sb)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
mode_t mask;
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
mask = umask (0777);
|
|
|
|
fp = fopen (name, mode);
|
2008-09-13 17:25:50 +05:30
|
|
|
(void) umask (mask);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == fp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return NULL;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#ifdef HAVE_FCHOWN
|
2008-06-11 01:57:16 +05:30
|
|
|
if (fchown (fileno (fp), sb->st_uid, sb->st_gid) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#else /* !HAVE_FCHOWN */
|
2008-06-11 01:57:16 +05:30
|
|
|
if (chown (name, sb->st_mode) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* !HAVE_FCHOWN */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#ifdef HAVE_FCHMOD
|
2008-06-11 01:57:16 +05:30
|
|
|
if (fchmod (fileno (fp), sb->st_mode & 0664) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#else /* !HAVE_FCHMOD */
|
2008-06-11 01:57:16 +05:30
|
|
|
if (chmod (name, sb->st_mode & 0664) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* !HAVE_FCHMOD */
|
2007-10-07 17:14:02 +05:30
|
|
|
return fp;
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
fail:
|
2009-05-01 03:23:54 +05:30
|
|
|
(void) fclose (fp);
|
|
|
|
/* fopen_set_perms is used for intermediate files */
|
|
|
|
(void) unlink (name);
|
2007-10-07 17:14:02 +05:30
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
static int create_backup (const char *backup, FILE * fp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct stat sb;
|
|
|
|
struct utimbuf ub;
|
|
|
|
FILE *bkfp;
|
|
|
|
int c;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (fstat (fileno (fp), &sb) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2016-11-15 20:34:24 +05:30
|
|
|
bkfp = fopen_set_perms (backup, "w", &sb);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == bkfp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/* TODO: faster copy, not one-char-at-a-time. --marekm */
|
2007-10-07 17:15:40 +05:30
|
|
|
c = 0;
|
2008-05-26 06:16:25 +05:30
|
|
|
if (fseek (fp, 0, SEEK_SET) == 0) {
|
2007-10-07 17:16:07 +05:30
|
|
|
while ((c = getc (fp)) != EOF) {
|
2008-06-11 01:57:16 +05:30
|
|
|
if (putc (c, bkfp) == EOF) {
|
2007-10-07 17:15:40 +05:30
|
|
|
break;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:15:40 +05:30
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
|
|
|
if ((c != EOF) || (ferror (fp) != 0) || (fflush (bkfp) != 0)) {
|
2009-05-01 03:23:54 +05:30
|
|
|
(void) fclose (bkfp);
|
|
|
|
/* FIXME: unlink the backup file? */
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
|
|
|
}
|
2009-03-22 00:42:00 +05:30
|
|
|
if ( (fsync (fileno (bkfp)) != 0)
|
|
|
|
|| (fclose (bkfp) != 0)) {
|
2009-05-01 03:23:54 +05:30
|
|
|
/* FIXME: unlink the backup file? */
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
ub.actime = sb.st_atime;
|
|
|
|
ub.modtime = sb.st_mtime;
|
2008-05-26 06:16:25 +05:30
|
|
|
(void) utime (backup, &ub);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
static void free_linked_list (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
while (NULL != db->head) {
|
2007-10-07 17:14:02 +05:30
|
|
|
p = db->head;
|
|
|
|
db->head = p->next;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (NULL != p->line) {
|
2007-10-07 17:16:07 +05:30
|
|
|
free (p->line);
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (NULL != p->eptr) {
|
2007-10-07 17:16:07 +05:30
|
|
|
db->ops->free (p->eptr);
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
free (p);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
db->tail = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_setname (struct commonio_db *db, const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:16:07 +05:30
|
|
|
snprintf (db->filename, sizeof (db->filename), "%s", name);
|
2019-05-02 18:03:06 +05:30
|
|
|
db->setname = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
bool commonio_present (const struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:16:07 +05:30
|
|
|
return (access (db->filename, F_OK) == 0);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-07-14 19:28:17 +05:30
|
|
|
int commonio_lock_nowait (struct commonio_db *db, bool log)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2018-03-29 00:44:12 +05:30
|
|
|
char* file = NULL;
|
|
|
|
char* lock = NULL;
|
2016-05-15 19:19:39 +05:30
|
|
|
size_t lock_file_len;
|
|
|
|
size_t file_len;
|
2018-10-10 15:52:04 +05:30
|
|
|
int err = 0;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (db->locked) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2016-05-15 19:19:39 +05:30
|
|
|
file_len = strlen(db->filename) + 11;/* %lu max size */
|
|
|
|
lock_file_len = strlen(db->filename) + 6; /* sizeof ".lock" */
|
|
|
|
file = (char*)malloc(file_len);
|
2018-03-29 00:44:12 +05:30
|
|
|
if(file == NULL) {
|
|
|
|
goto cleanup_ENOMEM;
|
|
|
|
}
|
2016-05-15 19:19:39 +05:30
|
|
|
lock = (char*)malloc(lock_file_len);
|
2018-03-29 00:44:12 +05:30
|
|
|
if(lock == NULL) {
|
|
|
|
goto cleanup_ENOMEM;
|
|
|
|
}
|
2016-05-15 19:19:39 +05:30
|
|
|
snprintf (file, file_len, "%s.%lu",
|
2008-05-26 06:16:25 +05:30
|
|
|
db->filename, (unsigned long) getpid ());
|
2016-05-15 19:19:39 +05:30
|
|
|
snprintf (lock, lock_file_len, "%s.lock", db->filename);
|
2011-07-14 19:28:17 +05:30
|
|
|
if (do_lock_file (file, lock, log) != 0) {
|
2008-05-26 06:16:25 +05:30
|
|
|
db->locked = true;
|
2007-10-07 17:14:32 +05:30
|
|
|
lock_count++;
|
2018-03-29 00:44:12 +05:30
|
|
|
err = 1;
|
|
|
|
}
|
|
|
|
cleanup_ENOMEM:
|
|
|
|
if(file)
|
2016-05-15 19:19:39 +05:30
|
|
|
free(file);
|
2018-03-29 00:44:12 +05:30
|
|
|
if(lock)
|
2016-05-15 19:19:39 +05:30
|
|
|
free(lock);
|
2018-03-29 00:44:12 +05:30
|
|
|
return err;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_lock (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2019-05-02 18:03:06 +05:30
|
|
|
int i;
|
2007-10-07 17:14:32 +05:30
|
|
|
|
2019-05-02 18:03:06 +05:30
|
|
|
#ifdef HAVE_LCKPWDF
|
2007-10-07 17:14:32 +05:30
|
|
|
/*
|
2019-05-02 18:03:06 +05:30
|
|
|
* Only if the system libc has a real lckpwdf() - the one from
|
|
|
|
* lockpw.c calls us and would cause infinite recursion!
|
|
|
|
* It is also not used with the prefix option.
|
2007-10-07 17:14:32 +05:30
|
|
|
*/
|
2019-05-02 18:03:06 +05:30
|
|
|
if (!db->setname) {
|
|
|
|
/*
|
|
|
|
* Call lckpwdf() on the first lock.
|
|
|
|
* If it succeeds, call *_lock() only once
|
|
|
|
* (no retries, it should always succeed).
|
|
|
|
*/
|
|
|
|
if (0 == lock_count) {
|
|
|
|
if (lckpwdf () == -1) {
|
|
|
|
if (geteuid () != 0) {
|
|
|
|
(void) fprintf (stderr,
|
|
|
|
"%s: Permission denied.\n",
|
|
|
|
Prog);
|
|
|
|
}
|
|
|
|
return 0; /* failure */
|
2011-07-14 19:28:17 +05:30
|
|
|
}
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:32 +05:30
|
|
|
|
2019-05-02 18:03:06 +05:30
|
|
|
if (commonio_lock_nowait (db, true) != 0) {
|
|
|
|
return 1; /* success */
|
|
|
|
}
|
2007-10-07 17:14:32 +05:30
|
|
|
|
2019-05-02 18:03:06 +05:30
|
|
|
ulckpwdf ();
|
|
|
|
return 0; /* failure */
|
|
|
|
}
|
|
|
|
#endif /* !HAVE_LCKPWDF */
|
2007-10-07 17:14:32 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* lckpwdf() not used - do it the old way.
|
|
|
|
*/
|
|
|
|
#ifndef LOCK_TRIES
|
|
|
|
#define LOCK_TRIES 15
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef LOCK_SLEEP
|
|
|
|
#define LOCK_SLEEP 1
|
|
|
|
#endif
|
|
|
|
for (i = 0; i < LOCK_TRIES; i++) {
|
2008-06-11 01:57:16 +05:30
|
|
|
if (i > 0) {
|
2007-10-07 17:16:07 +05:30
|
|
|
sleep (LOCK_SLEEP); /* delay between retries */
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2011-07-14 19:28:17 +05:30
|
|
|
if (commonio_lock_nowait (db, i==LOCK_TRIES-1) != 0) {
|
2007-10-07 17:16:07 +05:30
|
|
|
return 1; /* success */
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
/* no unnecessary retries on "permission denied" errors */
|
2008-05-26 06:16:25 +05:30
|
|
|
if (geteuid () != 0) {
|
2011-07-14 19:28:17 +05:30
|
|
|
(void) fprintf (stderr, "%s: Permission denied.\n",
|
|
|
|
Prog);
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
return 0; /* failure */
|
2007-10-07 17:14:32 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
static void dec_lock_count (void)
|
2007-10-07 17:14:32 +05:30
|
|
|
{
|
|
|
|
if (lock_count > 0) {
|
|
|
|
lock_count--;
|
|
|
|
if (lock_count == 0) {
|
|
|
|
/* Tell nscd when lock count goes to zero,
|
|
|
|
if any of the files were changed. */
|
|
|
|
if (nscd_need_reload) {
|
2007-10-07 17:16:07 +05:30
|
|
|
nscd_flush_cache ("passwd");
|
|
|
|
nscd_flush_cache ("group");
|
Flush sssd caches in addition to nscd caches
Some distributions, notably Fedora, have the following order of nsswitch
modules by default:
passwd: sss files
group: sss files
The advantage of serving local users through SSSD is that the nss_sss
module has a fast mmapped-cache that speeds up NSS lookups compared to
accessing the disk an opening the files on each NSS request.
Traditionally, this has been done with the help of nscd, but using nscd
in parallel with sssd is cumbersome, as both SSSD and nscd use their own
independent caching, so using nscd in setups where sssd is also serving
users from some remote domain (LDAP, AD, ...) can result in a bit of
unpredictability.
More details about why Fedora chose to use sss before files can be found
on e.g.:
https://fedoraproject.org//wiki/Changes/SSSDCacheForLocalUsers
or:
https://docs.pagure.org/SSSD.sssd/design_pages/files_provider.html
Now, even though sssd watches the passwd and group files with the help
of inotify, there can still be a small window where someone requests a
user or a group, finds that it doesn't exist, adds the entry and checks
again. Without some support in shadow-utils that would explicitly drop
the sssd caches, the inotify watch can fire a little late, so a
combination of commands like this:
getent passwd user || useradd user; getent passwd user
can result in the second getent passwd not finding the newly added user
as the racy behaviour might still return the cached negative hit from
the first getent passwd.
This patch more or less copies the already existing support that
shadow-utils had for dropping nscd caches, except using the "sss_cache"
tool that sssd ships.
2018-09-12 17:52:11 +05:30
|
|
|
sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);
|
2008-05-26 06:16:25 +05:30
|
|
|
nscd_need_reload = false;
|
2007-10-07 17:14:32 +05:30
|
|
|
}
|
|
|
|
#ifdef HAVE_LCKPWDF
|
2007-10-07 17:16:07 +05:30
|
|
|
ulckpwdf ();
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* HAVE_LCKPWDF */
|
2007-10-07 17:14:32 +05:30
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_unlock (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
char lock[1024];
|
|
|
|
|
|
|
|
if (db->isopen) {
|
2008-05-26 06:16:25 +05:30
|
|
|
db->readonly = true;
|
|
|
|
if (commonio_close (db) == 0) {
|
2008-06-11 01:57:16 +05:30
|
|
|
if (db->locked) {
|
2007-10-07 17:16:07 +05:30
|
|
|
dec_lock_count ();
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
2007-10-07 17:14:32 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
if (db->locked) {
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* Unlock in reverse order: remove the lock file,
|
|
|
|
* then call ulckpwdf() (if used) on last unlock.
|
|
|
|
*/
|
2008-05-26 06:16:25 +05:30
|
|
|
db->locked = false;
|
2007-10-07 17:16:07 +05:30
|
|
|
snprintf (lock, sizeof lock, "%s.lock", db->filename);
|
|
|
|
unlink (lock);
|
|
|
|
dec_lock_count ();
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-26 22:18:51 +05:30
|
|
|
/*
|
|
|
|
* Add an entry at the end.
|
|
|
|
*
|
|
|
|
* defines p->next, p->prev
|
|
|
|
* (unfortunately, owned special are not supported)
|
|
|
|
*/
|
2009-04-25 20:48:49 +05:30
|
|
|
static void add_one_entry (struct commonio_db *db,
|
|
|
|
/*@owned@*/struct commonio_entry *p)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@-mustfreeonly@*/
|
2007-10-07 17:14:02 +05:30
|
|
|
p->next = NULL;
|
|
|
|
p->prev = db->tail;
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@=mustfreeonly@*/
|
2008-06-11 01:57:16 +05:30
|
|
|
if (NULL == db->head) {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->head = p;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
|
|
|
if (NULL != db->tail) {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->tail->next = p;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
db->tail = p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
static bool name_is_nis (const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2008-06-11 01:57:16 +05:30
|
|
|
return (('+' == name[0]) || ('-' == name[0]));
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* New entries are inserted before the first NIS entry. Order is preserved
|
|
|
|
* when db is written out.
|
|
|
|
*/
|
|
|
|
#ifndef KEEP_NIS_AT_END
|
|
|
|
#define KEEP_NIS_AT_END 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KEEP_NIS_AT_END
|
2009-04-25 20:48:49 +05:30
|
|
|
static void add_one_entry_nis (struct commonio_db *db,
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@owned@*/struct commonio_entry *newp);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* Insert an entry between the regular entries, and the NIS entries.
|
2009-04-26 22:18:51 +05:30
|
|
|
*
|
|
|
|
* defines newp->next, newp->prev
|
|
|
|
* (unfortunately, owned special are not supported)
|
2008-01-02 02:04:47 +05:30
|
|
|
*/
|
2009-04-25 20:48:49 +05:30
|
|
|
static void add_one_entry_nis (struct commonio_db *db,
|
|
|
|
/*@owned@*/struct commonio_entry *newp)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
for (p = db->head; NULL != p; p = p->next) {
|
2008-06-11 01:57:16 +05:30
|
|
|
if (name_is_nis (p->eptr ? db->ops->getname (p->eptr)
|
|
|
|
: p->line)) {
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@-mustfreeonly@*/
|
2007-10-07 17:14:14 +05:30
|
|
|
newp->next = p;
|
|
|
|
newp->prev = p->prev;
|
2009-04-26 22:18:51 +05:30
|
|
|
/*@=mustfreeonly@*/
|
2008-06-11 01:57:16 +05:30
|
|
|
if (NULL != p->prev) {
|
2007-10-07 17:14:14 +05:30
|
|
|
p->prev->next = newp;
|
2008-06-11 01:57:16 +05:30
|
|
|
} else {
|
2007-10-07 17:14:14 +05:30
|
|
|
db->head = newp;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:14:14 +05:30
|
|
|
p->prev = newp;
|
2007-10-07 17:14:02 +05:30
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
add_one_entry (db, newp);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
#endif /* KEEP_NIS_AT_END */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:32 +05:30
|
|
|
/* Initial buffer size, as well as increment if not sufficient
|
|
|
|
(for reading very long lines in group files). */
|
|
|
|
#define BUFLEN 4096
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_open (struct commonio_db *db, int mode)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:14:32 +05:30
|
|
|
char *buf;
|
|
|
|
char *cp;
|
2007-10-07 17:14:02 +05:30
|
|
|
char *line;
|
|
|
|
struct commonio_entry *p;
|
2009-04-25 18:13:27 +05:30
|
|
|
void *eptr = NULL;
|
2007-10-07 17:14:02 +05:30
|
|
|
int flags = mode;
|
2009-04-25 18:13:27 +05:30
|
|
|
size_t buflen;
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
int fd;
|
2007-10-07 17:15:40 +05:30
|
|
|
int saved_errno;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
mode &= ~O_CREAT;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if ( db->isopen
|
|
|
|
|| ( (O_RDONLY != mode)
|
|
|
|
&& (O_RDWR != mode))) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
db->readonly = (mode == O_RDONLY);
|
|
|
|
if (!db->readonly && !db->locked) {
|
|
|
|
errno = EACCES;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-11-20 03:30:00 +05:30
|
|
|
db->head = NULL;
|
|
|
|
db->tail = NULL;
|
2009-04-25 19:46:22 +05:30
|
|
|
db->cursor = NULL;
|
2008-05-26 06:16:25 +05:30
|
|
|
db->changed = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2010-03-12 03:34:14 +05:30
|
|
|
fd = open (db->filename,
|
|
|
|
(db->readonly ? O_RDONLY : O_RDWR)
|
|
|
|
| O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
saved_errno = errno;
|
|
|
|
db->fp = NULL;
|
|
|
|
if (fd >= 0) {
|
|
|
|
#ifdef WITH_TCB
|
2010-03-12 03:34:14 +05:30
|
|
|
if (tcb_is_suspect (fd) != 0) {
|
2010-03-18 05:30:05 +05:30
|
|
|
(void) close (fd);
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* WITH_TCB */
|
|
|
|
db->fp = fdopen (fd, db->readonly ? "r" : "r+");
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
saved_errno = errno;
|
2010-03-18 05:29:47 +05:30
|
|
|
if (NULL == db->fp) {
|
|
|
|
(void) close (fd);
|
2010-03-12 03:34:14 +05:30
|
|
|
}
|
2010-01-30 Paweł Hajdan, Jr. <phajdan.jr@gentoo.org>
* NEWS: Add support for TCB.
* lib/tcbfuncs.h, lib/tcbfuncs.c, lib/Makefile.am: New library to
support TCB.
* lib/prototypes, libmisc/copydir.c (remove_tree): Add boolean
parameter remove_root.
* configure.in: Add conditional WITH_TCB.
* src/userdel.c, src/usermod.c: Add support for TCB. Update call to
remove_tree().
* src/pwconv.c, src/pwunconv.c: Should not be used with TCB enabled.
* src/vipw.c: Add support for TCB. Update call to remove_tree().
* src/useradd.c: Add support for TCB. Open the shadow file outside
of open_files().
* src/chage.c: Add support for TCB.
* src/Makefile.am: Install passwd sgid shadow when TCB is enabled.
* lib/getdefs.c, man/vipw.8.xml, man/login.defs.5.xml,
man/login.defs/TCB_AUTH_GROUP.xml, man/login.defs/USE_TCB.xml,
man/login.defs/TCB_SYMLINKS.xml, man/generate_mans.mak,
man/generate_mans.deps, man/Makefile.am: New configuration
parameters: TCB_AUTH_GROUP, TCB_SYMLINKS, USE_TCB.
* lib/shadowio.c, lib/commonio.c: Add support for TCB.
2010-03-04 23:41:13 +05:30
|
|
|
}
|
|
|
|
errno = saved_errno;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
/*
|
|
|
|
* If O_CREAT was specified and the file didn't exist, it will be
|
|
|
|
* created by commonio_close(). We have no entries to read yet. --marekm
|
|
|
|
*/
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == db->fp) {
|
2008-06-11 01:57:16 +05:30
|
|
|
if (((flags & O_CREAT) != 0) && (ENOENT == errno)) {
|
2008-05-26 06:16:25 +05:30
|
|
|
db->isopen = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2007-11-17 19:34:05 +05:30
|
|
|
|
|
|
|
/* Do not inherit fd in spawned processes (e.g. nscd) */
|
2010-03-12 03:34:14 +05:30
|
|
|
fcntl (fileno (db->fp), F_SETFD, FD_CLOEXEC);
|
2007-11-17 19:34:05 +05:30
|
|
|
|
2007-10-07 17:14:32 +05:30
|
|
|
buflen = BUFLEN;
|
2007-10-07 17:16:07 +05:30
|
|
|
buf = (char *) malloc (buflen);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == buf) {
|
2007-10-07 17:15:40 +05:30
|
|
|
goto cleanup_ENOMEM;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:32 +05:30
|
|
|
|
2009-04-25 18:13:27 +05:30
|
|
|
while (db->ops->fgets (buf, (int) buflen, db->fp) == buf) {
|
2008-06-11 01:57:16 +05:30
|
|
|
while ( ((cp = strrchr (buf, '\n')) == NULL)
|
|
|
|
&& (feof (db->fp) == 0)) {
|
2009-04-25 18:13:27 +05:30
|
|
|
size_t len;
|
2007-10-07 17:14:51 +05:30
|
|
|
|
2007-10-07 17:14:32 +05:30
|
|
|
buflen += BUFLEN;
|
2007-10-07 17:16:07 +05:30
|
|
|
cp = (char *) realloc (buf, buflen);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == cp) {
|
2007-10-07 17:14:32 +05:30
|
|
|
goto cleanup_buf;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:32 +05:30
|
|
|
buf = cp;
|
2007-10-07 17:16:07 +05:30
|
|
|
len = strlen (buf);
|
2009-04-25 18:13:27 +05:30
|
|
|
if (db->ops->fgets (buf + len,
|
|
|
|
(int) (buflen - len),
|
|
|
|
db->fp) == NULL) {
|
2008-06-11 01:57:16 +05:30
|
|
|
goto cleanup_buf;
|
|
|
|
}
|
2007-10-07 17:14:32 +05:30
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
cp = strrchr (buf, '\n');
|
|
|
|
if (NULL != cp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
*cp = '\0';
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
line = strdup (buf);
|
|
|
|
if (NULL == line) {
|
2007-10-07 17:14:32 +05:30
|
|
|
goto cleanup_buf;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
if (name_is_nis (line)) {
|
2007-10-07 17:14:14 +05:30
|
|
|
eptr = NULL;
|
2008-05-26 06:16:25 +05:30
|
|
|
} else {
|
|
|
|
eptr = db->ops->parse (line);
|
|
|
|
if (NULL != eptr) {
|
|
|
|
eptr = db->ops->dup (eptr);
|
|
|
|
if (NULL == eptr) {
|
|
|
|
goto cleanup_line;
|
|
|
|
}
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
p = (struct commonio_entry *) malloc (sizeof *p);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == p) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto cleanup_entry;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:14:14 +05:30
|
|
|
p->eptr = eptr;
|
2007-10-07 17:14:02 +05:30
|
|
|
p->line = line;
|
2008-05-26 06:16:25 +05:30
|
|
|
p->changed = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
add_one_entry (db, p);
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
free (buf);
|
2007-10-07 17:15:40 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (ferror (db->fp) != 0) {
|
2007-10-07 17:15:40 +05:30
|
|
|
goto cleanup_errno;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:15:40 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if ((NULL != db->ops->open_hook) && (db->ops->open_hook () == 0)) {
|
2007-11-23 05:37:59 +05:30
|
|
|
goto cleanup_errno;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-11-23 05:37:59 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
db->isopen = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
cleanup_entry:
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != eptr) {
|
2007-10-07 17:16:07 +05:30
|
|
|
db->ops->free (eptr);
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
cleanup_line:
|
|
|
|
free (line);
|
|
|
|
cleanup_buf:
|
|
|
|
free (buf);
|
|
|
|
cleanup_ENOMEM:
|
2007-10-07 17:15:40 +05:30
|
|
|
errno = ENOMEM;
|
2007-10-07 17:16:07 +05:30
|
|
|
cleanup_errno:
|
2007-10-07 17:15:40 +05:30
|
|
|
saved_errno = errno;
|
2007-10-07 17:16:07 +05:30
|
|
|
free_linked_list (db);
|
|
|
|
fclose (db->fp);
|
2007-10-07 17:14:02 +05:30
|
|
|
db->fp = NULL;
|
2007-10-07 17:15:40 +05:30
|
|
|
errno = saved_errno;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:51 +05:30
|
|
|
/*
|
|
|
|
* Sort given db according to cmp function (usually compares uids)
|
|
|
|
*/
|
|
|
|
int
|
2007-10-07 17:16:07 +05:30
|
|
|
commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
|
2007-10-07 17:14:51 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry **entries, *ptr;
|
2009-04-25 05:05:01 +05:30
|
|
|
size_t n = 0, i;
|
2010-03-19 04:51:21 +05:30
|
|
|
#if KEEP_NIS_AT_END
|
2010-03-19 16:31:32 +05:30
|
|
|
struct commonio_entry *nis = NULL;
|
2010-03-19 04:51:21 +05:30
|
|
|
#endif
|
2007-10-07 17:14:51 +05:30
|
|
|
|
2010-03-19 04:51:21 +05:30
|
|
|
for (ptr = db->head;
|
|
|
|
(NULL != ptr)
|
|
|
|
#if KEEP_NIS_AT_END
|
2017-03-31 19:55:06 +05:30
|
|
|
&& ((NULL == ptr->line)
|
|
|
|
|| (('+' != ptr->line[0])
|
|
|
|
&& ('-' != ptr->line[0])))
|
2010-03-19 04:51:21 +05:30
|
|
|
#endif
|
|
|
|
;
|
|
|
|
ptr = ptr->next) {
|
2007-10-07 17:14:51 +05:30
|
|
|
n++;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2010-03-19 04:51:21 +05:30
|
|
|
#if KEEP_NIS_AT_END
|
2017-03-31 19:55:06 +05:30
|
|
|
if (NULL != ptr) {
|
2010-03-19 04:51:21 +05:30
|
|
|
nis = ptr;
|
|
|
|
}
|
|
|
|
#endif
|
2007-10-07 17:14:51 +05:30
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (n <= 1) {
|
2007-10-07 17:14:51 +05:30
|
|
|
return 0;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
|
|
|
|
entries = malloc (n * sizeof (struct commonio_entry *));
|
2008-06-11 01:57:16 +05:30
|
|
|
if (entries == NULL) {
|
2007-10-07 17:14:51 +05:30
|
|
|
return -1;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2007-10-07 17:14:51 +05:30
|
|
|
n = 0;
|
2010-03-19 04:51:21 +05:30
|
|
|
for (ptr = db->head;
|
|
|
|
#if KEEP_NIS_AT_END
|
|
|
|
nis != ptr;
|
|
|
|
#else
|
|
|
|
NULL != ptr;
|
|
|
|
#endif
|
2010-08-21 02:04:44 +05:30
|
|
|
/*@ -nullderef @*/
|
|
|
|
ptr = ptr->next
|
|
|
|
/*@ +nullderef @*/
|
|
|
|
) {
|
2010-08-20 23:39:14 +05:30
|
|
|
entries[n] = ptr;
|
|
|
|
n++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
qsort (entries, n, sizeof (struct commonio_entry *), cmp);
|
|
|
|
|
2009-09-09 02:30:12 +05:30
|
|
|
/* Take care of the head and tail separately */
|
2007-10-07 17:14:51 +05:30
|
|
|
db->head = entries[0];
|
2009-09-09 02:30:12 +05:30
|
|
|
n--;
|
2010-03-19 04:51:21 +05:30
|
|
|
#if KEEP_NIS_AT_END
|
|
|
|
if (NULL == nis)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
db->tail = entries[n];
|
|
|
|
}
|
2007-10-07 17:14:51 +05:30
|
|
|
db->head->prev = NULL;
|
|
|
|
db->head->next = entries[1];
|
2010-03-19 04:51:21 +05:30
|
|
|
entries[n]->prev = entries[n - 1];
|
2011-07-14 19:28:17 +05:30
|
|
|
#if KEEP_NIS_AT_END
|
|
|
|
entries[n]->next = nis;
|
|
|
|
#else
|
2010-03-19 04:51:21 +05:30
|
|
|
entries[n]->next = NULL;
|
2011-07-14 19:28:17 +05:30
|
|
|
#endif
|
2007-10-07 17:14:51 +05:30
|
|
|
|
2009-09-09 02:30:12 +05:30
|
|
|
/* Now other elements have prev and next entries */
|
2007-10-07 17:14:51 +05:30
|
|
|
for (i = 1; i < n; i++) {
|
2007-10-07 17:16:07 +05:30
|
|
|
entries[i]->prev = entries[i - 1];
|
|
|
|
entries[i]->next = entries[i + 1];
|
2007-10-07 17:14:51 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
free (entries);
|
2008-05-26 06:16:25 +05:30
|
|
|
db->changed = true;
|
2007-10-07 17:14:51 +05:30
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Sort entries in db according to order in another.
|
|
|
|
*/
|
* libmisc/console.c, libmisc/motd.c, libmisc/setupenv.c,
libmisc/sulog.c, libmisc/hushed.c, libmisc/failure.c,
libmisc/loginprompt.c, libmisc/ttytype.c,
libmisc/pam_pass_non_interractive.c, src/userdel.c, src/login.c,
lib/commonio.c, lib/commonio.h: Fix some const issues.
* libmisc/motd.c: Avoid multi-statements lines.
* libmisc/motd.c: Support long MOTD_FILE.
* libmisc/list.c, lib/prototypes.h: Revert previous change.
dup_list and is_on_list are used with members as defined for the
group structure, and thus even if the list is not modified, the
list elements cannot be constant strings.
* libmisc/system.c: Avoid C++ comments.
* src/vipw.c: WITH_TCB cannot be tested inside a gettextized
string. Split the Usage string.
* lib/commonio.h: Re-indent.
2010-08-21 21:02:53 +05:30
|
|
|
int commonio_sort_wrt (struct commonio_db *shadow,
|
|
|
|
const struct commonio_db *passwd)
|
2007-10-07 17:14:51 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr;
|
|
|
|
const char *name;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if ((NULL == shadow) || (NULL == shadow->head)) {
|
2007-10-07 17:17:11 +05:30
|
|
|
return 0;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-10-07 17:17:11 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
for (pw_ptr = passwd->head; NULL != pw_ptr; pw_ptr = pw_ptr->next) {
|
|
|
|
if (NULL == pw_ptr->eptr) {
|
2007-10-07 17:14:59 +05:30
|
|
|
continue;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
name = passwd->ops->getname (pw_ptr->eptr);
|
2008-05-26 06:16:25 +05:30
|
|
|
for (spw_ptr = shadow->head;
|
|
|
|
NULL != spw_ptr;
|
|
|
|
spw_ptr = spw_ptr->next) {
|
2009-04-25 19:11:52 +05:30
|
|
|
if (NULL == spw_ptr->eptr) {
|
|
|
|
continue;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
if (strcmp (name, shadow->ops->getname (spw_ptr->eptr))
|
2008-05-26 06:16:25 +05:30
|
|
|
== 0) {
|
2007-10-07 17:14:51 +05:30
|
|
|
break;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
if (NULL == spw_ptr) {
|
2007-10-07 17:14:51 +05:30
|
|
|
continue;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
commonio_del_entry (shadow, spw_ptr);
|
2007-10-07 17:14:51 +05:30
|
|
|
spw_ptr->next = head;
|
|
|
|
head = spw_ptr;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
for (spw_ptr = head; NULL != spw_ptr; spw_ptr = head) {
|
2007-10-07 17:14:51 +05:30
|
|
|
head = head->next;
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != shadow->head) {
|
2007-10-07 17:14:51 +05:30
|
|
|
shadow->head->prev = spw_ptr;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:51 +05:30
|
|
|
spw_ptr->next = shadow->head;
|
|
|
|
shadow->head = spw_ptr;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
|
2007-10-07 17:14:51 +05:30
|
|
|
shadow->head->prev = NULL;
|
2008-05-26 06:16:25 +05:30
|
|
|
shadow->changed = true;
|
2007-10-07 17:14:51 +05:30
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* write_all - Write the database to its file.
|
|
|
|
*
|
2008-05-26 06:16:25 +05:30
|
|
|
* It returns 0 if all the entries could be written correctly.
|
2008-01-02 02:04:47 +05:30
|
|
|
*/
|
2007-10-07 17:16:07 +05:30
|
|
|
static int write_all (const struct commonio_db *db)
|
2009-04-25 19:11:52 +05:30
|
|
|
/*@requires notnull db->fp@*/
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
const struct commonio_entry *p;
|
2007-10-07 17:14:14 +05:30
|
|
|
void *eptr;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
for (p = db->head; NULL != p; p = p->next) {
|
2007-10-07 17:14:02 +05:30
|
|
|
if (p->changed) {
|
2007-10-07 17:14:14 +05:30
|
|
|
eptr = p->eptr;
|
2009-04-25 19:11:52 +05:30
|
|
|
assert (NULL != eptr);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (db->ops->put (eptr, db->fp) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2008-06-11 01:57:16 +05:30
|
|
|
} else if (NULL != p->line) {
|
2008-05-26 06:16:25 +05:30
|
|
|
if (db->ops->fputs (p->line, db->fp) == EOF) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
|
|
|
if (putc ('\n', db->fp) == EOF) {
|
2007-10-07 17:14:02 +05:30
|
|
|
return -1;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_close (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
char buf[1024];
|
|
|
|
int errors = 0;
|
|
|
|
struct stat sb;
|
|
|
|
|
|
|
|
if (!db->isopen) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
db->isopen = false;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (!db->changed || db->readonly) {
|
2019-03-25 19:21:26 +05:30
|
|
|
if (NULL != db->fp) {
|
|
|
|
(void) fclose (db->fp);
|
|
|
|
db->fp = NULL;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
goto success;
|
|
|
|
}
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if ((NULL != db->ops->close_hook) && (db->ops->close_hook () == 0)) {
|
2007-11-23 05:37:59 +05:30
|
|
|
goto fail;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-11-23 05:37:59 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
memzero (&sb, sizeof sb);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != db->fp) {
|
|
|
|
if (fstat (fileno (db->fp), &sb) != 0) {
|
2011-11-20 03:30:00 +05:30
|
|
|
(void) fclose (db->fp);
|
2007-10-07 17:14:02 +05:30
|
|
|
db->fp = NULL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2011-12-10 03:43:02 +05:30
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
/*
|
|
|
|
* Create backup file.
|
|
|
|
*/
|
2007-10-07 17:16:07 +05:30
|
|
|
snprintf (buf, sizeof buf, "%s-", db->filename);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2011-12-10 03:43:02 +05:30
|
|
|
#ifdef WITH_SELINUX
|
|
|
|
if (set_selinux_file_context (buf) != 0) {
|
|
|
|
errors++;
|
|
|
|
}
|
|
|
|
#endif
|
2008-05-26 06:16:25 +05:30
|
|
|
if (create_backup (buf, db->fp) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (fclose (db->fp) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2011-12-10 03:43:02 +05:30
|
|
|
#ifdef WITH_SELINUX
|
|
|
|
if (reset_selinux_file_context () != 0) {
|
|
|
|
errors++;
|
|
|
|
}
|
|
|
|
#endif
|
2008-05-26 06:16:25 +05:30
|
|
|
if (errors != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->fp = NULL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Default permissions for new [g]shadow files.
|
|
|
|
*/
|
2015-02-27 21:56:57 +05:30
|
|
|
sb.st_mode = db->st_mode;
|
|
|
|
sb.st_uid = db->st_uid;
|
|
|
|
sb.st_gid = db->st_gid;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
snprintf (buf, sizeof buf, "%s+", db->filename);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2012-05-19 01:14:53 +05:30
|
|
|
#ifdef WITH_SELINUX
|
|
|
|
if (set_selinux_file_context (buf) != 0) {
|
|
|
|
errors++;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
db->fp = fopen_set_perms (buf, "w", &sb);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == db->fp) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (write_all (db) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (fflush (db->fp) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
#ifdef HAVE_FSYNC
|
2008-05-26 06:16:25 +05:30
|
|
|
if (fsync (fileno (db->fp)) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2010-03-12 03:34:14 +05:30
|
|
|
#else /* !HAVE_FSYNC */
|
2007-10-07 17:16:07 +05:30
|
|
|
sync ();
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* !HAVE_FSYNC */
|
2008-05-26 06:16:25 +05:30
|
|
|
if (fclose (db->fp) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errors++;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
db->fp = NULL;
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (errors != 0) {
|
2007-10-07 17:16:07 +05:30
|
|
|
unlink (buf);
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (lrename (buf, db->filename) != 0) {
|
2007-10-07 17:14:02 +05:30
|
|
|
goto fail;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2012-05-19 01:14:53 +05:30
|
|
|
#ifdef WITH_SELINUX
|
|
|
|
if (reset_selinux_file_context () != 0) {
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
nscd_need_reload = true;
|
2007-10-07 17:15:40 +05:30
|
|
|
goto success;
|
2007-10-07 17:16:07 +05:30
|
|
|
fail:
|
2007-10-07 17:15:40 +05:30
|
|
|
errors++;
|
2007-10-07 17:16:07 +05:30
|
|
|
success:
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
free_linked_list (db);
|
|
|
|
return errors == 0;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2009-04-25 19:11:52 +05:30
|
|
|
static /*@dependent@*/ /*@null@*/struct commonio_entry *next_entry_by_name (
|
|
|
|
struct commonio_db *db,
|
|
|
|
/*@null@*/struct commonio_entry *pos,
|
|
|
|
const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
void *ep;
|
|
|
|
|
2008-06-11 01:57:16 +05:30
|
|
|
if (NULL == pos) {
|
2007-11-17 04:29:14 +05:30
|
|
|
return NULL;
|
2008-06-11 01:57:16 +05:30
|
|
|
}
|
2007-11-17 04:29:14 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
for (p = pos; NULL != p; p = p->next) {
|
2007-10-07 17:14:14 +05:30
|
|
|
ep = p->eptr;
|
2008-06-11 01:57:16 +05:30
|
|
|
if ( (NULL != ep)
|
|
|
|
&& (strcmp (db->ops->getname (ep), name) == 0)) {
|
2007-10-07 17:14:02 +05:30
|
|
|
break;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2009-04-25 19:11:52 +05:30
|
|
|
static /*@dependent@*/ /*@null@*/struct commonio_entry *find_entry_by_name (
|
|
|
|
struct commonio_db *db,
|
|
|
|
const char *name)
|
2007-11-17 04:29:14 +05:30
|
|
|
{
|
2010-03-12 03:34:14 +05:30
|
|
|
return next_entry_by_name (db, db->head, name);
|
2007-11-17 04:29:14 +05:30
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_update (struct commonio_db *db, const void *eptr)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
void *nentry;
|
|
|
|
|
|
|
|
if (!db->isopen || db->readonly) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
nentry = db->ops->dup (eptr);
|
|
|
|
if (NULL == nentry) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
p = find_entry_by_name (db, db->ops->getname (eptr));
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != p) {
|
|
|
|
if (next_entry_by_name (db, p->next, db->ops->getname (eptr)) != NULL) {
|
2007-11-17 04:29:14 +05:30
|
|
|
fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
|
2015-07-12 18:00:32 +05:30
|
|
|
db->ops->free (nentry);
|
2007-11-17 04:29:14 +05:30
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
db->ops->free (p->eptr);
|
2007-10-07 17:14:14 +05:30
|
|
|
p->eptr = nentry;
|
2008-05-26 06:16:25 +05:30
|
|
|
p->changed = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
db->cursor = p;
|
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
db->changed = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* not found, new entry */
|
2007-10-07 17:16:07 +05:30
|
|
|
p = (struct commonio_entry *) malloc (sizeof *p);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == p) {
|
2007-10-07 17:16:07 +05:30
|
|
|
db->ops->free (nentry);
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-07 17:14:14 +05:30
|
|
|
p->eptr = nentry;
|
2007-10-07 17:14:02 +05:30
|
|
|
p->line = NULL;
|
2008-05-26 06:16:25 +05:30
|
|
|
p->changed = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
#if KEEP_NIS_AT_END
|
2007-10-07 17:16:07 +05:30
|
|
|
add_one_entry_nis (db, p);
|
2010-03-12 03:34:14 +05:30
|
|
|
#else /* !KEEP_NIS_AT_END */
|
2007-10-07 17:16:07 +05:30
|
|
|
add_one_entry (db, p);
|
2010-03-12 03:34:14 +05:30
|
|
|
#endif /* !KEEP_NIS_AT_END */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
db->changed = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
Allow disabling of subordinate IDs.
* configure.in: Add configure options --enable-subordinate-ids /
--disable-subordinate-ids. Enabled by default.
* lib/prototypes.h: Include <config.h> before using its macros.
* lib/commonio.h, lib/commonio.c: Define commonio_append only when
ENABLE_SUBIDS is defined.
* lib/prototypes.h, libmisc/find_new_sub_gids.c,
libmisc/find_new_sub_uids.c: Likewise.
* lib/subordinateio.h, lib/subordinateio.c: Likewise.
* libmisc/user_busy.c: Only check if subordinate IDs are in use if
ENABLE_SUBIDS is defined.
* src/Makefile.am: Create newgidmap and newuidmap only if
ENABLE_SUBIDS is defined.
* src/newusers.c: Check for ENABLE_SUBIDS to enable support for
subordinate IDs.
* src/useradd.c: Likewise.
* src/userdel.c: Likewise.
* src/usermod.c: Likewise.
* man/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
man5/subgid.5, and man5/subuid.5 only if ENABLE_SUBIDS is defined.
* man/fr/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
man5/subgid.5, and man5/subuid.5 (not translated yet).
* man/generate_mans.mak: Add xsltproc conditionals
subids/no_subids.
* man/login.defs.d/SUB_GID_COUNT.xml: Add dependency on subids
condition.
* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
* man/usermod.8.xml: Document options for subordinate IDs and
reference subgid(5) / subuid(5) depending on the subids condition.
2013-08-11 18:24:22 +05:30
|
|
|
#ifdef ENABLE_SUBIDS
|
2013-01-22 14:43:26 +05:30
|
|
|
int commonio_append (struct commonio_db *db, const void *eptr)
|
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
void *nentry;
|
|
|
|
|
|
|
|
if (!db->isopen || db->readonly) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
nentry = db->ops->dup (eptr);
|
|
|
|
if (NULL == nentry) {
|
|
|
|
errno = ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/* new entry */
|
|
|
|
p = (struct commonio_entry *) malloc (sizeof *p);
|
|
|
|
if (NULL == p) {
|
|
|
|
db->ops->free (nentry);
|
|
|
|
errno = ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->eptr = nentry;
|
|
|
|
p->line = NULL;
|
|
|
|
p->changed = true;
|
|
|
|
add_one_entry (db, p);
|
|
|
|
|
|
|
|
db->changed = true;
|
|
|
|
return 1;
|
|
|
|
}
|
Allow disabling of subordinate IDs.
* configure.in: Add configure options --enable-subordinate-ids /
--disable-subordinate-ids. Enabled by default.
* lib/prototypes.h: Include <config.h> before using its macros.
* lib/commonio.h, lib/commonio.c: Define commonio_append only when
ENABLE_SUBIDS is defined.
* lib/prototypes.h, libmisc/find_new_sub_gids.c,
libmisc/find_new_sub_uids.c: Likewise.
* lib/subordinateio.h, lib/subordinateio.c: Likewise.
* libmisc/user_busy.c: Only check if subordinate IDs are in use if
ENABLE_SUBIDS is defined.
* src/Makefile.am: Create newgidmap and newuidmap only if
ENABLE_SUBIDS is defined.
* src/newusers.c: Check for ENABLE_SUBIDS to enable support for
subordinate IDs.
* src/useradd.c: Likewise.
* src/userdel.c: Likewise.
* src/usermod.c: Likewise.
* man/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
man5/subgid.5, and man5/subuid.5 only if ENABLE_SUBIDS is defined.
* man/fr/Makefile.am: Install man1/newgidmap.1, man1/newuidmap.1,
man5/subgid.5, and man5/subuid.5 (not translated yet).
* man/generate_mans.mak: Add xsltproc conditionals
subids/no_subids.
* man/login.defs.d/SUB_GID_COUNT.xml: Add dependency on subids
condition.
* man/login.defs.d/SUB_UID_COUNT.xml: Likewise.
* man/usermod.8.xml: Document options for subordinate IDs and
reference subgid(5) / subuid(5) depending on the subids condition.
2013-08-11 18:24:22 +05:30
|
|
|
#endif /* ENABLE_SUBIDS */
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2008-05-26 06:16:25 +05:30
|
|
|
if (p == db->cursor) {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->cursor = p->next;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != p->prev) {
|
2007-10-07 17:14:02 +05:30
|
|
|
p->prev->next = p->next;
|
2008-05-26 06:16:25 +05:30
|
|
|
} else {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->head = p->next;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != p->next) {
|
2007-10-07 17:14:02 +05:30
|
|
|
p->next->prev = p->prev;
|
2008-05-26 06:16:25 +05:30
|
|
|
} else {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->tail = p->prev;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
db->changed = true;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* commonio_remove - Remove the entry of the given name from the database.
|
|
|
|
*/
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_remove (struct commonio_db *db, const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
|
|
|
|
if (!db->isopen || db->readonly) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
p = find_entry_by_name (db, name);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == p) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = ENOENT;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
if (next_entry_by_name (db, p->next, name) != NULL) {
|
2008-03-09 04:22:44 +05:30
|
|
|
fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
|
|
|
|
return 0;
|
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2007-10-07 17:16:07 +05:30
|
|
|
commonio_del_entry (db, p);
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != p->line) {
|
2007-10-07 17:16:07 +05:30
|
|
|
free (p->line);
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != p->eptr) {
|
2007-10-07 17:16:07 +05:30
|
|
|
db->ops->free (p->eptr);
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* commonio_locate - Find the first entry with the specified name in
|
|
|
|
* the database.
|
|
|
|
*
|
|
|
|
* If found, it returns the entry and set the cursor of the database to
|
|
|
|
* that entry.
|
|
|
|
*
|
|
|
|
* Otherwise, it returns NULL.
|
|
|
|
*/
|
2009-04-24 02:49:02 +05:30
|
|
|
/*@observer@*/ /*@null@*/const void *commonio_locate (struct commonio_db *db, const char *name)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
struct commonio_entry *p;
|
|
|
|
|
|
|
|
if (!db->isopen) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-07 17:16:07 +05:30
|
|
|
p = find_entry_by_name (db, name);
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == p) {
|
2007-10-07 17:14:02 +05:30
|
|
|
errno = ENOENT;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
db->cursor = p;
|
2007-10-07 17:14:14 +05:30
|
|
|
return p->eptr;
|
2007-10-07 17:14:02 +05:30
|
|
|
}
|
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* commonio_rewind - Restore the database cursor to the first entry.
|
|
|
|
*
|
|
|
|
* It returns 0 on error, 1 on success.
|
|
|
|
*/
|
2007-10-07 17:16:07 +05:30
|
|
|
int commonio_rewind (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
|
|
|
if (!db->isopen) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
db->cursor = NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-01-02 02:04:47 +05:30
|
|
|
/*
|
|
|
|
* commonio_next - Return the next entry of the specified database
|
|
|
|
*
|
|
|
|
* It returns the next entry, or NULL if no other entries could be found.
|
|
|
|
*/
|
2009-04-24 02:49:02 +05:30
|
|
|
/*@observer@*/ /*@null@*/const void *commonio_next (struct commonio_db *db)
|
2007-10-07 17:14:02 +05:30
|
|
|
{
|
2007-10-07 17:14:14 +05:30
|
|
|
void *eptr;
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
if (!db->isopen) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return 0;
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL == db->cursor) {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->cursor = db->head;
|
2008-05-26 06:16:25 +05:30
|
|
|
} else {
|
2007-10-07 17:14:02 +05:30
|
|
|
db->cursor = db->cursor->next;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
2008-05-26 06:16:25 +05:30
|
|
|
while (NULL != db->cursor) {
|
2007-10-07 17:14:14 +05:30
|
|
|
eptr = db->cursor->eptr;
|
2008-05-26 06:16:25 +05:30
|
|
|
if (NULL != eptr) {
|
2007-10-07 17:14:14 +05:30
|
|
|
return eptr;
|
2008-05-26 06:16:25 +05:30
|
|
|
}
|
2007-10-07 17:14:02 +05:30
|
|
|
|
|
|
|
db->cursor = db->cursor->next;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-05-26 06:16:25 +05:30
|
|
|
|