Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / JAVA / libjafs / File.c
1 /*
2 * Copyright (c) 2001-2002 International Business Machines Corp.
3 * All rights reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 *
9 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
10 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
11 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
12 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
13 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
15 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
16 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
17 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
18 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20 */
21
22 #include <afs/param.h>
23 #include <afs/com_err.h>
24 #include <errno.h>
25
26 #include "Internal.h"
27 #include "org_openafs_jafs_File.h"
28
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <jni.h>
32 #include <pthread.h>
33 /*#include <afs/afs_usrops.h>*/
34 #include <afs/prs_fs.h>
35 #include <sys/time.h>
36 #include <unistd.h>
37
38 /* Access Rights */
39 #define UAFS_READ 1
40 #define UAFS_WRITE 2
41 #define UAFS_INSERT 4
42 #define UAFS_LOOKUP 8
43 #define UAFS_DELETE 16
44 #define UAFS_LOCK 32
45 #define UAFS_ADMIN 64
46
47 #ifdef DMALLOC
48 #include "dmalloc.h"
49 #endif
50
51 void setFileNotExistsAttributes(JNIEnv *env, jobject *obj);
52
53 typedef struct {
54 char *fileName;
55 void *next;
56 } FileNameNode;
57
58 /*static char compile_date[] = COMPILE_DATE;*/
59
60 int sub_time(struct timeval *tv1, struct timeval *tv2)
61 {
62 if (tv2->tv_usec > tv1->tv_usec) {
63 tv1->tv_usec += 1000000;
64 tv1->tv_usec -= 1;
65 }
66
67 tv1->tv_usec -= tv2->tv_usec;
68 tv1->tv_sec -= tv2->tv_sec;
69 }
70
71 /**
72 * Sets dirName to the absolute path according to the path field
73 * within the Java File object (obj).
74 *
75 * env the Java environment
76 * obj the current Java object
77 */
78 char* getAbsolutePath(JNIEnv *env, jobject *obj, char *dirName)
79 {
80 jclass thisClass;
81 jstring jDirName;
82 jmethodID getAbsolutePathID;
83 const char *auxDirName;
84 jfieldID fid;
85
86 thisClass = (*env)->GetObjectClass(env, *obj);
87 if(thisClass == NULL) {
88 fprintf(stderr, "File::getAbsolutePath(): GetObjectClass failed\n");
89 return NULL;
90 }
91 fid = (*env)->GetFieldID(env, thisClass, "path", "Ljava/lang/String;");
92 if (fid == 0) {
93 fprintf(stderr, "File::getAbsolutePath(): GetFieldID (path) failed\n");
94 return NULL;
95 }
96 jDirName = (*env)->GetObjectField(env, *obj, fid);
97
98 if(jDirName == NULL) {
99 fprintf(stderr, "File::getAbsolutePath(): failed to get file name\n");
100 return NULL;
101 }
102 auxDirName = (*env) -> GetStringUTFChars(env, jDirName, 0);
103 strcpy(dirName, auxDirName);
104 (*env) -> ReleaseStringUTFChars(env, jDirName, auxDirName);
105 }
106
107 /**
108 * Performs a file stat on the actual AFS file and populates
109 * the Java object's respective field members with the appropriate values.
110 * method will, if authorized, perform a stat on the
111 * actual AFS file and update its respective field members; defining
112 * this file object's attributes.
113 *
114 * env the Java environment
115 * obj the current Java object
116 *
117 * return true if and only if the current user is allowed to stat the file;
118 * false otherwise.
119 *
120 * throws AFSException
121 */
122 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_setAttributes
123 (JNIEnv *env, jobject obj)
124 {
125 char target[FILENAME_MAX+1];
126 char dirName[FILENAME_MAX];
127 jclass thisClass;
128 jfieldID fid;
129 struct stat st;
130 int rc, fd;
131 int mtpoint = 0;
132 jboolean islink = JNI_FALSE;
133 int i;
134 struct timeval tv0, tv1;
135
136 /*memset(target, 0, FILENAME_MAX);*/
137
138 *dirName = '\0';
139 getAbsolutePath(env, &obj, dirName);
140
141 /*fprintf(stderr, "dirName=%s\n", dirName);*/
142
143 if(*dirName == '\0') {
144 fprintf(stderr, "File::setAttributes(): failed to get dirName\n");
145 return JNI_FALSE;
146 }
147
148 thisClass = (*env) -> GetObjectClass(env, obj);
149 if(thisClass == NULL) {
150 fprintf(stderr, "File::setAttributes(): GetObjectClass failed\n");
151 return JNI_FALSE;
152 }
153
154 gettimeofday(&tv0, NULL);
155 if ((strcmp(dirName, "/afs") == 0) || (strcmp(dirName, "/afs/") == 0)) {
156 rc = 1; /* special case for /afs since statmountpoint fails on it */
157 } else {
158 rc = uafs_statmountpoint(dirName);
159 gettimeofday(&tv1, NULL);
160 sub_time(&tv1, &tv0);
161 /*printf("%s: statmountpoint %d.%06d\n", dirName, tv1.tv_sec, tv1.tv_usec);*/
162 }
163
164 if(rc < 0) {
165 setError(env, &obj, errno);
166 if(errno == ENOENT) {
167 setFileNotExistsAttributes(env, &obj);
168 return JNI_TRUE; /* not really an error */
169 } else {
170 fprintf(stderr, "File::setAttributes(): uafs_statmountpoint failed "
171 "for %s (%s)\n", dirName, afs_error_message(errno));
172 return JNI_FALSE;
173 }
174 }
175
176 if (rc == 1) {
177 /* this is an AFS mount point; we don't want to stat it */
178 /* fake up a stat entry instead */
179 mtpoint = 1;
180 st.st_mtime = 0;
181 st.st_size = 2048;
182 st.st_mode = 0; /* don't match anything */
183 } else {
184 mtpoint = 0;
185 fid = (*env)->GetFieldID(env, thisClass, "isLink", "Z");
186 if (fid == 0) {
187 fprintf(stderr, "File::setAttributes(): GetFieldID (isLink) failed\n");
188 setError(env, &obj, -1);
189 return JNI_FALSE;
190 }
191 islink = (*env)->GetBooleanField(env, obj, fid);
192 if (islink != JNI_TRUE) {
193 rc = uafs_lstat(dirName, &st);
194 } else {
195 /* Here we are being called on a link object for the second time,
196 so we want info on the object pointed to by the link. */
197 fprintf(stderr, "islink = TRUE on file %s\n", dirName);
198 rc = uafs_stat(dirName, &st);
199 }
200
201 if(rc < 0) {
202 setError(env, &obj, errno);
203 fprintf(stderr, "uafs_lstat failed for dir %s: error %d\n",
204 dirName, errno);
205 if(errno == ENOENT) {
206 setFileNotExistsAttributes(env, &obj);
207 return JNI_TRUE;
208 }
209 fprintf(stderr,
210 "File::setAttributes(): uafs_stat failed for %s (%s)\n",
211 dirName, afs_error_message(errno));
212 return JNI_FALSE;
213 }
214 }
215
216 fid = (*env)->GetFieldID(env, thisClass, "exists", "Z");
217 if (fid == 0) {
218 fprintf(stderr,
219 "File::setAttributes(): GetFieldID (exists) failed\n");
220 setError(env, &obj, -1);
221 return JNI_FALSE;
222 }
223 (*env)->SetBooleanField(env, obj, fid, JNI_TRUE);
224
225 fid = (*env)->GetFieldID(env, thisClass, "isDirectory", "Z");
226 if (fid == 0) {
227 fprintf(stderr,
228 "File::setAttributes(): GetFieldID (isDirectory) failed\n");
229 setError(env, &obj, -1);
230 return JNI_FALSE;
231 }
232 if ((st.st_mode & S_IFMT) == S_IFDIR && !mtpoint) {
233 (*env)->SetBooleanField(env, obj, fid, JNI_TRUE);
234 } else {
235 (*env)->SetBooleanField(env, obj, fid, JNI_FALSE);
236 }
237
238 fid = (*env)->GetFieldID(env, thisClass, "isFile", "Z");
239 if (fid == 0) {
240 fprintf(stderr,
241 "File::setAttributes(): GetFieldID (isFile) failed\n");
242 setError(env, &obj, -1);
243 return JNI_FALSE;
244 }
245 if ((st.st_mode & S_IFMT) == S_IFREG) {
246 (*env)->SetBooleanField(env, obj, fid, JNI_TRUE);
247 } else {
248 (*env)->SetBooleanField(env, obj, fid, JNI_FALSE);
249 }
250
251 fid = (*env)->GetFieldID(env, thisClass, "isLink", "Z");
252 if (fid == 0) {
253 fprintf(stderr,
254 "File::setAttributes(): GetFieldID (isLink) failed\n");
255 setError(env, &obj, -1);
256 return JNI_FALSE;
257 }
258
259 if (islink != JNI_TRUE) { /* don't re-process link */
260 if ((st.st_mode & S_IFMT) == S_IFLNK) {
261 (*env)->SetBooleanField(env, obj, fid, JNI_TRUE);
262
263 /* Find the target of the link */
264 rc = uafs_readlink(dirName, target, FILENAME_MAX);
265 if (rc < 0) {
266 fprintf(stderr, "File::setAttributes(): uafs_readlink failed\n");
267 setError(env, &obj, errno);
268 return JNI_FALSE;
269 } else {
270 target[rc] = 0; /* weird that we have to do this */
271 /*fprintf(stderr, "readlink %s succeeded, target=%s, rc=%d\n", dirName,
272 target, rc);*/
273 }
274
275 rc = setString(env, &obj, "target", target);
276 if (rc < 0) {
277 fprintf(stderr, "setString dirName=%s target=%s failed\n",
278 dirName, target);
279 }
280 } else {
281 (*env)->SetBooleanField(env, obj, fid, JNI_FALSE);
282 }
283 }
284
285 fid = (*env)->GetFieldID(env, thisClass, "isMountPoint", "Z");
286 if (fid == 0) {
287 fprintf(stderr,
288 "File::setAttributes(): GetFieldID (isMountPoint) failed\n");
289 setError(env, &obj, -1);
290 return JNI_FALSE;
291 }
292
293 if (mtpoint) {
294 (*env)->SetBooleanField(env, obj, fid, JNI_TRUE);
295 } else {
296 (*env)->SetBooleanField(env, obj, fid, JNI_FALSE);
297 }
298
299 fid = (*env)->GetFieldID(env, thisClass, "lastModified", "J");
300 if (fid == 0) {
301 fprintf(stderr,
302 "File::setAttributes(): GetFieldID (lastModified) failed\n");
303 setError(env, &obj, -1);
304 return JNI_FALSE;
305 }
306 (*env)->SetLongField(env, obj, fid, ((jlong) st.st_mtime)*1000);
307
308 fid = (*env)->GetFieldID(env, thisClass, "length", "J");
309 if (fid == 0) {
310 fprintf(stderr,
311 "File::setAttributes(): GetFieldID (length) failed\n");
312 setError(env, &obj, -1);
313 return JNI_FALSE;
314 }
315 (*env)->SetLongField(env, obj, fid, st.st_size);
316
317 setError(env, &obj, 0);
318
319 return JNI_TRUE;
320 }
321
322 /**
323 * Returns the permission/ACL mask for the represented directory
324 *
325 * env the Java environment
326 * obj the current Java object
327 *
328 * return permission/ACL mask
329 */
330 JNIEXPORT jint JNICALL Java_org_openafs_jafs_File_getRights
331 (JNIEnv *env, jobject obj)
332 {
333 char dirName[FILENAME_MAX];
334 jclass thisClass;
335 jfieldID fid;
336 int rc;
337 int afs_rights;
338 int rights;
339
340 *dirName = '\0';
341 getAbsolutePath(env, &obj, dirName);
342
343 if(*dirName == '\0') {
344 fprintf(stderr, "File::getRights(): failed to get dirName\n");
345 setError(env, &obj, -1);
346 return JNI_FALSE;
347 }
348
349 /*-Access Rights-
350 * UAFS_READ 1
351 * UAFS_WRITE 2
352 * UAFS_INSERT 4
353 * UAFS_LOOKUP 8
354 * UAFS_DELETE 16
355 * UAFS_LOCK 32
356 * UAFS_ADMIN 64
357 */
358
359 rights = 0;
360 afs_rights = uafs_getRights(dirName);
361 if (afs_rights < 0) {
362 setError(env, &obj, errno);
363 return -1;
364 }
365
366 if (afs_rights & PRSFS_READ)
367 rights |= UAFS_READ;
368 if (afs_rights & PRSFS_WRITE)
369 rights |= UAFS_WRITE;
370 if (afs_rights & PRSFS_INSERT)
371 rights |= UAFS_INSERT;
372 if (afs_rights & PRSFS_LOOKUP)
373 rights |= UAFS_LOOKUP;
374 if (afs_rights & PRSFS_DELETE)
375 rights |= UAFS_DELETE;
376 if (afs_rights & PRSFS_LOCK)
377 rights |= UAFS_LOCK;
378 if (afs_rights & PRSFS_ADMINISTER)
379 rights |= UAFS_ADMIN;
380
381 return rights;
382 }
383
384
385 /**
386 * List the contents of the represented directory.
387 *
388 * env the Java environment
389 * obj the current Java object
390 *
391 * return the directory handle
392 */
393 JNIEXPORT jlong JNICALL Java_org_openafs_jafs_File_listNative
394 (JNIEnv *env, jobject obj, jobject buffer)
395 {
396 return 0;
397 #if 0
398 char dirName[FILENAME_MAX];
399 jclass arrayListClass;
400 jmethodID addID;
401 jstring entryJString;
402 usr_DIR *dirp;
403 struct usr_dirent *enp;
404 int i, dirSize;
405
406 *dirName='\0';
407 getAbsolutePath(env, &obj, dirName);
408 if(*dirName == '\0') {
409 fprintf(stderr, "File::listNative(): failed to get dirName\n");
410 setError(env, &obj, -1);
411 return 0;
412 }
413 arrayListClass = (*env)->GetObjectClass(env, buffer);
414 if(arrayListClass == NULL) {
415 fprintf(stderr, "File::listNative(): GetObjectClass failed\n");
416 setError(env, &obj, -1);
417 return 0;
418 }
419 addID = (*env) -> GetMethodID(env, arrayListClass, "add",
420 "(Ljava/lang/Object;)Z");
421 if(addID == 0) {
422 fprintf(stderr,
423 "File::listNative(): failed to get addID\n");
424 setError(env, &obj, -1);
425 return 0;
426 }
427 dirp = uafs_opendir(dirName);
428 if(dirp == NULL) {
429 fprintf(stderr, "File::listNative(): uafs_opendir(%s) failed(%s)\n",
430 dirName, afs_error_message(errno));
431 setError(env, &obj, errno);
432 //throwAFSSecurityException( env, errno );
433 return 0;
434 }
435 while((enp = uafs_readdir(dirp)) != NULL) {
436 if(strcmp(enp->d_name, ".") == 0 || strcmp(enp->d_name, "..") == 0) {
437 continue;
438 }
439 entryJString = (*env) -> NewStringUTF(env, enp->d_name);
440 if(entryJString == NULL) {
441 fprintf(stderr, "File::listNative(): NewStringUTF failed\n");
442 setError(env, &obj, -1);
443 return 0;
444 }
445 (*env) -> CallBooleanMethod(env, buffer, addID, entryJString);
446 }
447 /*uafs_closedir(dirp);*/
448
449 setError(env, &obj, 0);
450
451 return (jlong) dirp;
452 #endif
453 }
454
455 /**
456 * Close the currently open directory using a provided directory handle.
457 *
458 * env the Java environment
459 * obj the current Java object
460 *
461 * return true if the directory closes without error
462 */
463 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_closeDir
464 (JNIEnv *env, jobject obj, jlong dp)
465 {
466
467 return JNI_TRUE;
468
469 #if 0
470 usr_DIR *dirp = (usr_DIR *) dp;
471 int rc;
472
473 rc = uafs_closedir(dirp);
474 if (rc < 0) {
475 setError(env, &obj, errno);
476 return JNI_FALSE;
477 }
478 else return JNI_TRUE;
479 #endif
480
481 }
482
483
484 /**
485 * Removes/deletes the represented file.
486 *
487 * env the Java environment
488 * obj the current Java object
489 *
490 * return true if the file is removed without error
491 */
492 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_rmfile
493 (JNIEnv *env, jobject obj)
494 {
495 char dirName[FILENAME_MAX];
496 int rc;
497
498 *dirName='\0';
499 getAbsolutePath(env, &obj, dirName);
500 if(*dirName == '\0') {
501 setError(env, &obj, EINVAL);
502 fprintf(stderr, "File::rmfile(): failed to get dirName\n");
503 return JNI_FALSE;
504 }
505 rc = uafs_unlink(dirName);
506 if(rc < 0) {
507 setError(env, &obj, errno);
508 fprintf(stderr, "File::rmfile(): uafs_unlink failed\n");
509 return JNI_FALSE;
510 }
511 setError(env, &obj, 0);
512 return JNI_TRUE;
513 }
514
515 /**
516 * Removes/deletes the represented directory.
517 *
518 * env the Java environment
519 * obj the current Java object
520 *
521 * return true if the directory is removed without error
522 */
523 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_rmdir
524 (JNIEnv *env, jobject obj)
525 {
526 char dirName[FILENAME_MAX];
527 int rc;
528
529 *dirName='\0';
530 getAbsolutePath(env, &obj, dirName);
531 if(*dirName == '\0') {
532 setError(env, &obj, -1);
533 fprintf(stderr, "File::rmdir(): failed to get dirName\n");
534 return JNI_FALSE;
535 }
536 rc = uafs_rmdir(dirName);
537 if(rc < 0) {
538 setError(env, &obj, errno);
539 fprintf(stderr, "File::rmdir(): uafs_unlink failed\n");
540 return JNI_FALSE;
541 }
542 setError(env, &obj, 0);
543 return JNI_TRUE;
544 }
545
546 /**
547 * Creates the directory named by this abstract pathname.
548 *
549 * env the Java environment
550 * obj the current Java object
551 *
552 * return true if and only if the directory was
553 * created; false otherwise
554 */
555 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_mkdir
556 (JNIEnv *env, jobject obj)
557 {
558 char dirName[FILENAME_MAX];
559 int rc;
560
561 *dirName='\0';
562 getAbsolutePath(env, &obj, dirName);
563 if(*dirName == '\0') {
564 setError(env, &obj, EINVAL);
565 fprintf(stderr, "File::mkdir(): failed to get dirName\n");
566 return JNI_FALSE;
567 }
568 rc = uafs_mkdir(dirName, 0755);
569 if(rc < 0) {
570 setError(env, &obj, errno);
571 fprintf(stderr, "File::mkdir(): uafs_mkdir failed\n");
572 return JNI_FALSE;
573 }
574 setError(env, &obj, 0);
575 return JNI_TRUE;
576 }
577
578 /**
579 * Renames the file denoted by this abstract pathname.
580 *
581 * env the Java environment
582 * obj the current Java object
583 * dest the new abstract pathname for the named file
584 *
585 * return true if and only if the renaming succeeded;
586 * false otherwise
587 *
588 * throws NullPointerException
589 * If parameter dest is null
590 */
591 JNIEXPORT jboolean JNICALL Java_org_openafs_jafs_File_renameTo
592 (JNIEnv *env, jobject obj, jobject newFile)
593 {
594 char thisDirName[FILENAME_MAX], newDirName[FILENAME_MAX];
595 int rc;
596
597 *thisDirName='\0';
598 getAbsolutePath(env, &obj, thisDirName);
599 if(*thisDirName == '\0') {
600 setError(env, &obj, -1);
601 fprintf(stderr, "File::renameTo(): failed to get dirName for this \n");
602 return JNI_FALSE;
603 }
604 *newDirName='\0';
605 getAbsolutePath(env, &newFile, newDirName);
606 if(*newDirName == '\0') {
607 setError(env, &obj, -1);
608 fprintf(stderr, "File::renameTo(): failed to get dirName for new \n");
609 return JNI_FALSE;
610 }
611 rc = uafs_rename(thisDirName, newDirName);
612 if(rc < 0) {
613 setError(env, &obj, errno);
614 fprintf(stderr, "File::renameTo(): uafs_rename failed\n");
615 return JNI_FALSE;
616 }
617 return JNI_TRUE;
618 }
619
620 /**
621 * Set all the necessary fields within the Java File class to indicate the
622 * does not exist.
623 *
624 * env the Java environment
625 * obj the current Java object
626 */
627 void setFileNotExistsAttributes
628 (JNIEnv *env, jobject *obj)
629 {
630 jclass thisClass;
631 jfieldID fid;
632
633 thisClass = (*env) -> GetObjectClass(env, *obj);
634 if(thisClass == NULL) {
635 fprintf(stderr,
636 "File::setFileNotExistsAttributes(): GetObjectClass failed\n");
637 return;
638 }
639
640 fid = (*env)->GetFieldID(env, thisClass, "exists", "Z");
641 if (fid == 0) {
642 fprintf(stderr,
643 "File::setFileNotExistsAttributes(): GetFieldID (exists) failed\n");
644 return;
645 }
646 (*env)->SetBooleanField(env, *obj, fid, JNI_FALSE);
647
648 fid = (*env)->GetFieldID(env, thisClass, "isDirectory", "Z");
649 if (fid == 0) {
650 fprintf(stderr,
651 "File::setFileNotExistsAttributes(): GetFieldID (isDirectory) failed\n");
652 return;
653 }
654 (*env)->SetBooleanField(env, *obj, fid, JNI_FALSE);
655
656 fid = (*env)->GetFieldID(env, thisClass, "isFile", "Z");
657 if (fid == 0) {
658 fprintf(stderr,
659 "File::setFileNotExistsAttributes(): GetFieldID (isDirectory) failed\n");
660 return;
661 }
662 (*env)->SetBooleanField(env, *obj, fid, JNI_FALSE);
663
664 fid = (*env)->GetFieldID(env, thisClass, "lastModified", "J");
665 if (fid == 0) {
666 fprintf(stderr,
667 "File::setFileNotExistsAttributes(): GetFieldID (lastModified) failed\n");
668 return;
669 }
670 (*env)->SetLongField(env, *obj, fid, 0);
671
672
673 fid = (*env)->GetFieldID(env, thisClass, "length", "J");
674 if (fid == 0) {
675 fprintf(stderr,
676 "File::setFileNotExistsAttributes(): GetFieldID (length) failed\n");
677 return;
678 }
679 (*env)->SetLongField(env, *obj, fid, 0);
680
681 return;
682 }
683
684