platform_win32.c
author Ryan C. Gordon <icculus@icculus.org>
Thu, 02 Feb 2006 07:07:03 +0000
changeset 104 339482f858af
parent 98 4912346d49c9
child 108 0b8bcaef83e7
permissions -rw-r--r--
Argh, really fix byte order serialization.
icculus@0
     1
icculus@0
     2
#include <windows.h>
icculus@0
     3
#include <io.h>
icculus@0
     4
#include <direct.h>
icculus@0
     5
icculus@0
     6
#include "platform.h"
icculus@0
     7
icculus@0
     8
int file_exists(const char *fname)
icculus@0
     9
{
icculus@0
    10
    return(GetFileAttributes(fname) != 0xffffffff);
icculus@0
    11
} /* file_exists */
icculus@0
    12
icculus@0
    13
icculus@0
    14
int file_is_directory(const char *fname)
icculus@0
    15
{
icculus@0
    16
    return((GetFileAttributes(fname) & FILE_ATTRIBUTE_DIRECTORY) != 0);
icculus@0
    17
} /* file_is_directory */
icculus@0
    18
icculus@0
    19
icculus@0
    20
int file_is_symlink(const char *fname)
icculus@0
    21
{
icculus@0
    22
    return(0);
icculus@0
    23
} /* file_is_symlink */
icculus@0
    24
icculus@0
    25
icculus@0
    26
static const char *win32strerror(void)
icculus@0
    27
{
icculus@0
    28
    static TCHAR msgbuf[255];
icculus@0
    29
icculus@0
    30
    FormatMessage(
icculus@0
    31
        FORMAT_MESSAGE_FROM_SYSTEM |
icculus@0
    32
        FORMAT_MESSAGE_IGNORE_INSERTS,
icculus@0
    33
        NULL,
icculus@0
    34
        GetLastError(),
icculus@0
    35
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
icculus@0
    36
        msgbuf,
icculus@0
    37
        sizeof (msgbuf) / sizeof (TCHAR),
icculus@0
    38
        NULL 
icculus@0
    39
    );
icculus@0
    40
icculus@0
    41
    return((const char *) msgbuf);
icculus@0
    42
} /* win32strerror */
icculus@0
    43
icculus@0
    44
icculus@0
    45
/* enumerate contents of (base) directory. */
icculus@0
    46
file_list *make_filelist(const char *base)
icculus@0
    47
{
icculus@0
    48
    file_list *retval = NULL;
icculus@0
    49
    file_list *l = NULL;
icculus@0
    50
    file_list *prev = NULL;
icculus@0
    51
    HANDLE dir;
icculus@0
    52
    WIN32_FIND_DATA ent;
icculus@0
    53
    char wildcard[MAX_PATH];
icculus@0
    54
    snprintf(wildcard, sizeof (wildcard), "%s\\*", base);
icculus@0
    55
icculus@0
    56
    dir = FindFirstFile(wildcard, &ent);
icculus@0
    57
    if (dir == INVALID_HANDLE_VALUE)
icculus@0
    58
    {
icculus@0
    59
        fprintf(stderr, "Error: Can't list files in %s: %s.\n", base, win32strerror());
icculus@0
    60
        return(NULL);
icculus@0
    61
    } /* if */
icculus@0
    62
icculus@0
    63
    while (FindNextFile(dir, &ent) != 0)
icculus@0
    64
    {
icculus@0
    65
        if (strcmp(ent.cFileName, ".") == 0)
icculus@0
    66
            continue;
icculus@0
    67
icculus@0
    68
        if (strcmp(ent.cFileName, "..") == 0)
icculus@0
    69
            continue;
icculus@0
    70
icculus@0
    71
        l = (file_list *) malloc(sizeof (file_list));
icculus@0
    72
        if (l == NULL)
icculus@0
    73
        {
icculus@0
    74
            fprintf(stderr, "Error: out of memory.\n");
icculus@0
    75
            break;
icculus@0
    76
        } /* if */
icculus@0
    77
icculus@0
    78
        l->fname = (char *) malloc(strlen(ent.cFileName) + 1);
icculus@0
    79
        if (l->fname == NULL)
icculus@0
    80
        {
icculus@0
    81
            fprintf(stderr, "Error: out of memory.\n");
icculus@0
    82
            free(l);
icculus@0
    83
            break;
icculus@0
    84
        } /* if */
icculus@0
    85
icculus@0
    86
        strcpy(l->fname, ent.cFileName);
icculus@0
    87
icculus@0
    88
        if (retval == NULL)
icculus@0
    89
            retval = l;
icculus@0
    90
        else
icculus@0
    91
            prev->next = l;
icculus@0
    92
icculus@0
    93
        prev = l;
icculus@0
    94
        l->next = NULL;
icculus@0
    95
    } /* while */
icculus@0
    96
icculus@0
    97
    FindClose(dir);
icculus@0
    98
    return(retval);
icculus@0
    99
} /* make_filelist */
icculus@0
   100
