unixutil.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,877 行 · 第 1/4 页

C
1,877
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Installer utility functions for Unix.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <dirent.h>
#include <string.h>
#include <malloc.h>
#if defined( __UNIX__ ) && !defined( __WATCOMC__ )
  #include <alloca.h>
#endif
#include <fcntl.h>
#include <ctype.h>
#include <setjmp.h>
#include <limits.h>
#include <process.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utime.h>
#include "gui.h"
#include "text.h"
#include "setupinf.h"
#include "setup.h"
#include "genvbl.h"
#include "gendlg.h"
#include "guiutil.h"
#include "utils.h"
#include "disksize.h"
#include "wpack.h"

#include "errno.h"


extern void     BumpStatus( long );

bool            ConfigModified = FALSE;
static enum { SRC_UNKNOWN, SRC_CD, SRC_DISK } SrcInstState;

int             SkipDialogs;
char            *VariablesFile;
//DEF_VAR         *ExtraVariables;
int             Invisible;

#ifdef PATCH
extern int      InitIO( void );
extern int      Decode( arccmd *);

static int      DecodeError;
extern int      IsPatch;
#endif
extern bool     CancelSetup;
extern vhandle  UnInstall;
extern vhandle  PreviousInstall;

extern bool ModifyEnvironment( bool uninstall )
/*********************************************/
{
    bool                ret;

    ret = TRUE;
    uninstall = uninstall;
    return( ret );
}

extern bool ModifyStartup( bool uninstall )
/*****************************************/
{
    bool                ret;

    ret = ModifyAutoExec();
    return( ret );
}

typedef struct {
    unsigned long       free_space;
    unsigned            cluster_size;
    unsigned            use_target_for_tmp_file : 1;
    unsigned            fixed : 1;
    unsigned            diskette : 1;
} drive_info;

static drive_info       Drives[32];

typedef __far (HANDLER)( unsigned deverr,
                                  unsigned errcode,
                                  unsigned far *devhdr );

static bool DoSpawnCmd( char *cmd )
{
    bool        rc;

    system( cmd );
    rc = TRUE;
    GUIWndDirty( NULL );
    return( rc );
}


void DoSpawn( when_time when )
{
    char buff[2*_MAX_PATH];
    int         i, num_spawns;

    num_spawns = SimNumSpawns();
    for( i = 0; i < num_spawns; ++i ) {
        if( when != SimWhen( i ) ) continue;
        if( !SimEvalSpawnCondition( i ) ) continue;
        SimGetSpawnCommand( buff, i );
        if( buff[0] == '\0' ) continue;
        DoSpawnCmd( buff );
    }
}


#define TMPFILENAME "_watcom_.tmp"
static void GetTmpFileName( unsigned drive, char *buff )
{
    strcpy( buff, "/tmp" );
    strcat( buff, "/" TMPFILENAME );
}

static void GetTmpFileNameInTarget( unsigned drive, char *buff )
{
    int         i;
    int         max_targets = SimNumTargets();
    int         len;

    for( i = 0; i < max_targets; ++i ) {
        SimTargetDir( i, buff );
        if( tolower( buff[0] ) == tolower( drive ) && buff[1] == ':' ) {
            len = strlen( buff );
            if( len != 0 && buff[len-1] != '/' ) {
                strcat( buff, "/" );
            }
            strcat( buff, TMPFILENAME );
            return;
        }
    }
    GetTmpFileName( drive, buff );
}

void ResetDriveInfo()
{
    int         i;

    for( i = 0; i < sizeof( Drives ) / sizeof( Drives[0] ); ++i ) {
        Drives[ i ].cluster_size = 0;
    }
}

static int GetDriveNum( int drive )
{
    drive = toupper( drive ) - 'A' + 1;
    if( drive < 1 || drive > 26 ) drive = 0;
    return( drive );
}

static unsigned GetDriveInfo( int drive, bool removable )
{
    return 0;
}

static long GetFreeDiskSpace( unsigned drive, bool removable )
/**********************************************************/
{
    return( Drives[ GetDriveInfo( drive, removable ) ].free_space );
}

void ResetDiskInfo()
/******************/
{
    memset( Drives, 0, sizeof( Drives ) );
}

bool IsFixedDisk( unsigned drive )
/************************************/
{
    if( drive == 0 ) return( FALSE );
    // don't bang diskette every time!
    if( Drives[ GetDriveNum( drive ) ].diskette ) return( FALSE );
    return( Drives[ GetDriveInfo( drive, FALSE ) ].fixed != 0 );
}

