summaryrefslogtreecommitdiffstats
path: root/private/windows/diamond/misc.c
blob: 19123737eb4704eef849292ba59cba9d5c80d7f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/***    misc.c - Miscellaneous functions for DIAMOND.EXE
 *
 *      Microsoft Confidential
 *      Copyright (C) Microsoft Corporation 1993-1994
 *      All Rights Reserved.
 *
 *  Author:
 *      Benjamin W. Slivka
 *
 *  History:
 *      25-Apr-1994 bens    Initial version
 *      11-Jul-1994 bens    copyBounded was undercounting by 1 byte
 */

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>

#include "types.h"
#include "asrt.h"
#include "error.h"
#include "mem.h"
#include "message.h"

#include "fileutil.h"

#include "misc.h"
#include "misc.msg"
#include "dfparse.msg"


/***    nameFromTemplate - Construct name from template with * and integer
 *
 *  NOTE: see misc.h for entry/exit conditions.
 */
BOOL nameFromTemplate(char   *pszResult,
                      int     cbResult,
                      char   *pszTemplate,
                      int     i,
                      char   *pszName,
                      PERROR  perr)
{
    char    ach[cbFILE_NAME_MAX];       // Buffer for resulting name
    char    achFmt[cbFILE_NAME_MAX];    // Buffer for sprintf format string
    int     cch;
    int     cWildCards=0;               // Count of wild cards
    char   *pch;
    char   *pchDst;

    //** Replace any wild card characters with %d
    pchDst = achFmt;
    for (pch=pszTemplate; *pch; pch++) {
        if (*pch == chDF_WILDCARD) {    // Got a wild card
            *pchDst++ = '%';            // Replace with %d format specifier
            *pchDst++ = 'd';
            cWildCards++;               // Count how many we see
        }
        else {
            *pchDst++ = *pch;           // Copy character
        }
    }
    *pchDst++ = '\0';                   // Terminate string

    if (cWildCards > 4) {
        ErrSet(perr,pszMISCERR_TWO_MANY_WILDS,"%c%d%s",
                chDF_WILDCARD,4,pszName);
        return FALSE;
    }

    //** Replace first four(4) occurences (just to be hard-coded!)
    cch = sprintf(ach,achFmt,i,i,i,i);

    //** Fail if expanded result is too long
    if (cch >= cbResult) {
        ErrSet(perr,pszMISCERR_EXPANDED_TOO_LONG,"%s%d%s",
                pszName,cbResult-1,ach);
        return FALSE;
    }
    strcpy(pszResult,ach);

    //** Success
    return TRUE;
} /* nameFromTemplate() */


/***    copyBounded - Copy bytes from src to dst, checking for overflow
 *
 *  Entry:
 *      ppszDst - pointer to pointer to destination buffer
 *      pcbDst  - pointer to bytes remaining in destination buffer
 *      ppszSrc - pointer to pointer to source buffer
 *      cbCopy  - Number of bytes to copy
 *                ==> 0 means copy to end of ppszSrc, including NULL terminator
 *
 *  Exit-Success:
 *      Returns TRUE; Bytes copied; *ppszDst, *pcbDst, and *ppszSrc updated.
 *
 *  Exit-Failure:
 *      Returns FALSE; *ppszDst overflowed.
 */
BOOL copyBounded(char **ppszDst, int *pcbDst, char **ppszSrc, int cbCopy)
{
    char    *pszDst = *ppszDst;
    int      cbDst  = *pcbDst;
    char    *pszSrc = *ppszSrc;

    if (cbCopy == 0) {
        //** Copy to end of source string
        //   NOTE: I know the "," operator is pretty obscure, but this
        //         was the most straightforward way I could figure out
        //         to do the string copy and keep cbDst up to date!
        while ((cbDst > 0) && (cbDst--, *pszDst++ = *pszSrc++)) {
        }

        //** Make sure we didn't overflow buffer
        if (pszSrc[-1] != '\0') {      // Oops, didn't get all of source
             return FALSE;
        }
    }
    else {
        //** Copy specified number of bytes or until end of
        //   source string or out of space in destination buffer.
        //   NOTE: I know the "," operator is pretty obscure, but this
        //         was the most straightforward way I could figure out
        //         to do the string copy and keep cbDst and cbCopy up to date!
        while ((cbCopy>0) &&
               (cbDst>0)  &&
               (cbCopy--, cbDst--, *pszDst++ = *pszSrc++)) {
        }

        //** See if we copied all the bytes requested
        if (0 < cbCopy) {           // Did not copy all the bytes
            //** Check if a NULL byte terminated the copy
            if (pszSrc[-1] == '\0') {
                AssertForce("copyBounded(): string has NULL byte",
                                                     __FILE__, __LINE__);
            }
            return FALSE;               // Failure
        }
    }

    //** Update caller's parameters and return success
    Assert((pszDst - *ppszDst) == (*pcbDst - cbDst));
    *ppszDst = pszDst;
    *pcbDst  = cbDst;
    *ppszSrc = pszSrc;

    return TRUE;
} /* copyBounded */