/* Copyright (c) 1999 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@suse.de>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>
#include <locale.h>
#include <libintl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <rpcsvc/nis.h>
#include "nis_xdr.h"
#include "nisd.h"
#include "log_msg.h"

#ifndef _
#define _(String) gettext (String)
#endif

bool_t
nis_rmdir_3_r (nis_name *argp, nis_error *result, struct svc_req *rqstp)
{
  bool_t retval = TRUE;
  struct sockaddr_in *rqhost;
  SERVER_CLOCK_DECLS;
  char *principal;
  directory_obj *dir = NULL;
  db_result *db_res;
  u_int i;

  start_clock (SERVER_CLOCK);

  principal = get_nis_principal (rqstp);

  if (verbose)
    {
      rqhost = svc_getcaller (rqstp->rq_xprt);
      log_msg (LOG_DEBUG, "nis_rmdir_3() [From: %s:%d,%s]",
	       inet_ntoa (rqhost->sin_addr), ntohs (rqhost->sin_port),
	       principal ? principal : "{error}");
    }

  if (readonly)
    {
      *result = NIS_TRYAGAIN;
      goto bailout;
    }

  /* We should never see an indexed name. */
  if (strchr (*argp, '[') != NULL)
    {
      *result = NIS_BADNAME;
      goto bailout;
    }

  /* Do some sanity checks */
  *result = nis_validname (*argp);
  if (*result != NIS_SUCCESS)
    goto bailout;

  /* It is ok if the directory doesn't exist. Then the directory object
     is already removed. If some other error occurs, bail out. */
  *result = nis_dcache_lookup (*argp, LOOKUP_ONLY | CHECK_SERVER,
                               MASTER_ONLY, &dir);
  if (*result != NIS_SUCCESS && *result != NIS_NOTFOUND &&
      *result != NIS_NOSUCHNAME && *result != NIS_NAMEUNREACHABLE)
    goto bailout;
#if 0
  /*
   * If the directory object does still exist, check that we
   * no longer serve it.
   */
  if (result == NIS_SUCCESS)
    {
      if (__is_local_dir (dir) == TRUE)
        {
          nis_err ("rmdir called for directory %s"
                   " which we still serve!",
                   (char *) *argp);
          result = NIS_NOT_ME;
          nis_update_stats (NIS_RMDIR, FALSE,
                            __stop_clock (SERVER_CLOCK));
          return (&result);
        }
    }
#endif

  /* We should check for access rights here. But which ? The original
     object with the rights is already removed. */

  /* For a master server, it's a mistake to remove a directory that contains
     subdirectories since doing so would leave the subdirectories orphaned.
     For a replica however, it's ok to allow this. */
  if (*result == NIS_SUCCESS)
    {
      /* This checks if the first entry is our name, which means we are the
	 master. */
      if (nis_dir_cmp (dir->do_servers.do_servers_val[0].name, nis_local_host ()) != SAME_NAME)
        goto skip_check;
    }

  db_res = db_list_entries (nis_name_of (*argp), 0, NULL);
  if (db_res->status != DB_SUCCESS && db_res->status != DB_NOTFOUND)
    {
      *result = db2nis_error (db_res->status);
      db_free_result (db_res);
      goto bailout;
    }

  for (i = 0; i < db_res->objects.objects_len; ++i)
    if (strcmp (db_res->objects.objects_val[i]->en_type, "IN_DIRECTORY") == 0)
      {
	*result = NIS_NOTEMPTY;
	db_free_result (db_res);
	goto bailout;
      }

  for (i = 0; i < db_res->objects.objects_len; ++i)
    {
#if 0  
      /* XXX Remove tables */
      db_destroy_table ();
      remove_from_cache ();
#endif
    }

  db_free_result (db_res);

 skip_check:
  /* XXX Not thread safe */
  *result = db2nis_error (db_destroy_table (nis_name_of (*argp)));
  if (*result != NIS_SUCCESS)
    goto bailout;

  remove_from_cache (*argp);

  *result = remove_from_srvlist (*argp);

 bailout:
  free (principal);

  if (verbose)
    log_msg (LOG_DEBUG, "\tresult = %s", nis_sperrno (*result));

  nis_update_stats (NIS_RMDIR, *result == NIS_SUCCESS ? TRUE : FALSE,
                    stop_clock (SERVER_CLOCK));

  return retval;
}
