Commit | Line | Data |
e929a76b |
1 | /* |
2 | * Suffix appending for in-place editing under MS-DOS and OS/2. |
3 | * |
4 | * Here are the rules: |
5 | * |
6 | * Style 0: Append the suffix exactly as standard perl would do it. |
7 | * If the filesystem groks it, use it. (HPFS will always |
8 | * grok it. FAT will rarely accept it.) |
9 | * |
10 | * Style 1: The suffix begins with a '.'. The extension is replaced. |
11 | * If the name matches the original name, use the fallback method. |
12 | * |
13 | * Style 2: The suffix is a single character, not a '.'. Try to add the |
14 | * suffix to the following places, using the first one that works. |
15 | * [1] Append to extension. |
16 | * [2] Append to filename, |
17 | * [3] Replace end of extension, |
18 | * [4] Replace end of filename. |
19 | * If the name matches the original name, use the fallback method. |
20 | * |
21 | * Style 3: Any other case: Ignore the suffix completely and use the |
22 | * fallback method. |
23 | * |
24 | * Fallback method: Change the extension to ".$$$". If that matches the |
25 | * original name, then change the extension to ".~~~". |
26 | * |
27 | * If filename is more than 1000 characters long, we die a horrible |
28 | * death. Sorry. |
29 | * |
30 | * The filename restriction is a cheat so that we can use buf[] to store |
31 | * assorted temporary goo. |
32 | * |
33 | * Examples, assuming style 0 failed. |
34 | * |
35 | * suffix = ".bak" (style 1) |
36 | * foo.bar => foo.bak |
37 | * foo.bak => foo.$$$ (fallback) |
38 | * foo.$$$ => foo.~~~ (fallback) |
39 | * makefile => makefile.bak |
40 | * |
41 | * suffix = "~" (style 2) |
42 | * foo.c => foo.c~ |
43 | * foo.c~ => foo.c~~ |
44 | * foo.c~~ => foo~.c~~ |
45 | * foo~.c~~ => foo~~.c~~ |
46 | * foo~~~~~.c~~ => foo~~~~~.$$$ (fallback) |
47 | * |
48 | * foo.pas => foo~.pas |
49 | * makefile => makefile.~ |
50 | * longname.fil => longname.fi~ |
51 | * longname.fi~ => longnam~.fi~ |
52 | * longnam~.fi~ => longnam~.$$$ |
53 | * |
54 | */ |
55 | |
56 | #include "EXTERN.h" |
57 | #include "perl.h" |
58 | #ifdef OS2 |
59 | #define INCL_DOSFILEMGR |
60 | #define INCL_DOSERRORS |
61 | #include <os2.h> |
62 | #endif /* OS2 */ |
63 | |
64 | static char suffix1[] = ".$$$"; |
65 | static char suffix2[] = ".~~~"; |
66 | |
67 | #define ext (&buf[1000]) |
68 | |
69 | add_suffix(str,suffix) |
70 | register STR *str; |
71 | register char *suffix; |
72 | { |
73 | int baselen; |
74 | int extlen; |
75 | char *s, *t, *p; |
76 | STRLEN slen; |
77 | |
78 | if (!(str->str_pok)) (void)str_2ptr(str); |
79 | if (str->str_cur > 1000) |
80 | fatal("Cannot do inplace edit on long filename (%d characters)", str->str_cur); |
81 | |
82 | #ifdef OS2 |
83 | /* Style 0 */ |
84 | slen = str->str_cur; |
85 | str_cat(str, suffix); |
86 | if (valid_filename(str->str_ptr)) return; |
87 | |
88 | /* Fooey, style 0 failed. Fix str before continuing. */ |
89 | str->str_ptr[str->str_cur = slen] = '\0'; |
90 | #endif /* OS2 */ |
91 | |
92 | slen = strlen(suffix); |
93 | t = buf; baselen = 0; s = str->str_ptr; |
94 | while ( (*t = *s) && *s != '.') { |
95 | baselen++; |
96 | if (*s == '\\' || *s == '/') baselen = 0; |
97 | s++; t++; |
98 | } |
99 | p = t; |
100 | |
101 | t = ext; extlen = 0; |
102 | while (*t++ = *s++) extlen++; |
103 | if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; } |
104 | |
105 | if (*suffix == '.') { /* Style 1 */ |
106 | if (strEQ(ext, suffix)) goto fallback; |
107 | strcpy(p, suffix); |
108 | } else if (suffix[1] == '\0') { /* Style 2 */ |
109 | if (extlen < 4) { |
110 | ext[extlen] = *suffix; |
111 | ext[++extlen] = '\0'; |
112 | } else if (baselen < 8) { |
113 | *p++ = *suffix; |
114 | } else if (ext[3] != *suffix) { |
115 | ext[3] = *suffix; |
116 | } else if (buf[7] != *suffix) { |
117 | buf[7] = *suffix; |
118 | } else goto fallback; |
119 | strcpy(p, ext); |
120 | } else { /* Style 3: Panic */ |
121 | fallback: |
122 | (void)bcopy(strEQ(ext, suffix1) ? suffix2 : suffix1, p, 4+1); |
123 | } |
124 | str_set(str, buf); |
125 | } |
126 | |
127 | #ifdef OS2 |
128 | int |
129 | valid_filename(s) |
130 | char *s; |
131 | { |
132 | HFILE hf; |
133 | USHORT usAction; |
134 | |
135 | switch(DosOpen(s, &hf, &usAction, 0L, 0, FILE_OPEN, |
136 | OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0L)) { |
fe14fcc3 |
137 | case ERROR_INVALID_NAME: |
138 | case ERROR_FILENAME_EXCED_RANGE: |
139 | return 0; |
e929a76b |
140 | case NO_ERROR: |
141 | DosClose(hf); |
142 | /*FALLTHROUGH*/ |
143 | default: |
144 | return 1; |
e929a76b |
145 | } |
146 | } |
147 | #endif /* OS2 */ |