static char *SccsId = "@(#)dmrmcell.c 3.11 (TU-Delft) 04/28/93";
/**********************************************************

Name/Version      : The Design Data Management Project

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000/S500

Author(s)         : G.W. Sloof
		    P. van der Wolf
Creation date     : 22-Mar-1988
Modified by       : S. de Graaf
Modification date : 08-Apr-1988


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1985-1988, All rights reserved
**********************************************************/
#include "dmstd.h"
#include "errno.h"

#  if defined(__STDC__) && !defined(MSDOS)
#include <dirent.h>
#define MAXPATHLEN 1024
#  else				/* not __STDC__ */
#if defined (MSDOS)
#include "ndir.h"
#define MAXPATHLEN 1024
#else
#include <sys/dir.h>
#define MAXPATHLEN 1024
#endif
#  endif			/* else not __STDC__ */

/*
** dmRemoveCell removes a 'cell' with viewtype 'view', with
** versionstatus 'versionstatus', and versionnumber 'versionnumber 
** from the project identified by 'dmproject'. 
** The arguments are: dmproject, cell, versionstatus, versionnumber, view)
** It calles the (for internal use added) function dmRmCellForce which has an 
** extra argument : a force-flag.
** In the next release it will be possible to call this function with a 
** list of pointers to keys instead of only one cell-name.
*/
dmRemoveCell (dmproject, cell, versionstatus, versionnumber, view)
DM_PROJECT * dmproject;
char   *cell,
       *versionstatus,
       *view;
int     versionnumber;
{
    return (dmRmCellForce (dmproject, cell, versionstatus, versionnumber,
		view, 0));
}

dmRmCellForce (dmproject, cell, versionstatus, versionnumber, view, force)
DM_PROJECT * dmproject;
char   *cell,
       *versionstatus,
       *view;
int     versionnumber;
int     force;			/* if force == 0 : check if cell is a
				   root-cell */
 /* else no check */
{
    int     exist;
    int     found;
    int     nr_cells_inlist;
    FILE * celllist_fp;
    char   *celllist_array[DM_MAXCELLS + 1];
    char    celllist_member[DM_MAXNAME + 1];
    char    path[MAXLINE];
    register int    i;

#ifdef DM_DEBUG
    IFDEBUG {
	fprintf (stderr, "_dmRmCell: cell: %s, version: %s, view: %s\n",
		cell, versionstatus, view);
    }
#endif				/* DM_DEBUG */

    if (_dmCh_project (dmproject) != 0) {
	dmError ("_dmRmCell: project key");
	return (-1);
    }

 /* Check existence of cell in view. ** The cellname and view are also
    tested. ** If exist == 0 cell doesnot exist, ** if exist == 1 cell
    does exist. */
    if ((exist = (int) dmGetMetaDesignData (EXISTCELL,
		    dmproject, cell, view)) <= 0) {
	if (exist == 0)
	    dmError2 ("_dmRmCell", cell);
	return (-1);
    }

 /* check if cell has already been checked out by this tool */
    if (_dmCh_cell (dmproject, cell, view)) {
	dmError2 ("_dmRmCell", cell);
	return (-1);
    }

    if (strcmp (versionstatus, ACTUAL))
	if (strcmp (versionstatus, WORKING))
	    if (strcmp (versionstatus, BACKUP))
		if (strcmp (versionstatus, DERIVED)) {
		    dmerrno = DME_BADARG;
		    dmError2 ("_dmRmCell", versionstatus);
		    return (-1);
		}

 /* extra (superfluous) check of permissions */
    if (!((dmproject -> mode) & PROJ_WRITE)) {
	dmerrno = DME_MODE;
	dmError ("_dmRmCell");
	return (-1);
    }

    _dmSprintf (path, "%s/%s/celllist", dmproject -> dmpath, view);

    if ((celllist_fp = fopen (path, "r")) == NULL) {
	dmerrno = DME_NOCELLL;
	dmError2 ("_dmRmCell", path);
	return (-1);
    }

    i = 0;
    while (fscanf (celllist_fp, "%s", celllist_member) != EOF) {
	if (i == DM_MAXCELLS) {
	    dmerrno = DME_CORE;
	    dmError ("_dmRmCell: too many cells in celllist");
	    nr_cells_inlist = i;
	    goto err_ret;
	}
	celllist_array[i++] = _dmStrSave (celllist_member);
    }
    nr_cells_inlist = i;
    celllist_array[i] = NULL;

    fclose (celllist_fp);

    if (force == 0 && (i = _dmCellIsRoot2 (dmproject,
		    cell, view, celllist_array)) != 1) {
	if (i == 0) {
	    dmerrno = DME_NOROOT;
	    dmError2 ("_dmRmCell", cell);
	}
	goto err_ret;
    }

#ifdef DM_DEBUG
    IFDEBUG {
	fprintf (stderr, "_dmRmCell: trying to remove '%s' of viewtype '%s'\n",
		cell, view);
    }
#endif				/* DM_DEBUG */

 /* Everything seems to work out fine: perform the actual operations. */
 /* Perform removal of cell-streams and cell. */

    if (_dmRmCell (dmproject, cell, view))
	goto err_ret;

    if ((celllist_fp = fopen (path, "w")) == NULL) {
	dmerrno = DME_FOPEN;
	dmError2 ("_dmRmCell", path);
	goto err_ret;
    }

 /* Write new celllist. */
    for (found = i = 0; i < nr_cells_inlist; ++i) {
	if (!found) {
	    if (strcmp (cell, celllist_array[i]) == 0) {
		++found;
		_dmStrFree (celllist_array[i]);
		continue;
	    }
	}
	fprintf (celllist_fp, "%s\n", celllist_array[i]);
	_dmStrFree (celllist_array[i]);
    }
    fclose (celllist_fp);

    return (0);

err_ret: 
    for (i = 0; i < nr_cells_inlist; ++i) {
	_dmStrFree (celllist_array[i]);
    }
    return (-1);
}

