Project

General

Profile

filesys.c

Fixed native source for get_current_dir_name() issue - Eugenie Lyzenko, 10/16/2018 11:45 AM

Download (12.4 KB)

 
1
/*
2
** Module   : filesys.c
3
** Abstract : implementation for detection of symbolic links, non-FIFO pipes
4
**            and special devices (used by com.goldencode.p2j.util.FileChecker)
5
**
6
** Copyright (c) 2013-2018, Golden Code Development Corporation.
7
**
8
** -#- -I- --Date-- --------------------------------Description---------------------------------
9
** 001 CS  20130104 First version for OS-DIR support as an INPUT stream task.
10
** 002 CS  20130115 Task 1613: finish FILE-INFO system handle support (added a native function
11
**                  for getting the file creation date time).
12
** 003 EVL 20130329 Made changes to compile as a Windows DLL.
13
** 004 GES 20131029 Cleaned up possible memory leaks where we weren't releasing our reference to
14
**                  the string on the Java heap. Made code formatting improvements.
15
** 005 EVL 20140221 Adding call to check if the STDOUT is redirected in command line.
16
** 006 OM  20170206 Fixed file information bits for Windows OS.
17
** 007 EVL 20180206 Fix file separator platform dependency.
18
** 008 EVL 20180530 Adding support for native get/set working directory.
19
** 009 EVL 20181016 Fix for missing get_current_dir_name() function in MinGW fro Windows package.
20
**                  We have to use more common CRT function to get the current directory for both
21
**                  Windows and Linux/UNIX environments.
22
*/ 
23
/*
24
** This program is free software: you can redistribute it and/or modify
25
** it under the terms of the GNU Affero General Public License as
26
** published by the Free Software Foundation, either version 3 of the
27
** License, or (at your option) any later version.
28
**
29
** This program is distributed in the hope that it will be useful,
30
** but WITHOUT ANY WARRANTY; without even the implied warranty of
31
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
** GNU Affero General Public License for more details.
33
**
34
** You may find a copy of the GNU Affero GPL version 3 at the following
35
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
36
** 
37
** Additional terms under GNU Affero GPL version 3 section 7:
38
** 
39
**   Under Section 7 of the GNU Affero GPL version 3, the following additional
40
**   terms apply to the works covered under the License.  These additional terms
41
**   are non-permissive additional terms allowed under Section 7 of the GNU
42
**   Affero GPL version 3 and may not be removed by you.
43
** 
44
**   0. Attribution Requirement.
45
** 
46
**     You must preserve all legal notices or author attributions in the covered
47
**     work or Appropriate Legal Notices displayed by works containing the covered
48
**     work.  You may not remove from the covered work any author or developer
49
**     credit already included within the covered work.
50
** 
51
**   1. No License To Use Trademarks.
52
** 
53
**     This license does not grant any license or rights to use the trademarks
54
**     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
55
**     of Golden Code Development Corporation. You are not authorized to use the
56
**     name Golden Code, FWD, or the names of any author or contributor, for
57
**     publicity purposes without written authorization.
58
** 
59
**   2. No Misrepresentation of Affiliation.
60
** 
61
**     You may not represent yourself as Golden Code Development Corporation or FWD.
62
** 
63
**     You may not represent yourself for publicity purposes as associated with
64
**     Golden Code Development Corporation, FWD, or any author or contributor to
65
**     the covered work, without written authorization.
66
** 
67
**   3. No Misrepresentation of Source or Origin.
68
** 
69
**     You may not represent the covered work as solely your work.  All modified
70
**     versions of the covered work must be marked in a reasonable way to make it
71
**     clear that the modified work is not originating from Golden Code Development
72
**     Corporation or FWD.  All modified versions must contain the notices of
73
**     attribution required in this license.
74
*/
75
#include "filesys.h"
76

    
77
#include "com_goldencode_p2j_util_FileChecker.h"
78
#include "com_goldencode_p2j_util_FileSystemDaemon.h"
79

    
80
/**
81
 * Utility method to check the type of the given file.
82
 * <p>
83
 * There are 4 main types a file can be: Directory , File , Device and Unknown. In addition to
84
 * the 4 main types there are 3 additive stats (they can be added to the main type). For example,
85
 * FH has both FILE and HIDDEN flags marked and DL has both DIRECTORY and LINK flags.
86
 * <p>
87
 * In some cases the additive status can only be added to a specific main type.  For example,
88
 * in Progress only hidden files are marked as hidden, hidden directories are only marked as
89
 * directory.
90
 *
91
 * @param    env 
92
 *           pointer to a structure that provides access to JNI environment
93
 * @param    jc 
94
 *           reference to the Java class who called this function
95
 *           (from static context)
96
 * @param    fname 
97
 *           The file name to be checked passed from FileChecker.checkFileType()
98
 *
99
 * @return   An bitfield representing the status codes for the given pathname.
100
 */
