Esempio n. 1
0
/*
** Name: LOmkingpath	- make INGRES location's area path
**
** Description:
**	Makes missing subdirectories in a location's area path.
**
** Inputs:
**	area	"device" that the location is on
**	what	path to db, ckp, dmp, work, jnl
**	loc	set to full path of location
**	
** Outputs:
**	none
**
** Returns:
**	LO_NULL_ARG	area or what were NULL or empty
**	LO_NO_SUCH	required path component does not exist
**
** History:
**	03-dec-2003 (abbjo03)
**	    Created.
*/
STATUS
LOmkingpath(
char		*area,		/* "device" that the database is on */
char		*what,		/* path to db, ckp, dmp, work, or jnl */
LOCATION	*loc)		/* set to full path of location */
{
    STATUS	status;
    char	path[MAX_LOC+1];
    i4		flags;
    LOINFORMATION	info;

    /* check for legal arguments */
    if (area == NULL || *area == EOS || STtrmwhite(area) == 0 ||
		what == NULL || *what == EOS)
	return LO_NULL_ARG;

    LOdev_to_root(area, path);
    if ((status = LOfroms(PATH, path, loc)) != OK)
	return status;
    flags = LO_I_TYPE;
    if (LOinfo(loc, &flags, &info))
	return LO_NO_SUCH;
    if ((flags & LO_I_TYPE) == 0 || info.li_type != LO_IS_DIR)
	return LO_NO_SUCH;

    LOfaddpath(loc, SystemLocationSubdirectory, loc);
    if ((status = LOfroms(PATH, path, loc)) != OK)
	return status;
    flags = LO_I_TYPE;
    if (LOinfo(loc, &flags, &info))
    {
	if ((status = LOcreate(loc)) != OK)
	    return status;
    }
    /* Set protections */
    if (setperms(loc, PROT_SRWE_ORWE_G_WRE) != OK)
	return FAIL;
	
    LOfaddpath(loc, what, loc);
    if ((status = LOfroms(PATH, path, loc)) != OK)
	return status;
    flags = LO_I_TYPE;
    if (LOinfo(loc, &flags, &info))
    {
	if ((status = LOcreate(loc)) != OK)
	    return status;
    }
    if (setperms(loc, PROT_SRWE_ORWE_G_WRE) != OK)
	return FAIL;

    flags = LO_I_PERMS;
    if ((status = LOinfo(loc, &flags, &info)) == OK &&
		(info.li_perms & LO_P_WRITE) == 0)
	status = LO_NO_PERM;

    return status;
}
Esempio n. 2
0
STATUS
LOsize(
    register LOCATION	*loc,
    register OFFSET_TYPE	*loc_size)