/*
** _dmRmCell executes the actual removal of the 'cell'
** with viewtype 'view'.
*/
_dmRmCell (dmproject, cell, view)
DM_PROJECT * dmproject;
char   *cell,
       *view;
{
    char    path[MAXPATHLEN];

    _dmSprintf (path, "%s/%s/%s", dmproject -> dmpath, view, cell);
#ifdef DM_DEBUG
    IFDEBUG {
	fprintf (stderr, "_dmRmCell: path = '%s'\n", path);
    }
#endif				/* DM_DEBUG */

    return (_dmRmDir (dmproject, path));
}

_dmRmDir (dmproject, path)
DM_PROJECT * dmproject;
char   *path;
{
    char    newpath[MAXPATHLEN];
    DIR * dirp;
    struct stat st_buf;
#if defined(__STDC__) && !defined(MSDOS)
    struct dirent  *dp;
#else
#if defined (MSDOS)
    direct *e, dp;
#  else			
    struct direct  *dp;
#  endif
#endif			

#ifdef MSDOS
    dirp = opendir (path, D_READ);
    for (e = readdir (dirp, &dp); e != NULL; e = readdir (dirp, &dp)) {
	if (strcmp (dp.d_name, ".") != 0
		&& strcmp (dp.d_name, "..") != 0) {
	    sprintf (newpath, "%s/%s", path, dp.d_name);
	    if (stat (newpath, &st_buf) != 0) {
		dmerrno = DME_SYS;
		dmError2 ("_dmRmDir: stat", path);
		return (-1);
	    }
	    if (st_buf.st_mode & S_IFDIR) {
		if (_dmRmDir (dmproject, newpath) == (-1))
		    return (-1);
	    }
	    else
		unlink (newpath);
	}
    }
#else
    dirp = opendir (path);
    for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp)) {
	if (strcmp (dp -> d_name, ".") != 0
		&& strcmp (dp -> d_name, "..") != 0) {
	    sprintf (newpath, "%s/%s", path, dp -> d_name);
	    if (stat (newpath, &st_buf) != 0) {
		dmerrno = DME_SYS;
		dmError2 ("_dmRmDir: stat", path);
		return (-1);
	    }

#ifdef __STDC__
	    if (S_ISDIR (st_buf.st_mode))
# else
	    if (st_buf.st_mode & S_IFDIR)
#endif
		{
		    if (_dmRmDir (dmproject, newpath) == (-1))
			return (-1);
		}
		else
		    unlink (newpath);
	}
    }
#endif
    closedir (dirp);
    if (rmdir (path)) {
	dmerrno = DME_SYS;
	dmError2 ("_dmRmDir: rmdir", path);
	return (-1);
    }
    return (0);
}
