ocran 1.3.18 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.txt +306 -292
- data/LICENSE.txt +22 -22
- data/README.md +549 -533
- data/exe/ocran +5 -5
- data/ext/extconf.rb +15 -0
- data/lib/ocran/build_constants.rb +16 -16
- data/lib/ocran/build_facade.rb +17 -17
- data/lib/ocran/build_helper.rb +110 -105
- data/lib/ocran/command_output.rb +22 -22
- data/lib/ocran/dir_builder.rb +162 -0
- data/lib/ocran/direction.rb +623 -458
- data/lib/ocran/file_path_set.rb +69 -69
- data/lib/ocran/gem_spec_queryable.rb +172 -172
- data/lib/ocran/host_config_helper.rb +57 -44
- data/lib/ocran/inno_setup_script_builder.rb +111 -111
- data/lib/ocran/launcher_batch_builder.rb +85 -85
- data/lib/ocran/library_detector.rb +61 -61
- data/lib/ocran/library_detector_posix.rb +55 -0
- data/lib/ocran/option.rb +323 -273
- data/lib/ocran/refine_pathname.rb +104 -104
- data/lib/ocran/runner.rb +115 -105
- data/lib/ocran/runtime_environment.rb +46 -46
- data/lib/ocran/stub_builder.rb +298 -264
- data/lib/ocran/version.rb +5 -5
- data/lib/ocran/windows_command_escaping.rb +15 -15
- data/lib/ocran.rb +7 -7
- data/share/ocran/lzma.exe +0 -0
- data/src/Makefile +75 -0
- data/src/edicon.c +161 -0
- data/src/error.c +100 -0
- data/src/error.h +66 -0
- data/src/inst_dir.c +334 -0
- data/src/inst_dir.h +157 -0
- data/src/lzma/7zTypes.h +529 -0
- data/src/lzma/Compiler.h +43 -0
- data/src/lzma/LzmaDec.c +1363 -0
- data/src/lzma/LzmaDec.h +236 -0
- data/src/lzma/Precomp.h +10 -0
- data/src/script_info.c +246 -0
- data/src/script_info.h +7 -0
- data/src/stub.c +133 -0
- data/src/stub.manifest +29 -0
- data/src/stub.rc +3 -0
- data/src/system_utils.c +1002 -0
- data/src/system_utils.h +209 -0
- data/src/system_utils_posix.c +500 -0
- data/src/unpack.c +574 -0
- data/src/unpack.h +85 -0
- data/src/vit-ruby.ico +0 -0
- metadata +52 -16
- data/share/ocran/edicon.exe +0 -0
- data/share/ocran/stub.exe +0 -0
- data/share/ocran/stubw.exe +0 -0
data/src/inst_dir.c
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
#ifndef _WIN32
|
|
4
|
+
#include <unistd.h>
|
|
5
|
+
#include <errno.h>
|
|
6
|
+
#endif
|
|
7
|
+
#include "error.h"
|
|
8
|
+
#include "system_utils.h"
|
|
9
|
+
#include "inst_dir.h"
|
|
10
|
+
|
|
11
|
+
// Static variable to hold the installation directory path.
|
|
12
|
+
static char *InstDir = NULL;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @brief Checks whether the installation directory is configured.
|
|
16
|
+
*
|
|
17
|
+
* @return true if InstDir is non-NULL and not empty; false otherwise.
|
|
18
|
+
*/
|
|
19
|
+
static inline bool IsInstDirSet(void)
|
|
20
|
+
{
|
|
21
|
+
return InstDir != NULL && InstDir[0] != '\0';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Creates an installation directory with a unique name in the specified target directory.
|
|
25
|
+
static char *create_uniq_dir(const char *target_dir)
|
|
26
|
+
{
|
|
27
|
+
char *base_path = JoinPath(target_dir, "ocran" "XXXXXX");
|
|
28
|
+
if (!base_path) {
|
|
29
|
+
APP_ERROR("Failed to construct a base path");
|
|
30
|
+
return NULL;
|
|
31
|
+
}
|
|
32
|
+
return CreateUniqueDirectory(base_path);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Creates a debug installation directory next to the executable.
|
|
36
|
+
static char *create_debug_extract_inst_dir(void)
|
|
37
|
+
{
|
|
38
|
+
char *image_path = GetImagePath();
|
|
39
|
+
if (!image_path) {
|
|
40
|
+
APP_ERROR("Failed to get executable name");
|
|
41
|
+
return NULL;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
char *image_dir = GetParentPath(image_path);
|
|
45
|
+
free(image_path);
|
|
46
|
+
if (!image_dir) {
|
|
47
|
+
APP_ERROR("Failed to obtain the directory path of the executable file");
|
|
48
|
+
return NULL;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
char *inst_dir = create_uniq_dir(image_dir);
|
|
52
|
+
|
|
53
|
+
if (!inst_dir) {
|
|
54
|
+
APP_ERROR("Failed to create installation directory in '%s'", image_dir);
|
|
55
|
+
free(image_dir);
|
|
56
|
+
return NULL;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
free(image_dir);
|
|
60
|
+
return inst_dir;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Creates a temporary installation directory in the system's temp directory.
|
|
64
|
+
static char *create_temporary_inst_dir(void)
|
|
65
|
+
{
|
|
66
|
+
char *temp_dir = GetTempDirectoryPath();
|
|
67
|
+
if (!temp_dir) {
|
|
68
|
+
APP_ERROR("Failed to obtain the temporary directory path");
|
|
69
|
+
return NULL;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
char *inst_dir = create_uniq_dir(temp_dir);
|
|
73
|
+
if (!inst_dir) {
|
|
74
|
+
APP_ERROR("Failed to create installation directory in '%s'", temp_dir);
|
|
75
|
+
free(temp_dir);
|
|
76
|
+
return NULL;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
free(temp_dir);
|
|
80
|
+
return inst_dir;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const char *CreateInstDir(bool is_extract_to_exe_dir)
|
|
84
|
+
{
|
|
85
|
+
if (InstDir != NULL) {
|
|
86
|
+
APP_ERROR("Installation directory has already been set");
|
|
87
|
+
return NULL;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
char *inst_dir = NULL;
|
|
91
|
+
|
|
92
|
+
if (is_extract_to_exe_dir) {
|
|
93
|
+
inst_dir = create_debug_extract_inst_dir();
|
|
94
|
+
} else {
|
|
95
|
+
inst_dir = create_temporary_inst_dir();
|
|
96
|
+
}
|
|
97
|
+
if (!inst_dir) {
|
|
98
|
+
return NULL;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
InstDir = inst_dir;
|
|
102
|
+
return inst_dir;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Frees the allocated memory for the installation directory path.
|
|
106
|
+
void FreeInstDir(void)
|
|
107
|
+
{
|
|
108
|
+
free(InstDir);
|
|
109
|
+
InstDir = NULL;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Returns the path to the installation directory.
|
|
113
|
+
const char *GetInstDir()
|
|
114
|
+
{
|
|
115
|
+
if (!IsInstDirSet()) {
|
|
116
|
+
APP_ERROR("Installation directory has not been set");
|
|
117
|
+
return NULL;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return InstDir;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Concatenates the installation directory path with a relative path.
|
|
124
|
+
char *ExpandInstDirPath(const char *rel_path)
|
|
125
|
+
{
|
|
126
|
+
if (!IsInstDirSet()) {
|
|
127
|
+
APP_ERROR("Installation directory has not been set");
|
|
128
|
+
return NULL;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!rel_path || !*rel_path) {
|
|
132
|
+
APP_ERROR("relative path is NULL or empty");
|
|
133
|
+
return NULL;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (!IsCleanRelativePath(rel_path)) {
|
|
137
|
+
APP_ERROR("invalid relative path '%s'", rel_path);
|
|
138
|
+
return NULL;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
char *full_path = JoinPath(InstDir, rel_path);
|
|
142
|
+
if (!full_path) {
|
|
143
|
+
APP_ERROR("Failed to build full path");
|
|
144
|
+
}
|
|
145
|
+
return full_path;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Deletes the installation directory and all its contents.
|
|
149
|
+
bool DeleteInstDir(void)
|
|
150
|
+
{
|
|
151
|
+
if (!IsInstDirSet()) {
|
|
152
|
+
APP_ERROR("Installation directory has not been set");
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return DeleteRecursively(InstDir);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Replaces placeholders in a string with the installation directory path.
|
|
160
|
+
char *ReplaceInstDirPlaceholder(const char *tmpl)
|
|
161
|
+
{
|
|
162
|
+
if (!IsInstDirSet()) {
|
|
163
|
+
APP_ERROR("Installation directory has not been set");
|
|
164
|
+
return NULL;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const char *replacement = InstDir;
|
|
168
|
+
size_t replacement_len = strlen(replacement);
|
|
169
|
+
size_t c = 0;
|
|
170
|
+
|
|
171
|
+
for (const char *p = tmpl; *p; p++) { if (*p == PLACEHOLDER) c++; }
|
|
172
|
+
size_t replaced_len = strlen(tmpl) - c + replacement_len * c + 1;
|
|
173
|
+
char *replaced = calloc(replaced_len, sizeof(*replaced));
|
|
174
|
+
if (!replaced) {
|
|
175
|
+
APP_ERROR("Memory allocation failed for placeholder replacement");
|
|
176
|
+
return NULL;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
char *out = replaced;
|
|
180
|
+
for (const char *in = tmpl; *in; in++) {
|
|
181
|
+
if (*in == PLACEHOLDER) {
|
|
182
|
+
memcpy(out, replacement, replacement_len);
|
|
183
|
+
out += replacement_len;
|
|
184
|
+
} else {
|
|
185
|
+
*out = *in;
|
|
186
|
+
out++;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
*out = '\0';
|
|
190
|
+
|
|
191
|
+
return replaced;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
bool CreateDirectoryUnderInstDir(const char *rel_path)
|
|
195
|
+
{
|
|
196
|
+
if (!IsInstDirSet()) {
|
|
197
|
+
APP_ERROR("Installation directory has not been set");
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (!rel_path) {
|
|
202
|
+
APP_ERROR("relative path is NULL");
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* Treat empty string as a no-op and return success */
|
|
207
|
+
if (rel_path[0] == '\0') {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
char *dir = ExpandInstDirPath(rel_path);
|
|
212
|
+
if (!dir) {
|
|
213
|
+
APP_ERROR("Failed to build full path");
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
bool result = CreateDirectoriesRecursively(dir);
|
|
218
|
+
if (!result) {
|
|
219
|
+
APP_ERROR(
|
|
220
|
+
"Failed to create directory under installation directory: '%s'",
|
|
221
|
+
dir
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
free(dir);
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
bool ExportFileToInstDir(const char *rel_path, const void *buf, size_t len)
|
|
230
|
+
{
|
|
231
|
+
bool result = false;
|
|
232
|
+
char *path = NULL;
|
|
233
|
+
|
|
234
|
+
if (!IsInstDirSet()) {
|
|
235
|
+
APP_ERROR("Installation directory has not been set");
|
|
236
|
+
goto cleanup;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (rel_path == NULL || *rel_path == '\0') {
|
|
240
|
+
APP_ERROR("Relative path is null or empty");
|
|
241
|
+
goto cleanup;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
DEBUG("ExportFileToInstDir: rel_path=\"%s\", len=%zu", rel_path, len);
|
|
245
|
+
|
|
246
|
+
if (len > 0 && buf == NULL) {
|
|
247
|
+
APP_ERROR("Buffer pointer is NULL for non-zero length");
|
|
248
|
+
goto cleanup;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
path = ExpandInstDirPath(rel_path);
|
|
252
|
+
if (!path) {
|
|
253
|
+
goto cleanup;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (!ExportFile(path, buf, len)) {
|
|
257
|
+
APP_ERROR("Failed to export file: %s", path);
|
|
258
|
+
goto cleanup;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
result = true;
|
|
262
|
+
|
|
263
|
+
cleanup:
|
|
264
|
+
if (path) {
|
|
265
|
+
free(path);
|
|
266
|
+
}
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
#ifndef _WIN32
|
|
271
|
+
bool CreateSymlinkUnderInstDir(const char *rel_link_path, const char *target)
|
|
272
|
+
{
|
|
273
|
+
if (!IsInstDirSet()) {
|
|
274
|
+
APP_ERROR("Installation directory has not been set");
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (!rel_link_path || !*rel_link_path) {
|
|
279
|
+
APP_ERROR("rel_link_path is NULL or empty");
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (!target || !*target) {
|
|
284
|
+
APP_ERROR("target is NULL or empty");
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
char *link_path = ExpandInstDirPath(rel_link_path);
|
|
289
|
+
if (!link_path) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
bool result = false;
|
|
294
|
+
char *parent = GetParentPath(link_path);
|
|
295
|
+
if (parent && *parent && !CreateDirectoriesRecursively(parent)) {
|
|
296
|
+
APP_ERROR("Failed to create parent directory for symlink '%s'", link_path);
|
|
297
|
+
goto cleanup;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (symlink(target, link_path) < 0) {
|
|
301
|
+
APP_ERROR("Failed to create symlink '%s' -> '%s': %s", link_path, target, strerror(errno));
|
|
302
|
+
goto cleanup;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
DEBUG("CreateSymlinkUnderInstDir: '%s' -> '%s'", link_path, target);
|
|
306
|
+
result = true;
|
|
307
|
+
|
|
308
|
+
cleanup:
|
|
309
|
+
if (parent) {
|
|
310
|
+
free(parent);
|
|
311
|
+
}
|
|
312
|
+
free(link_path);
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
#endif /* _WIN32 */
|
|
316
|
+
|
|
317
|
+
bool SetEnvWithInstDir(const char *name, const char *value)
|
|
318
|
+
{
|
|
319
|
+
char *replaced_value = ReplaceInstDirPlaceholder(value);
|
|
320
|
+
if (!replaced_value) {
|
|
321
|
+
APP_ERROR("Failed to replace the value placeholder");
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
DEBUG("SetEnv(%s, %s)", name, replaced_value);
|
|
326
|
+
|
|
327
|
+
bool result = SetEnvVar(name, replaced_value);
|
|
328
|
+
if (!result) {
|
|
329
|
+
APP_ERROR("Failed to set environment variable: %s", name);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
free(replaced_value);
|
|
333
|
+
return result;
|
|
334
|
+
}
|
data/src/inst_dir.h
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#include <stdbool.h>
|
|
2
|
+
#include <stddef.h>
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @brief Creates an installation directory with a unique name.
|
|
6
|
+
*
|
|
7
|
+
* Attempts to create a directory within the specified target directory. This
|
|
8
|
+
* directory is assigned a unique name based on the "ocran" prefix to avoid
|
|
9
|
+
* conflicts. The function manages the lifetime of the created directory path's
|
|
10
|
+
* memory, which should not be freed by the caller.
|
|
11
|
+
* If directory cleanup is needed, call FreeInstDir().
|
|
12
|
+
*
|
|
13
|
+
* @param is_extract_to_exe_dir
|
|
14
|
+
* If true, the extraction directory will be created in the same folder as
|
|
15
|
+
* the executable; if false, it will be created in the system’s temporary
|
|
16
|
+
* directory.
|
|
17
|
+
* @return
|
|
18
|
+
* A pointer to the created directory path if successful, NULL if an error
|
|
19
|
+
* occurred. The returned path should not be freed by the caller.
|
|
20
|
+
*/
|
|
21
|
+
const char *CreateInstDir(bool is_extract_to_exe_dir);
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @brief Free the allocated installation directory path
|
|
25
|
+
* and reset the internal pointer to NULL.
|
|
26
|
+
*
|
|
27
|
+
* Frees memory previously allocated for the installation directory path
|
|
28
|
+
* and clears the stored pointer so that GetInstDir() returns NULL until
|
|
29
|
+
* a new directory is set.
|
|
30
|
+
*/
|
|
31
|
+
void FreeInstDir(void);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @brief Get the current installation directory path.
|
|
35
|
+
*
|
|
36
|
+
* @return
|
|
37
|
+
* A pointer to the installation directory path if set, or NULL if the
|
|
38
|
+
* directory has not been initialized or has been freed.
|
|
39
|
+
*/
|
|
40
|
+
const char *GetInstDir(void);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @brief Concatenates the installation directory path with a given
|
|
44
|
+
* relative path.
|
|
45
|
+
*
|
|
46
|
+
* This function guarantees that the resulting path will not escape the
|
|
47
|
+
* installation directory. It will fail and return NULL if any of the following
|
|
48
|
+
* conditions are met:
|
|
49
|
+
* - the installation directory (InstDir) is not set or is empty
|
|
50
|
+
* - rel_path is NULL or empty
|
|
51
|
+
* - rel_path contains prohibited path elements such as "." or "..", including
|
|
52
|
+
* patterns like "/./" or "/../"
|
|
53
|
+
*
|
|
54
|
+
* @param rel_path
|
|
55
|
+
* A relative path to be combined with the installation directory path.
|
|
56
|
+
* Must not be absolute, must not be empty, and must not contain any "." or
|
|
57
|
+
* ".." segments (e.g., "/./", "/../", "./", "../").
|
|
58
|
+
*
|
|
59
|
+
* @return
|
|
60
|
+
* A newly allocated string representing the full path on success; NULL on
|
|
61
|
+
* error (and an appropriate error message is logged).
|
|
62
|
+
*/
|
|
63
|
+
char *ExpandInstDirPath(const char *rel_path);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @brief Deletes the installation directory and its contents.
|
|
67
|
+
*
|
|
68
|
+
* @return true if the directory and its contents were deleted successfully,
|
|
69
|
+
* false otherwise.
|
|
70
|
+
*/
|
|
71
|
+
bool DeleteInstDir(void);
|
|
72
|
+
|
|
73
|
+
// Placeholder character used in paths.
|
|
74
|
+
#define PLACEHOLDER '|'
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @brief Replace placeholders in a template string
|
|
78
|
+
* with the installation directory path.
|
|
79
|
+
*
|
|
80
|
+
* @param tmpl
|
|
81
|
+
* The template string containing placeholder characters defined by the
|
|
82
|
+
* PLACEHOLDER macro, which will be replaced by the installation directory
|
|
83
|
+
* path.
|
|
84
|
+
* @return
|
|
85
|
+
* A newly allocated string with all PLACEHOLDER occurrences replaced by the
|
|
86
|
+
* installation directory path. Returns NULL on failure.
|
|
87
|
+
*/
|
|
88
|
+
char *ReplaceInstDirPlaceholder(const char *tmpl);
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @brief Recursively create a directory under the installation directory.
|
|
92
|
+
*
|
|
93
|
+
* This function ensures that a directory exists at the specified relative
|
|
94
|
+
* path under the installation directory. An empty rel_path is treated as
|
|
95
|
+
* already existing (returns true). If rel_path is NULL, ExpandInstDirPath
|
|
96
|
+
* fails, or directory creation fails, the function returns false and logs
|
|
97
|
+
* an error.
|
|
98
|
+
*
|
|
99
|
+
* @param rel_path
|
|
100
|
+
* A relative path to a directory under the installation directory.
|
|
101
|
+
* NULL is invalid (returns false). An empty string is treated as
|
|
102
|
+
* already existing (returns true).
|
|
103
|
+
*
|
|
104
|
+
* @return
|
|
105
|
+
* true if the directory already exists or was created successfully;
|
|
106
|
+
* false on error (and an error is logged).
|
|
107
|
+
*/
|
|
108
|
+
bool CreateDirectoryUnderInstDir(const char *rel_path);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @brief Atomically write a file under the installation dir.
|
|
112
|
+
*
|
|
113
|
+
* This function writes the given buffer as a file at the specified
|
|
114
|
+
* relative path under the installation directory. It validates rel_path
|
|
115
|
+
* and buf, expands the full path, creates any missing parent directories,
|
|
116
|
+
* and writes the data atomically. If len is zero, an empty file is
|
|
117
|
+
* created.
|
|
118
|
+
*
|
|
119
|
+
* @param rel_path
|
|
120
|
+
* A relative file path under the installation directory. NULL or empty
|
|
121
|
+
* string is invalid (returns false).
|
|
122
|
+
* @param buf
|
|
123
|
+
* Pointer to the data to write. Must be non-NULL if len > 0.
|
|
124
|
+
* @param len
|
|
125
|
+
* Number of bytes to write. Zero creates an empty file. Values above
|
|
126
|
+
* MAXDWORD cause an error.
|
|
127
|
+
*
|
|
128
|
+
* @return
|
|
129
|
+
* true on success; false on failure (error logged via APP_ERROR/DEBUG).
|
|
130
|
+
*/
|
|
131
|
+
bool ExportFileToInstDir(const char *rel_path, const void *buf, size_t len);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @brief Expands any installation-directory placeholder found in 'value' and
|
|
135
|
+
* sets the environment variable.
|
|
136
|
+
*
|
|
137
|
+
* @param name Environment variable name to set (must not be NULL).
|
|
138
|
+
* @param value Value string that may include a placeholder for the
|
|
139
|
+
* installation directory.
|
|
140
|
+
*
|
|
141
|
+
* @return true on success; false on failure.
|
|
142
|
+
*/
|
|
143
|
+
bool SetEnvWithInstDir(const char *name, const char *value);
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @brief Create a symlink under the installation directory (POSIX only).
|
|
147
|
+
*
|
|
148
|
+
* Creates a symbolic link at rel_link_path that points to target.
|
|
149
|
+
* Both paths are relative to the installation directory.
|
|
150
|
+
* The target is treated as a bare filename within the same directory.
|
|
151
|
+
*
|
|
152
|
+
* @param rel_link_path Relative path for the new symlink (e.g. "bin/libruby.so").
|
|
153
|
+
* @param target Symlink target filename (e.g. "libruby.so.3.2.0").
|
|
154
|
+
*
|
|
155
|
+
* @return true on success; false on failure.
|
|
156
|
+
*/
|
|
157
|
+
bool CreateSymlinkUnderInstDir(const char *rel_link_path, const char *target);
|