Path: blob/master/src/java.base/unix/native/libjava/UnixFileSystem_md.c
41119 views
/*1* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <unistd.h>26#include <assert.h>27#include <sys/types.h>28#include <sys/time.h>29#include <sys/stat.h>30#ifdef MACOSX31#include <sys/param.h>32#include <sys/mount.h>33#else34#include <sys/statvfs.h>35#endif36#include <string.h>37#include <stdlib.h>38#include <dlfcn.h>39#include <limits.h>40#include <errno.h>41#include <fcntl.h>42#include <dirent.h>4344#include "jni.h"45#include "jni_util.h"46#include "jlong.h"47#include "jdk_util.h"48#include "io_util.h"49#include "io_util_md.h"50#include "java_io_FileSystem.h"51#include "java_io_UnixFileSystem.h"5253#if defined(_AIX)54#if !defined(NAME_MAX)55#define NAME_MAX MAXNAMLEN56#endif57#define DIR DIR6458#define dirent dirent6459#define opendir opendir6460#define readdir readdir6461#define closedir closedir6462#define stat stat6463#endif6465#if defined(_ALLBSD_SOURCE)66#ifndef MACOSX67#define statvfs64 statvfs68#define stat64 stat69#endif70#endif7172/* -- Field IDs -- */7374static struct {75jfieldID path;76} ids;777879JNIEXPORT void JNICALL80Java_java_io_UnixFileSystem_initIDs(JNIEnv *env, jclass cls)81{82jclass fileClass = (*env)->FindClass(env, "java/io/File");83if (!fileClass) return;84ids.path = (*env)->GetFieldID(env, fileClass,85"path", "Ljava/lang/String;");86}8788/* -- Path operations -- */8990JNIEXPORT jstring JNICALL91Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,92jstring pathname)93{94jstring rv = NULL;9596WITH_PLATFORM_STRING(env, pathname, path) {97char canonicalPath[PATH_MAX];98if (JDK_Canonicalize((char *)path,99canonicalPath, PATH_MAX) < 0) {100JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");101} else {102#ifdef MACOSX103rv = newStringPlatform(env, canonicalPath);104#else105rv = JNU_NewStringPlatform(env, canonicalPath);106#endif107}108} END_PLATFORM_STRING(env, path);109return rv;110}111112113/* -- Attribute accessors -- */114115116static jboolean117statMode(const char *path, int *mode)118{119struct stat64 sb;120if (stat64(path, &sb) == 0) {121*mode = sb.st_mode;122return JNI_TRUE;123}124return JNI_FALSE;125}126127128JNIEXPORT jint JNICALL129Java_java_io_UnixFileSystem_getBooleanAttributes0(JNIEnv *env, jobject this,130jobject file)131{132jint rv = 0;133134WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {135int mode;136if (statMode(path, &mode)) {137int fmt = mode & S_IFMT;138rv = (jint) (java_io_FileSystem_BA_EXISTS139| ((fmt == S_IFREG) ? java_io_FileSystem_BA_REGULAR : 0)140| ((fmt == S_IFDIR) ? java_io_FileSystem_BA_DIRECTORY : 0));141}142} END_PLATFORM_STRING(env, path);143return rv;144}145146JNIEXPORT jboolean JNICALL147Java_java_io_UnixFileSystem_checkAccess(JNIEnv *env, jobject this,148jobject file, jint a)149{150jboolean rv = JNI_FALSE;151int mode = 0;152switch (a) {153case java_io_FileSystem_ACCESS_READ:154mode = R_OK;155break;156case java_io_FileSystem_ACCESS_WRITE:157mode = W_OK;158break;159case java_io_FileSystem_ACCESS_EXECUTE:160mode = X_OK;161break;162default: assert(0);163}164WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {165int res;166RESTARTABLE(access(path, mode), res);167if (res == 0) {168rv = JNI_TRUE;169}170} END_PLATFORM_STRING(env, path);171return rv;172}173174175JNIEXPORT jboolean JNICALL176Java_java_io_UnixFileSystem_setPermission(JNIEnv *env, jobject this,177jobject file,178jint access,179jboolean enable,180jboolean owneronly)181{182jboolean rv = JNI_FALSE;183184WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {185int amode = 0;186int mode;187int res;188switch (access) {189case java_io_FileSystem_ACCESS_READ:190if (owneronly)191amode = S_IRUSR;192else193amode = S_IRUSR | S_IRGRP | S_IROTH;194break;195case java_io_FileSystem_ACCESS_WRITE:196if (owneronly)197amode = S_IWUSR;198else199amode = S_IWUSR | S_IWGRP | S_IWOTH;200break;201case java_io_FileSystem_ACCESS_EXECUTE:202if (owneronly)203amode = S_IXUSR;204else205amode = S_IXUSR | S_IXGRP | S_IXOTH;206break;207default:208assert(0);209}210if (statMode(path, &mode)) {211if (enable)212mode |= amode;213else214mode &= ~amode;215RESTARTABLE(chmod(path, mode), res);216if (res == 0) {217rv = JNI_TRUE;218}219}220} END_PLATFORM_STRING(env, path);221return rv;222}223224JNIEXPORT jlong JNICALL225Java_java_io_UnixFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,226jobject file)227{228jlong rv = 0;229230WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {231struct stat64 sb;232if (stat64(path, &sb) == 0) {233#if defined(_AIX)234rv = (jlong)sb.st_mtime * 1000;235rv += (jlong)sb.st_mtime_n / 1000000;236#elif defined(MACOSX)237rv = (jlong)sb.st_mtimespec.tv_sec * 1000;238rv += (jlong)sb.st_mtimespec.tv_nsec / 1000000;239#else240rv = (jlong)sb.st_mtim.tv_sec * 1000;241rv += (jlong)sb.st_mtim.tv_nsec / 1000000;242#endif243}244} END_PLATFORM_STRING(env, path);245return rv;246}247248249JNIEXPORT jlong JNICALL250Java_java_io_UnixFileSystem_getLength(JNIEnv *env, jobject this,251jobject file)252{253jlong rv = 0;254255WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {256struct stat64 sb;257if (stat64(path, &sb) == 0) {258rv = sb.st_size;259}260} END_PLATFORM_STRING(env, path);261return rv;262}263264265/* -- File operations -- */266267268JNIEXPORT jboolean JNICALL269Java_java_io_UnixFileSystem_createFileExclusively(JNIEnv *env, jclass cls,270jstring pathname)271{272jboolean rv = JNI_FALSE;273274WITH_PLATFORM_STRING(env, pathname, path) {275FD fd;276/* The root directory always exists */277if (strcmp (path, "/")) {278fd = handleOpen(path, O_RDWR | O_CREAT | O_EXCL, 0666);279if (fd < 0) {280if (errno != EEXIST)281JNU_ThrowIOExceptionWithLastError(env, "Could not open file");282} else {283if (close(fd) == -1)284JNU_ThrowIOExceptionWithLastError(env, "Could not close file");285rv = JNI_TRUE;286}287}288} END_PLATFORM_STRING(env, path);289return rv;290}291292293JNIEXPORT jboolean JNICALL294Java_java_io_UnixFileSystem_delete0(JNIEnv *env, jobject this,295jobject file)296{297jboolean rv = JNI_FALSE;298299WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {300if (remove(path) == 0) {301rv = JNI_TRUE;302}303} END_PLATFORM_STRING(env, path);304return rv;305}306307308JNIEXPORT jobjectArray JNICALL309Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,310jobject file)311{312DIR *dir = NULL;313struct dirent *ptr;314int len, maxlen;315jobjectArray rv, old;316jclass str_class;317318str_class = JNU_ClassString(env);319CHECK_NULL_RETURN(str_class, NULL);320321WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {322dir = opendir(path);323} END_PLATFORM_STRING(env, path);324if (dir == NULL) return NULL;325326/* Allocate an initial String array */327len = 0;328maxlen = 16;329rv = (*env)->NewObjectArray(env, maxlen, str_class, NULL);330if (rv == NULL) goto error;331332/* Scan the directory */333while ((ptr = readdir(dir)) != NULL) {334jstring name;335if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))336continue;337if (len == maxlen) {338old = rv;339rv = (*env)->NewObjectArray(env, maxlen <<= 1, str_class, NULL);340if (rv == NULL) goto error;341if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;342(*env)->DeleteLocalRef(env, old);343}344#ifdef MACOSX345name = newStringPlatform(env, ptr->d_name);346#else347name = JNU_NewStringPlatform(env, ptr->d_name);348#endif349if (name == NULL) goto error;350(*env)->SetObjectArrayElement(env, rv, len++, name);351(*env)->DeleteLocalRef(env, name);352}353closedir(dir);354355/* Copy the final results into an appropriately-sized array */356if (len < maxlen) {357old = rv;358rv = (*env)->NewObjectArray(env, len, str_class, NULL);359if (rv == NULL) {360return NULL;361}362if (JNU_CopyObjectArray(env, rv, old, len) < 0) {363return NULL;364}365}366return rv;367368error:369closedir(dir);370return NULL;371}372373374JNIEXPORT jboolean JNICALL375Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,376jobject file)377{378jboolean rv = JNI_FALSE;379380WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {381if (mkdir(path, 0777) == 0) {382rv = JNI_TRUE;383}384} END_PLATFORM_STRING(env, path);385return rv;386}387388389JNIEXPORT jboolean JNICALL390Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,391jobject from, jobject to)392{393jboolean rv = JNI_FALSE;394395WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {396WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {397if (rename(fromPath, toPath) == 0) {398rv = JNI_TRUE;399}400} END_PLATFORM_STRING(env, toPath);401} END_PLATFORM_STRING(env, fromPath);402return rv;403}404405JNIEXPORT jboolean JNICALL406Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,407jobject file, jlong time)408{409jboolean rv = JNI_FALSE;410411WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {412struct stat64 sb;413414if (stat64(path, &sb) == 0) {415struct timeval tv[2];416417/* Preserve access time */418#if defined(_AIX)419tv[0].tv_sec = sb.st_atime;420tv[0].tv_usec = sb.st_atime_n / 1000;421#elif defined(MACOSX)422tv[0].tv_sec = sb.st_atimespec.tv_sec;423tv[0].tv_usec = sb.st_atimespec.tv_nsec / 1000;424#else425tv[0].tv_sec = sb.st_atim.tv_sec;426tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;427#endif428/* Change last-modified time */429tv[1].tv_sec = time / 1000;430tv[1].tv_usec = (time % 1000) * 1000;431432if (utimes(path, tv) == 0)433rv = JNI_TRUE;434}435} END_PLATFORM_STRING(env, path);436437return rv;438}439440441JNIEXPORT jboolean JNICALL442Java_java_io_UnixFileSystem_setReadOnly(JNIEnv *env, jobject this,443jobject file)444{445jboolean rv = JNI_FALSE;446447WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {448int mode;449int res;450if (statMode(path, &mode)) {451RESTARTABLE(chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)), res);452if (res == 0) {453rv = JNI_TRUE;454}455}456} END_PLATFORM_STRING(env, path);457return rv;458}459460JNIEXPORT jlong JNICALL461Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,462jobject file, jint t)463{464jlong rv = 0L;465466WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {467#ifdef MACOSX468struct statfs fsstat;469#else470struct statvfs64 fsstat;471int res;472#endif473memset(&fsstat, 0, sizeof(fsstat));474#ifdef MACOSX475if (statfs(path, &fsstat) == 0) {476switch(t) {477case java_io_FileSystem_SPACE_TOTAL:478rv = jlong_mul(long_to_jlong(fsstat.f_bsize),479long_to_jlong(fsstat.f_blocks));480break;481case java_io_FileSystem_SPACE_FREE:482rv = jlong_mul(long_to_jlong(fsstat.f_bsize),483long_to_jlong(fsstat.f_bfree));484break;485case java_io_FileSystem_SPACE_USABLE:486rv = jlong_mul(long_to_jlong(fsstat.f_bsize),487long_to_jlong(fsstat.f_bavail));488break;489default:490assert(0);491}492}493#else494RESTARTABLE(statvfs64(path, &fsstat), res);495if (res == 0) {496switch(t) {497case java_io_FileSystem_SPACE_TOTAL:498rv = jlong_mul(long_to_jlong(fsstat.f_frsize),499long_to_jlong(fsstat.f_blocks));500break;501case java_io_FileSystem_SPACE_FREE:502rv = jlong_mul(long_to_jlong(fsstat.f_frsize),503long_to_jlong(fsstat.f_bfree));504break;505case java_io_FileSystem_SPACE_USABLE:506rv = jlong_mul(long_to_jlong(fsstat.f_frsize),507long_to_jlong(fsstat.f_bavail));508break;509default:510assert(0);511}512}513#endif514} END_PLATFORM_STRING(env, path);515return rv;516}517518JNIEXPORT jlong JNICALL519Java_java_io_UnixFileSystem_getNameMax0(JNIEnv *env, jobject this,520jstring pathname)521{522jlong length = -1;523WITH_PLATFORM_STRING(env, pathname, path) {524length = (jlong)pathconf(path, _PC_NAME_MAX);525} END_PLATFORM_STRING(env, path);526return length != -1 ? length : (jlong)NAME_MAX;527}528529530