OSDN Git Service

Imported GNU Classpath 0.20
[pf3gnuchains/gcc-fork.git] / libjava / classpath / native / jni / java-io / java_io_VMFile.c
1 /* java_io_VMFile.c - Native methods for java.io.File class
2    Copyright (C) 1998, 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10  
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 /* do not move; needed here because of some macro definitions */
39 #include <config.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43
44 #include <jni.h>
45 #include <jcl.h>
46
47 #include "target_native.h"
48 #ifndef WITHOUT_FILESYSTEM
49 #include "target_native_file.h"
50 #endif
51 #include "target_native_math_int.h"
52
53 #include "java_io_VMFile.h"
54
55 /*************************************************************************/
56
57 /*
58  * Method to create an empty file.
59  *
60  * Class:     java_io_VMFile
61  * Method:    create
62  * Signature: (Ljava/lang/String;)Z
63  */
64
65 JNIEXPORT jboolean JNICALL
66 Java_java_io_VMFile_create (JNIEnv * env,
67                             jclass clazz __attribute__ ((__unused__)),
68                             jstring name)
69 {
70 #ifndef WITHOUT_FILESYSTEM
71   const char *filename;
72   int fd;
73   int result;
74
75   filename = JCL_jstring_to_cstring (env, name);
76   if (filename == NULL)
77     {
78       return (0);
79     }
80
81   TARGET_NATIVE_FILE_OPEN_CREATE (filename, fd, result);
82   if (result != TARGET_NATIVE_OK)
83     {
84       /* XXX ??? NYI */
85       if (errno != EEXIST)
86         JCL_ThrowException (env,
87                             "java/io/IOException",
88                             TARGET_NATIVE_LAST_ERROR_STRING ());
89       JCL_free_cstring (env, name, filename);
90       return (0);
91     }
92   TARGET_NATIVE_FILE_CLOSE (fd, result);
93
94   JCL_free_cstring (env, name, filename);
95   return (1);
96 #else /* not WITHOUT_FILESYSTEM */
97   return (0);
98 #endif /* not WITHOUT_FILESYSTEM */
99 }
100
101 /*************************************************************************/
102
103 /*
104  * This method checks to see if we have read permission on a file.
105  *
106  * Class:     java_io_VMFile
107  * Method:    canRead
108  * Signature: (Ljava/lang/String;)Z
109  */
110
111 JNIEXPORT jboolean JNICALL
112 Java_java_io_VMFile_canRead (JNIEnv * env,
113                              jobject obj __attribute__ ((__unused__)),
114                              jstring name)
115 {
116 #ifndef WITHOUT_FILESYSTEM
117   const char *filename;
118   int fd;
119   int result;
120
121   /* Don't use the JCL convert function because it throws an exception
122      on failure */
123   filename = (*env)->GetStringUTFChars (env, name, 0);
124   if (filename == NULL)
125     {
126       return (0);
127     }
128
129   /* The lazy man's way out.  We actually do open the file for reading
130      briefly to verify it can be done */
131   TARGET_NATIVE_FILE_OPEN_READ (filename, fd, result);
132   (*env)->ReleaseStringUTFChars (env, name, filename);
133   if (result != TARGET_NATIVE_OK)
134     {
135       return (0);
136     }
137   TARGET_NATIVE_FILE_CLOSE (fd, result);
138
139   return (1);
140 #else /* not WITHOUT_FILESYSTEM */
141   return (0);
142 #endif /* not WITHOUT_FILESYSTEM */
143 }
144
145 /*************************************************************************/
146
147 /*
148  * This method checks to see if we have write permission on a file.
149  *
150  * Class:     java_io_VMFile
151  * Method:    canWrite
152  * Signature: (Ljava/lang/String;)Z
153  */
154
155 JNIEXPORT jboolean JNICALL
156 Java_java_io_VMFile_canWrite (JNIEnv * env,
157                               jobject obj __attribute__ ((__unused__)),
158                               jstring name)
159 {
160 #ifndef WITHOUT_FILESYSTEM
161   const char *filename;
162   int fd;
163   int result;
164
165   /* Don't use the JCL convert function because it throws an exception
166      on failure */
167   filename = (*env)->GetStringUTFChars (env, name, 0);
168   if (filename == NULL)
169     {
170       return (0);
171     }
172
173   /* The lazy man's way out.  We actually do open the file for writing
174      briefly to verify it can be done */
175   TARGET_NATIVE_FILE_OPEN_READWRITE (filename, fd, result);
176   (*env)->ReleaseStringUTFChars (env, name, filename);
177   if (result != TARGET_NATIVE_OK)
178     {
179       return (0);
180     }
181   TARGET_NATIVE_FILE_CLOSE (fd, result);
182
183   return (1);
184 #else /* not WITHOUT_FILESYSTEM */
185   return (0);
186 #endif /* not WITHOUT_FILESYSTEM */
187 }
188
189 /*************************************************************************/
190
191 /*
192  * This method makes a file read only.
193  *
194  * Class:     java_io_VMFile
195  * Method:    setReadOnly
196  * Signature: (Ljava/lang/String;)Z
197  */
198
199 JNIEXPORT jboolean JNICALL
200 Java_java_io_VMFile_setReadOnly (JNIEnv * env,
201                                  jobject obj __attribute__ ((__unused__)),
202                                  jstring name)
203 {
204 #ifndef WITHOUT_FILESYSTEM
205   const char *filename;
206   int result;
207
208   /* Don't use the JCL convert function because it throws an exception
209      on failure */
210   filename = (*env)->GetStringUTFChars (env, name, 0);
211   if (filename == NULL)
212     {
213       return (0);
214     }
215
216   TARGET_NATIVE_FILE_SET_MODE_READONLY (filename, result);
217   (*env)->ReleaseStringUTFChars (env, name, filename);
218
219   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
220 #else /* not WITHOUT_FILESYSTEM */
221   return (0);
222 #endif /* not WITHOUT_FILESYSTEM */
223 }
224
225 /*************************************************************************/
226
227 /*
228  * This method checks to see if a file exists.
229  *
230  * Class:     java_io_VMFile
231  * Method:    exists
232  * Signature: (Ljava/lang/String;)Z
233  */
234
235 JNIEXPORT jboolean JNICALL
236 Java_java_io_VMFile_exists (JNIEnv * env,
237                             jobject obj __attribute__ ((__unused__)),
238                             jstring name)
239 {
240 #ifndef WITHOUT_FILESYSTEM
241   const char *filename;
242   int result;
243
244   /* Don't use the JCL convert function because it throws an exception
245      on failure */
246   filename = (*env)->GetStringUTFChars (env, name, 0);
247   if (filename == NULL)
248     {
249       return (0);
250     }
251
252   TARGET_NATIVE_FILE_EXISTS (filename, result);
253   (*env)->ReleaseStringUTFChars (env, name, filename);
254
255   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
256 #else /* not WITHOUT_FILESYSTEM */
257   return (0);
258 #endif /* not WITHOUT_FILESYSTEM */
259 }
260
261 /*************************************************************************/
262
263 /*
264  * This method checks to see if a file is a "plain" file; that is, not
265  * a directory, pipe, etc.
266  *
267  * Class:     java_io_VMFile
268  * Method:    isFile
269  * Signature: (Ljava/lang/String;)Z
270  */
271
272 JNIEXPORT jboolean JNICALL
273 Java_java_io_VMFile_isFile (JNIEnv * env,
274                             jobject obj __attribute__ ((__unused__)),
275                             jstring name)
276 {
277 #ifndef WITHOUT_FILESYSTEM
278   const char *filename;
279   int result;
280
281   /* Don't use the JCL convert function because it throws an exception
282      on failure */
283   filename = (*env)->GetStringUTFChars (env, name, 0);
284   if (filename == NULL)
285     {
286       return (0);
287     }
288
289   TARGET_NATIVE_FILE_IS_FILE (filename, result);
290   (*env)->ReleaseStringUTFChars (env, name, filename);
291
292   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
293 #else /* not WITHOUT_FILESYSTEM */
294   return (0);
295 #endif /* not WITHOUT_FILESYSTEM */
296 }
297
298 /*************************************************************************/
299
300 /*
301  * This method checks to see if a file is a directory or not.
302  *
303  * Class:     java_io_VMFile
304  * Method:    isDirectory
305  * Signature: (Ljava/lang/String;)Z
306  */
307
308 JNIEXPORT jboolean JNICALL
309 Java_java_io_VMFile_isDirectory (JNIEnv * env,
310                                  jobject obj __attribute__ ((__unused__)),
311                                  jstring name)
312 {
313 #ifndef WITHOUT_FILESYSTEM
314   const char *filename;
315   int result;
316
317   /* Don't use the JCL convert function because it throws an exception
318      on failure */
319   filename = (*env)->GetStringUTFChars (env, name, 0);
320   if (filename == NULL)
321     {
322       return (0);
323     }
324
325   TARGET_NATIVE_FILE_IS_DIRECTORY (filename, result);
326   (*env)->ReleaseStringUTFChars (env, name, filename);
327
328   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
329 #else /* not WITHOUT_FILESYSTEM */
330   return (0);
331 #endif /* not WITHOUT_FILESYSTEM */
332 }
333
334 /*************************************************************************/
335
336 /*
337  * This method returns the length of the file.
338  *
339  * Class:     java_io_VMFile
340  * Method:    length
341  * Signature: (Ljava/lang/String;)J
342  */
343
344 JNIEXPORT jlong JNICALL
345 Java_java_io_VMFile_length (JNIEnv * env,
346                             jobject obj __attribute__ ((__unused__)),
347                             jstring name)
348 {
349 #ifndef WITHOUT_FILESYSTEM
350   const char *filename;
351   int tmpfd;
352   jlong length;
353   int result;
354
355   /* Don't use the JCL convert function because it throws an exception
356      on failure */
357   filename = (*env)->GetStringUTFChars (env, name, 0);
358   if (filename == NULL)
359     {
360       return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
361     }
362
363   /* open file for reading, get size and close file */
364   TARGET_NATIVE_FILE_OPEN_READ (filename, tmpfd, result);
365   if (result != TARGET_NATIVE_OK)
366     {
367       return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
368     }
369   TARGET_NATIVE_FILE_SIZE (tmpfd, length, result);
370   if (result != TARGET_NATIVE_OK)
371     {
372       TARGET_NATIVE_FILE_CLOSE (tmpfd, result);
373       return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
374     }
375   TARGET_NATIVE_FILE_CLOSE (tmpfd, result);
376   (*env)->ReleaseStringUTFChars (env, name, filename);
377
378   return ((result ==
379            TARGET_NATIVE_OK) ? length : TARGET_NATIVE_MATH_INT_INT64_CONST_0);
380 #else /* not WITHOUT_FILESYSTEM */
381   return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
382 #endif /* not WITHOUT_FILESYSTEM */
383 }
384
385 /*************************************************************************/
386
387 /*
388  * This method returns the modification date of the file.
389  *
390  * Class:     java_io_VMFile
391  * Method:    lastModified
392  * Signature: (Ljava/lang/String;)J
393  */
394
395 JNIEXPORT jlong JNICALL
396 Java_java_io_VMFile_lastModified (JNIEnv * env,
397                                   jobject obj __attribute__ ((__unused__)),
398                                   jstring name)
399 {
400 #ifndef WITHOUT_FILESYSTEM
401   const char *filename;
402   jlong mtime;
403   int result;
404
405   /* Don't use the JCL convert function because it throws an exception
406      on failure */
407   filename = (*env)->GetStringUTFChars (env, name, 0);
408   if (filename == NULL)
409     {
410       return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
411     }
412
413   TARGET_NATIVE_FILE_GET_LAST_MODIFIED (filename, mtime, result);
414   (*env)->ReleaseStringUTFChars (env, name, filename);
415
416   return ((result ==
417            TARGET_NATIVE_OK) ? mtime : TARGET_NATIVE_MATH_INT_INT64_CONST_0);
418 #else /* not WITHOUT_FILESYSTEM */
419   return (TARGET_NATIVE_MATH_INT_INT64_CONST_0);
420 #endif /* not WITHOUT_FILESYSTEM */
421 }
422
423 /*************************************************************************/
424
425 /*
426  * This method sets the modification date of the file.
427  *
428  * Class:     java_io_VMFile
429  * Method:    setLastModified
430  * Signature: (Ljava/lang/String;J)Z
431  */
432
433 JNIEXPORT jboolean JNICALL
434 Java_java_io_VMFile_setLastModified (JNIEnv * env,
435                                      jobject obj __attribute__ ((__unused__)),
436                                      jstring name, jlong newtime)
437 {
438 #ifndef WITHOUT_FILESYSTEM
439   const char *filename;
440   int result;
441
442   /* Don't use the JCL convert function because it throws an exception
443      on failure */
444   filename = (*env)->GetStringUTFChars (env, name, 0);
445   if (filename == NULL)
446     {
447       return (0);
448     }
449
450   TARGET_NATIVE_FILE_SET_LAST_MODIFIED (filename, newtime, result);
451   (*env)->ReleaseStringUTFChars (env, name, filename);
452
453   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
454 #else /* not WITHOUT_FILESYSTEM */
455   return (0);
456 #endif /* not WITHOUT_FILESYSTEM */
457 }
458
459 /*************************************************************************/
460
461 /*
462  * This method deletes a file (actually a name for a file - additional
463  * links could exist).
464  *
465  * Class:     java_io_VMFile
466  * Method:    delete
467  * Signature: (Ljava/lang/String;)Z
468  */
469
470 JNIEXPORT jboolean JNICALL
471 Java_java_io_VMFile_delete (JNIEnv * env,
472                             jobject obj __attribute__ ((__unused__)),
473                             jstring name)
474 {
475 #ifndef WITHOUT_FILESYSTEM
476   const char *filename;
477   int result;
478
479   /* Don't use the JCL convert function because it throws an exception
480      on failure */
481   filename = (*env)->GetStringUTFChars (env, name, 0);
482   if (filename == NULL)
483     {
484       return (0);
485     }
486
487   TARGET_NATIVE_FILE_DELETE (filename, result);
488   (*env)->ReleaseStringUTFChars (env, name, filename);
489
490   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
491 #else /* not WITHOUT_FILESYSTEM */
492   return (0);
493 #endif /* not WITHOUT_FILESYSTEM */
494 }
495
496 /*************************************************************************/
497
498 /*
499  * This method creates a directory.
500  *
501  * Class:     java_io_VMFile
502  * Method:    mkdir
503  * Signature: (Ljava/lang/String;)Z
504  */
505
506 JNIEXPORT jboolean JNICALL
507 Java_java_io_VMFile_mkdir (JNIEnv * env,
508                            jobject obj __attribute__ ((__unused__)),
509                            jstring name)
510 {
511 #ifndef WITHOUT_FILESYSTEM
512   const char *pathname;
513   int result;
514
515   /* Don't use the JCL convert function because it throws an exception
516      on failure */
517   pathname = (*env)->GetStringUTFChars (env, name, 0);
518   if (pathname == NULL)
519     {
520       return (0);
521     }
522
523   TARGET_NATIVE_FILE_MAKE_DIR (pathname, result);
524   (*env)->ReleaseStringUTFChars (env, name, pathname);
525
526   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
527 #else /* not WITHOUT_FILESYSTEM */
528   return (0);
529 #endif /* not WITHOUT_FILESYSTEM */
530 }
531
532 /*************************************************************************/
533
534 /*
535  * This method renames a (link to a) file.
536  *
537  * Class:     java_io_VMFile
538  * Method:    renameTo
539  * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
540  */
541
542 JNIEXPORT jboolean JNICALL
543 Java_java_io_VMFile_renameTo (JNIEnv * env,
544                               jobject obj __attribute__ ((__unused__)),
545                               jstring t, jstring d)
546 {
547 #ifndef WITHOUT_FILESYSTEM
548   const char *old_filename, *new_filename;
549   int result;
550
551   /* Don't use the JCL convert function because it throws an exception
552      on failure */
553   old_filename = (*env)->GetStringUTFChars (env, t, 0);
554   if (old_filename == NULL)
555     {
556       return (0);
557     }
558
559   new_filename = (*env)->GetStringUTFChars (env, d, 0);
560   if (new_filename == NULL)
561     {
562       (*env)->ReleaseStringUTFChars (env, t, old_filename);
563       return (0);
564     }
565
566   TARGET_NATIVE_FILE_RENAME (old_filename, new_filename, result);
567   (*env)->ReleaseStringUTFChars (env, d, new_filename);
568   (*env)->ReleaseStringUTFChars (env, t, old_filename);
569
570   return ((result == TARGET_NATIVE_OK) ? 1 : 0);
571 #else /* not WITHOUT_FILESYSTEM */
572   return (0);
573 #endif /* not WITHOUT_FILESYSTEM */
574 }
575
576 /*************************************************************************/
577
578 /*
579  * This method returns an array of String representing all the files
580  * in a directory except "." and "..".
581  *
582  * Class:     java_io_VMFile
583  * Method:    list
584  * Signature: (Ljava/lang/String;)[Ljava/lang/String;
585  */
586
587 JNIEXPORT jobjectArray JNICALL
588 Java_java_io_VMFile_list (JNIEnv * env, jobject obj
589                           __attribute__ ((__unused__)), jstring name)
590 {
591 #ifndef WITHOUT_FILESYSTEM
592   const int REALLOC_SIZE = 10;
593
594   const char *dirname;
595   int result;
596   char **filelist;
597   void *handle;
598   const char *filename;
599   unsigned long int filelist_count, max_filelist_count;
600   char **tmp_filelist;
601   jclass str_clazz;
602   jobjectArray filearray;
603   unsigned long int i;
604   jstring str;
605
606   /* Don't use the JCL convert function because it throws an exception
607      on failure */
608   dirname = (*env)->GetStringUTFChars (env, name, 0);
609   if (dirname == NULL)
610     {
611       return (0);
612     }
613
614   /* open directory for reading */
615   TARGET_NATIVE_FILE_OPEN_DIR (dirname, handle, result);
616
617   (*env)->ReleaseStringUTFChars (env, name, dirname);
618
619   if (result != TARGET_NATIVE_OK)
620     {
621       return (0);
622     }
623
624   /* allocate filelist */
625   filelist = (char **) JCL_malloc (env, sizeof (char *) * REALLOC_SIZE);
626   if (filelist == NULL)
627     {
628       TARGET_NATIVE_FILE_CLOSE_DIR (handle, result);
629       return (0);
630     }
631   filelist_count = 0;
632   max_filelist_count = REALLOC_SIZE;
633
634   /* read the files from the directory */
635   TARGET_NATIVE_FILE_READ_DIR (handle, filename, result);
636   while (result == TARGET_NATIVE_OK)
637     {
638       if ((strcmp (filename, ".") != 0) && (strcmp (filename, "..") != 0))
639         {
640           /* allocate more memory if necessary */
641           if (filelist_count >= max_filelist_count)
642             {
643               tmp_filelist = (char **) JCL_realloc (env,
644                                                     filelist,
645                                                     (max_filelist_count +
646                                                      REALLOC_SIZE) *
647                                                     sizeof (char *));
648               if (tmp_filelist == NULL)
649                 {
650                   for (i = 0; i < filelist_count; i++)
651                     {
652                       JCL_free (env, filelist[i]);
653                     }
654                   JCL_free (env, filelist);
655                   TARGET_NATIVE_FILE_CLOSE_DIR (handle, result);
656                   return (0);
657                 }
658               filelist = tmp_filelist;
659               max_filelist_count += REALLOC_SIZE;
660             }
661
662           /* save entry in list (avoid strdup, because it is not ANSI C, thus difficult to port) */
663           filelist[filelist_count] =
664             (char *) JCL_malloc (env, strlen (filename) + 1);
665           assert (filelist[filelist_count] != NULL);
666           strcpy (filelist[filelist_count], filename);
667           filelist_count++;
668         }
669
670       /* read next directory entry */
671       TARGET_NATIVE_FILE_READ_DIR (handle, filename, result);
672     }
673
674   /* close directory */
675   TARGET_NATIVE_FILE_CLOSE_DIR (handle, result);
676
677   /* put the list of files into a Java String array and return it */
678   str_clazz = (*env)->FindClass (env, "java/lang/String");
679   if (str_clazz == NULL)
680     {
681       for (i = 0; i < filelist_count; i++)
682         {
683           JCL_free (env, filelist[i]);
684         }
685       JCL_free (env, filelist);
686       return (0);
687     }
688   filearray = (*env)->NewObjectArray (env, filelist_count, str_clazz, 0);
689   if (filearray == NULL)
690     {
691       for (i = 0; i < filelist_count; i++)
692         {
693           JCL_free (env, filelist[i]);
694         }
695       JCL_free (env, filelist);
696       return (0);
697     }
698   for (i = 0; i < filelist_count; i++)
699     {
700       /* create new string */
701       str = (*env)->NewStringUTF (env, filelist[i]);
702       if (str == NULL)
703         {
704           /* We don't clean up everything here, but if this failed,
705              something serious happened anyway */
706           for (i = 0; i < filelist_count; i++)
707             {
708               JCL_free (env, filelist[i]);
709             }
710           JCL_free (env, filelist);
711           return (0);
712         }
713
714       /* save into array */
715       (*env)->SetObjectArrayElement (env, filearray, i, str);
716
717       /* delete local reference */
718       (*env)->DeleteLocalRef (env, str);
719     }
720
721   /* free resources */
722   for (i = 0; i < filelist_count; i++)
723     {
724       JCL_free (env, filelist[i]);
725     }
726   JCL_free (env, filelist);
727
728   return (filearray);
729 #else /* not WITHOUT_FILESYSTEM */
730   return (0);
731 #endif /* not WITHOUT_FILESYSTEM */
732 }