101
JNIEXPORT jint JNICALL 
102
       Java_com_goldencode_p2j_util_FileChecker_checkFileType(JNIEnv  *env,
103
                                                              jclass  jc, 
104
                                                              jstring fname) 
105
{
106
   const char *file_path = (*env)->GetStringUTFChars(env, fname, NULL);
107
   
108
   if (file_path == NULL) 
109
   {
110
      return -1; /* OutOfMemoryError already thrown */
111
   }
112
   
113
   int status = UNIX;
114
   int fd     = open_native(file_path, O_RDONLY);
115
   
116
   if (fd < 0)
117
   {
118
      // free the string on the Java heap
119
      (*env)->ReleaseStringUTFChars(env, fname, file_path);
120
      
121
     return getSymLinkStatus(env, file_path, status);
122
   }
123
   
124
   struct stat st;
125
   
126
   // Use fstat to detect files and directories or links that point to files
127
   // and directories as files or directories
128
   if (fstat(fd, &st)) 
129
   {
130
      // close the file 
131
      close(fd);
132
      
133
      // free the string on the Java heap
134
      (*env)->ReleaseStringUTFChars(env, fname, file_path);
135
      
136
      // allow more advanced queries to be performed, that don't involve opening the file
137
      return getSymLinkStatus(env, file_path, status); 
138
   }
139
   
140
   // check if regular file
141
   if (S_ISREG(st.st_mode)) 
142
   {
143
      // file status is standalone status
144
      status |= FILE;
145
   }
146
   
147
   // extract the filename from the path
148
   // replicate the Unix 4GL bug in which upper dir appears as hidden
149
   // by nontreating .. special case when checking for hidden.
150
   char* filename = (strrchr(file_path, getFileSeparator())) + 1;
151
   
152
   // in unix hidden files don't have a property that determines if
153
   // they are hidden instead a hidden file will start with '.'
154
   //check if first letter is '.'
155
   if (*filename == '.')
156
   {
157
      // hidden status is additive status
158
      status |= HIDDEN;
159
   }
160
   
161
   // check if file is directory
162
   if (S_ISDIR(st.st_mode)) 
163
   { 
164
      status |= DIR;
165
   }
166
   
167
   // check for fifo pipe
168
   if (S_ISFIFO(st.st_mode))
169
   {
170
      // Pipe code status is additive but may not detected as file
171
      // File code status is also added if
172
      if (!(status & FILE))
173
      {
174
         status |= FILE;
175
      }
176
      status |= PIPE;
177
   }
178
   
179
   // close the file 
180
   close(fd);
181
   
182
   // get the platform specific sym link status
183
   status = getSymLinkStatus(env, file_path, status);
184
   
185
   // free the string on the Java heap
186
   (*env)->ReleaseStringUTFChars(env, fname, file_path);
187
   
188
   return status;
189
}
190

    
191
/**
192
 * Utility method that will return the creation date of a file 
193
 * represented as milliseconds from year 1970.
194
 * 
195
 * @param    env 
196
 *           pointer to a structure that provides access to JNI environment
197
 * @param    jc 
198
 *           reference to the Java class who called this function
199
 *           (from static context)
200
 * @param    fname 
201
 *           The file name to be checked passed from 
202
 *           FileChecker.getFileCreationTime.
203
 *           
204
 * @return   A wrapped integer representing the  file creation time in 
205
 *           milliseconds from 1970 or -1 if operation has failed , 
206
 *           (real data cannot be -1 since precision
207
 *           for returned date is at the level of seconds).
208
 */
209
JNIEXPORT jlong JNICALL 
210
   Java_com_goldencode_p2j_util_FileChecker_getFileCreationTime(JNIEnv  *env,
211
                                                                jclass  jc, 
212
                                                                jstring fname) 
