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 + -
显示快捷键?