summaryrefslogtreecommitdiff
path: root/os2/suffix.c
blob: d766da37bc4cb6982c739b8de57509a58db308bf (plain)
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
/*
 * Suffix appending for in-place editing under MS-DOS and OS/2.
 *
 * Here are the rules:
 *
 * Style 0:  Append the suffix exactly as standard perl would do it.
 *           If the filesystem groks it, use it.  (HPFS will always
 *           grok it.  FAT will rarely accept it.)
 *
 * Style 1:  The suffix begins with a '.'.  The extension is replaced.
 *           If the name matches the original name, use the fallback method.
 *
 * Style 2:  The suffix is a single character, not a '.'.  Try to add the 
 *           suffix to the following places, using the first one that works.
 *               [1] Append to extension.  
 *               [2] Append to filename, 
 *               [3] Replace end of extension, 
 *               [4] Replace end of filename.
 *           If the name matches the original name, use the fallback method.
 *
 * Style 3:  Any other case:  Ignore the suffix completely and use the
 *           fallback method.
 *
 * Fallback method:  Change the extension to ".$$$".  If that matches the
 *           original name, then change the extension to ".~~~".
 *
 * If filename is more than 1000 characters long, we die a horrible
 * death.  Sorry.
 *
 * The filename restriction is a cheat so that we can use buf[] to store
 * assorted temporary goo.
 *
 * Examples, assuming style 0 failed.
 *
 * suffix = ".bak" (style 1)
 *                foo.bar => foo.bak
 *                foo.bak => foo.$$$	(fallback)
 *                foo.$$$ => foo.~~~	(fallback)
 *                makefile => makefile.bak
 *
 * suffix = "~" (style 2)
 *                foo.c => foo.c~
 *                foo.c~ => foo.c~~
 *                foo.c~~ => foo~.c~~
 *                foo~.c~~ => foo~~.c~~
 *                foo~~~~~.c~~ => foo~~~~~.$$$ (fallback)
 *
 *                foo.pas => foo~.pas
 *                makefile => makefile.~
 *                longname.fil => longname.fi~
 *                longname.fi~ => longnam~.fi~
 *                longnam~.fi~ => longnam~.$$$
 *                
 */

#include "EXTERN.h"
#include "perl.h"
#ifdef OS2
#define INCL_DOSFILEMGR
#define INCL_DOSERRORS
#include <os2.h>
#endif /* OS2 */

static char suffix1[] = ".$$$";
static char suffix2[] = ".~~~";

#define ext (&buf[1000])

add_suffix(str,suffix)
register STR *str;
register char *suffix;
{
    int baselen;
    int extlen;
    char *s, *t, *p;
    STRLEN slen;

    if (!(str->str_pok)) (void)str_2ptr(str);
    if (str->str_cur > 1000)
        fatal("Cannot do inplace edit on long filename (%d characters)", str->str_cur);

#ifdef OS2
    /* Style 0 */
    slen = str->str_cur;
    str_cat(str, suffix);
    if (valid_filename(str->str_ptr)) return;

    /* Fooey, style 0 failed.  Fix str before continuing. */
    str->str_ptr[str->str_cur = slen] = '\0';
#endif /* OS2 */

    slen = strlen(suffix);
    t = buf; baselen = 0; s = str->str_ptr;
    while ( (*t = *s) && *s != '.') {
	baselen++;
	if (*s == '\\' || *s == '/') baselen = 0;
 	s++; t++;
    }
    p = t;

    t = ext; extlen = 0;
    while (*t++ = *s++) extlen++;
    if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; }

    if (*suffix == '.') {        /* Style 1 */
        if (strEQ(ext, suffix)) goto fallback;
	strcpy(p, suffix);
    } else if (suffix[1] == '\0') {  /* Style 2 */
        if (extlen < 4) { 
	    ext[extlen] = *suffix;
	    ext[++extlen] = '\0';
        } else if (baselen < 8) {
   	    *p++ = *suffix;
	} else if (ext[3] != *suffix) {
	    ext[3] = *suffix;
	} else if (buf[7] != *suffix) {
	    buf[7] = *suffix;
	} else goto fallback;
	strcpy(p, ext);
    } else { /* Style 3:  Panic */
fallback:
	(void)bcopy(strEQ(ext, suffix1) ? suffix2 : suffix1, p, 4+1);
    }
    str_set(str, buf);
}

#ifdef OS2
int 
valid_filename(s)
char *s;
{
    HFILE hf;
    USHORT usAction;

    switch(DosOpen(s, &hf, &usAction, 0L, 0, FILE_OPEN,
	OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L)) {
    case ERROR_INVALID_NAME:
    case ERROR_FILENAME_EXCED_RANGE:
	return 0;
    case NO_ERROR:
	DosClose(hf);
	/*FALLTHROUGH*/
    default:
	return 1;
    }
}
#endif /* OS2 */