213
{
214
   const char *file_path = (*env)->GetStringUTFChars(env, fname, NULL);
215
   
216
   if (file_path == NULL) 
217
   {
218
      return -1; // OutOfMemoryError already thrown
219
   }
220
   
221
   struct stat st;
222
   
223
   int rc = stat(file_path, &st);
224
   
225
   (*env)->ReleaseStringUTFChars(env, fname, file_path);
226
   
227
   if (rc != 0) 
228
   {
229
      return -1; 
230
   }
231
   
232
   // the return variable must be long long otherwise it will truncate
233
   // on Linux/UNIX the only date that is kept is last modify time
234
   long long m = (long long) st.st_ctime;
235
   return m * 1000L;
236
}
237

    
238
/**
239
 * Utility method that will return the value of the system environment variable with a given
240
 * name. 
241
 * 
242
 * @param    env 
243
 *           pointer to a structure that provides access to JNI environment
244
 * @param    jc 
245
 *           reference to the Java class who called this function
246
 *           (from static context)
247
 * @param    vname 
248
 *           The name of the environment variable to get.
249
 *           
250
 * @return   A string representing the system anvironment variable if exists or NULL pointer if 
251
 *           the varable is unknown.
252
 */
253
JNIEXPORT jstring JNICALL 
254
   Java_com_goldencode_p2j_util_FileSystemDaemon_getEnvironmentValue(JNIEnv  *env,
255
                                                                     jclass  jc, 
256
                                                                     jstring vname) 
257
{
258
   const char* env_var = (*env)->GetStringUTFChars(env, vname, NULL);
259
   
260
   char* result = NULL;
261
   
262
   if (env_var != NULL)
263
   {
264
      if (strlen(env_var) > 0)
265
      {
266
         result = getenv(env_var);
267
      }
268
      
269
      (*env)->ReleaseStringUTFChars(env, vname, env_var);
270
   }
271
   
272
   return (result != NULL) ? (*env)->NewStringUTF(env, result) : NULL;
273
}
274

    
275
/**
276
 * Checks if the current STDOUT handle is redirected to the file by command line option.
277
 *
278
 * @param    env 
279
 *           pointer to a structure that provides access to JNI environment
280
 * @param    jc 
281
 *           reference to the Java class who called this function
282
 *           (from static context)
283
 *
284
 * @return   <code>true</code> if STDOUT is redirected <code>false</code> otherwise.
285
 */
286
JNIEXPORT jboolean JNICALL
287
   Java_com_goldencode_p2j_util_FileChecker_isStdoutRedirected(JNIEnv *env, jclass  jc)
288
{
289
   struct stat st;
290
   
291
   return (fstat(STDOUT_FILENO, &st) == 0) && // Means success call to fstat
292
          (S_ISCHR(st.st_mode) == 0) &&       // The output is not character device
293
          (S_ISREG(st.st_mode) != 0);         // but regular file
294
}
295

    
296
/**
297
 * Gets current setting for working directory.
298
 *
299
 * @param    env 
300
 *           pointer to a structure that provides access to JNI environment
301
 * @param    jc 
302
 *           reference to the Java class who called this function
303
 *           (from static context)
304
 *
305
 * @return   string with requested current directory or NULL in case of failure.
306
 */
307
JNIEXPORT jstring JNICALL
308
   Java_com_goldencode_p2j_util_FileSystemDaemon_getWorkingDir(JNIEnv *env, jclass jc)
309
{
310
   char* curr_dir = NULL;
311
   jstring jsRes = NULL;
312
   // use the common CRT function which works on both Windows and Linux/UNIX
313
   curr_dir = (char*)getcwd(NULL, 0);
314
   if (curr_dir != NULL)
315
   {
316
      // make a copy to return to Java
317
      jsRes = (*env)->NewStringUTF(env, curr_dir);
318
      // get_current_dir_name() does malloc to store the value - we need to free memory
319
      free(curr_dir);
320
   }
321
   
322
   return jsRes;
323
}
324

    
325
/**
326
 * Sets new working directory.
327
 *
328
 * @param    env 
329
 *           pointer to a structure that provides access to JNI environment
330
 * @param    jc 
331
 *           reference to the Java class who called this function
332
 *           (from static context)
333
 *
334
 * @return   <code>true</code> if success <code>false</code> otherwise.
335
 */
336
JNIEXPORT jboolean JNICALL
337
   Java_com_goldencode_p2j_util_FileSystemDaemon_setWorkingDir(JNIEnv *env,
338
                                                               jclass jc,
339
                                                               jstring newDirName)
340
{
341
   int rc = -1;
342
   const char* new_dir = (*env)->GetStringUTFChars(env, newDirName, NULL);
343
   
344
   if (new_dir != NULL)
345
   {
346
      rc = chdir(new_dir);
347
      
348
      (*env)->ReleaseStringUTFChars(env, newDirName, new_dir);
349
   }
350
   
351
   return rc == 0;
352
}