{
    LOINFORMATION 	info;
    STATUS		status;
    i4		flags;

    /* We want size info only */
    flags = LO_I_SIZE;

    /* Call LOinfo to get the info */
    status = LOinfo(loc, &flags, &info);

    /* return the data and/or status */
    if (status != OK)
    {
        return(status);
    }
    else if ((flags & LO_I_SIZE) == 0)
    {
        return (LO_CANT_TELL);
    }
    else
    {
        *loc_size = (OFFSET_TYPE) info.li_size;
        return (OK);
    }
}
Esempio n. 3
0
/*{
** Name: NMwritesyms - write the symbol table list to file.
**
** Description:
**    Write the symbol table list back out to the file.
**
**    This duplicates the function in ingunset.c, but shouldn't be in 
**    compatlib because no one else has any business writing the file.
**
** Inputs:
**	none.
**
** Output:
**	none.
**
**      Returns:
**          OK                         	    Function completed normally. 
**          FAIL                            Function completed abnormally.
**
** History:
**      20-jul-87 (mmm)
**          Updated to meet jupiter standards.
**	14-apr-89 (arana)
**	    When LOlast was added to update symbol table mod time,
**	    return value was saved off but not returned.
**	15-jul-93 (ed)
**	    adding <gl.h> after <compat.h>
**      29-sep-94 (cwaldman)
**          Changed check of NMopensyms return value to compare against
**          (FILE *)NULL (was NULL).
**          Changed write routine to write into a temporary file first,
**          check whether this file has been written OK, and rename
**          temporary file to symbol.tbl if it is alright. This is part
**          of the fix for bug 44445 (symbol.tbl disappears). There is
**          still a slight chance of something going wrong during the
**          rename, but in that case variables are at least preserved
**          in symbol.tmp.
**      19-oct-94 (abowler)
**          Minor correction to change above. Cal to SIopen should be
**          passed address of location structure. (Didn't show up as
**          a bug on su4_u42 !)
**      28-feb-95 (cwaldman)
**          Amendment to change on 29 Sep. Part of the check whether
**          the temporary symbol table had been written OK was to check
**          the file size. The check would return the file size if
**          check was OK and 0 otherwise. If a 0 was returned, the old
**          symbol.tbl would not be replaced. This made it impossible
**          to 'ingunset' the last variable in a symbol.tbl. Changed
**          'OK-check' to use -1 as error indicator.
**	02-jul-1996 (sweeney)
**	    Apply umask fix (bug #71890) from ingres63p
**	07-apr-2004 (somsa01)
**	    Added backup of symbol.tbl logic.
*/
STATUS
NMwritesyms()
{
    register SYM	*sp;
    FILE		*fp, *tfp = NULL;
    register i4 	status = OK;
    register i4 	closestat;
    char		buf[ MAXLINE + NULL_NL_NULL ];
    char		tbuf[ MAXLINE + NULL_NL_NULL ];
    i4			flagword, size, symcount = 0, bksymcount;
    STATUS		retval;
    LOCATION		t_loc;
    LOINFORMATION	loinfo;
    bool		perform_backup = TRUE;
    OFFSET_TYPE		bk_size;

    /*
    ** ensure sensible umask for symbol.tmp, as it will become symbol.tbl
    */
    PEsave();
    PEumask("rw-r--");
 
    if ((FILE *)NULL == (fp = NMopensyms( "r" )))
    {
	PEreset();
	return (NM_STOPN);
    }
    SIclose(fp);
 
    LOcopy(&NMSymloc, tbuf, &t_loc);
    if ( OK != LOfstfile("symbol.tmp", &t_loc) ||
         OK != SIopen(&t_loc, "w", &tfp))
    {
	return (NM_STOPN);
    }

    for ( sp = s_list; sp != NULL; sp = sp->s_next )
    {
	(VOID) STpolycat( 3, sp->s_sym, "\t", sp->s_val, buf );
	STmove( buf, ' ', MAXLINE, buf );

	buf[ MAXLINE - 1 ] = '\n';
	buf[ MAXLINE ] = '\0';
 
	if ( OK != (status = SIputrec(buf, tfp)))
	    break;

	symcount++;
    }
 
    /* Very interested in close status of file being written */
 
    closestat = SIclose( tfp );
    flagword = (LO_I_SIZE);
    size = (OK == LOinfo(&t_loc,&flagword,&loinfo) ? loinfo.li_size : -1);
 
    retval=(status != OK || closestat != OK || size == -1 ? NM_STAPP : OK);

    /* if file written ok update modification time */
    if(retval == OK)
    {
	LOrename(&t_loc, &NMSymloc);
	LOlast(&NMSymloc, &NMtime);
 
#if defined(su4_cmw)
	/* Now reset the old MAC label if any */
	if (NM_got_label)
	{
	    (void)setcmwlabel(NM_path, &NM_saved_label, SETCL_ALL);
	    NM_got_label=0;
	}
#endif

	/*
	** If we have no backup to check against, just do it. Otherwise,
	** make sure our new symbol table differs from the backup by at most
	** one symbol before performing a backup.
	*/
	if (LOexist(&NMBakSymloc) == OK)
	{
	    LOsize(&NMBakSymloc, &bk_size);
	    bksymcount = (i4)(bk_size / (MAXLINE + 1));
	    if (bksymcount != symcount && bksymcount != symcount - 1 &&
		bksymcount != symcount + 1)
	    {
		perform_backup = FALSE;
	    }
	}

	if (perform_backup)
	{
	    if (SIopen(&NMBakSymloc, "w", &tfp) == OK)
	    {
		for (sp = s_list; sp != NULL; sp = sp->s_next)
		{
		    STpolycat(3, sp->s_sym, "\t", sp->s_val, buf);
		    STmove(buf, ' ', MAXLINE, buf);

		    buf[MAXLINE - 1] = '\n';
		    buf[MAXLINE] = '\0';
 
               	    if ((status = SIputrec(buf, tfp)) != OK)
			break;
		}
 
		SIclose(tfp);
	    }
	} 
    }

    PEreset();
    return (retval);
}
Esempio n. 4
0
/*
** Writes or erases a transaction log and displays a completion thermometer.
**
** 'context' must not be NULL, and defaults for element 0 & 1 of context
** must have been set.
*/
i4
write_transaction_log(bool create, PM_CONTEXT *context,
	char *log_dir[], char *log_file[],
	void (*message)(char *), void (*init_graph)(bool, i4), 
	i4 graph_size, void (*update_graph)())
{

# define LG_PAGE_SIZE		2048L
# define LG_NUMBER_OF_PAGES	32L	/* Number of pages to write at a time */

    DI_IO 		dio[LG_MAX_FILE];
    char 		buf[LG_PAGE_SIZE * LG_NUMBER_OF_PAGES];
    char		nodename[GL_MAXNAME];
    i4  		i, j, marker, count, num_logs;
    i4 		num_pages, page, part_size, remainder, loop;
    CL_ERR_DESC 	err;
    char		*string;
    LOCATION 		loc[LG_MAX_FILE];
    char 		locbuf[MAX_LOC + 1];
    char 		*path[LG_MAX_FILE];
    i4  		LOinfo_flag;
    LOINFORMATION 	loc_info;
    i8 		size;
    CS_SCB 		scb;
    bool		size_in_kbytes = FALSE;

    MEfill( sizeof( scb ), 0, ( PTR ) &scb ); 
    
    ++graph_size;

    /* Prepare transaction for log LOCATION(s) */
    for (num_logs = 0; num_logs < LG_MAX_FILE; num_logs++)
    {
	if (log_dir[num_logs] == 0)
	    break;
	STcopy( log_dir[num_logs], locbuf );
	LOfroms( PATH, locbuf, &loc[num_logs] );
	LOfstfile( log_file[num_logs], &loc[num_logs] );
	LOtos( &loc[num_logs], &path[num_logs] );
    }

    /* get size (in bytes) of log file to be created or erased */
    if( create )
    {
	STATUS status;
	char *value;
	bool havevalue = FALSE;

	status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value );
	if ( status == OK )
	{
	    havevalue = TRUE;
	    size_in_kbytes = TRUE;
	}

	if ( havevalue == FALSE )
	{
	    status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value );
	    if ( status == OK )
		havevalue = TRUE;
	}

	if ( havevalue == FALSE )
	{
	    if ( message != NULL )
	    {
		char msg[ BIG_ENOUGH ];
		STprintf( msg, ERx( "%s %s" ),
			PMmExpandRequest( context,
			ERx( "$.$.rcp.file.kbytes" ) ),
			"not found." );
		message( msg );
	    }
	    return( 0 );	
	}
	CVal8( value, &size );
    }
    else
    {
	LOinfo_flag = LO_I_SIZE;
	size = 0;

	for (i = 0; i < num_logs; i++)
	{
	    if ( LOinfo( &loc[i], &LOinfo_flag, &loc_info ) != OK )
	    {
		if ( message != NULL )
		{
		    char msg[ BIG_ENOUGH ];

		    STprintf( msg,
			    "Unable to get size of transaction log:\n\n\t%s",
			    path[i] );	
		    (*message)( msg );
		}
		return( 0 );	
	    }
	    else
		size += loc_info.li_size;
	    if ((LOinfo_flag & LO_I_SIZE) == 0)
		break;
	}

	if ( (LOinfo_flag & LO_I_SIZE) == 0 || size == 0L)
	{
	    STATUS status;
	    char *value;
	    bool havevalue = FALSE;

	    status = PMmGet( context, ERx( "$.$.rcp.file.kbytes" ), &value );
	    if ( status == OK )
	    {
		havevalue = TRUE;
		size_in_kbytes = TRUE;
	    }

	    if ( havevalue == FALSE )
	    {
		status = PMmGet( context, ERx( "$.$.rcp.file.size" ), &value );
		if ( status == OK )
		    havevalue = TRUE;
	    }

	    if ( havevalue == FALSE  )
	    {
		if ( message != NULL )
		{
		    char msg[ BIG_ENOUGH ];

		    STprintf( msg, ERx( "%s %s." ),
			    PMmExpandRequest( context,
			    ERx( "$.$.rcp.file.kbytes" ) ),
			    "not found." );
		    message( msg );
		}
		return( 0 );	
	    }
	    CVal8( value, &size );
	}
    }

    for (i = 0; i < num_logs; i++)
    {
	if ( create && LOexist( &loc[i] ) == OK )
	{
		char msg[ BIG_ENOUGH ];

		if ( message != NULL )
		{
			STprintf( msg, "%s already exists.", path[i] ); 
			(*message)( msg ); 
			STprintf( msg, "To create a new transaction log, you must first delete all partitions of the old one." ); 
			(*message)( msg ); 
		}
		return( 0 );	
	}
    }

    if ( CSinitiate( (i4 *) NULL, (char ***) NULL, (CS_CB *) NULL )
	    != OK )
    {
	    if ( message != NULL )
		    message( "Unable to connect to shared memory" );
	    return( 0 );	
    }

    CSset_sid( &scb );

    /* create DI file */
    for (i = 0; i < num_logs; i++)
    {
	if ( create && DIcreate( &dio[i], 
		log_dir[i],  (u_i4)STlength(log_dir[i]), 
		log_file[i], (u_i4)STlength(log_file[i]),
		(i4)LG_PAGE_SIZE, &err) != OK )
	{
	    char msg[ BIG_ENOUGH ];

	    if ( message != NULL )
	    {
		STprintf( msg,
			"Unable to create transaction log:\n\n\t%s",
			path[i] );	
		(*message)( msg );
	    }
	    return( 0 );
	}

	/* open DI file */
	if ( DIopen( &dio[i],
		log_dir[i],  (u_i4)STlength(log_dir[i]), 
		log_file[i], (u_i4)STlength(log_file[i]),
		(i4)LG_PAGE_SIZE, DI_IO_WRITE, 0, &err) != OK )
	{
	    if ( message != NULL )
	    {
		char msg[ BIG_ENOUGH ];

		STprintf( msg,
			"Unable to open transaction log:\n\n\t%s",
			path[i] );	
		(*message)( msg );
	    }
	    return( 0 );
	}
    }

    if ( size_in_kbytes == FALSE )
	size = (size + 1023) / 1024;

    (*init_graph)( create, (i4) size );

    num_pages = size / (LG_PAGE_SIZE/1024);

    part_size = num_pages / num_logs;

    /* Readjust num_pages to be a multiple of num_logs */
    num_pages = part_size * num_logs;

    loop = part_size / LG_NUMBER_OF_PAGES;
    remainder = part_size % LG_NUMBER_OF_PAGES;

    marker = loop / graph_size;

    /* Fill buffer with zeroes */
    MEfill( sizeof( buf ), 0 , buf);

    for (i = 0; i < num_logs; i++)
    {
	if ( create &&
		DIalloc( &dio[i], part_size, &page, &err ) != OK )
	{
	    DIdelete( &dio[i], log_dir[i], (u_i4)STlength( log_dir[i] ),
		    log_file[i], (u_i4)STlength( log_file[i] ), &err );
	    if ( message != NULL )
		    (*message)( "Unable to allocate space in transaction log file." );
	    return( 0 );
	}
    }

    count = 0;
    for( j = 0; j < loop; j++ )
    {
	i4	n = LG_NUMBER_OF_PAGES;
	i4	page_no = j * n;

	for (i = 0; i < num_logs; i++)
	{
	    if ( DIwrite( &dio[i], &n, page_no, 
			buf, &err ) != OK )
	    {
		DIdelete( &dio[i], 
		    log_dir[i], (u_i4)STlength(log_dir[i]),
		    log_file[i], (u_i4)STlength(log_file[i]),
		    &err );
		if ( message != NULL )
			(*message)( "Unable to continue writing transaction log." );
		return( 0 );
	    }
	}

	if ( j >= marker && j % marker == 0 &&
		(f4) ((f4) j / (f4) loop) >= ((f4) count + 1) /
		graph_size )
	{
	    ++count;
	    (*update_graph)();
	    SIflush( stdout );
	}
    }

    if (remainder)
    {
	i4	page_no = loop * LG_NUMBER_OF_PAGES;

	for (i = 0; i < num_logs; i++)
	{
	    if ( DIwrite( &dio[i], &remainder, page_no,
			buf, &err ) != OK )
	    {
		DIdelete( &dio[i], 
		    log_dir[i], (u_i4)STlength(log_dir[i]),
		    log_file[i], (u_i4)STlength(log_file[i]),
		    &err );
		if ( message != NULL )
			(*message)( "Unable to continue writing transaction log." );
		return( 0 );
	    }
	}
    }

    for (i = 0; i < num_logs; i++)
    {
	if ( DIforce( &dio[i], &err ) != OK )
	{
	    DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]),
		    log_file[i], (u_i4)STlength(log_file[i]), &err );
	    if ( message != NULL )
		(*message)( "Unable to force changes to transaction log." );
	    return( 0 );
	}

	if ( create && DIflush( &dio[i], &err ) != OK )
	{
	    DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]),
		    log_file[i], (u_i4)STlength(log_file[i]), &err );
	    if ( message != NULL )
		(*message)( "Unable to flush transaction log to disk." );
	    return( 0 );
	}

	if( DIclose( &dio[i], &err ) != OK)
	{
	    DIdelete( &dio[i], log_dir[i], (u_i4)STlength(log_dir[i]),
		    log_file[i], (u_i4)STlength(log_file[i]), &err );
	    if ( message != NULL )
		(*message)( "Unable to finish writing transaction log." );
	    return( 0 );
	}
    }

    return( (i4) size );
}
Esempio n. 5
0
/*
** Name: check_path
**
** Description:
**      Function to test the specified path for:
**          1. Valid characters.
**          2. An existing or valid parent directory.
**          3. Write permissions for 2.
**
** Inputs:
**      chkpath     pointer to the path string for validation.
**      eflags      flags specifying the actions to be taken.
**
** Outputs:
**      None.
**
** Returns:
**      OK          Path validation successful.
**      !OK         Path validation failed.
**
** History:
**      27-Jun-2005 (fanra01)
**          Created.
**      11-Jul-2005 (fanra01)
**          Return a more specific status code.
*/
static STATUS
check_path( char* chkpath, int eflags )
{
    STATUS          status = II_SUCCESSFUL;
    STATUS          rc;
    int             retcode = FAIL;
    LOCATION        tloc;                      /* target location */
    LOCATION        wloc;                      /* working location */
    LOCATION        cloc;                      /* working location */
    LOINFORMATION   linfo;
    i4              info;
    char*           temp = NULL;
    char*           path = NULL;
    char*           work = NULL;
    char*           curr = NULL;
    char*	        d;
    char*           p;
    char*           f;
    char*           e;
    char*           v;
    
    char*           s;

    while(TRUE)
    {
        /*
        ** Allocate working area up front.  Saves declaring arrays on the
        ** stack.
        */
        if ((temp = MEreqmem( 0, (MAX_LOC+1) * 8, TRUE, &status )) == NULL)
        {
            break;
        }
        
        /*
        ** Initialize working pointers with memory
        */
        path = temp;
        work = temp + MAX_LOC + 1;
        curr = work + MAX_LOC + 1;
        d = curr + MAX_LOC + 1;
        p = d + MAX_LOC + 1;
        f = p + MAX_LOC + 1;
        e = f + MAX_LOC + 1;
        v = e + MAX_LOC + 1;

        /*
        ** Initialize a location structure with the specified path
        ** string.
        */
        if ((eflags & (II_CHK_PATHCHAR | II_CHK_PATHDIR | II_CHK_PATHPERM)) &&
            (LOfroms( PATH, chkpath, &tloc ) != OK))
        {
            status = II_BAD_PATH;
            break;
        }

        /*
        ** Perform an illegal characters check, for all path tests.
        */
        if ((eflags & (II_CHK_PATHCHAR | II_CHK_PATHDIR | II_CHK_PATHPERM)) &&
            (check_path_chars( &tloc, &rc )))
        {
            switch(rc)
            {
                case LO_BAD_DEVICE:
                    status = II_BAD_PATH;
                    break;
                case LO_NOT_PATH:
                case LO_NOT_FILE:
                default:
                    status = II_INVAL_CHARS_IN_PATH;
                    break;
            }
            break;
        }

        /*
        ** Duplicate the specified path location into a work location.
        */
        LOcopy( &tloc, work, &wloc );
        
        /*
        ** Create an empty location for the current working device,
        ** split the target path into components and
        ** create a location of the target device.
        */
        if ((eflags & (II_CHK_PATHDIR | II_CHK_PATHPERM)) &&
            ((status = LOfroms( PATH, curr, &cloc )) == OK) &&
            ((status = LOdetail( &wloc, d, p, f, e, v )) == OK) &&
            ((status = LOcompose( d, CURR_DIR, NULL, NULL, NULL,
            &cloc )) == OK))
        {
            /*
            ** Save the current working directory
            */
            LOsave();
            
            /*
            ** Change working path to the target device
            */
            status = LOchange( &cloc );
        
            /*
            ** Starting with the whole path work backwards looking for
            ** a valid directory
            */
            for (s=work, info=0;
                (status == OK) && (retcode != OK) && (s != NULL);
                )
            {
                if ((status = LOfroms( PATH, p, &wloc )) != OK)
                {
                    status = II_BAD_PATH;
                    break;
                }
                /*
                ** Reset requested information flags for each iteration.
                */
                info = (LO_I_TYPE | LO_I_PERMS);

                switch(retcode = LOinfo( &wloc, &info, &linfo ))
                {
                    case OK:
                        /*
                        ** If the path or permission test is requested and
                        ** type info is returned test for directory flag. 
                        */
                        if ((eflags & (II_CHK_PATHDIR | II_CHK_PATHPERM)) &&
                            ((info & LO_I_TYPE) == LO_I_TYPE))
                            status = (linfo.li_type == LO_IS_DIR) ? OK : II_PATH_NOT_DIR;

                        /*
                        ** If the permission test is requested and
                        ** permissions are returned test the flags for read
                        ** and write.
                        */
                        if ((status == OK) && (eflags & II_CHK_PATHPERM))
                        {
                            if (((info & LO_I_PERMS) == LO_I_PERMS) &&
                                (linfo.li_perms & (LO_P_READ|LO_P_WRITE))
                                == (LO_P_READ|LO_P_WRITE))
                            {
                                /*
                                ** Read and write permission
                                */
                                break;
                            }
                            else
                            {
                                /*
                                ** missing a permission
                                */
                                status = II_PATH_CANNOT_WRITE;
                            }
                        }
                        else
                        {
                            break;
                        }
                    case LO_NO_SUCH:
                        /*
                        ** Look backwards for the next path separator
                        */
                        if((s = STrindex( p, PATH_SEPARATOR, 0 )) != NULL)
                        {
                            /*
                            ** If separator found truncate the path
                            ** otherwise the start of the path has
                            ** been reached, update string to test the
                            ** root directory.
                            */
                            if (s != p)
                            {
                                *s = '\0';
                            }
                            else
                            {
                                *(s+1) = '\0';
                            }
                        }
                        else
                        {
                            /*
                            ** A root path character was included in the
                            ** path that has been reached and still no
                            ** installable area found.
                            */                                
                            if (p && *p && *p == SLASH)
                            {
                                status = II_BAD_PATH;
                            }
                            else
                            {
                                /*
                                ** A relative path was specified and no
                                ** installable area has been found.
                                ** Test the current working directory of the
                                ** target device.
                                */
                                if ((status = LOgt( p, &wloc )) == OK)
                                {
                                    /*
                                    ** Reset temporary pointer to a work
                                    ** area to satisfy the loop condition.
                                    */
                                    s = work;
                                }
                            }
                        }
                        break;
                    default:
                        status = II_BAD_PATH;
                        break;
                }
            }
            break;
        }
        else
        {
            if (status != II_SUCCESSFUL)
            {
                status = II_BAD_PATH;
            }
            break;
        }
    }
    /*
    ** Free the working area
    */
    if (temp != NULL)
    {
        MEfree( temp );
    }
    return(status);
}
Esempio n. 6
0
/*{
** Name: II_PrecheckInstallation - Pre-check installation environment
**
** Description:
**	Verify that a machine environment will support the current release of
**	Ingres. The following checks are made:
**(E
**	a. A minimum operating system version
**	b. Other required software (currently none)
**	c. Check the install path
**	   - exists
**	   - that user can write to it
**	   - does not have any disallowed characters (Windows only).
**)E
**
** Inputs:
**	response_file	path to the Embedded Ingres response file.
**                  For more information concerning response file options
**                  please see the Ingres Embedded Edition User Guide.
**
** Outputs:
**  error_msg       Message text for status.  If the message text exceeds
**                  MAX_IIERR_LEN then the message is truncated to
**                  MAX_IIERR_LEN.
**                  Unchanged if II_SUCCESSFUL is returned.
**
** Returns:
**  II_SUCCESSFUL           The environment test completed successfully
**  II_NULL_PARAM           The parameters passed are invalid
**  II_NO_INSTALL_PATH      Error reading response file or no II_SYSTEM entry
**  II_CHARMAP_ERROR        Error processing character mapping file
**  II_GET_COMPUTER_FAIL    Attempt to retrieve computer name failed
**  II_INVALID_HOST         Computer name contains illegal characters
**  II_GET_HOST_FAILED      Attempt to retrieve the network name failed
**  II_INVALID_USER         The username contains illegal characters
**  II_UNMATCHED_NAME       Computer name does not match network name
**  II_OS_NOT_MIN_VERSION   OS version does not meet the minimum requirement
**  II_BAD_PATH             The II_SYSTEM path is incorrectly formed
**  II_INVAL_CHARS_IN_PATH  The II_SYSTEM path contains illegal characters
**  II_PATH_NOT_DIR         The II_SYSTEM path is not a directory
**  II_PATH_CANNOT_WRITE    No write permission in the II_SYSTEM directory
**  II_PATH_EXCEEDED        Length of the path exceeds permitted maximum
**
** Example:
**  # include "tngapi.h"
**
**  # if defined(UNIX)
**  II_CHAR reponsefile[] = {"./ingres.rsp"};
**  # else
**  II_CHAR reponsefile[] = {".\\ingres.rsp"};
**  # endif
**  II_INT4 status;
**  II_CHAR error_msg[MAX_IIERR_LEN + 1] = { '\0' };
**
**  if ((status = II_PrecheckInstallation( responsefile, error_msg )) !=
**      II_SUCCESSFUL)
**  {
**      printf( "II_PrecheckInstallation failed - %s\n", error_msg );
**  }
**
** Side Effects:
**	none
**
** History:
**	16-apr-2002 (abbjo03)
**	    Written.
**  11-Jul-2005 (fanra01)
**      Add more specific status code from check_path_chars.
*/
int
II_PrecheckInstallation(
char	*response_file,
char	*error_msg)
{
    LOCATION		loc;
    char		buf[MAX_LOC];
    char		charmap[MAX_LOC+1];
    LOINFORMATION	loinfo;
    i4			flags;
    int			result;
    CL_ERR_DESC clerr;

    if (!response_file || !error_msg)
    {
        result = II_NULL_PARAM;
        if (error_msg)
            II_GetErrorMessage(error_msgs[result], error_msg);
        return result;
    }

    if (!GetPrivateProfileString("Ingres Configuration", "II_SYSTEM", "", buf,
	    sizeof(buf), response_file))
    {
        result = II_NO_INSTALL_PATH;
        II_GetErrorMessage(error_msgs[result], error_msg);
        return result;
    }
    
    /*
    ** Get the charmap field from the response file.
    */
    if (!GetPrivateProfileString("Ingres Configuration", II_CHARMAP, "",
        charmap, sizeof(charmap), response_file))
    {
        result = II_NO_CHAR_MAP;
        II_GetErrorMessage(error_msgs[result], error_msg);
        return result;
    }

    /*
    ** Open and read the character map specified in the response file.
    ** This is a special installation character description file.
    */
#if defined(UNIX)
    if ((result = CMset_attr( charmap, &clerr )) != 0)
#else
    if ((result = CMread_attr( II_CHARSET, charmap, &clerr )) != 0)
#endif 
    {
        result = II_CHARMAP_ERROR;
        II_GetErrorMessage( error_msgs[result], error_msg );
        return(result);
    }

    if ((result = check_user()) != II_SUCCESSFUL)
    {
        II_GetErrorMessage( error_msgs[result], error_msg );
        return(result);
    }

    if ((result = check_host()) != II_SUCCESSFUL)
    {
        II_GetErrorMessage( error_msgs[result], error_msg );
        return(result);
    }
    
    if (check_platform( II_DEFARCH ) != OK)
    {
	result = II_OS_NOT_MIN_VERSION;
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }

    if (LOfroms(PATH & FILENAME, buf, &loc) != OK)
    {
	result = II_BAD_PATH;
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }

    flags = LO_I_TYPE | LO_I_PERMS;
    if (LOinfo(&loc, &flags, &loinfo) != OK)
    {
	result = II_BAD_PATH;
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }

    if ((flags & LO_I_TYPE) == 0 || loinfo.li_type != LO_IS_DIR)
    {
	result = II_PATH_NOT_DIR;
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }
    if ((flags & LO_I_PERMS) == 0 || (loinfo.li_perms & LO_P_WRITE) == 0)
    {
	result = II_PATH_CANNOT_WRITE;
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }
    
    if (check_path_chars(&loc, &result))
    {
        switch(result)
        {
            case LO_BAD_DEVICE:
                result = II_BAD_PATH;
                break;
            case LO_NOT_PATH:
            case LO_NOT_FILE:
            default:
                result = II_INVAL_CHARS_IN_PATH;
                break;
        }
	II_GetErrorMessage(error_msgs[result], error_msg);
	return result;
    }
    
    result = II_SUCCESSFUL;
    II_GetErrorMessage(error_msgs[result], error_msg);
    return result;
}