unsigned GetClusterSize( unsigned drive )
/***************************************/
{
    if( drive == 0 ) return( 1 );
    return( Drives[ GetDriveInfo( drive, FALSE ) ].cluster_size );
}

unsigned UseTargetForTmpFile( unsigned drive )
/*************************************/
{
    if( drive == 0 ) return( 0 );
    return( Drives[ GetDriveInfo( drive, FALSE ) ].use_target_for_tmp_file );
}

// ********** Functions for Creating the destination directory tree **********

static void RemoveDstDir( int dir_index, char *dst_dir )
/**********************************************/
{
    int         child;
    int         max_dirs = SimNumDirs();

    SimDirNoSlash( dir_index, dst_dir );
    if( access( dst_dir, F_OK ) != 0 ) return;
    for( child = 0; child < max_dirs; ++child ) {
        if( SimDirParent( child ) == dir_index ) {
            RemoveDstDir( child, dst_dir );
        }
    }
    if( SimDirParent( dir_index ) == -1 ) {
//        return; // leave root dir (for config.new, etc)
    }
    SimDirNoSlash( dir_index, dst_dir );
    rmdir( dst_dir );
}


void MakeParentDir( char *dir, char *drive, char *path )
{
    char                *parent,*end;
    int                 path_len;

    _splitpath( dir, drive, path, NULL, NULL );
    path_len = strlen( path );
    end = path + path_len - 1;
    if( path_len == 0 ) return;
    if( *end == '\\' || *end == '/' ) {
        *end = '\0';
    }
    if( path[0] == '\0' ) return;
    parent = alloca( strlen( drive ) + path_len + 10 ); // lotsa room
    strcpy( parent, drive );
    strcat( parent, path );
    MakeParentDir( parent, drive, path );
    mkdir( parent, 0777 );
}


static bool CreateDstDir( int i, char *dst_dir )
/**********************************************/
// check for directory existence.  If dir exists return TRUE.
// Else try and create directory.
{
    bool                ok;
    int                 parent;
    char                drive[_MAX_DRIVE];
    char                path[_MAX_PATH];


    parent = SimDirParent( i );
    if( parent != -1 ) {
        ok = CreateDstDir( parent, dst_dir );
        if( !ok ) return( FALSE );
    }
    SimDirNoSlash( i, dst_dir );
    if( access( dst_dir, F_OK ) == 0 ) return( TRUE );          // check for existence
    MakeParentDir( dst_dir, drive, path );
    if( mkdir( dst_dir, 0777 ) == 0 ) return( TRUE );
    MsgBox( NULL, "IDS_CANTMAKEDIR", GUI_OK, dst_dir );
    return( FALSE );
}

static void catnum( char *buff, long num )
{

    char        num_buff[128];
    char        ch;

    ch = ' ';
    if( num < 0 ) {
        num = -num;
        ch = '-';
    }
    if( num < 1000 ) {
        sprintf( num_buff, "%c%d bytes", ch, (int)num );
    } else {
        num /= 1000;
        if( num > 1000000 ) {
            sprintf( num_buff, "%c%d,%3.3d,%3.3dK", ch, (int)((num/1000000)%1000), (int)((num/1000)%1000), (int)(num%1000) );
        } else if( num > 1000 ) {
            sprintf( num_buff, "%c%d,%3.3dK", ch, (int)((num/1000)%1000), (int)(num%1000) );
        } else {
            sprintf( num_buff, "%c%dK", ch, (int)num );
        }
    }
    strcat( buff, num_buff );
}

static bool MatchEnd( char *path, char *end )
/*******************************************/
{
    int plen, endlen;

    plen = strlen( path );
    endlen = strlen( end );
    if( endlen > plen ) return( FALSE );
    return( stricmp( path + plen - endlen, end ) == 0 );
}

