java_io_VMFile.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /* java_io_VMFile.c - Native methods for java.io.File class
  2. Copyright (C) 1998, 2004, 2006 Free Software Foundation, Inc.
  3. This file is part of GNU Classpath.
  4. GNU Classpath is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.
  8. GNU Classpath is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Classpath; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. Linking this library statically or dynamically with other modules is
  17. making a combined work based on this library. Thus, the terms and
  18. conditions of the GNU General Public License cover the whole
  19. combination.
  20. As a special exception, the copyright holders of this library give you
  21. permission to link this library with independent modules to produce an
  22. executable, regardless of the license terms of these independent
  23. modules, and to copy and distribute the resulting executable under
  24. terms of your choice, provided that you also meet, for each linked
  25. independent module, the terms and conditions of the license of that
  26. module. An independent module is a module which is not derived from
  27. or based on this library. If you modify this library, you may extend
  28. this exception to your version of the library, but you are not
  29. obligated to do so. If you do not wish to do so, delete this
  30. exception statement from your version. */
  31. /* do not move; needed here because of some macro definitions */
  32. #include <config.h>
  33. #include <assert.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #if defined (HAVE_LSTAT) && defined (HAVE_READLINK)
  37. #include <sys/types.h>
  38. #include <sys/stat.h>
  39. #include <unistd.h>
  40. #endif
  41. #include <jni.h>
  42. #include <jcl.h>
  43. #include "cpio.h"
  44. #include "cpnative.h"
  45. #include "java_io_VMFile.h"
  46. /* ***** PRIVATE FUNCTIONS DELCARATION ***** */
  47. /**
  48. * Enables of disables the passed permission bit of a file.
  49. */
  50. static jboolean set_file_permissions (JNIEnv *env, jstring name,
  51. jboolean enable,
  52. jboolean ownerOnly,
  53. int permissions);
  54. /* ***** END: PRIVATE FUNCTIONS DELCARATION ***** */
  55. /*************************************************************************/
  56. /*
  57. * Method to create an empty file.
  58. *
  59. * Class: java_io_VMFile
  60. * Method: create
  61. * Signature: (Ljava/lang/String;)Z
  62. */
  63. JNIEXPORT jboolean JNICALL
  64. Java_java_io_VMFile_create (JNIEnv * env,
  65. jclass clazz __attribute__ ((__unused__)),
  66. jstring name)
  67. {
  68. #ifndef WITHOUT_FILESYSTEM
  69. const char *filename;
  70. int fd;
  71. int result;
  72. filename = JCL_jstring_to_cstring (env, name);
  73. if (filename == NULL)
  74. {
  75. return 0;
  76. }
  77. result = cpio_openFile (filename, &fd, CPFILE_FLAG_CREATE|CPFILE_FLAG_WRITE, CPFILE_PERMISSION_NORMAL);
  78. if (result != CPNATIVE_OK)
  79. {
  80. if (result != EEXIST)
  81. JCL_ThrowException (env,
  82. "java/io/IOException",
  83. cpnative_getErrorString (result));
  84. JCL_free_cstring (env, name, filename);
  85. return 0;
  86. }
  87. cpio_closeFile (fd);
  88. JCL_free_cstring (env, name, filename);
  89. return 1;
  90. #else /* not WITHOUT_FILESYSTEM */
  91. return 0;
  92. #endif /* not WITHOUT_FILESYSTEM */
  93. }
  94. /*************************************************************************/
  95. /*
  96. * This method checks to see if we have read permission on a file.
  97. *
  98. * Class: java_io_VMFile
  99. * Method: canRead
  100. * Signature: (Ljava/lang/String;)Z
  101. */
  102. JNIEXPORT jboolean JNICALL
  103. Java_java_io_VMFile_canRead (JNIEnv * env,
  104. jclass clazz __attribute__ ((__unused__)),
  105. jstring name)
  106. {
  107. #ifndef WITHOUT_FILESYSTEM
  108. const char *filename;
  109. int result;
  110. /* Don't use the JCL convert function because it throws an exception
  111. on failure */
  112. filename = (*env)->GetStringUTFChars (env, name, 0);
  113. if (filename == NULL)
  114. {
  115. return JNI_FALSE;
  116. }
  117. result = cpio_checkAccess (filename, CPFILE_FLAG_READ);
  118. (*env)->ReleaseStringUTFChars (env, name, filename);
  119. if (result != CPNATIVE_OK)
  120. return JNI_FALSE;
  121. return JNI_TRUE;
  122. #else /* not WITHOUT_FILESYSTEM */
  123. return JNI_FALSE;
  124. #endif /* not WITHOUT_FILESYSTEM */
  125. }
  126. /*************************************************************************/
  127. /*
  128. * This method checks to see if we have write permission on a file.
  129. *
  130. * Class: java_io_VMFile
  131. * Method: canWrite
  132. * Signature: (Ljava/lang/String;)Z
  133. */
  134. JNIEXPORT jboolean JNICALL
  135. Java_java_io_VMFile_canWrite (JNIEnv * env,
  136. jclass clazz __attribute__ ((__unused__)),
  137. jstring name)
  138. {
  139. #ifndef WITHOUT_FILESYSTEM
  140. const char *filename;
  141. int result;
  142. /* Don't use the JCL convert function because it throws an exception
  143. on failure */
  144. filename = (*env)->GetStringUTFChars (env, name, 0);
  145. if (filename == NULL)
  146. {
  147. return JNI_FALSE;
  148. }
  149. result = cpio_checkAccess (filename, CPFILE_FLAG_WRITE);
  150. (*env)->ReleaseStringUTFChars (env, name, filename);
  151. if (result != CPNATIVE_OK)
  152. {
  153. return JNI_FALSE;
  154. }
  155. return JNI_TRUE;
  156. #else /* not WITHOUT_FILESYSTEM */
  157. return JNI_FALSE;
  158. #endif /* not WITHOUT_FILESYSTEM */
  159. }
  160. /*************************************************************************/
  161. JNIEXPORT jboolean JNICALL
  162. Java_java_io_VMFile_canWriteDirectory (JNIEnv *env, jclass clazz, jstring path)
  163. {
  164. /* this is only valid on *nix systems */
  165. return Java_java_io_VMFile_canWrite(env, clazz, path);
  166. }
  167. /*************************************************************************/
  168. /*
  169. * This method checks to see if we have execute permission on a file.
  170. *
  171. * Class: java_io_VMFile
  172. * Method: canExecute
  173. * Signature: (Ljava/lang/String;)Z
  174. */
  175. JNIEXPORT jboolean JNICALL
  176. Java_java_io_VMFile_canExecute (JNIEnv * env,
  177. jclass clazz __attribute__ ((__unused__)),
  178. jstring name)
  179. {
  180. #ifndef WITHOUT_FILESYSTEM
  181. const char *filename;
  182. int result;
  183. /* Don't use the JCL convert function because it throws an exception
  184. on failure */
  185. filename = (*env)->GetStringUTFChars (env, name, 0);
  186. if (filename == NULL)
  187. {
  188. return JNI_FALSE;
  189. }
  190. result = cpio_checkAccess (filename, CPFILE_FLAG_EXEC);
  191. (*env)->ReleaseStringUTFChars (env, name, filename);
  192. if (result != CPNATIVE_OK)
  193. return JNI_FALSE;
  194. return JNI_TRUE;
  195. #else /* not WITHOUT_FILESYSTEM */
  196. return JNI_FALSE;
  197. #endif /* not WITHOUT_FILESYSTEM */
  198. }
  199. /*************************************************************************/
  200. /*
  201. * This method makes a file read only.
  202. *
  203. * Class: java_io_VMFile
  204. * Method: setReadOnly
  205. * Signature: (Ljava/lang/String;)Z
  206. */
  207. JNIEXPORT jboolean JNICALL
  208. Java_java_io_VMFile_setReadOnly (JNIEnv * env,
  209. jclass clazz __attribute__ ((__unused__)),
  210. jstring name)
  211. {
  212. #ifndef WITHOUT_FILESYSTEM
  213. const char *filename;
  214. int result;
  215. /* Don't use the JCL convert function because it throws an exception
  216. on failure */
  217. filename = (*env)->GetStringUTFChars (env, name, 0);
  218. if (filename == NULL)
  219. {
  220. return 0;
  221. }
  222. result = cpio_setFileReadonly (filename);
  223. (*env)->ReleaseStringUTFChars (env, name, filename);
  224. return result == CPNATIVE_OK ? 1 : 0;
  225. #else /* not WITHOUT_FILESYSTEM */
  226. return 0;
  227. #endif /* not WITHOUT_FILESYSTEM */
  228. }
  229. /*************************************************************************/
  230. /*
  231. * This method changes the read permission bit of a file.
  232. *
  233. * Class: java_io_VMFile
  234. * Method: setReadable
  235. * Signature: (Ljava/lang/String;ZZ)Z
  236. */
  237. JNIEXPORT jboolean JNICALL
  238. Java_java_io_VMFile_setReadable (JNIEnv *env,
  239. jclass clazz __attribute__ ((__unused__)),
  240. jstring name,
  241. jboolean readable,
  242. jboolean ownerOnly)
  243. {
  244. return set_file_permissions (env, name, readable, ownerOnly,
  245. CPFILE_FLAG_READ);
  246. }
  247. /*************************************************************************/
  248. /*
  249. * This method changes the write permission bit of a file.
  250. *
  251. * Class: java_io_VMFile
  252. * Method: setWritable
  253. * Signature: (Ljava/lang/String;ZZ)Z
  254. */
  255. JNIEXPORT jboolean JNICALL
  256. Java_java_io_VMFile_setWritable (JNIEnv *env,
  257. jclass clazz __attribute__ ((__unused__)),
  258. jstring name,
  259. jboolean writable,
  260. jboolean ownerOnly)
  261. {
  262. return set_file_permissions (env, name, writable, ownerOnly,
  263. CPFILE_FLAG_WRITE);
  264. }
  265. /*************************************************************************/
  266. /*
  267. * This method changes the execute permission bit of a file.
  268. *
  269. * Class: java_io_VMFile
  270. * Method: setExecutable
  271. * Signature: (Ljava/lang/String;ZZ)Z
  272. */
  273. JNIEXPORT jboolean JNICALL
  274. Java_java_io_VMFile_setExecutable (JNIEnv *env,
  275. jclass clazz __attribute__ ((__unused__)),
  276. jstring name,
  277. jboolean executable,
  278. jboolean ownerOnly)
  279. {
  280. return set_file_permissions (env, name, executable, ownerOnly,
  281. CPFILE_FLAG_EXEC);
  282. }
  283. /*************************************************************************/
  284. JNIEXPORT jlong JNICALL
  285. Java_java_io_VMFile_getTotalSpace (JNIEnv *env,
  286. jclass clazz __attribute__ ((__unused__)),
  287. jstring path)
  288. {
  289. #ifndef WITHOUT_FILESYSTEM
  290. jlong result;
  291. const char *_path = NULL;
  292. _path = (*env)->GetStringUTFChars (env, path, 0);
  293. if (_path == NULL)
  294. {
  295. return 0L;
  296. }
  297. result = cpio_df (_path, TOTAL);
  298. (*env)->ReleaseStringUTFChars (env, path, _path);
  299. return result;
  300. #else /* not WITHOUT_FILESYSTEM */
  301. return 0L;
  302. #endif /* not WITHOUT_FILESYSTEM */
  303. }
  304. /*************************************************************************/
  305. JNIEXPORT jlong JNICALL
  306. Java_java_io_VMFile_getFreeSpace (JNIEnv *env,
  307. jclass clazz __attribute__ ((__unused__)),
  308. jstring path)
  309. {
  310. #ifndef WITHOUT_FILESYSTEM
  311. jlong result;
  312. const char *_path = NULL;
  313. _path = (*env)->GetStringUTFChars (env, path, 0);
  314. if (_path == NULL)
  315. {
  316. return 0L;
  317. }
  318. result = cpio_df (_path, FREE);
  319. (*env)->ReleaseStringUTFChars (env, path, _path);
  320. return result;
  321. #else /* not WITHOUT_FILESYSTEM */
  322. return 0L;
  323. #endif /* not WITHOUT_FILESYSTEM */
  324. }
  325. /*************************************************************************/
  326. JNIEXPORT jlong JNICALL
  327. Java_java_io_VMFile_getUsableSpace (JNIEnv *env,
  328. jclass clazz __attribute__ ((__unused__)),
  329. jstring path)
  330. {
  331. #ifndef WITHOUT_FILESYSTEM
  332. jlong result;
  333. const char *_path = NULL;
  334. _path = (*env)->GetStringUTFChars (env, path, 0);
  335. if (_path == NULL)
  336. {
  337. return 0L;
  338. }
  339. result = cpio_df (_path, USABLE);
  340. (*env)->ReleaseStringUTFChars (env, path, _path);
  341. return result;
  342. #else /* not WITHOUT_FILESYSTEM */
  343. return 0L;
  344. #endif /* not WITHOUT_FILESYSTEM */
  345. }
  346. /*************************************************************************/
  347. /*
  348. * This method checks to see if a file exists.
  349. *
  350. * Class: java_io_VMFile
  351. * Method: exists
  352. * Signature: (Ljava/lang/String;)Z
  353. */
  354. JNIEXPORT jboolean JNICALL
  355. Java_java_io_VMFile_exists (JNIEnv * env,
  356. jclass clazz __attribute__ ((__unused__)),
  357. jstring name)
  358. {
  359. #ifndef WITHOUT_FILESYSTEM
  360. const char *filename;
  361. int result;
  362. /* Don't use the JCL convert function because it throws an exception
  363. on failure */
  364. filename = (*env)->GetStringUTFChars (env, name, 0);
  365. if (filename == NULL)
  366. {
  367. return 0;
  368. }
  369. result = cpio_isFileExists (filename);
  370. (*env)->ReleaseStringUTFChars (env, name, filename);
  371. return result == CPNATIVE_OK ? 1 : 0;
  372. #else /* not WITHOUT_FILESYSTEM */
  373. return 0;
  374. #endif /* not WITHOUT_FILESYSTEM */
  375. }
  376. /*************************************************************************/
  377. /*
  378. * This method checks to see if a file is a "plain" file; that is, not
  379. * a directory, pipe, etc.
  380. *
  381. * Class: java_io_VMFile
  382. * Method: isFile
  383. * Signature: (Ljava/lang/String;)Z
  384. */
  385. JNIEXPORT jboolean JNICALL
  386. Java_java_io_VMFile_isFile (JNIEnv * env,
  387. jclass clazz __attribute__ ((__unused__)),
  388. jstring name)
  389. {
  390. #ifndef WITHOUT_FILESYSTEM
  391. const char *filename;
  392. int result;
  393. jint entryType;
  394. /* Don't use the JCL convert function because it throws an exception
  395. on failure */
  396. filename = (*env)->GetStringUTFChars (env, name, 0);
  397. if (filename == NULL)
  398. {
  399. return 0;
  400. }
  401. result = cpio_checkType (filename, &entryType);
  402. (*env)->ReleaseStringUTFChars (env, name, filename);
  403. return result == CPNATIVE_OK && entryType == CPFILE_FILE ? 1 : 0;
  404. #else /* not WITHOUT_FILESYSTEM */
  405. return 0;
  406. #endif /* not WITHOUT_FILESYSTEM */
  407. }
  408. /*************************************************************************/
  409. /*
  410. * This method checks to see if a file is a directory or not.
  411. *
  412. * Class: java_io_VMFile
  413. * Method: isDirectory
  414. * Signature: (Ljava/lang/String;)Z
  415. */
  416. JNIEXPORT jboolean JNICALL
  417. Java_java_io_VMFile_isDirectory (JNIEnv * env,
  418. jclass clazz __attribute__ ((__unused__)),
  419. jstring name)
  420. {
  421. #ifndef WITHOUT_FILESYSTEM
  422. const char *filename;
  423. int result;
  424. jint entryType;
  425. /* Don't use the JCL convert function because it throws an exception
  426. on failure */
  427. filename = (*env)->GetStringUTFChars (env, name, 0);
  428. if (filename == NULL)
  429. {
  430. return 0;
  431. }
  432. result = cpio_checkType (filename, &entryType);
  433. (*env)->ReleaseStringUTFChars (env, name, filename);
  434. return result == CPNATIVE_OK && entryType == CPFILE_DIRECTORY ? 1 : 0;
  435. #else /* not WITHOUT_FILESYSTEM */
  436. return 0;
  437. #endif /* not WITHOUT_FILESYSTEM */
  438. }
  439. /*************************************************************************/
  440. /*
  441. * This method returns the length of the file.
  442. *
  443. * Class: java_io_VMFile
  444. * Method: length
  445. * Signature: (Ljava/lang/String;)J
  446. */
  447. JNIEXPORT jlong JNICALL
  448. Java_java_io_VMFile_length (JNIEnv * env,
  449. jclass clazz __attribute__ ((__unused__)),
  450. jstring name)
  451. {
  452. #ifndef WITHOUT_FILESYSTEM
  453. const char *filename;
  454. int tmpfd;
  455. jlong length;
  456. int result;
  457. /* Don't use the JCL convert function because it throws an exception
  458. on failure */
  459. filename = (*env)->GetStringUTFChars (env, name, 0);
  460. if (filename == NULL)
  461. return 0;
  462. /* open file for reading, get size and close file */
  463. result = cpio_openFile (filename, &tmpfd, CPFILE_FLAG_READ, 0);
  464. if (result != CPNATIVE_OK)
  465. return 0;
  466. result = cpio_getFileSize (tmpfd, &length);
  467. if (result != CPNATIVE_OK)
  468. {
  469. cpio_closeFile (tmpfd);
  470. return 0;
  471. }
  472. result = cpio_closeFile (tmpfd);
  473. (*env)->ReleaseStringUTFChars (env, name, filename);
  474. return result == CPNATIVE_OK ? length : 0;
  475. #else /* not WITHOUT_FILESYSTEM */
  476. return 0;
  477. #endif /* not WITHOUT_FILESYSTEM */
  478. }
  479. /*************************************************************************/
  480. /*
  481. * This method returns the modification date of the file.
  482. *
  483. * Class: java_io_VMFile
  484. * Method: lastModified
  485. * Signature: (Ljava/lang/String;)J
  486. */
  487. JNIEXPORT jlong JNICALL
  488. Java_java_io_VMFile_lastModified (JNIEnv * env,
  489. jclass clazz __attribute__ ((__unused__)),
  490. jstring name)
  491. {
  492. #ifndef WITHOUT_FILESYSTEM
  493. const char *filename;
  494. jlong mtime;
  495. int result;
  496. /* Don't use the JCL convert function because it throws an exception
  497. on failure */
  498. filename = (*env)->GetStringUTFChars (env, name, 0);
  499. if (filename == NULL)
  500. {
  501. return 0;
  502. }
  503. result = cpio_getModificationTime (filename, &mtime);
  504. (*env)->ReleaseStringUTFChars (env, name, filename);
  505. return result == CPNATIVE_OK ? mtime : 0;
  506. #else /* not WITHOUT_FILESYSTEM */
  507. return 0;
  508. #endif /* not WITHOUT_FILESYSTEM */
  509. }
  510. /*************************************************************************/
  511. /*
  512. * This method sets the modification date of the file.
  513. *
  514. * Class: java_io_VMFile
  515. * Method: setLastModified
  516. * Signature: (Ljava/lang/String;J)Z
  517. */
  518. JNIEXPORT jboolean JNICALL
  519. Java_java_io_VMFile_setLastModified (JNIEnv * env,
  520. jclass clazz __attribute__ ((__unused__)),
  521. jstring name, jlong newtime)
  522. {
  523. #ifndef WITHOUT_FILESYSTEM
  524. const char *filename;
  525. int result;
  526. /* Don't use the JCL convert function because it throws an exception
  527. on failure */
  528. filename = (*env)->GetStringUTFChars (env, name, 0);
  529. if (filename == NULL)
  530. {
  531. return 0;
  532. }
  533. result = cpio_setModificationTime (filename, newtime);
  534. (*env)->ReleaseStringUTFChars (env, name, filename);
  535. return result == CPNATIVE_OK ? 1 : 0;
  536. #else /* not WITHOUT_FILESYSTEM */
  537. return 0;
  538. #endif /* not WITHOUT_FILESYSTEM */
  539. }
  540. /*************************************************************************/
  541. /*
  542. * This method deletes a file (actually a name for a file - additional
  543. * links could exist).
  544. *
  545. * Class: java_io_VMFile
  546. * Method: delete
  547. * Signature: (Ljava/lang/String;)Z
  548. */
  549. JNIEXPORT jboolean JNICALL
  550. Java_java_io_VMFile_delete (JNIEnv * env,
  551. jclass clazz __attribute__ ((__unused__)),
  552. jstring name)
  553. {
  554. #ifndef WITHOUT_FILESYSTEM
  555. const char *filename;
  556. int result;
  557. /* Don't use the JCL convert function because it throws an exception
  558. on failure */
  559. filename = (*env)->GetStringUTFChars (env, name, 0);
  560. if (filename == NULL)
  561. {
  562. return 0;
  563. }
  564. result = cpio_removeFile (filename);
  565. (*env)->ReleaseStringUTFChars (env, name, filename);
  566. return result == CPNATIVE_OK ? 1 : 0;
  567. #else /* not WITHOUT_FILESYSTEM */
  568. return 0;
  569. #endif /* not WITHOUT_FILESYSTEM */
  570. }
  571. /*************************************************************************/
  572. /*
  573. * This method creates a directory.
  574. *
  575. * Class: java_io_VMFile
  576. * Method: mkdir
  577. * Signature: (Ljava/lang/String;)Z
  578. */
  579. JNIEXPORT jboolean JNICALL
  580. Java_java_io_VMFile_mkdir (JNIEnv * env,
  581. jclass clazz __attribute__ ((__unused__)),
  582. jstring name)
  583. {
  584. #ifndef WITHOUT_FILESYSTEM
  585. const char *pathname;
  586. int result;
  587. /* Don't use the JCL convert function because it throws an exception
  588. on failure */
  589. pathname = (*env)->GetStringUTFChars (env, name, 0);
  590. if (pathname == NULL)
  591. {
  592. return 0;
  593. }
  594. result = cpio_mkdir (pathname);
  595. (*env)->ReleaseStringUTFChars (env, name, pathname);
  596. return (result == CPNATIVE_OK) ? 1 : 0;
  597. #else /* not WITHOUT_FILESYSTEM */
  598. return 0;
  599. #endif /* not WITHOUT_FILESYSTEM */
  600. }
  601. /*************************************************************************/
  602. /*
  603. * This method renames a (link to a) file.
  604. *
  605. * Class: java_io_VMFile
  606. * Method: renameTo
  607. * Signature: (Ljava/lang/String;Ljava/lang/String;)Z
  608. */
  609. JNIEXPORT jboolean JNICALL
  610. Java_java_io_VMFile_renameTo (JNIEnv * env,
  611. jclass clazz __attribute__ ((__unused__)),
  612. jstring t, jstring d)
  613. {
  614. #ifndef WITHOUT_FILESYSTEM
  615. const char *old_filename, *new_filename;
  616. int result;
  617. /* Don't use the JCL convert function because it throws an exception
  618. on failure */
  619. old_filename = (*env)->GetStringUTFChars (env, t, 0);
  620. if (old_filename == NULL)
  621. {
  622. return 0;
  623. }
  624. new_filename = (*env)->GetStringUTFChars (env, d, 0);
  625. if (new_filename == NULL)
  626. {
  627. (*env)->ReleaseStringUTFChars (env, t, old_filename);
  628. return 0;
  629. }
  630. result = cpio_rename (old_filename, new_filename);
  631. (*env)->ReleaseStringUTFChars (env, d, new_filename);
  632. (*env)->ReleaseStringUTFChars (env, t, old_filename);
  633. return (result == CPNATIVE_OK) ? 1 : 0;
  634. #else /* not WITHOUT_FILESYSTEM */
  635. return 0;
  636. #endif /* not WITHOUT_FILESYSTEM */
  637. }
  638. /*************************************************************************/
  639. /*
  640. * This method returns an array of String representing all the files
  641. * in a directory except "." and "..".
  642. *
  643. * Class: java_io_VMFile
  644. * Method: list
  645. * Signature: (Ljava/lang/String;)[Ljava/lang/String;
  646. */
  647. JNIEXPORT jobjectArray JNICALL
  648. Java_java_io_VMFile_list (JNIEnv * env,
  649. jclass clazz __attribute__ ((__unused__)),
  650. jstring name)
  651. {
  652. #ifndef WITHOUT_FILESYSTEM
  653. const int REALLOC_SIZE = 10;
  654. const char *dirname;
  655. int result;
  656. char **filelist;
  657. void *handle;
  658. char *filename = (char *) JCL_malloc (env, FILENAME_MAX);
  659. unsigned long int filelist_count, max_filelist_count;
  660. char **tmp_filelist;
  661. jclass str_clazz;
  662. jobjectArray filearray;
  663. unsigned long int i;
  664. jstring str;
  665. /* Don't use the JCL convert function because it throws an exception
  666. on failure */
  667. dirname = (*env)->GetStringUTFChars (env, name, 0);
  668. if (dirname == NULL)
  669. {
  670. return 0;
  671. }
  672. /* open directory for reading */
  673. result = cpio_openDir (dirname, &handle);
  674. (*env)->ReleaseStringUTFChars (env, name, dirname);
  675. if (result != CPNATIVE_OK)
  676. {
  677. return 0;
  678. }
  679. /* allocate filelist */
  680. filelist = (char **) JCL_malloc (env, sizeof (char *) * REALLOC_SIZE);
  681. if (filelist == NULL)
  682. {
  683. result = cpio_closeDir (handle);
  684. return 0;
  685. }
  686. filelist_count = 0;
  687. max_filelist_count = REALLOC_SIZE;
  688. /* read the files from the directory */
  689. result = cpio_readDir (handle, filename);
  690. while (result == CPNATIVE_OK)
  691. {
  692. if ((strcmp (filename, ".") != 0) && (strcmp (filename, "..") != 0))
  693. {
  694. /* allocate more memory if necessary */
  695. if (filelist_count >= max_filelist_count)
  696. {
  697. tmp_filelist = (char **) JCL_realloc (env,
  698. filelist,
  699. (max_filelist_count +
  700. REALLOC_SIZE) *
  701. sizeof (char *));
  702. if (tmp_filelist == NULL)
  703. {
  704. for (i = 0; i < filelist_count; i++)
  705. {
  706. JCL_free (env, filelist[i]);
  707. }
  708. JCL_free (env, filelist);
  709. result = cpio_closeDir (handle);
  710. return 0;
  711. }
  712. filelist = tmp_filelist;
  713. max_filelist_count += REALLOC_SIZE;
  714. }
  715. /* save entry in list (avoid strdup, because it is not ANSI C, thus difficult to port) */
  716. filelist[filelist_count] =
  717. (char *) JCL_malloc (env, strlen (filename) + 1);
  718. assert (filelist[filelist_count] != NULL);
  719. strcpy (filelist[filelist_count], filename);
  720. filelist_count++;
  721. }
  722. /* read next directory entry */
  723. result = cpio_readDir (handle, filename);
  724. }
  725. JCL_free (env, filename);
  726. /* close directory */
  727. result = cpio_closeDir (handle);
  728. /* put the list of files into a Java String array and return it */
  729. str_clazz = (*env)->FindClass (env, "java/lang/String");
  730. if (str_clazz == NULL)
  731. {
  732. for (i = 0; i < filelist_count; i++)
  733. {
  734. JCL_free (env, filelist[i]);
  735. }
  736. JCL_free (env, filelist);
  737. return 0;
  738. }
  739. filearray = (*env)->NewObjectArray (env, filelist_count, str_clazz, 0);
  740. if (filearray == NULL)
  741. {
  742. for (i = 0; i < filelist_count; i++)
  743. {
  744. JCL_free (env, filelist[i]);
  745. }
  746. JCL_free (env, filelist);
  747. return 0;
  748. }
  749. (*env)->DeleteLocalRef (env, str_clazz);
  750. for (i = 0; i < filelist_count; i++)
  751. {
  752. /* create new string */
  753. str = (*env)->NewStringUTF (env, filelist[i]);
  754. if (str == NULL)
  755. {
  756. /* We don't clean up everything here, but if this failed,
  757. something serious happened anyway */
  758. for (i = 0; i < filelist_count; i++)
  759. {
  760. JCL_free (env, filelist[i]);
  761. }
  762. JCL_free (env, filelist);
  763. return 0;
  764. }
  765. /* save into array */
  766. (*env)->SetObjectArrayElement (env, filearray, i, str);
  767. /* delete local reference */
  768. (*env)->DeleteLocalRef (env, str);
  769. }
  770. /* free resources */
  771. for (i = 0; i < filelist_count; i++)
  772. {
  773. JCL_free (env, filelist[i]);
  774. }
  775. JCL_free (env, filelist);
  776. return filearray;
  777. #else /* not WITHOUT_FILESYSTEM */
  778. return 0;
  779. #endif /* not WITHOUT_FILESYSTEM */
  780. }
  781. /*************************************************************************/
  782. /*
  783. * These two methods are used to maintain dynamically allocated
  784. * buffers for getCanonicalPath without the overhead of calling
  785. * realloc every time a buffer is modified. Buffers are sized
  786. * at the smallest multiple of CHUNKSIZ that is greater than or
  787. * equal to the desired length. The default CHUNKSIZ is 256,
  788. * longer than most paths, so in most cases a getCanonicalPath
  789. * will require only one malloc per buffer.
  790. */
  791. #define CHUNKLOG 8
  792. #define CHUNKSIZ (1 << CHUNKLOG)
  793. static int
  794. nextChunkSize (int size)
  795. {
  796. return ((size >> CHUNKLOG) + ((size & (CHUNKSIZ - 1)) ? 1 : 0)) << CHUNKLOG;
  797. }
  798. static char *
  799. maybeGrowBuf (JNIEnv *env, char *buf, int *size, int required)
  800. {
  801. if (required > *size)
  802. {
  803. *size = nextChunkSize (required);
  804. buf = JCL_realloc (env, buf, *size);
  805. }
  806. return buf;
  807. }
  808. /*************************************************************************/
  809. /*
  810. * This method converts a path to canonical form on GNU/Posix systems.
  811. * This involves the removal of redundant separators, references to
  812. * "." and "..", and symbolic links.
  813. *
  814. * The conversion proceeds on a component-by-component basis: symbolic
  815. * links and references to ".." are resolved as and when they occur.
  816. * This means that if "/foo/bar" is a symbolic link to "/baz" then the
  817. * canonical form of "/foo/bar/.." is "/" and not "/foo".
  818. *
  819. * In order to mimic the behaviour of proprietary JVMs, non-existant
  820. * path components are allowed (a departure from the normal GNU system
  821. * convention). This means that if "/foo/bar" is a symbolic link to
  822. * "/baz", the canonical form of "/non-existant-directory/../foo/bar"
  823. * is "/baz".
  824. *
  825. * Class: java_io_VMFile
  826. * Method: toCanonicalForm
  827. * Signature: (Ljava/lang/String)Ljava/lang/String
  828. */
  829. JNIEXPORT jstring JNICALL
  830. Java_java_io_VMFile_toCanonicalForm (JNIEnv *env,
  831. jclass class __attribute__ ((__unused__)),
  832. jstring jpath)
  833. {
  834. #ifndef WITHOUT_FILESYSTEM
  835. const char *path;
  836. char *src, *dst;
  837. int srci, dsti;
  838. int srcl, dstl;
  839. int len;
  840. int fschecks;
  841. #if defined (HAVE_LSTAT) && defined (HAVE_READLINK)
  842. struct stat sb;
  843. #endif /* HAVE_LSTAT && HAVE_READLINK */
  844. path = JCL_jstring_to_cstring (env, jpath);
  845. if (path == NULL)
  846. return NULL;
  847. /* It is the caller's responsibility to ensure the path is absolute. */
  848. if (path[0] == 0 || path[0] != '/')
  849. {
  850. JCL_free_cstring (env, jpath, path);
  851. JCL_ThrowException (env, "java/lang/RuntimeException", "Not absolute");
  852. return NULL;
  853. }
  854. len = strlen (path);
  855. srcl = nextChunkSize (len + 1);
  856. src = JCL_malloc (env, srcl);
  857. if (src == NULL)
  858. {
  859. JCL_free_cstring (env, jpath, path);
  860. return NULL;
  861. }
  862. strcpy (src, path);
  863. JCL_free_cstring (env, jpath, path);
  864. srci = 1;
  865. dstl = nextChunkSize (2);
  866. dst = JCL_malloc (env, dstl);
  867. if (dst == NULL)
  868. {
  869. JCL_free (env, src);
  870. return NULL;
  871. }
  872. dst[0] = '/';
  873. dsti = 1;
  874. fschecks = JNI_TRUE;
  875. while (src[srci] != '\0')
  876. {
  877. int tmpi, dsti_save;
  878. /* Skip slashes. */
  879. while (src[srci] == '/')
  880. srci++;
  881. tmpi = srci;
  882. /* Find next slash. */
  883. while (src[srci] != '/' && src[srci] != '\0')
  884. srci++;
  885. if (srci == tmpi)
  886. /* We hit the end. */
  887. break;
  888. len = srci - tmpi;
  889. /* Handle "." and "..". */
  890. if (len == 1 && src[tmpi] == '.')
  891. continue;
  892. if (len == 2 && src[tmpi] == '.' && src[tmpi + 1] == '.')
  893. {
  894. while (dsti > 1 && dst[dsti - 1] != '/')
  895. dsti--;
  896. if (dsti != 1)
  897. dsti--;
  898. /* Reenable filesystem checking if disabled, as we might
  899. * have reversed over whatever caused the problem before.
  900. * At least one proprietary JVM has inconsistencies because
  901. * it does not do this.
  902. */
  903. fschecks = JNI_TRUE;
  904. continue;
  905. }
  906. /* Handle real path components. */
  907. dst = maybeGrowBuf (env,
  908. dst, &dstl, dsti + (dsti > 1 ? 1 : 0) + len + 1);
  909. if (dst == NULL)
  910. {
  911. JCL_free (env, src);
  912. return NULL;
  913. }
  914. dsti_save = dsti;
  915. if (dsti > 1)
  916. dst[dsti++] = '/';
  917. strncpy (&dst[dsti], &src[tmpi], len);
  918. dsti += len;
  919. if (fschecks == JNI_FALSE)
  920. continue;
  921. #if defined (HAVE_LSTAT) && defined (HAVE_READLINK)
  922. dst[dsti] = '\0';
  923. if (lstat (dst, &sb) == 0)
  924. {
  925. if (S_ISLNK (sb.st_mode))
  926. {
  927. int tmpl = CHUNKSIZ;
  928. char *tmp = JCL_malloc (env, tmpl);
  929. if (tmp == NULL)
  930. {
  931. JCL_free (env, src);
  932. JCL_free (env, dst);
  933. return NULL;
  934. }
  935. while (1)
  936. {
  937. tmpi = readlink (dst, tmp, tmpl);
  938. if (tmpi < 1)
  939. {
  940. JCL_free (env, src);
  941. JCL_free (env, dst);
  942. JCL_free (env, tmp);
  943. JCL_ThrowException (env, "java/io/IOException",
  944. "readlink failed");
  945. return NULL;
  946. }
  947. if (tmpi < tmpl)
  948. break;
  949. tmpl += CHUNKSIZ;
  950. tmp = JCL_realloc (env, tmp, tmpl);
  951. }
  952. /* Prepend the link's path to src. */
  953. tmp = maybeGrowBuf (env,
  954. tmp, &tmpl, tmpi + strlen (&src[srci]) + 1);
  955. if (tmp == NULL)
  956. {
  957. JCL_free (env, src);
  958. JCL_free (env, dst);
  959. return NULL;
  960. }
  961. strcpy (&tmp[tmpi], &src[srci]);
  962. JCL_free (env, src);
  963. src = tmp;
  964. srcl = tmpl;
  965. srci = 0;
  966. /* Either replace or append dst depending on whether the
  967. * link is relative or absolute.
  968. */
  969. dsti = src[0] == '/' ? 1 : dsti_save;
  970. }
  971. }
  972. else
  973. {
  974. /* Something doesn't exist, or we don't have permission to
  975. * read it, or a previous path component is a directory, or
  976. * a symlink is looped. Whatever, we can't check the
  977. * filesystem any more.
  978. */
  979. fschecks = JNI_FALSE;
  980. }
  981. #endif /* HAVE_LSTAT && HAVE_READLINK */
  982. }
  983. dst[dsti] = '\0';
  984. jpath = (*env)->NewStringUTF (env, dst);
  985. JCL_free (env, src);
  986. JCL_free (env, dst);
  987. return jpath;
  988. #else /* not WITHOUT_FILESYSTEM */
  989. return NULL;
  990. #endif /* not WITHOUT_FILESYSTEM */
  991. }
  992. /*************************************************************************/
  993. /* ***** PRIVATE FUNCTIONS IMPLEMENTATION ***** */
  994. static jboolean set_file_permissions (JNIEnv *env, jstring name,
  995. jboolean enable,
  996. jboolean ownerOnly,
  997. int permissions)
  998. {
  999. #ifndef WITHOUT_FILESYSTEM
  1000. const char *filename;
  1001. int result = JNI_FALSE;
  1002. /* Don't use the JCL convert function because it throws an exception
  1003. on failure */
  1004. filename = (*env)->GetStringUTFChars (env, name, 0);
  1005. if (filename == NULL)
  1006. {
  1007. return JNI_FALSE;
  1008. }
  1009. if (ownerOnly)
  1010. {
  1011. permissions |= CPFILE_FLAG_USR;
  1012. }
  1013. if (!enable)
  1014. {
  1015. permissions |= CPFILE_FLAG_OFF;
  1016. }
  1017. result = cpio_chmod (filename, permissions);
  1018. (*env)->ReleaseStringUTFChars (env, name, filename);
  1019. return result == CPNATIVE_OK ? JNI_TRUE : JNI_FALSE;
  1020. #else /* not WITHOUT_FILESYSTEM */
  1021. return JNI_FALSE;
  1022. #endif /* not WITHOUT_FILESYSTEM */
  1023. }