if (remaining > 0) pwrite (fd, tmpbuf, remaining, offset);
if (remaining > 0 && pwrite (fd, tmpbuf, remaining, offset) != remaining) goto write_fail;
nscd_init (void){  /* Secure mode and unprivileged mode are incompatible */  if (server_user != NULL && secure_in_use)    {      dbg_log (_("Cannot run nscd in secure mode as unprivileged user"));      exit (4);    }  /* Look up unprivileged uid/gid/groups before we start listening on the     socket  */  if (server_user != NULL)    begin_drop_privileges ();  if (nthreads == -1)    /* No configuration for this value, assume a default.  */    nthreads = 2 * lastdb;  for (size_t cnt = 0; cnt < lastdb; ++cnt)    if (dbs[cnt].enabled)      {	pthread_rwlock_init (&dbs[cnt].lock, NULL);	pthread_mutex_init (&dbs[cnt].memlock, NULL);	if (dbs[cnt].persistent)	  {	    /* Try to open the appropriate file on disk.  */	    int fd = open (dbs[cnt].db_filename, O_RDWR);	    if (fd != -1)	      {		struct stat64 st;		void *mem;		size_t total;		struct database_pers_head head;		ssize_t n = TEMP_FAILURE_RETRY (read (fd, &head,						      sizeof (head)));		if (n != sizeof (head) || fstat64 (fd, &st) != 0)		  {		  fail_db:		    dbg_log (_("invalid persistent database file \"%s\": %s"),			     dbs[cnt].db_filename, strerror (errno));		    dbs[cnt].persistent = 0;		  }		else if (head.module == 0 && head.data_size == 0)		  {		    /* The file has been created, but the head has not been		       initialized yet.  Remove the old file.  */		    unlink (dbs[cnt].db_filename);		  }		else if (head.header_size != (int) sizeof (head))		  {		    dbg_log (_("invalid persistent database file \"%s\": %s"),			     dbs[cnt].db_filename,			     _("header size does not match"));		    dbs[cnt].persistent = 0;		  }		else if ((total = (sizeof (head)				   + roundup (head.module * sizeof (ref_t),					      ALIGN)				   + head.data_size))			 > st.st_size)		  {		    dbg_log (_("invalid persistent database file \"%s\": %s"),			     dbs[cnt].db_filename,			     _("file size does not match"));		    dbs[cnt].persistent = 0;		  }		else if ((mem = mmap (NULL, total, PROT_READ | PROT_WRITE,				      MAP_SHARED, fd, 0)) == MAP_FAILED)		  goto fail_db;		else		  {		    /* Success.  We have the database.  */		    dbs[cnt].head = mem;		    dbs[cnt].memsize = total;		    dbs[cnt].data = (char *)		      &dbs[cnt].head->array[roundup (dbs[cnt].head->module,						     ALIGN / sizeof (ref_t))];		    dbs[cnt].mmap_used = true;		    if (dbs[cnt].suggested_module > head.module)		      dbg_log (_("suggested size of table for database %s larger than the persistent database's table"),			       dbnames[cnt]);		    dbs[cnt].wr_fd = fd;		    fd = -1;		    /* We also need a read-only descriptor.  */		    if (dbs[cnt].shared)		      {			dbs[cnt].ro_fd = open (dbs[cnt].db_filename, O_RDONLY);			if (dbs[cnt].ro_fd == -1)			  dbg_log (_("\cannot create read-only descriptor for \"%s\"; no mmap"),				   dbs[cnt].db_filename);		      }		    // XXX Shall we test whether the descriptors actually		    // XXX point to the same file?		  }		/* Close the file descriptors in case something went		   wrong in which case the variable have not been		   assigned -1.  */		if (fd != -1)		  close (fd);	      }	  }	if (dbs[cnt].head == NULL)	  {	    /* No database loaded.  Allocate the data structure,	       possibly on disk.  */	    struct database_pers_head head;	    size_t total = (sizeof (head)			    + roundup (dbs[cnt].suggested_module				       * sizeof (ref_t), ALIGN)			    + (dbs[cnt].suggested_module			       * DEFAULT_DATASIZE_PER_BUCKET));	    /* Try to create the database.  If we do not need a	       persistent database create a temporary file.  */	    int fd;	    int ro_fd = -1;	    if (dbs[cnt].persistent)	      {		fd = open (dbs[cnt].db_filename,			   O_RDWR | O_CREAT | O_EXCL | O_TRUNC,			   S_IRUSR | S_IWUSR);		if (fd != -1 && dbs[cnt].shared)		  ro_fd = open (dbs[cnt].db_filename, O_RDONLY);	      }	    else	      {		char fname[] = _PATH_NSCD_XYZ_DB_TMP;		fd = mkstemp (fname);		/* We do not need the file name anymore after we		   opened another file descriptor in read-only mode.  */		if (fd != -1)		  {		    if (dbs[cnt].shared)		      ro_fd = open (fname, O_RDONLY);		    unlink (fname);		  }	      }	    if (fd == -1)	      {		if (errno == EEXIST)		  {		    dbg_log (_("database for %s corrupted or simultaneously used; remove %s manually if necessary and restart"),			     dbnames[cnt], dbs[cnt].db_filename);		    // XXX Correct way to terminate?		    exit (1);		  }		if  (dbs[cnt].persistent)		  dbg_log (_("cannot create %s; no persistent database used"),			   dbs[cnt].db_filename);		else		  dbg_log (_("cannot create %s; no sharing possible"),			   dbs[cnt].db_filename);		dbs[cnt].persistent = 0;		// XXX remember: no mmap	      }	    else	      {		/* Tell the user if we could not create the read-only		   descriptor.  */		if (ro_fd == -1 && dbs[cnt].shared)		  dbg_log (_("\cannot create read-only descriptor for \"%s\"; no mmap"),			   dbs[cnt].db_filename);		/* Before we create the header, initialiye the hash		   table.  So that if we get interrupted if writing		   the header we can recognize a partially initialized		   database.  */		size_t ps = sysconf (_SC_PAGESIZE);		char tmpbuf[ps];		assert (~ENDREF == 0);		memset (tmpbuf, '\xff', ps);		size_t remaining = dbs[cnt].suggested_module * sizeof (ref_t);		off_t offset = sizeof (head);		size_t towrite;		if (offset % ps != 0)		  {		    towrite = MIN (remaining, ps - (offset % ps));		    pwrite (fd, tmpbuf, towrite, offset);		    offset += towrite;		    remaining -= towrite;		  }		while (remaining > ps)		  {		    pwrite (fd, tmpbuf, ps, offset);		    offset += ps;		    remaining -= ps;		  }		if (remaining > 0)		  pwrite (fd, tmpbuf, remaining, offset);		/* Create the header of the file.  */		struct database_pers_head head =		  {		    .version = DB_VERSION,		    .header_size = sizeof (head),		    .module = dbs[cnt].suggested_module,		    .data_size = (dbs[cnt].suggested_module				  * DEFAULT_DATASIZE_PER_BUCKET),		    .first_free = 0		  };		void *mem;		if ((TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head)))		     != sizeof (head))		    || ftruncate (fd, total) != 0		    || (mem = mmap (NULL, total, PROT_READ | PROT_WRITE,				    MAP_SHARED, fd, 0)) == MAP_FAILED)		  {		    unlink (dbs[cnt].db_filename);		    dbg_log (_("cannot write to database file %s: %s"),			     dbs[cnt].db_filename, strerror (errno));		    dbs[cnt].persistent = 0;		  }		else		  {		    /* Success.  */		    dbs[cnt].head = mem;		    dbs[cnt].data = (char *)		      &dbs[cnt].head->array[roundup (dbs[cnt].head->module,						     ALIGN / sizeof (ref_t))];		    dbs[cnt].memsize = total;		    dbs[cnt].mmap_used = true;		    /* Remember the descriptors.  */		    dbs[cnt].wr_fd = fd;		    dbs[cnt].ro_fd = ro_fd;		    fd = -1;		    ro_fd = -1;		  }		if (fd != -1)		  close (fd);		if (ro_fd != -1)		  close (ro_fd);	      }	  }	if (paranoia	    && ((dbs[cnt].wr_fd != -1		 && fcntl (dbs[cnt].wr_fd, F_SETFD, FD_CLOEXEC) == -1)		|| (dbs[cnt].ro_fd != -1		    && fcntl (dbs[cnt].ro_fd, F_SETFD, FD_CLOEXEC) == -1)))	  {	    dbg_log (_("\cannot set socket to close on exec: %s; disabling paranoia mode"),		     strerror (errno));	    paranoia = 0;	  }	if (dbs[cnt].head == NULL)	  {	    /* We do not use the persistent database.  Just	       create an in-memory data structure.  */	    assert (! dbs[cnt].persistent);	    dbs[cnt].head = xmalloc (sizeof (struct database_pers_head)				     + (dbs[cnt].suggested_module					* sizeof (ref_t)));	    memset (dbs[cnt].head, '\0', sizeof (dbs[cnt].head));	    assert (~ENDREF == 0);	    memset (dbs[cnt].head->array, '\xff',		    dbs[cnt].suggested_module * sizeof (ref_t));	    dbs[cnt].head->module = dbs[cnt].suggested_module;	    dbs[cnt].head->data_size = (DEFAULT_DATASIZE_PER_BUCKET					* dbs[cnt].head->module);	    dbs[cnt].data = xmalloc (dbs[cnt].head->data_size);	    dbs[cnt].head->first_free = 0;	    dbs[cnt].shared = 0;	    assert (dbs[cnt].ro_fd == -1);	  }	if (dbs[cnt].check_file)	  {	    /* We need the modification date of the file.  */	    struct stat st;	    if (stat (dbs[cnt].filename, &st) < 0)	      {		/* We cannot stat() the file, disable file checking.  */		dbg_log (_("cannot stat() file `%s': %s"),			 dbs[cnt].filename, strerror (errno));		dbs[cnt].check_file = 0;	      }	    else	      dbs[cnt].file_mtime = st.st_mtime;	  }      }  /* Create the socket.  */  sock = socket (AF_UNIX, SOCK_STREAM, 0);  if (sock < 0)    {      dbg_log (_("cannot open socket: %s"), strerror (errno));      exit (errno == EACCES ? 4 : 1);    }  /* Bind a name to the socket.  */  struct sockaddr_un sock_addr;  sock_addr.sun_family = AF_UNIX;  strcpy (sock_addr.sun_path, _PATH_NSCDSOCKET);  if (bind (sock, (struct sockaddr *) &sock_addr, sizeof (sock_addr)) < 0)    {      dbg_log ("%s: %s", _PATH_NSCDSOCKET, strerror (errno));      exit (errno == EACCES ? 4 : 1);    }  /* We don't want to get stuck on accept.  */  int fl = fcntl (sock, F_GETFL);  if (fl == -1 || fcntl (sock, F_SETFL, fl | O_NONBLOCK) == -1)    {      dbg_log (_("cannot change socket to nonblocking mode: %s"),	       strerror (errno));      exit (1);    }  /* The descriptor needs to be closed on exec.  */  if (paranoia && fcntl (sock, F_SETFD, FD_CLOEXEC) == -1)    {      dbg_log (_("cannot set socket to close on exec: %s"),	       strerror (errno));      exit (1);    }  /* Set permissions for the socket.  */  chmod (_PATH_NSCDSOCKET, DEFFILEMODE);  /* Set the socket up to accept connections.  */  if (listen (sock, SOMAXCONN) < 0)    {      dbg_log (_("cannot enable socket to accept connections: %s"),	       strerror (errno));      exit (1);    }  /* Change to unprivileged uid/gid/groups if specifed in config file */  if (server_user != NULL)    finish_drop_privileges ();}