icculus@0
   101
icculus@98
   102
int get_file_size(const char *fname, unsigned int *fsize)
icculus@0
   103
{
icculus@0
   104
    DWORD FileSz;
icculus@0
   105
    DWORD FileSzHigh;
icculus@0
   106
    HANDLE hFil;
icculus@0
   107
icculus@0
   108
    assert(fsize != NULL);
icculus@0
   109
	
icculus@0
   110
	hFil = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
icculus@0
   111
    if (hFil == INVALID_HANDLE_VALUE)
icculus@0
   112
    {
icculus@0
   113
        fprintf(stderr, "Error: Couldn't get size of [%s]: %s.\n", fname, win32strerror());
icculus@0
   114
        return(0);
icculus@0
   115
    } /* if */
icculus@0
   116
icculus@0
   117
    FileSz = GetFileSize(hFil, &FileSzHigh);
icculus@0
   118
    assert(FileSzHigh == 0);
icculus@0
   119
    CloseHandle(hFil);
icculus@0
   120
    *fsize = FileSz;
icculus@0
   121
    return(1);
icculus@0
   122
} /* get_file_size */
icculus@0
   123
icculus@0
   124
icculus@89
   125
char *get_current_dir(char *buf, size_t bufsize);
icculus@0
   126
{
icculus@89
   127
    DWORD buflen = GetCurrentDirectory(bufsize, buf);
icculus@89
   128
    if (buflen <= bufsize)
icculus@0
   129
    {
icculus@89
   130
        *buf = '\0';
icculus@90
   131
        return(NULL);
icculus@0
   132
    } /* if */
icculus@0
   133
icculus@89
   134
    if (buf[buflen - 2] != '\\')
icculus@89
   135
        strcat(buf, "\\");
icculus@0
   136
icculus@89
   137
    return(buf);
icculus@0
   138
} /* get_current_dir */
icculus@0
   139
icculus@0
   140
icculus@0
   141