static bool FindUpgradeFile( char *path )
/***************************************/
{
    DIR                 *d;
    struct dirent       *info;
    char                *path_end;
    int                 upgrades = SimNumUpgrades();
    int                 i;
    struct stat         statbuf;
    char                full_path[_MAX_PATH];

    StatusAmount( 0,1 );
    StatusLines( STAT_CHECKING, path );
    if( StatusCancelled() ) return( FALSE );
    d = opendir( path );
    path_end = path+strlen(path);
    if( path_end > path && path_end[-1] == '/' ) --path_end;
    *path_end = '/';
    while( ( info = readdir( d ) ) ) {
        strcpy( path_end+1, info->d_name );
        _fullpath( full_path, info->d_name, _MAX_PATH );
        stat( full_path, &statbuf );
        if( S_ISDIR( statbuf.st_mode ) ) {
            if( info->d_name[0] != '.' ) {
                if( FindUpgradeFile( path ) ) return( TRUE );
            }
        } else {
            for( i = 0; i < upgrades; ++i ) {
                if( MatchEnd( path, SimGetUpgradeName( i ) ) ) {
                    return( TRUE );
                }
            }
        }
    }
    *path_end = '\0';
    closedir( d );
    return( FALSE );
}

extern bool CheckUpgrade()
/************************/
{
    char                disk[_MAX_PATH];
    dlg_state           return_state;

    if( GetVariableIntVal( "PreviousInstall" ) ) return( TRUE );
    DoDialog( "UpgradeStart" );
    for( disk[0] = 'c'; disk[0] <= 'z'; disk[0]++ ) {
        if( !IsFixedDisk( disk[0] ) ) continue;
        strcpy( disk+1, ":\\" );
        StatusCancelled();
        if( FindUpgradeFile( disk ) ) return( TRUE );
    }
    return_state = DoDialog( "UpgradeNotQualified" );
    return( return_state != DLG_CAN && return_state != DLG_DONE );
}

extern bool CheckDrive( bool issue_message )
/******************************************/
//check if there is enough disk space
{
// For now assume that there will always be enough space to install the product until we learn how to find out how much
// available disk space there is.

    bool                ret;
    long                free_disk_space;
    long                disk_space_needed;
    long                max_tmp_file;
    int                 max_targs;
    int                 i, j, targ_num;
    char                disks[ MAX_DRIVES ];
    char                disk;
    gui_message_return  reply;
    char                buff[_MAX_PATH];
    char                drive[20];
    struct {
        char    drive;
        long    needed;
        long    max_tmp;
        long    free;
        int     num_files;
    } space[ MAX_DRIVES ];


    for( i = 0; i < MAX_DRIVES; ++i ) {
        space[i].drive = 0;
    }
    ret = TRUE;
    if( !SimCalcTargetSpaceNeeded() ) return( FALSE );
    max_targs = SimNumTargets();
    for( i = 0; i < max_targs; ++i ) {
        // get drive letter for each target
        disks[ i ] = tolower( *SimGetDriveLetter( i ) );
    }
    // check for enough disk space, combine drives that are the same
    for( i = 0; i < max_targs; ++i ) {
        if( islower( disks[ i ] ) || (disks[ i ] == '/') ) {
            targ_num = i;
            disk_space_needed = SimTargetSpaceNeeded( i );
            max_tmp_file = SimMaxTmpFile( i );
            for( j = i + 1; j < max_targs; ++j ) {
                if( disks[ j ] == disks[ i ] ) {
                    targ_num = j;
                    disk_space_needed += SimTargetSpaceNeeded( j );
                    if( SimMaxTmpFile( j ) > max_tmp_file ) {
                        max_tmp_file = SimMaxTmpFile( j );
                    }
                    disks[ j ] = toupper( disks[ j ] );
                }
            }
            free_disk_space = GetFreeDiskSpace( disks[i], FALSE );
            if( free_disk_space == -1 ) free_disk_space = 0;
            space[i].drive = disks[i];
            space[i].free = free_disk_space;
            space[i].needed = disk_space_needed;
            space[i].max_tmp = max_tmp_file;
            space[i].num_files = SimGetTargNumFiles( targ_num );
            if( free_disk_space < disk_space_needed + max_tmp_file ) {
                for( disk = 'c'; disk <= 'z'; ++disk ) {
                    if( disk == tolower( disks[ i ] ) ) continue;
                    if( !IsFixedDisk( disk ) ) continue;
                    if( GetFreeDiskSpace( disk, FALSE ) > max_tmp_file ) {
                        SimSetTargTempDisk( i, disk );
                        for( j = i + 1; j < max_targs; ++j ) {
                            if( tolower( disks[ j ] ) == disks[ i ] ) {
                                SimSetTargTempDisk( j, disk );
                            }
                        }
                        break;
                    }
                    if( disk == 'z' && issue_message ) {
                        MsgBox( NULL, "IDS_NODISKSPACE", GUI_OK,
                                max_tmp_file/1000 );
                        return( FALSE );
                    }
                }
            }
            if( issue_message ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?