8229872: (fs) Increase buffer size used with getmntent
authorvkempik
Tue, 24 Sep 2019 14:54:57 +0300
changeset 58397 2d40e6a7ce8e
parent 58394 b1c3d24553e0
child 58398 ff559f979c4b
child 58403 9c198ad5da8e
8229872: (fs) Increase buffer size used with getmntent Summary: Dynamically allocate memory for getmntent Reviewed-by: alanb
src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java
src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java
src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c
src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java
src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java	Mon Sep 30 10:21:11 2019 +0200
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystem.java	Tue Sep 24 14:54:57 2019 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,10 +79,26 @@
         ArrayList<UnixMountEntry> entries = new ArrayList<>();
         try {
             long fp = setmntent(Util.toBytes(fstab), Util.toBytes("r"));
+            int maxLineSize = 1024;
+            try {
+                for (;;) {
+                    int lineSize = getlinelen(fp);
+                    if (lineSize == -1)
+                        break;
+                    if (lineSize > maxLineSize)
+                        maxLineSize = lineSize;
+                }
+            } catch (UnixException x) {
+                // nothing we need to do
+            } finally {
+                rewind(fp);
+            }
+
             try {
                 for (;;) {
                     UnixMountEntry entry = new UnixMountEntry();
-                    int res = getmntent(fp, entry);
+                    // count in NUL character at the end
+                    int res = getmntent(fp, entry, maxLineSize + 1);
                     if (res < 0)
                         break;
                     entries.add(entry);
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java	Mon Sep 30 10:21:11 2019 +0200
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxNativeDispatcher.java	Tue Sep 24 14:54:57 2019 +0300
@@ -51,7 +51,17 @@
     /**
      * int getmntent(FILE *fp, struct mnttab *mp, int len);
      */
-    static native int getmntent(long fp, UnixMountEntry entry)
+
+    static int getmntent(long fp, UnixMountEntry entry, int buflen) throws UnixException {
+        NativeBuffer buffer = NativeBuffers.getNativeBuffer(buflen);
+        try {
+            return getmntent0(fp, entry, buffer.address(), buflen);
+        } finally {
+            buffer.release();
+        }
+    }
+
+    static native int getmntent0(long fp, UnixMountEntry entry, long buffer, int bufLen)
         throws UnixException;
 
     /**
--- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c	Mon Sep 30 10:21:11 2019 +0200
+++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c	Tue Sep 24 14:54:57 2019 +0300
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -169,12 +169,11 @@
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this,
-    jlong value, jobject entry)
+Java_sun_nio_fs_LinuxNativeDispatcher_getmntent0(JNIEnv* env, jclass this,
+    jlong value, jobject entry, jlong buffer, jint bufLen)
 {
     struct mntent ent;
-    char buf[1024];
-    int buflen = sizeof(buf);
+    char * buf = (char*)jlong_to_ptr(buffer);
     struct mntent* m;
     FILE* fp = jlong_to_ptr(value);
     jsize len;
@@ -184,7 +183,7 @@
     char* fstype;
     char* options;
 
-    m = getmntent_r(fp, &ent, (char*)&buf, buflen);
+    m = getmntent_r(fp, &ent, buf, (int)bufLen);
     if (m == NULL)
         return -1;
     name = m->mnt_fsname;
--- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Mon Sep 30 10:21:11 2019 +0200
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Tue Sep 24 14:54:57 2019 +0300
@@ -119,6 +119,16 @@
     static native void fclose(long stream) throws UnixException;
 
     /**
+     * void rewind(FILE* stream);
+     */
+    static native void rewind(long stream) throws UnixException;
+
+    /**
+     * ssize_t getline(char **lineptr, size_t *n, FILE *stream);
+     */
+    static native int getlinelen(long stream) throws UnixException;
+
+    /**
      * link(const char* existing, const char* new)
      */
     static void link(UnixPath existing, UnixPath newfile) throws UnixException {
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Mon Sep 30 10:21:11 2019 +0200
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Tue Sep 24 14:54:57 2019 +0300
@@ -403,6 +403,51 @@
     }
 }
 
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_rewind(JNIEnv* env, jclass this, jlong stream)
+{
+    FILE* fp = jlong_to_ptr(stream);
+    int saved_errno;
+
+    errno = 0;
+    rewind(fp);
+    saved_errno = errno;
+    if (ferror(fp)) {
+        throwUnixException(env, saved_errno);
+    }
+}
+
+/**
+ * This function returns line length without NUL terminator or -1 on EOF.
+ */
+JNIEXPORT jint JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_getlinelen(JNIEnv* env, jclass this, jlong stream)
+{
+    FILE* fp = jlong_to_ptr(stream);
+    size_t lineSize = 0;
+    char * lineBuffer = NULL;
+    int saved_errno;
+
+    ssize_t res = getline(&lineBuffer, &lineSize, fp);
+    saved_errno = errno;
+
+    /* Should free lineBuffer no matter result, according to man page */
+    if (lineBuffer != NULL)
+        free(lineBuffer);
+
+    if (feof(fp))
+        return -1;
+
+    /* On successfull return res >= 0, otherwise res is -1 */
+    if (res == -1)
+        throwUnixException(env, saved_errno);
+
+    if (res > INT_MAX)
+        throwUnixException(env, EOVERFLOW);
+
+    return (jint)res;
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_fs_UnixNativeDispatcher_open0(JNIEnv* env, jclass this,
     jlong pathAddress, jint oflags, jint mode)