char *get_realpath(const char *path)
icculus@0
   142
{
icculus@0
   143
    char *retval = NULL;
icculus@0
   144
    char *p = NULL;
icculus@0
   145
icculus@0
   146
    retval = (char *) malloc(MAX_PATH);
icculus@0
   147
    if (retval == NULL)
icculus@0
   148
    {
icculus@0
   149
        fprintf(stderr, "Error: out of memory.\n");
icculus@0
   150
        return(NULL);
icculus@0
   151
    } /* if */
icculus@0
   152
icculus@0
   153
        /*
icculus@0
   154
         * If in \\server\path format, it's already an absolute path.
icculus@0
   155
         *  We'll need to check for "." and ".." dirs, though, just in case.
icculus@0
   156
         */
icculus@0
   157
    if ((path[0] == '\\') && (path[1] == '\\'))
icculus@0
   158
        strcpy(retval, path);
icculus@0
   159
icculus@0
   160
    else
icculus@0
   161
    {
icculus@0
   162
        char *currentDir = get_current_dir();
icculus@0
   163
        if (currentDir == NULL)
icculus@0
   164
        {
icculus@0
   165
            free(retval);
icculus@0
   166
            fprintf(stderr, "Error: out of memory.\n");
icculus@0
   167
            return(NULL);
icculus@0
   168
        } /* if */
icculus@0
   169
icculus@0
   170
        if (path[1] == ':')   /* drive letter specified? */
icculus@0
   171
        {
icculus@0
   172
            /*
icculus@0
   173
             * Apparently, "D:mypath" is the same as "D:\\mypath" if
icculus@0
   174
             *  D: is not the current drive. However, if D: is the
icculus@0
   175
             *  current drive, then "D:mypath" is a relative path. Ugh.
icculus@0
   176
             */
icculus@0
   177
            if (path[2] == '\\')  /* maybe an absolute path? */
icculus@0
   178
                strcpy(retval, path);
icculus@0
   179
            else  /* definitely an absolute path. */
icculus@0
   180
            {
icculus@0
   181
                if (path[0] == currentDir[0]) /* current drive; relative. */
icculus@0
   182
                {
icculus@0
   183
                    strcpy(retval, currentDir);
icculus@0
   184
                    strcat(retval, path + 2);
icculus@0
   185
                } /* if */
icculus@0
   186
icculus@0
   187
                else  /* not current drive; absolute. */
icculus@0
   188
                {
icculus@0
   189
                    retval[0] = path[0];
icculus@0
   190
                    retval[1] = ':';
icculus@0
   191
                    retval[2] = '\\';
icculus@0
   192
                    strcpy(retval + 3, path + 2);
icculus@0
   193
                } /* else */
icculus@0
   194
            } /* else */
icculus@0
   195
        } /* if */
icculus@0
   196
icculus@0
   197
        else  /* no drive letter specified. */
icculus@0
   198
        {
icculus@0
   199
            if (path[0] == '\\')  /* absolute path. */
icculus@0
   200
            {
icculus@0
   201
                retval[0] = currentDir[0];
icculus@0
   202
                retval[1] = ':';
icculus@0
   203
                strcpy(retval + 2, path);
icculus@0
   204
            } /* if */
icculus@0
   205
            else
icculus@0
   206
            {
icculus@0
   207
                strcpy(retval, currentDir);
icculus@0
   208
                strcat(retval, path);
icculus@0
   209
            } /* else */
icculus@0
   210
        } /* else */
icculus@0
   211
icculus@0
   212
        free(currentDir);
icculus@0
   213
    } /* else */
icculus@0
   214
icculus@0
   215
    /* (whew.) Ok, now take out "." and ".." path entries... */
icculus@0
   216
icculus@0
   217
    p = retval;
icculus@0
   218
    while ( (p = strstr(p, "\\.")) != NULL)
icculus@0
   219
    {
icculus@0
   220
            /* it's a "." entry that doesn't end the string. */
icculus@0
   221
        if (p[2] == '\\')
icculus@0
   222
            memmove(p + 1, p + 3, strlen(p + 3) + 1);
icculus@0
   223
icculus@0
   224
            /* it's a "." entry that ends the string. */
icculus@0
   225
        else if (p[2] == '\0')
icculus@0
   226
            p[0] = '\0';
icculus@0
   227
icculus@0
   228
            /* it's a ".." entry. */
icculus@0
   229
        else if (p[2] == '.')
icculus@0
   230
        {
icculus@0
   231
            char *prevEntry = p - 1;
icculus@0
   232
            while ((prevEntry != retval) && (*prevEntry != '\\'))
icculus@0
   233
                prevEntry--;
icculus@0
   234
icculus@0
   235
            if (prevEntry == retval)  /* make it look like a "." entry. */
icculus@0
   236
                memmove(p + 1, p + 2, strlen(p + 2) + 1);
icculus@0
   237
            else
icculus@0
   238
            {
icculus@0
   239
                if (p[3] != '\0') /* doesn't end string. */
icculus@0
   240
                    *prevEntry = '\0';
icculus@0
   241
                else /* ends string. */
icculus@0
   242
                    memmove(prevEntry + 1, p + 4, strlen(p + 4) + 1);
icculus@0
   243
icculus@0
   244
                p = prevEntry;
icculus@0
   245
            } /* else */
icculus@0
   246
        } /* else if */
icculus@0
   247
icculus@0
   248
        else
icculus@0
   249
        {
icculus@0
   250
            p++;  /* look past current char. */
icculus@0
   251
        } /* else */
icculus@0
   252
    } /* while */
icculus@0
   253
icculus@0
   254
        /* shrink the retval's memory block if possible... */
icculus@0
   255
    p = (char *) realloc(retval, strlen(retval) + 1);
icculus@0
   256
    if (p != NULL)
icculus@0
   257
        retval = p;
icculus@0
   258
icculus@0
   259
    return(retval);
icculus@0
   260
} /* get_realpath */
icculus@0
   261
icculus@0
   262
icculus@0
   263
int main(int argc, char **argv)   /* !!! FIXME: WinMain, in the future? */
icculus@0
   264
{
icculus@0
   265
    return(mojopatch_main(argc, argv));
icculus@0
   266
} /* main */
icculus@0
   267
icculus@0
   268
/* end of platform_win32.c ... */
icculus@0
   269