Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/attach.c
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2009, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "j9port.h"
24
#include "j9.h"
25
#include "ut_j9jcl.h"
26
#include "stackwalk.h"
27
#include "jclglob.h"
28
#include "jclprots.h"
29
30
extern char * getTmpDir(JNIEnv *env, char**envSpace);
31
32
/**
33
* Test if the file is owned by this process's owner or the process is running as root.
34
* @param pathUTF pathname of the file. Must be a valid path
35
* @return TRUE if the file is owned by this process or the user is root.
36
*/
37
static BOOLEAN
38
isFileOwnedByMe(JNIEnv *env, const char *pathUTF) {
39
40
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
41
42
struct J9FileStat fileStat;
43
jlong ownerUid = -1;
44
jlong myUid = (jlong) j9sysinfo_get_euid();
45
I_32 statRc;
46
47
if (0 == myUid) { /* I am root */
48
return TRUE;
49
}
50
51
statRc = j9file_stat(pathUTF, 0, &fileStat);
52
if (statRc == 0) {
53
ownerUid = fileStat.ownerUid;
54
}
55
return (ownerUid == myUid);
56
57
}
58
59
/* all native methods defined herein are static */
60
61
/**
62
* Get the system temporary directory path (/tmp on all but Windows).
63
* Note that this may be different from the java.io.tmpdir system property.
64
* @return jstring object with the path
65
*/
66
67
#define TMP_PATH_BUFFER_SIZE 128
68
jstring JNICALL
69
Java_openj9_internal_tools_attach_target_IPC_getTempDirImpl(JNIEnv *env, jclass clazz)
70
{
71
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
72
jstring result = NULL;
73
char *envSpace = NULL;
74
char *charResult = getTmpDir(env, &envSpace);
75
if (NULL != charResult) {
76
uint8_t defaultConversionBuffer[TMP_PATH_BUFFER_SIZE];
77
uint8_t *conversionBuffer = defaultConversionBuffer;
78
size_t pathLength = strlen(charResult);
79
int32_t conversionResult = 0;
80
Trc_JCL_attach_getTmpDir(env, charResult);
81
conversionResult = j9str_convert(J9STR_CODE_PLATFORM_OMR_INTERNAL, J9STR_CODE_MUTF8, charResult, pathLength, (char*)defaultConversionBuffer, sizeof(defaultConversionBuffer));
82
if (OMRPORT_ERROR_STRING_BUFFER_TOO_SMALL == conversionResult) {
83
/* determine how much space we really need */
84
int32_t requiredSize = j9str_convert(J9STR_CODE_PLATFORM_OMR_INTERNAL, J9STR_CODE_MUTF8, charResult, pathLength, NULL, 0);
85
if (requiredSize > 0) {
86
requiredSize += 1; /* leave room for null */
87
conversionBuffer = j9mem_allocate_memory(requiredSize, OMRMEM_CATEGORY_VM);
88
if (NULL != conversionBuffer) {
89
j9str_convert(J9STR_CODE_PLATFORM_OMR_INTERNAL, J9STR_CODE_MUTF8, charResult, pathLength, (char*)conversionBuffer, requiredSize);
90
}
91
} else {
92
conversionBuffer = NULL; /* string is bogus */
93
}
94
} else if (conversionResult < 0) {
95
Trc_JCL_stringConversionFailed(env, charResult, conversionResult);
96
conversionBuffer = NULL; /* string conversion failed */
97
}
98
if (NULL != conversionBuffer) {
99
result = (*env)->NewStringUTF(env, (char*)conversionBuffer);
100
if (defaultConversionBuffer != conversionBuffer) {
101
jclmem_free_memory(env,conversionBuffer);
102
}
103
}
104
if (NULL != envSpace) {
105
jclmem_free_memory(env,envSpace);
106
}
107
}
108
return result;
109
}
110
111
112
/**
113
* @param path file system path
114
* @param mode the file's new access permissions (posix format)
115
* @return actual file permissions, which may be different than those requested due to OS limitations
116
*/
117
118
jint JNICALL
119
Java_openj9_internal_tools_attach_target_IPC_chmod(JNIEnv *env, jclass clazz, jstring path, jint mode)
120
{
121
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
122
123
jint result = JNI_ERR;
124
const char *pathUTF;
125
126
pathUTF = (*env)->GetStringUTFChars(env, path, NULL);
127
if (NULL != pathUTF) {
128
if (isFileOwnedByMe(env, pathUTF)) {
129
result = j9file_chmod(pathUTF, mode);
130
Trc_JCL_attach_chmod(env, pathUTF, mode, result);
131
}
132
(*env)->ReleaseStringUTFChars(env, path, pathUTF);
133
}
134
return result;
135
}
136
137
/**
138
* @param path file system path
139
* @param uid user identity to which to chown the file. This was upcast from UDATA.
140
* @return result of chown() operation
141
*/
142
jint JNICALL
143
Java_openj9_internal_tools_attach_target_IPC_chownFileToTargetUid(JNIEnv *env, jclass clazz, jstring path, jlong uid)
144
{
145
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
146
147
jint result = JNI_OK;
148
const char *pathUTF;
149
150
pathUTF = (*env)->GetStringUTFChars(env, path, NULL);
151
if (NULL != pathUTF) {
152
if (isFileOwnedByMe(env, pathUTF)) { /* j9file_chown takes a UTF8 string for the path */
153
/* uid value was upcast from a UDATA to jlong. */
154
result = (jint)j9file_chown(pathUTF, (UDATA) uid, J9PORT_FILE_IGNORE_ID);
155
Trc_JCL_attach_chown(env, pathUTF, uid, result);
156
}
157
(*env)->ReleaseStringUTFChars(env, path, pathUTF);
158
} else {
159
result = JNI_ERR;
160
}
161
return result;
162
}
163
164
/**
165
* Call file stat and get the effective UID of the file owner.
166
* @param path file system path
167
* @return Returns 0 on Windows and the effective UID of owner on other operation systems. Returns -1 in the case of an error.
168
*/
169
jlong JNICALL
170
Java_openj9_internal_tools_attach_target_CommonDirectory_getFileOwner(JNIEnv *env, jclass clazz, jstring path) {
171
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
172
173
jlong ownerUid = -1;
174
const char *pathUTF;
175
176
pathUTF = (*env)->GetStringUTFChars(env, path, NULL);
177
if (NULL != pathUTF) {
178
struct J9FileStat fileStat;
179
I_32 statRc = j9file_stat(pathUTF, 0, &fileStat);
180
181
if (statRc == 0) {
182
ownerUid = fileStat.ownerUid;
183
}
184
Trc_JCL_attach_getFileOwner(env, pathUTF, ownerUid);
185
(*env)->ReleaseStringUTFChars(env, path, pathUTF);
186
}
187
return ownerUid;
188
}
189
190
/**
191
* This crawls the z/OS control blocks to determine if the current process is using the default UID.
192
* This handles both job- and task-level security.
193
* For information on the control blocks, see the z/OS V1R9.0 MVS Data Areas documentation.
194
* @return JNI_TRUE if the process is running on z/OS and is using the default UID
195
* @note A batch process runs as the default UID if it has no USS segment.
196
*/
197
jboolean JNICALL
198
Java_openj9_internal_tools_attach_target_IPC_isUsingDefaultUid(JNIEnv *env, jclass clazz)
199
{
200
201
jboolean usingDuid = JNI_FALSE;
202
#if defined(J9ZOS390)
203
204
/* all offsets are byte offsets */
205
U_32* PSATOLD_ADDR = (U_32 *)(UDATA) 0x21c; /* z/OS Pointer to current TCB or zero if in SRB mode. Field fixed by architecture. */
206
U_32 tcbBase; /* base of the z/OS Task Control Block */
207
const TCBSENV_OFFSET = 0x154; /* offset of the TCBSENV field in the TCB. This field contains a pointer to the ACEE. */
208
U_32 aceeBaseAddr; /* Address of a control block field which contains a pointer to the base of the RACF Accessor Environment Element (ACEE) */
209
U_32 aceeBase; /* absolute address of the start of the ACEE */
210
U_32 aceeflg3Addr; /* address of the "Miscellaneous flags" byte of the ACEE */
211
U_8 aceeflg3Value; /* contents of the "Miscellaneous flags" byte of the ACEE */
212
const U_32 ACEEFLG3_OFFSET = 0x28; /* offset of flag 3 from the base of the ACEE */
213
const U_8 ACEE_DUID = 0X02; /* 1 if current thread is using the defaultUID */
214
215
tcbBase = *PSATOLD_ADDR;
216
aceeBaseAddr = tcbBase+TCBSENV_OFFSET;
217
aceeBase = *((U_32 *)(UDATA) aceeBaseAddr);
218
if (0 == aceeBase) { /* not using task-level ACEE */
219
U_32* PSAAOLD_ADDR= (U_32 *) 0x224; /* Pointer to the home (current) ASCB. */
220
U_32 ascbAddr; /* address of the ACSB (ADDRESS SPACE CONTROL BLOCK) */
221
const U_32 ASCBASXB_OFFSET = 0x6c; /* offset of the address space extension control block (ASXB) field in the ASCB */
222
U_32 asxbBaseAddr; /* absolute address of the ASXB field in the ASCB */
223
U_32 asxbBase; /* Contents of the ASXB field in the ASCB. This points the ASXB itself. */
224
const U_32 ASXBSENV_OFFSET = 0xc8; /* offset of the ASXBSENV field in the ASXB. This field contains a pointer to the ACEE. */
225
226
ascbAddr = *PSAAOLD_ADDR;
227
228
asxbBaseAddr = ascbAddr+ASCBASXB_OFFSET;
229
asxbBase = *((U_32 *)(UDATA) asxbBaseAddr);
230
231
aceeBaseAddr = asxbBase+ASXBSENV_OFFSET;
232
aceeBase = *((U_32 *)(UDATA) aceeBaseAddr);
233
}
234
235
aceeflg3Addr = aceeBase + ACEEFLG3_OFFSET;
236
aceeflg3Value = *((U_8 *)(UDATA) aceeflg3Addr);
237
Trc_JCL_com_ibm_tools_attach_javaSE_IPC_isUsingDefaultUid(env, aceeBase, aceeflg3Addr, aceeflg3Value);
238
239
if (0 != (aceeflg3Value & ACEE_DUID)) { /* Running with default UID.*/
240
usingDuid = JNI_TRUE;
241
}
242
#endif
243
return usingDuid;
244
}
245
246
247
/**
248
* Create a directory with specified file permissions.
249
* These permissions are masked with the user's umask
250
* @param absolutePath path of the directory to create
251
* @param cdPerms file access permissions (posix format) for the new directory
252
* @return JNI_OK if success
253
*/
254
255
jint JNICALL
256
Java_openj9_internal_tools_attach_target_IPC_mkdirWithPermissionsImpl(JNIEnv *env, jclass clazz, jstring absolutePath, jint cdPerms)
257
{
258
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
259
jint status = JNI_OK;
260
const char *absolutePathUTF = (*env)->GetStringUTFChars(env, absolutePath, NULL);
261
262
if (NULL != absolutePathUTF) {
263
status = j9file_mkdir(absolutePathUTF); /* file perms ignored for now */
264
Java_openj9_internal_tools_attach_target_IPC_chmod(env, clazz, absolutePath, cdPerms);
265
/* ensure that the directory group is the same as this process's. Some OS's set the group to that of the parent directory */
266
j9file_chown(absolutePathUTF, J9PORT_FILE_IGNORE_ID, j9sysinfo_get_egid());
267
Trc_JCL_attach_mkdirWithPermissions(env, absolutePathUTF, cdPerms, status);
268
(*env)->ReleaseStringUTFChars(env, absolutePath, absolutePathUTF);
269
} else {
270
status = JNI_ERR;
271
}
272
return status;
273
}
274
275
/**
276
* @param path file system path
277
* @param mode file access permissions (posix format) for the new file
278
* @return JNI_OK on success, JNI_ERR on failure
279
* Create the file, set the permissions (to override umask) and close it
280
*/
281
jint JNICALL
282
Java_openj9_internal_tools_attach_target_IPC_createFileWithPermissionsImpl(JNIEnv *env, jclass clazz, jstring path, jint mode)
283
{
284
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
285
286
jint status = JNI_OK;
287
const char *pathUTF = (*env)->GetStringUTFChars(env, path, NULL);
288
289
if (NULL != pathUTF) {
290
IDATA fd = j9file_open(pathUTF, EsOpenCreateNew | EsOpenWrite | EsOpenTruncate , mode);
291
if (-1 == fd) {
292
status = JNI_ERR;
293
} else {
294
j9file_close(fd);
295
}
296
Trc_JCL_attach_createFileWithPermissions(env, pathUTF, mode, status);
297
(*env)->ReleaseStringUTFChars(env, path, pathUTF);
298
} else {
299
status = JNI_ERR;
300
}
301
return status;
302
}
303
304
/**
305
* @return JNI_OK if no error, JNI_ERR otherwise
306
*/
307
#define SHRDIR_NAME_LENGTH 255
308
309
static jint createSharedResourcesDir(JNIEnv *env, jstring ctrlDirName)
310
{
311
IDATA status = JNI_ERR;
312
const char *ctrlDirUTF = NULL;
313
314
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
315
316
/* TODO: should use OS native encoding for the file path */
317
ctrlDirUTF = (*env)->GetStringUTFChars(env, ctrlDirName, NULL);
318
if (NULL != ctrlDirUTF) {
319
I_32 statRc=0;
320
struct J9FileStat ctrlDirStat;
321
statRc = j9file_stat(ctrlDirUTF, 0, &ctrlDirStat);
322
323
if ((statRc == 0) && ctrlDirStat.isFile) {
324
j9file_unlink(ctrlDirUTF);
325
status = j9file_mkdir(ctrlDirUTF);
326
} else if (statRc < 0){ /* directory does not exist */
327
status = j9file_mkdir(ctrlDirUTF);
328
} else {
329
status = JNI_OK;
330
}
331
Trc_JCL_attach_createSharedResourcesDir(env, ctrlDirUTF, status);
332
(*env)->ReleaseStringUTFChars(env, ctrlDirName, ctrlDirUTF);
333
}
334
return (jint)status;
335
}
336
337
/**
338
* prepare to use semaphores, creating resources as required
339
* @param ctrlDirName location of semaphore control files
340
* @return JNI_OK if no error, JNI_ERR otherwise
341
*/
342
343
jint JNICALL
344
Java_openj9_internal_tools_attach_target_IPC_setupSemaphore(JNIEnv *env, jclass clazz, jstring ctrlDirName)
345
{
346
347
348
jint status;
349
350
status = createSharedResourcesDir(env, ctrlDirName);
351
return status;
352
}
353
354
/**
355
* open the semaphore and save into a specified struct
356
* @param ctrlDirName directory for the control file
357
* @param semaName name for the control file
358
* @param semaphore out parameter for the resulting handle
359
* @return JNI_ERR if cannot allocate string, j9shsem_open status otherwise
360
*/
361
362
static jint JNICALL
363
openSemaphore(JNIEnv *env, jclass clazz, jstring ctrlDirName, jstring semaName, BOOLEAN global, struct j9shsem_handle** semaphore)
364
{
365
366
PORT_ACCESS_FROM_VMC((J9VMThread *) env );
367
368
jint status = JNI_OK;
369
const char *semaNameUTF = (*env)->GetStringUTFChars(env, semaName, NULL);
370
const char *ctrlDirNameUTF = (*env)->GetStringUTFChars(env, ctrlDirName, NULL);
371
372
if ((NULL != semaNameUTF) && (NULL != ctrlDirNameUTF)) {
373
J9PortShSemParameters openParams;
374
j9shsem_params_init(&openParams);
375
openParams.semName = semaNameUTF;
376
openParams.setSize = 1;
377
openParams.permission = 0666;
378
openParams.controlFileDir = ctrlDirNameUTF;
379
openParams.proj_id = 0xa1;
380
openParams.deleteBasefile = 0;
381
if (global) {
382
openParams.global = 1;
383
}
384
385
status = (jint) j9shsem_open(semaphore, &openParams);
386
Trc_JCL_attach_openSemaphore(env, semaNameUTF, ctrlDirNameUTF, status);
387
} else {
388
status = JNI_ERR;
389
}
390
if (NULL != semaNameUTF) {
391
(*env)->ReleaseStringUTFChars(env, semaName, semaNameUTF);
392
}
393
if (NULL != ctrlDirNameUTF){
394
(*env)->ReleaseStringUTFChars(env, ctrlDirName, ctrlDirNameUTF);
395
}
396
return status;
397
}
398
399
/**
400
* @param ctrlDirName path to directory holding the semaphore files
401
* @param semaName name of the notification semaphore for this process
402
* @return JNI_OK on success, j9shsem_open status otherwise
403
* Saves the semaphore handle into the VM struct.
404
*/
405
406
jint JNICALL
407
Java_openj9_internal_tools_attach_target_IPC_openSemaphore(JNIEnv *env, jclass clazz, jstring ctrlDirName, jstring semaName)
408
{
409
jint rc = 0;
410
J9JavaVM* javaVM = ((J9VMThread*) env)->javaVM;
411
412
Trc_JCL_attach_openSemaphoreEntry(env);
413
rc = openSemaphore(env, clazz, ctrlDirName, semaName, TRUE, &(javaVM->attachContext.semaphore));
414
415
if ((J9PORT_INFO_SHSEM_OPENED == rc) || (J9PORT_INFO_SHSEM_OPENED_STALE == rc) || (J9PORT_INFO_SHSEM_CREATED == rc)) {
416
rc = JNI_OK;
417
}
418
Trc_JCL_attach_openSemaphoreExit(env, rc);
419
return rc;
420
}
421
422
/**
423
* Open a semaphore, post to it, and close it. Do not store the semaphore handle.
424
* @param ctrlDirName path to directory holding the semaphore files
425
* @param semaName name of the notification semaphore for this process
426
* @param numberOfPosts the number of times to increment the semaphore
427
* @param global use the global semaphore namespace (Windows only)
428
* @return JNI_OK on success, j9shsem_open or close status otherwise
429
*/
430
jint JNICALL
431
Java_openj9_internal_tools_attach_target_IPC_notifyVm(JNIEnv *env, jclass clazz, jstring ctrlDirName, jstring semaName, jint numberOfPosts, jboolean global)
432
{
433
434
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
435
436
jint status;
437
struct j9shsem_handle* semaphore;
438
439
Trc_JCL_attach_notifyVmEntry(env);
440
status = openSemaphore(env, clazz, ctrlDirName, semaName, global, &semaphore);
441
if ((J9PORT_INFO_SHSEM_OPENED == status) || (J9PORT_INFO_SHSEM_OPENED_STALE == status)) {
442
while (numberOfPosts > 0) {
443
status = (jint) j9shsem_post(semaphore, 0, J9PORT_SHSEM_MODE_DEFAULT);
444
--numberOfPosts;
445
}
446
j9shsem_close(&semaphore);
447
status = JNI_OK;
448
} else if (J9PORT_INFO_SHSEM_CREATED == status) {
449
/* Jazz 27080. the semaphore should already have been created. We are probably shutting down. */
450
status = (jint) j9shsem_destroy(&semaphore);
451
}
452
Trc_JCL_attach_notifyVmExit(env, status);
453
return status;
454
}
455
456
/**
457
* Open a semaphore, decrement it N times (non-blocking) to it, and close it. Do not store the semaphore handle.
458
* @param ctrlDirName path to directory holding the semaphore files
459
* @param semaName name of the notification semaphore for this process
460
* @param numberOfDecrements the number of times to decrement the semaphore
461
* @return JNI_OK on success, j9shsem_open or close status otherwise
462
*/
463
jint JNICALL
464
Java_openj9_internal_tools_attach_target_IPC_cancelNotify(JNIEnv *env, jclass clazz, jstring ctrlDirName, jstring semaName, jint numberOfDecrements, jboolean global)
465
{
466
467
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
468
469
jint status;
470
struct j9shsem_handle* semaphore;
471
472
Trc_JCL_attach_cancelNotifyVmEntry(env);
473
status = openSemaphore(env, clazz, ctrlDirName, semaName, global, &semaphore);
474
if ((J9PORT_INFO_SHSEM_OPENED == status) || (J9PORT_INFO_SHSEM_OPENED_STALE == status)) {
475
while (numberOfDecrements > 0) {
476
status = (jint) j9shsem_wait(semaphore, 0, J9PORT_SHSEM_MODE_NOWAIT);
477
--numberOfDecrements;
478
}
479
j9shsem_close(&semaphore);
480
status = JNI_OK;
481
} else if (J9PORT_INFO_SHSEM_CREATED == status) {
482
/* Jazz 27080. this was supposed to be consuming posts on an existing semaphore, but it appears to have disappeared */
483
status = (jint) j9shsem_destroy(&semaphore);
484
}
485
Trc_JCL_attach_cancelNotifyVmExit(env, status);
486
return status;
487
}
488
489
/**
490
* @return result of j9shsem_wait: 0 on success, -1 on failure
491
* Block until semaphore becomes non-zero.
492
*/
493
jint JNICALL
494
Java_openj9_internal_tools_attach_target_IPC_waitSemaphore(JNIEnv *env, jclass clazz)
495
{
496
J9JavaVM *javaVM = ((J9VMThread*) env)->javaVM;
497
jint status = 0;
498
499
PORT_ACCESS_FROM_JAVAVM(javaVM);
500
Trc_JCL_attach_waitSemaphoreEntry2(env, javaVM->attachContext.semaphore);
501
status = (jint) j9shsem_wait(javaVM->attachContext.semaphore, 0, 0);
502
Trc_JCL_attach_waitSemaphoreExit(env, status);
503
return status;
504
}
505
506
/**
507
* Close semaphore
508
*/
509
void JNICALL
510
Java_openj9_internal_tools_attach_target_IPC_closeSemaphore(JNIEnv *env, jclass clazz)
511
{
512
J9JavaVM *javaVM = ((J9VMThread*) env)->javaVM;
513
514
PORT_ACCESS_FROM_JAVAVM(javaVM);
515
Trc_JCL_attach_closeSemaphoreEntry(env, javaVM->attachContext.semaphore);
516
j9shsem_close(&javaVM->attachContext.semaphore);
517
Trc_JCL_attach_closeSemaphore(env);
518
return;
519
}
520
521
/**
522
* @return 0 on success, -1 on failure
523
*/
524
jint JNICALL
525
Java_openj9_internal_tools_attach_target_IPC_destroySemaphore(JNIEnv *env, jclass clazz)
526
{
527
jint status = 0; /* return success if the semaphore is already closed or destroyed */
528
struct j9shsem_handle **handle = NULL;
529
J9JavaVM *javaVM = ((J9VMThread*) env)->javaVM;
530
531
PORT_ACCESS_FROM_JAVAVM(javaVM);
532
Trc_JCL_attach_destroySemaphoreEntry(env, javaVM->attachContext.semaphore);
533
handle = &javaVM->attachContext.semaphore;
534
if (NULL != handle) {
535
status = (jint) j9shsem_destroy(handle);
536
}
537
Trc_JCL_attach_destroySemaphore(env, status);
538
return status;
539
}
540
541
/**
542
* @return numeric user ID of the caller. This is upcast from a UDATA.
543
*/
544
jlong JNICALL
545
Java_openj9_internal_tools_attach_target_IPC_getUid(JNIEnv *env, jclass clazz)
546
{
547
548
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
549
550
jlong uid;
551
552
uid = (jlong) j9sysinfo_get_euid();
553
Trc_JCL_attach_getUid(env, uid);
554
return uid;
555
}
556
557
/**
558
* @return process ID of the caller. This is upcast from UDATA.
559
*/
560
jlong JNICALL
561
Java_openj9_internal_tools_attach_target_IPC_getProcessId(JNIEnv *env, jclass clazz)
562
{
563
564
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
565
566
jlong pid;
567
568
pid = (jlong) j9sysinfo_get_pid();
569
Trc_JCL_attach_getProcessId(env, pid);
570
return pid;
571
}
572
573
/**
574
* Indicate if a specific process exists. Non-positive process IDs and processes owned by
575
* other users return an error.
576
* @param pid process ID
577
* @return positive value if the process exists, 0 if the process does not exist, otherwise negative error code
578
*/
579
jint JNICALL
580
Java_openj9_internal_tools_attach_target_IPC_processExistsImpl(JNIEnv *env, jclass clazz, jlong pid)
581
{
582
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
583
/* PID value was upcast from a UDATA to jlong. */
584
jint rc = (pid > 0) ? (jint) j9sysinfo_process_exists((UDATA) pid) : -1;
585
Trc_JCL_attach_processExists(env, pid, rc);
586
return rc;
587
}
588
589
/**
590
* Opens and locks a file. Creates the file if it does not exist.
591
* @param path file path to the file
592
* @param mode file mode to create the file with
593
* @param blocking true if process is to wait for the file to be unlocked
594
* @return file descriptor if the file is successfully locked, otherwise negative value
595
* @note J9PORT_ERROR_FILE_OPFAILED (-300) indicates file cannot be opened or the path could not be converted, J9PORT_ERROR_FILE_LOCK_BADLOCK (-316) indicates that the file could not be locked.
596
*/
597
jlong JNICALL
598
Java_openj9_internal_tools_attach_target_FileLock_lockFileImpl(JNIEnv *env, jclass clazz, jstring path, jint mode, jboolean blocking)
599
{
600
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
601
602
jlong result = JNI_OK;
603
const char *pathUTF;
604
605
pathUTF = (*env)->GetStringUTFChars(env, path, NULL); /* j9file_open takes a UTF8 string for the path */
606
if (NULL != pathUTF) {
607
IDATA fd = j9file_open(pathUTF, EsOpenCreate | EsOpenWrite, mode);
608
if (isFileOwnedByMe(env, pathUTF)) {
609
j9file_chmod(pathUTF, mode); /* override UMASK */
610
}
611
Trc_JCL_attach_lockFileImpl(env, pathUTF, mode, blocking, fd);
612
(*env)->ReleaseStringUTFChars(env, path, pathUTF);
613
if (0 >= fd) {
614
result = J9PORT_ERROR_FILE_OPFAILED;
615
} else {
616
IDATA lockStatus;
617
/*
618
* Must be a write lock to get exclusive access.
619
* Must lock at least one byte on Windows, otherwise it returns a false positive.
620
* Both Posix and Windows allow the lock range to extend past the end of the file.
621
*/
622
lockStatus = j9file_lock_bytes(fd, J9PORT_FILE_WRITE_LOCK | ((0 == blocking)? J9PORT_FILE_NOWAIT_FOR_LOCK: J9PORT_FILE_WAIT_FOR_LOCK), 0, 1);
623
if (0 != lockStatus) {
624
j9file_close(fd);
625
result = J9PORT_ERROR_FILE_LOCK_BADLOCK;
626
} else {
627
result = fd;
628
}
629
}
630
} else {
631
result = J9PORT_ERROR_FILE_OPFAILED;
632
}
633
Trc_JCL_attach_lockFileStatus(env, result);
634
return result;
635
}
636
637
/* use for debugging or to record normal events. Use message to distinguish errors */
638
#define TRACEPOINT_STATUS_NORMAL 0
639
#define TRACEPOINT_STATUS_LOGGING 1
640
641
/* use for debugging only. Use message to distinguish errors */
642
#define TRACEPOINT_STATUS_ERROR -1
643
644
#define TRACEPOINT_STATUS_OOM_DURING_WAIT -2
645
#define TRACEPOINT_STATUS_OOM_DURING_TERMINATE -3
646
/**
647
* generate a tracepoint with a status code and message.
648
*
649
* @param statusCode numeric status value
650
* @param message descriptive message. May be null.
651
*/
652
void JNICALL
653
Java_openj9_internal_tools_attach_target_IPC_tracepoint(JNIEnv *env, jclass clazz, jint statusCode, jstring message) {
654
655
const char *msgUTF = NULL;
656
const char *statusText = "STATUS_NORMAL";
657
658
if (NULL != message) {
659
msgUTF = (*env)->GetStringUTFChars(env, message, NULL);
660
}
661
662
switch (statusCode) {
663
case TRACEPOINT_STATUS_LOGGING:
664
statusText = "STATUS_LOGGING";
665
break;
666
case TRACEPOINT_STATUS_NORMAL:
667
statusText = "STATUS_NORMAL";
668
break;
669
case TRACEPOINT_STATUS_OOM_DURING_WAIT:
670
statusText = "STATUS_OOM_DURING_WAIT"; /* from wait loop */
671
break;
672
case TRACEPOINT_STATUS_OOM_DURING_TERMINATE:
673
statusText = "STATUS_OOM_DURING_TERMINATE"; /* from terminate code */
674
break;
675
default: /* FALLTHROUGH */
676
case -1:
677
statusText = "STATUS_ERROR"; /* unspecified error */
678
break;
679
}
680
if (NULL != msgUTF) {
681
Trc_JCL_com_ibm_tools_attach_javaSE_IPC_tracepoint(env, statusCode, statusText, msgUTF);
682
(*env)->ReleaseStringUTFChars(env, message, msgUTF);
683
} else {
684
Trc_JCL_com_ibm_tools_attach_javaSE_IPC_tracepoint(env, statusCode, statusText, "<unavailable>");
685
}
686
}
687
688
/**
689
* Unlock and close a file.
690
* @param file descriptor
691
* @return 0 if successful, -1 if failed
692
*/
693
jint JNICALL
694
Java_openj9_internal_tools_attach_target_FileLock_unlockFileImpl(JNIEnv *env, jclass clazz, jlong fd) {
695
PORT_ACCESS_FROM_VMC( ((J9VMThread *) env) );
696
697
jint result = JNI_OK;
698
j9file_unlock_bytes((IDATA) fd, 0, 0);
699
result = j9file_close((IDATA) fd);
700
Trc_JCL_attach_unlockFileWithStatus(env, (IDATA) fd, result);
701
return result;
702
}
703
704