Mercurial > dwindows
diff dwcompat.c @ 1594:6baf177f335c
Rename compat.c/h dwcompat.c/h and configure option to --with-dwcompat.
There are several other projects that include compat.c and compat.h...
To avoid conflicts make sure the header and source files match the library.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Thu, 23 Feb 2012 12:44:15 +0000 |
parents | compat.c@007ed833ac79 |
children | 71e0a3ad07f7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwcompat.c Thu Feb 23 12:44:15 2012 +0000 @@ -0,0 +1,833 @@ +/* $Id$ */ + +#include "dwcompat.h" +#include "dw.h" +#if defined(__OS2__) || defined(__WIN32__) +#include <share.h> +#endif + +#if defined(__UNIX__) || defined(__MAC__) +#if defined(__FreeBSD__) || defined(__MAC__) +#include <sys/param.h> +#include <sys/ucred.h> +#include <sys/mount.h> +#elif defined(__sun__) +#include <sys/mnttab.h> +#include <sys/param.h> +#include <sys/mount.h> +#include <sys/statvfs.h> +#else +#include <mntent.h> +#include <sys/vfs.h> +#endif +#endif +#include <time.h> +#include <errno.h> + +#if defined(__UNIX__) || defined(__MAC__) +void msleep(long period) +{ +#ifdef __sun__ + /* usleep() isn't threadsafe on Solaris */ + struct timespec req; + + req.tv_sec = 0; + if(period >= 1000) + { + req.tv_sec = (int)(period / 1000); + period -= (req.tv_sec * 1000); + } + req.tv_nsec = period * 10000000; + + nanosleep(&req, NULL); +#else + usleep((int)(period * 1000)); +#endif +} +#endif + +int API makedir(char *path) +{ +#if defined(__IBMC__) || defined(__WATCOMC__) || (defined(__WIN32__) && !defined(__CYGWIN32__)) + return mkdir(path); +#else + return mkdir(path,S_IRWXU); +#endif +} + +char * API vargs(char *buf, int len, char *format, ...) +{ + va_list args; + + va_start(args, format); +#ifdef HAVE_VSNPRINTF + vsnprintf(buf, len, format, args); +#else + len = len; + vsprintf(buf, format, args); +#endif + va_end(args); + + return buf; +} + +long double API drivefree(int drive) +{ +#if defined(__EMX__) || defined(__OS2__) + ULONG aulFSInfoBuf[40] = {0}; + APIRET rc = NO_ERROR; + + DosError(FERR_DISABLEHARDERR); + rc = DosQueryFSInfo(drive, + FSIL_ALLOC, + (PVOID)aulFSInfoBuf, + sizeof(aulFSInfoBuf)); + + DosError(FERR_ENABLEHARDERR); + if (rc != NO_ERROR) + return 0; + + return (long double)((double)aulFSInfoBuf[3] * (double)aulFSInfoBuf[1] * (double)aulFSInfoBuf[4]); +#elif defined(__WIN32__) || defined(WINNT) + char buffer[10] = "C:\\"; + DWORD spc, bps, fc, tc; + + buffer[0] = drive + 'A' - 1; + + if(GetDiskFreeSpace(buffer, &spc, &bps, &fc, &tc) == 0) + return 0; + + return (long double)((double)spc*(double)bps*(double)fc); +#elif defined(__FreeBSD__) || defined(__MAC__) + struct statfs *fsp; + int entries, index = 1; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + + for (; entries-- > 0; fsp++) + { + if(index == drive) + return (long double)((double)fsp->f_bsize * (double)fsp->f_bavail); + index++; + } + return 0; +#elif defined(__sun__) + FILE *fp = fopen("/etc/mnttab", "r"); + struct mnttab mnt; + struct statvfs sfs; + int index = 1; + + if(fp) + { + while((getmntent(fp, &mnt) == 0)) + { + if(index == drive) + { + long double size = 0; + + if(mnt.mnt_mountp) + { + if(!statvfs(mnt.mnt_mountp, &sfs)) + { + size = (long double)((double)sfs.f_bsize * (double)sfs.f_bavail); + } + } + fclose(fp); + return size; + } + index++; + } + fclose(fp); + } + return 0; +#else + FILE *fp = setmntent(MOUNTED, "r"); + struct mntent mnt; + struct statfs sfs; + char buffer[1024]; + int index = 1; + + if(fp) + { + while(getmntent_r(fp, &mnt, buffer, sizeof(buffer))) + { + if(index == drive) + { + long double size = 0; + + if(mnt.mnt_dir) + { + if(!statfs(mnt.mnt_dir, &sfs)) + { + size = (long double)((double)sfs.f_bsize * (double)sfs.f_bavail); + } + } + endmntent(fp); + return size; + } + index++; + } + endmntent(fp); + } + return 0; +#endif +} + +long double API drivesize(int drive) +{ +#if defined(__EMX__) || defined(__OS2__) + ULONG aulFSInfoBuf[40] = {0}; + APIRET rc = NO_ERROR; + + DosError(FERR_DISABLEHARDERR); + rc = DosQueryFSInfo(drive, + FSIL_ALLOC, + (PVOID)aulFSInfoBuf, + sizeof(aulFSInfoBuf)); + + DosError(FERR_ENABLEHARDERR); + if (rc != NO_ERROR) + return 0; + + return (long double)((double)aulFSInfoBuf[2] * (double)aulFSInfoBuf[1] * (double)aulFSInfoBuf[4]); +#elif defined(__WIN32__) || defined(WINNT) + char buffer[10] = "C:\\"; + DWORD spc, bps, fc, tc; + + buffer[0] = drive + 'A' - 1; + + if(GetDiskFreeSpace(buffer, &spc, &bps, &fc, &tc) == 0) + return 0; + + return (long double)((double)spc*(double)bps*(double)tc); +#elif defined(__FreeBSD__) || defined(__MAC__) + struct statfs *fsp; + int entries, index = 1; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + + for (; entries-- > 0; fsp++) + { + if(index == drive) + return (long double)((double)fsp->f_bsize * (double)fsp->f_blocks); + index++; + } + return 0; +#elif defined(__sun__) + FILE *fp = fopen("/etc/mnttab", "r"); + struct mnttab mnt; + struct statvfs sfs; + int index = 1; + + if(fp) + { + while(getmntent(fp, &mnt) == 0) + { + if(index == drive) + { + long double size = 0; + + if(mnt.mnt_mountp) + { + if(!statvfs(mnt.mnt_mountp, &sfs)) + { + size = (long double)((double)sfs.f_bsize * (double)sfs.f_blocks); + } + } + fclose(fp); + return size; + } + index++; + } + fclose(fp); + } + return 0; +#else + FILE *fp = setmntent(MOUNTED, "r"); + struct mntent mnt; + char buffer[1024]; + struct statfs sfs; + int index = 1; + + if(fp) + { + while(getmntent_r(fp, &mnt, buffer, sizeof(buffer))) + { + if(index == drive) + { + long double size = 0; + + if(mnt.mnt_dir) + { + if(!statfs(mnt.mnt_dir, &sfs)) + { + size = (long double)((double)sfs.f_bsize * (double)sfs.f_blocks); + } + } + endmntent(fp); + return size; + } + index++; + } + endmntent(fp); + } + return 0; +#endif +} + +int API isdrive(int drive) +{ +#if defined(__EMX__) || defined(__OS2__) + APIRET rc = NO_ERROR; + FSINFO volinfo; + + DosError(FERR_DISABLEHARDERR); + rc = DosQueryFSInfo(drive, + FSIL_VOLSER, + (PVOID)&volinfo, + sizeof(FSINFO)); + + DosError(FERR_ENABLEHARDERR); + if (rc == NO_ERROR) + return 1; + +#elif defined(__WIN32__) || defined(WINNT) + char buffer[10] = "C:\\", volname[100]; + DWORD spc, bps, fc; + + buffer[0] = drive + 'A' - 1; + + if(GetVolumeInformation(buffer, volname, 100, &spc, &bps, &fc, NULL, 0) != 0) + return 1; +#elif defined(__FreeBSD__) || defined(__MAC__) + struct statfs *fsp; + int entries, index = 1; + + entries = getmntinfo (&fsp, MNT_NOWAIT); + + for (; entries-- > 0; fsp++) + { + if(index == drive && fsp->f_blocks) + return 1; + index++; + } + return 0; +#elif defined(__sun__) + FILE *fp = fopen("/etc/mnttab", "r"); + struct mnttab mnt; + struct statvfs sfs; + int index = 1; + + if(fp) + { + while(getmntent(fp, &mnt) == 0) + { + if(index == drive) + { + fclose(fp); + if(mnt.mnt_mountp) + { + if(!statvfs(mnt.mnt_mountp, &sfs) && sfs.f_blocks) + return 1; + } + return 0; + } + index++; + } + fclose(fp); + } +#else + FILE *fp = setmntent(MOUNTED, "r"); + struct mntent mnt; + char buffer[1024]; + struct statfs sfs; + int index = 1; + + if(fp) + { + while(getmntent_r(fp, &mnt, buffer, sizeof(buffer))) + { + if(index == drive) + { + endmntent(fp); + if(mnt.mnt_dir) + { + if(!statfs(mnt.mnt_dir, &sfs) && sfs.f_blocks) + { + return 1; + } + } + return 0; + } + index++; + } + endmntent(fp); + } +#endif + return 0; +} + +void API getfsname(int drive, char *buf, int len) +{ +#if defined(__UNIX__) || defined(__MAC__) +#if defined(__FreeBSD__) || defined(__MAC__) + struct statfs *fsp; + int entries, index = 1; + + strncpy(buf, "Unknown", len); + + entries = getmntinfo (&fsp, MNT_NOWAIT); + + for (; entries-- > 0; fsp++) + { + if(index == drive) + strncpy(buf, fsp->f_mntonname, len); + index++; + } +#elif defined(__sun__) + FILE *fp = fopen("/etc/mnttab", "r"); + struct mnttab mnt; + int index = 1; + + strncpy(buf, "Unknown", len); + + if(fp) + { + while(getmntent(fp, &mnt) == 0) + { + if(index == drive && mnt.mnt_mountp) + strncpy(buf, mnt.mnt_mountp, len); + index++; + } + fclose(fp); + } +#else + FILE *fp = setmntent(MOUNTED, "r"); + struct mntent mnt; + char buffer[1024]; + int index = 1; + + strncpy(buf, "Unknown", len); + + if(fp) + { + while(getmntent_r(fp, &mnt, buffer, sizeof(buffer))) + { + if(index == drive && mnt.mnt_dir) + strncpy(buf, mnt.mnt_dir, len); + index++; + } + endmntent(fp); + } +#endif +#elif defined(__OS2__) + /* No snprintf() on OS/2 ??? */ + len = len; + sprintf(buf, "Drive %c", (char)drive + 'A' - 1); +#else + _snprintf(buf, len, "Drive %c", (char)drive + 'A' - 1); +#endif +} + +void API setfileinfo(char *filename, char *url, char *logfile) +{ + time_t ltime; + struct tm *tm; + char buffer[200], timebuf[200]; +#ifdef __OS2__ + const unsigned fea2listsize = 6000; + char *pData; + EAOP2 eaop2; + PFEA2 pFEA2; +#else + FILE *urlfile; +#endif + + ltime = time(NULL); + + tm = localtime(<ime); + + strftime(timebuf, 200, "%c", tm); + + sprintf(buffer, "%s %s", url, timebuf); + +#ifdef __OS2__ + logfile = logfile; + eaop2.fpGEA2List = 0; + eaop2.fpFEA2List = (PFEA2LIST)malloc(fea2listsize); + pFEA2 = &eaop2.fpFEA2List->list[0]; + + pFEA2->fEA = 0; + /* .COMMENTS is 9 characters long */ + pFEA2->cbName = 9; + + /* space for the type and length field. */ + pFEA2->cbValue = strlen(buffer)+2*sizeof(USHORT); + + strcpy(pFEA2->szName, ".COMMENTS"); + pData = pFEA2->szName+pFEA2->cbName+1; + /* data begins at first byte after the name */ + + *(USHORT*)pData = EAT_ASCII; /* type */ + *((USHORT*)pData+1) = strlen(buffer); /* length */ + strcpy(pData+2*sizeof(USHORT), buffer);/* content */ + + pFEA2->oNextEntryOffset = 0; + + eaop2.fpFEA2List->cbList = ((PCHAR)pData+2*sizeof(USHORT)+ + pFEA2->cbValue)-((PCHAR)eaop2.fpFEA2List); + + DosSetPathInfo((PSZ)filename, + FIL_QUERYEASIZE, + &eaop2, + sizeof(eaop2), + 0); + + free((void *)eaop2.fpFEA2List); +#else + + if((urlfile = fopen(logfile, "a"))!=NULL) + { + fprintf(urlfile, "%s\n", buffer); + fclose(urlfile); + } +#endif +} + +#if defined(__OS2__) || defined(__WIN32__) +typedef struct _fsinfo { + FILE *fp; + int fd; +} FSInfo; + +FSInfo *FSIRoot = NULL; + +#define FSI_MAX 100 +#endif + +/* Sharable fopen() and fclose() calls. */ +FILE * API fsopen(char *path, char *modes) +{ +#if (defined(__OS2__) && !defined(__WATCOMC__)) || defined(__WIN32__) + int z; + + if(!FSIRoot) + FSIRoot = calloc(sizeof(struct _fsinfo), FSI_MAX); + + for(z=0;z<FSI_MAX;z++) + { + if(FSIRoot[z].fd < 1) + { + int s, sopenmode = 0, wrmode = 0; + + /* Check the flags passed */ + for(s=0;s<3;s++) + { + if(modes[s] == 'b') + sopenmode |= O_BINARY; + if(modes[s] == 'r') + wrmode |= O_RDONLY; + if(modes[s] == 'w') + wrmode |= O_WRONLY; + if(modes[s] == 'a') + sopenmode |= O_APPEND; + if(modes[s] == 't') + sopenmode |= O_TEXT; + } + + /* Check the read/write request */ + if((wrmode & O_RDONLY) && (wrmode & O_WRONLY)) + sopenmode |= O_RDWR; + else + sopenmode |= wrmode; + FSIRoot[z].fd = _sopen(path, sopenmode, SH_DENYNO, S_IREAD|S_IWRITE); + if(FSIRoot[z].fd > 0) + { + FSIRoot[z].fp = fdopen(FSIRoot[z].fd, modes); + + return FSIRoot[z].fp; + } + } + } + return NULL; +#else + return fopen(path, modes); +#endif +} + +int API fsclose(FILE *fp) +{ +#if defined(__OS2__) || defined(__WIN32__) + if(FSIRoot) + { + + int z; + for(z=0;z<FSI_MAX;z++) + { + if(fp == FSIRoot[z].fp) + { + int ret = fclose(fp); + close(FSIRoot[z].fd); + FSIRoot[z].fd = 0; + FSIRoot[z].fp = NULL; + return ret; + } + } + } +#endif + return fclose(fp); +} + +char * API fsgets(char *str, int size, FILE *stream) +{ + return fgets(str, size, stream); +} + +int API fsseek(FILE *stream, long offset, int whence) +{ + return fseek(stream, offset, whence); +} + +void API nice_strformat(char *dest, long double val, int dec) +{ + char formatbuf[10]; + char format = 0; + double printval; + + /* 1024 ^ 3 = Gigabytes */ + if(val >= 1073741824L) + { + printval = val/(1073741824L); + format = 'G'; + } + /* 1024 ^ 2 = Megabytes */ + else if(val >= 1048576) + { + printval = val/(1048576); + format = 'M'; + } + /* 1024 = Kilobytes */ + else if(val > 1024) + { + printval = val/1024; + format = 'K'; + } + else + printval = val; + + /* Generate the format string */ + sprintf(formatbuf, "%%.%df%c", dec, format); + /* Create the pretty value */ + sprintf(dest, formatbuf, printval); +} + +/* Update the current working directory based on the + * path of the executable being executed. + */ +void API initdir(int argc, char *argv[]) +{ + if(argc > 0) + { + char *tmpdir = strdup(argv[0]); + int z, len = (int)strlen(argv[0]); + + for(z=len;z > -1;z--) + { + if(tmpdir[z] == '/') + { + tmpdir[z+1] = 0; + setpath(tmpdir); + free(tmpdir); + return; + } + } + free(tmpdir); + } +} + +/* + * Sets the current directory (and drive) information. + * Parameters: + * path: A buffer containing the new path. + * Returns: + * -1 on error. + */ +int API setpath(char *path) +{ +#if defined(__OS2__) || defined(__WIN32__) + if(strlen(path) > 2) + { + if(path[1] == ':') + { + char drive = toupper(path[0]); + _chdrive((drive - 'A')+1); + } + } +#endif + return chdir(path); +} + +static int locale_number = -1, locale_count = 0; +static char **locale_text = NULL; + +void _compat_free_locale(void) +{ + if(locale_text) + { + int z; + + for(z=0;z<locale_count;z++) + { + if(locale_text[z]) + free(locale_text[z]); + } + free(locale_text); + locale_text = NULL; + } +} + +int _stripcrlf(char *buf) +{ + int z, len = (int)strlen(buf); + + for(z=0;z<len;z++) + { + if(buf[z] == '\r' || buf[z] == '\n') + { + buf[z] = 0; + return 1; + } + } + return 1; +} + +#ifdef __WIN32__ +#define LOCALE_CHARACTERS 62 +static char locale_table[LOCALE_CHARACTERS * 2] = { + 0xc0, 0xb7, 0xc1, 0xb5, 0xc2, 0xb6, 0xc3, 0xc7, 0xc4, 0x8e, 0xc5, 0x8f, + 0xc6, 0x92, 0xc7, 0x80, 0xc8, 0xd4, 0xc9, 0x90, 0xcb, 0xd3, 0xcc, 0xde, + 0xcd, 0xd6, 0xce, 0xd7, 0xcf, 0xd8, 0xd0, 0xd1, 0xd1, 0xa5, 0xd2, 0xe3, + 0xd3, 0xe0, 0xd4, 0xe2, 0xd5, 0xe5, 0xd6, 0x99, 0xd8, 0x9d, 0xd9, 0xeb, + 0xda, 0xe9, 0xdb, 0xea, 0xdc, 0x9a, 0xde, 0xed, 0xde, 0xe8, 0xdf, 0xe1, + 0xe0, 0x85, 0xe1, 0xa0, 0xe2, 0x83, 0xe3, 0xc6, 0xe4, 0x84, 0xe5, 0x86, + 0xe6, 0x91, 0xe7, 0x87, 0xe8, 0x8a, 0xe9, 0x82, 0xea, 0x88, 0xeb, 0x89, + 0xec, 0x8d, 0xed, 0xa1, 0xee, 0x8c, 0xef, 0x8b, 0xf0, 0xd0, 0xf1, 0xa4, + 0xf2, 0x95, 0xf3, 0xa3, 0xf4, 0x93, 0xf5, 0xe4, 0xf6, 0x94, 0xf7, 0xf6, + 0xf8, 0x9b, 0xf9, 0x97, 0xfa, 0xa3, 0xfb, 0x96, 0xfc, 0x81, 0xfd, 0xec, + 0xfe, 0xe7, 0xff, 0x9e + +}; + +char locale_convert(int codepage, char c) +{ + int z; + + for(z=0;z<LOCALE_CHARACTERS;z++) + { + if(locale_table[(z*2)+1] == c) + return locale_table[z*2]; + } + return c; +} +#endif + +/* Initialize the locale engine + * Returns: TRUE on success, FALSE on failure. + */ +int API locale_init(char *filename, int my_locale) +{ + FILE *fp = fopen(filename, FOPEN_READ_TEXT); + static char text[1025]; + int count = 0; + + _compat_free_locale(); + + if(fp) + { + if(fgets(text, 1024, fp) && strncasecmp(text, "MESSAGES=", 9) == 0 && (count = atoi(&text[9])) > 0) + { + int current = -1; + + locale_text = calloc(count, sizeof(char *)); + + while(!feof(fp)) + { + if(fgets(text, 1024, fp) && _stripcrlf(text) && + strncasecmp(text, "LOCALE=", 7) == 0) + { + if(current > -1) + { + fclose(fp); + locale_count = count; + locale_number = my_locale; + return 1; + } + if(atoi(&text[7]) == my_locale) + current = 0; + } + else if(current > -1 && current < count) + { + /* Use defaults on blank lines */ + if(text[0]) + { + int x = 0, z, len = (int)strlen(text); + + locale_text[current] = calloc(1, len + 1); + + for(z=0;z<len;z++) + { + if(text[z] == '\\' && (text[z+1] == 'r' || text[z+1] == 'n' + || text[z+1] == '\"' || text[z+1] == '\'')) + { + switch(text[z+1]) + { + case 'r': + locale_text[current][x] = '\r'; + break; + case 'n': + locale_text[current][x] = '\n'; + break; + case '\"': + locale_text[current][x] = '\"'; + break; + case '\'': + locale_text[current][x] = '\''; + break; + } + x++; + z++; + } + else + { +#ifdef __WIN32__ + locale_text[current][x] = locale_convert(1252, text[z]); +#else + locale_text[current][x] = text[z]; +#endif + x++; + } + } + } + current++; + } + } + } + fclose(fp); + } + if(locale_text && count) + { + locale_count = count; + locale_number = my_locale; + return 1; + } + return 0; +} + +/* Retrieve a localized string if available */ +char * API locale_string(char *default_text, int message) +{ + if(locale_number > -1 && message < locale_count && message > -1 && locale_text[message]) + return locale_text[message]; + return default_text; +} +