Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
73d65ed1
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
73d65ed1
编写于
3月 10, 2008
作者:
L
lmalvent
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
62acf0ec
240ad09d
变更
23
展开全部
隐藏空白更改
内联
并排
Showing
23 changed file
with
1884 addition
and
622 deletion
+1884
-622
make/java/java/mapfile-vers
make/java/java/mapfile-vers
+0
-1
src/share/classes/java/io/FileInputStream.java
src/share/classes/java/io/FileInputStream.java
+6
-6
src/share/classes/java/io/FileOutputStream.java
src/share/classes/java/io/FileOutputStream.java
+17
-30
src/share/classes/java/lang/Process.java
src/share/classes/java/lang/Process.java
+50
-21
src/share/classes/java/lang/ProcessBuilder.java
src/share/classes/java/lang/ProcessBuilder.java
+635
-91
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
+4
-0
src/share/classes/sun/nio/ch/FileChannelImpl.java
src/share/classes/sun/nio/ch/FileChannelImpl.java
+14
-35
src/share/native/java/io/io_util.c
src/share/native/java/io/io_util.c
+6
-6
src/solaris/classes/java/io/FileDescriptor.java
src/solaris/classes/java/io/FileDescriptor.java
+9
-1
src/solaris/classes/java/lang/ProcessImpl.java
src/solaris/classes/java/lang/ProcessImpl.java
+58
-1
src/solaris/classes/java/lang/UNIXProcess.java.linux
src/solaris/classes/java/lang/UNIXProcess.java.linux
+105
-79
src/solaris/classes/java/lang/UNIXProcess.java.solaris
src/solaris/classes/java/lang/UNIXProcess.java.solaris
+209
-183
src/solaris/native/java/io/FileOutputStream_md.c
src/solaris/native/java/io/FileOutputStream_md.c
+4
-7
src/solaris/native/java/lang/UNIXProcess_md.c
src/solaris/native/java/lang/UNIXProcess_md.c
+68
-22
src/windows/classes/java/io/FileDescriptor.java
src/windows/classes/java/io/FileDescriptor.java
+19
-14
src/windows/classes/java/lang/ProcessImpl.java
src/windows/classes/java/lang/ProcessImpl.java
+121
-29
src/windows/native/java/io/FileOutputStream_md.c
src/windows/native/java/io/FileOutputStream_md.c
+4
-32
src/windows/native/java/io/io_util_md.c
src/windows/native/java/io/io_util_md.c
+10
-21
src/windows/native/java/io/io_util_md.h
src/windows/native/java/io/io_util_md.h
+0
-1
src/windows/native/java/lang/ProcessImpl_md.c
src/windows/native/java/lang/ProcessImpl_md.c
+70
-34
src/windows/native/java/lang/java_props_md.c
src/windows/native/java/lang/java_props_md.c
+18
-5
test/java/io/FileOutputStream/AtomicAppend.java
test/java/io/FileOutputStream/AtomicAppend.java
+81
-0
test/java/lang/ProcessBuilder/Basic.java
test/java/lang/ProcessBuilder/Basic.java
+376
-3
未找到文件。
make/java/java/mapfile-vers
浏览文件 @
73d65ed1
...
...
@@ -85,7 +85,6 @@ SUNWprivate_1.1 {
Java_java_io_FileOutputStream_close0;
Java_java_io_FileOutputStream_initIDs;
Java_java_io_FileOutputStream_open;
Java_java_io_FileOutputStream_openAppend;
Java_java_io_FileOutputStream_write;
Java_java_io_FileOutputStream_writeBytes;
Java_java_io_FileSystem_getFileSystem;
...
...
src/share/classes/java/io/FileInputStream.java
浏览文件 @
73d65ed1
...
...
@@ -48,15 +48,15 @@ public
class
FileInputStream
extends
InputStream
{
/* File Descriptor - handle to the open file */
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
private
FileChannel
channel
=
null
;
private
Object
closeLock
=
new
Object
();
private
final
Object
closeLock
=
new
Object
();
private
volatile
boolean
closed
=
false
;
private
static
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
private
static
final
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
private
static
boolean
isRunningFinalize
()
{
Boolean
val
;
...
...
@@ -151,7 +151,7 @@ class FileInputStream extends InputStream
* is thrown.
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
* is {link java.io.FileDescriptor#valid() invalid}.
* is {
@
link java.io.FileDescriptor#valid() invalid}.
* However, if the methods are invoked on the resulting stream to attempt
* I/O on the stream, an <code>IOException</code> is thrown.
*
...
...
@@ -389,7 +389,7 @@ class FileInputStream extends InputStream
* @see java.io.FileInputStream#close()
*/
protected
void
finalize
()
throws
IOException
{
if
((
fd
!=
null
)
&&
(
fd
!=
fd
.
in
))
{
if
((
fd
!=
null
)
&&
(
fd
!=
FileDescriptor
.
in
))
{
/*
* Finalizer should not release the FileDescriptor if another
...
...
src/share/classes/java/io/FileOutputStream.java
浏览文件 @
73d65ed1
...
...
@@ -52,20 +52,16 @@ public
class
FileOutputStream
extends
OutputStream
{
/**
* The system dependent file descriptor. The value is
* 1 more than actual file descriptor. This means that
* the default value 0 indicates that the file is not open.
* The system dependent file descriptor.
*/
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
private
FileChannel
channel
=
null
;
private
boolean
append
=
false
;
private
Object
closeLock
=
new
Object
();
private
final
Object
closeLock
=
new
Object
();
private
volatile
boolean
closed
=
false
;
private
static
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
private
static
final
ThreadLocal
<
Boolean
>
runningFinalize
=
new
ThreadLocal
<
Boolean
>();
private
static
boolean
isRunningFinalize
()
{
Boolean
val
;
...
...
@@ -75,7 +71,7 @@ class FileOutputStream extends OutputStream
}
/**
* Creates a
n output file
stream to write to the file with the
* Creates a
file output
stream to write to the file with the
* specified name. A new <code>FileDescriptor</code> object is
* created to represent this file connection.
* <p>
...
...
@@ -100,8 +96,8 @@ class FileOutputStream extends OutputStream
}
/**
* Creates a
n output file
stream to write to the file with the specified
*
<code>name</code>
. If the second argument is <code>true</code>, then
* Creates a
file output
stream to write to the file with the specified
*
name
. If the second argument is <code>true</code>, then
* bytes will be written to the end of the file rather than the beginning.
* A new <code>FileDescriptor</code> object is created to represent this
* file connection.
...
...
@@ -202,16 +198,11 @@ class FileOutputStream extends OutputStream
}
fd
=
new
FileDescriptor
();
fd
.
incrementAndGetUseCount
();
this
.
append
=
append
;
if
(
append
)
{
openAppend
(
name
);
}
else
{
open
(
name
);
}
open
(
name
,
append
);
}
/**
* Creates a
n output file
stream to write to the specified file
* Creates a
file output
stream to write to the specified file
* descriptor, which represents an existing connection to an actual
* file in the file system.
* <p>
...
...
@@ -223,7 +214,7 @@ class FileOutputStream extends OutputStream
* is thrown.
* <p>
* This constructor does not throw an exception if <code>fdObj</code>
* is {link java.io.FileDescriptor#valid() invalid}.
* is {
@
link java.io.FileDescriptor#valid() invalid}.
* However, if the methods are invoked on the resulting stream to attempt
* I/O on the stream, an <code>IOException</code> is thrown.
*
...
...
@@ -252,16 +243,12 @@ class FileOutputStream extends OutputStream
}
/**
* Opens a file, with the specified name, for writing.
* @param name name of file to be opened
*/
private
native
void
open
(
String
name
)
throws
FileNotFoundException
;
/**
* Opens a file, with the specified name, for appending.
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
private
native
void
openAppend
(
String
name
)
throws
FileNotFoundException
;
private
native
void
open
(
String
name
,
boolean
append
)
throws
FileNotFoundException
;
/**
* Writes the specified byte to this file output stream. Implements
...
...
@@ -385,7 +372,7 @@ class FileOutputStream extends OutputStream
public
FileChannel
getChannel
()
{
synchronized
(
this
)
{
if
(
channel
==
null
)
{
channel
=
FileChannelImpl
.
open
(
fd
,
false
,
true
,
this
,
append
);
channel
=
FileChannelImpl
.
open
(
fd
,
false
,
true
,
this
);
/*
* Increment fd's use count. Invoking the channel's close()
...
...
@@ -408,7 +395,7 @@ class FileOutputStream extends OutputStream
*/
protected
void
finalize
()
throws
IOException
{
if
(
fd
!=
null
)
{
if
(
fd
==
fd
.
out
||
fd
==
fd
.
err
)
{
if
(
fd
==
FileDescriptor
.
out
||
fd
==
FileDescriptor
.
err
)
{
flush
();
}
else
{
...
...
src/share/classes/java/lang/Process.java
浏览文件 @
73d65ed1
...
...
@@ -41,18 +41,24 @@ import java.io.*;
* <p>The methods that create processes may not work well for special
* processes on certain native platforms, such as native windowing
* processes, daemon processes, Win16/DOS processes on Microsoft
* Windows, or shell scripts. The created subprocess does not have
* its own terminal or console. All its standard I/O (i.e. stdin,
* stdout, stderr) operations will be redirected to the parent process
* through three streams
* ({@link #getOutputStream()},
* {@link #getInputStream()},
* {@link #getErrorStream()}).
* Windows, or shell scripts.
*
* <p>By default, the created subprocess does not have its own terminal
* or console. All its standard I/O (i.e. stdin, stdout, stderr)
* operations will be redirected to the parent process, where they can
* be accessed via the streams obtained using the methods
* {@link #getOutputStream()},
* {@link #getInputStream()}, and
* {@link #getErrorStream()}.
* The parent process uses these streams to feed input to and get output
* from the subprocess. Because some native platforms only provide
* limited buffer size for standard input and output streams, failure
* to promptly write the input stream or read the output stream of
* the subprocess may cause the subprocess to block, and even deadlock.
* the subprocess may cause the subprocess to block, or even deadlock.
*
* <p>Where desired, <a href="ProcessBuilder.html#redirect-input">
* subprocess I/O can also be redirected</a>
* using methods of the {@link ProcessBuilder} class.
*
* <p>The subprocess is not killed when there are no more references to
* the {@code Process} object, but rather the subprocess
...
...
@@ -62,16 +68,22 @@ import java.io.*;
* Process} object execute asynchronously or concurrently with respect
* to the Java process that owns the {@code Process} object.
*
* @author unascribed
* @see ProcessBuilder
* <p>As of 1.5, {@link ProcessBuilder#start()} is the preferred way
* to create a {@code Process}.
*
* @since JDK1.0
*/
public
abstract
class
Process
{
/**
* Returns the output stream connected to the normal input of the
* subprocess. Output to the stream is piped into the standard
* input stream of the process represented by this {@code Process}
* object.
* input of the process represented by this {@code Process} object.
*
* <p>If the standard input of the subprocess has been redirected using
* {@link ProcessBuilder#redirectInput(Redirect)
* ProcessBuilder.redirectInput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-input">null output stream</a>.
*
* <p>Implementation note: It is a good idea for the returned
* output stream to be buffered.
...
...
@@ -84,30 +96,47 @@ public abstract class Process {
/**
* Returns the input stream connected to the normal output of the
* subprocess. The stream obtains data piped from the standard
* output stream of the process represented by this {@code
* Process} object.
* output of the process represented by this {@code Process} object.
*
* <p>If the standard output of the subprocess has been redirected using
* {@link ProcessBuilder#redirectOutput(Redirect)
* ProcessBuilder.redirectOutput}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Otherwise, if the standard error of the subprocess has been
* redirected using
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then the input stream returned by this method will receive the
* merged standard output and the standard error of the subprocess.
*
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
*
* @return the input stream connected to the normal output of the
* subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
abstract
public
InputStream
getInputStream
();
/**
* Returns the input stream connected to the error output stream of
* the subprocess. The stream obtains data piped from the error
* output stream of the process represented by this {@code Process}
* object.
* Returns the input stream connected to the error output of the
* subprocess. The stream obtains data piped from the error output
* of the process represented by this {@code Process} object.
*
* <p>If the standard error of the subprocess has been redirected using
* {@link ProcessBuilder#redirectError(Redirect)
* ProcessBuilder.redirectError} or
* {@link ProcessBuilder#redirectErrorStream(boolean)
* ProcessBuilder.redirectErrorStream}
* then this method will return a
* <a href="ProcessBuilder.html#redirect-output">null input stream</a>.
*
* <p>Implementation note: It is a good idea for the returned
* input stream to be buffered.
*
* @return the input stream connected to the error output
stream
of
* @return the input stream connected to the error output of
* the subprocess
* @see ProcessBuilder#redirectErrorStream()
*/
abstract
public
InputStream
getErrorStream
();
...
...
src/share/classes/java/lang/ProcessBuilder.java
浏览文件 @
73d65ed1
此差异已折叠。
点击以展开。
src/share/classes/sun/misc/JavaIOFileDescriptorAccess.java
浏览文件 @
73d65ed1
...
...
@@ -33,4 +33,8 @@ import java.io.FileDescriptor;
public
interface
JavaIOFileDescriptorAccess
{
public
void
set
(
FileDescriptor
obj
,
int
fd
);
public
int
get
(
FileDescriptor
fd
);
// Only valid on Windows
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
);
public
long
getHandle
(
FileDescriptor
obj
);
}
src/share/classes/sun/nio/ch/FileChannelImpl.java
浏览文件 @
73d65ed1
...
...
@@ -52,39 +52,37 @@ public class FileChannelImpl
{
// Used to make native read and write calls
private
static
NativeDispatcher
nd
;
private
static
final
NativeDispatcher
nd
;
// Memory allocation size for mapping buffers
private
static
long
allocationGranularity
;
private
static
final
long
allocationGranularity
;
// Cached field for MappedByteBuffer.isAMappedBuffer
private
static
Field
isAMappedBufferField
;
private
static
final
Field
isAMappedBufferField
;
// File descriptor
private
FileDescriptor
fd
;
private
final
FileDescriptor
fd
;
// File access mode (immutable)
private
boolean
writable
;
private
boolean
readable
;
private
boolean
appending
;
private
final
boolean
writable
;
private
final
boolean
readable
;
// Required to prevent finalization of creating stream (immutable)
private
Object
parent
;
private
final
Object
parent
;
// Thread-safe set of IDs of native threads, for signalling
private
NativeThreadSet
threads
=
new
NativeThreadSet
(
2
);
private
final
NativeThreadSet
threads
=
new
NativeThreadSet
(
2
);
// Lock for operations involving position and size
private
Object
positionLock
=
new
Object
();
private
final
Object
positionLock
=
new
Object
();
private
FileChannelImpl
(
FileDescriptor
fd
,
boolean
readable
,
boolean
writable
,
Object
parent
,
boolean
append
)
boolean
writable
,
Object
parent
)
{
this
.
fd
=
fd
;
this
.
readable
=
readable
;
this
.
writable
=
writable
;
this
.
parent
=
parent
;
this
.
appending
=
append
;
}
// Invoked by getChannel() methods
...
...
@@ -94,14 +92,7 @@ public class FileChannelImpl
boolean
readable
,
boolean
writable
,
Object
parent
)
{
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
,
false
);
}
public
static
FileChannel
open
(
FileDescriptor
fd
,
boolean
readable
,
boolean
writable
,
Object
parent
,
boolean
append
)
{
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
,
append
);
return
new
FileChannelImpl
(
fd
,
readable
,
writable
,
parent
);
}
private
void
ensureOpen
()
throws
IOException
{
...
...
@@ -134,15 +125,7 @@ public class FileChannelImpl
// superclass AbstractInterruptibleChannel, but the isOpen logic in
// that method will prevent this method from being reinvoked.
//
if
(
parent
instanceof
FileInputStream
)
((
FileInputStream
)
parent
).
close
();
else
if
(
parent
instanceof
FileOutputStream
)
((
FileOutputStream
)
parent
).
close
();
else
if
(
parent
instanceof
RandomAccessFile
)
((
RandomAccessFile
)
parent
).
close
();
else
assert
false
;
((
java
.
io
.
Closeable
)
parent
).
close
();
}
else
{
nd
.
close
(
fd
);
}
...
...
@@ -218,8 +201,6 @@ public class FileChannelImpl
if
(!
isOpen
())
return
0
;
ti
=
threads
.
add
();
if
(
appending
)
position
(
size
());
do
{
n
=
IOUtil
.
write
(
fd
,
src
,
-
1
,
nd
,
positionLock
);
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
...
...
@@ -244,8 +225,6 @@ public class FileChannelImpl
if
(!
isOpen
())
return
0
;
ti
=
threads
.
add
();
if
(
appending
)
position
(
size
());
do
{
n
=
IOUtil
.
write
(
fd
,
srcs
,
nd
);
}
while
((
n
==
IOStatus
.
INTERRUPTED
)
&&
isOpen
());
...
...
@@ -1051,7 +1030,7 @@ public class FileChannelImpl
private
FileKey
fileKey
;
FileLockReference
(
FileLock
referent
,
ReferenceQueue
queue
,
ReferenceQueue
<
FileLock
>
queue
,
FileKey
key
)
{
super
(
referent
,
queue
);
this
.
fileKey
=
key
;
...
...
@@ -1073,7 +1052,7 @@ public class FileChannelImpl
new
ConcurrentHashMap
<
FileKey
,
ArrayList
<
FileLockReference
>>();
// reference queue for cleared refs
private
static
ReferenceQueue
queue
=
new
ReferenceQueue
();
private
static
ReferenceQueue
<
FileLock
>
queue
=
new
ReferenceQueue
<
FileLock
>
();
// the enclosing file channel
private
FileChannelImpl
fci
;
...
...
src/share/native/java/io/io_util.c
浏览文件 @
73d65ed1
...
...
@@ -40,7 +40,7 @@ readSingle(JNIEnv *env, jobject this, jfieldID fid) {
char
ret
;
FD
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
-
1
;
}
nread
=
IO_Read
(
fd
,
&
ret
,
1
);
...
...
@@ -94,8 +94,8 @@ readBytes(JNIEnv *env, jobject this, jbyteArray bytes,
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
-
1
;
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
-
1
;
}
nread
=
IO_Read
(
fd
,
buf
,
len
);
...
...
@@ -121,7 +121,7 @@ writeSingle(JNIEnv *env, jobject this, jint byte, jfieldID fid) {
int
n
;
FD
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
}
n
=
IO_Write
(
fd
,
&
c
,
1
);
...
...
@@ -172,8 +172,8 @@ writeBytes(JNIEnv *env, jobject this, jbyteArray bytes,
while
(
len
>
0
)
{
fd
=
GET_FD
(
this
,
fid
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
break
;
}
n
=
IO_Write
(
fd
,
buf
+
off
,
len
);
if
(
n
==
JVM_IO_ERR
)
{
...
...
src/solaris/classes/java/io/FileDescriptor.java
浏览文件 @
73d65ed1
...
...
@@ -152,11 +152,19 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
throw
new
UnsupportedOperationException
();
}
public
long
getHandle
(
FileDescriptor
obj
)
{
throw
new
UnsupportedOperationException
();
}
}
);
}
// pac
akge private methods used by FIS,
FOS and RAF
// pac
kage private methods used by FIS,
FOS and RAF
int
incrementAndGetUseCount
()
{
return
useCount
.
incrementAndGet
();
...
...
src/solaris/classes/java/lang/ProcessImpl.java
浏览文件 @
73d65ed1
...
...
@@ -26,7 +26,10 @@
package
java.lang
;
import
java.io.IOException
;
import
java.lang.Process
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
import
java.lang.ProcessBuilder.Redirect
;
/**
* This class is for the exclusive use of ProcessBuilder.start() to
...
...
@@ -36,6 +39,9 @@ import java.lang.Process;
* @since 1.5
*/
final
class
ProcessImpl
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
private
ProcessImpl
()
{}
// Not instantiable
private
static
byte
[]
toCString
(
String
s
)
{
...
...
@@ -54,6 +60,7 @@ final class ProcessImpl {
static
Process
start
(
String
[]
cmdarray
,
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
throws
IOException
{
...
...
@@ -78,11 +85,61 @@ final class ProcessImpl {
int
[]
envc
=
new
int
[
1
];
byte
[]
envBlock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
,
envc
);
int
[]
std_fds
;
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
if
(
redirects
==
null
)
{
std_fds
=
new
int
[]
{
-
1
,
-
1
,
-
1
};
}
else
{
std_fds
=
new
int
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
std_fds
[
0
]
=
-
1
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
std_fds
[
0
]
=
0
;
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
std_fds
[
0
]
=
fdAccess
.
get
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
std_fds
[
1
]
=
-
1
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
std_fds
[
1
]
=
1
;
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
std_fds
[
1
]
=
fdAccess
.
get
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
std_fds
[
2
]
=
-
1
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
std_fds
[
2
]
=
2
;
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
std_fds
[
2
]
=
fdAccess
.
get
(
f2
.
getFD
());
}
}
return
new
UNIXProcess
(
toCString
(
cmdarray
[
0
]),
argBlock
,
args
.
length
,
envBlock
,
envc
[
0
],
toCString
(
dir
),
std_fds
,
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
}
src/solaris/classes/java/lang/UNIXProcess.java.linux
浏览文件 @
73d65ed1
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
/*
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
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
...
...
@@ -34,9 +34,9 @@ import java.io.*;
*/
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
FileDescriptor
stdout_fd
;
private
FileDescriptor
stderr_fd
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
int
pid
;
private
int
exitcode
;
private
boolean
hasExited
;
...
...
@@ -48,15 +48,26 @@ final class UNIXProcess extends Process {
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
boolean
redirectErrorStream
,
FileDescriptor
stdin_fd
,
FileDescriptor
stdout_fd
,
FileDescriptor
stderr_fd
)
throws
IOException
;
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
int
[]
std_fds
,
boolean
redirectErrorStream
)
throws
IOException
;
/*
In
the
process
constructor
we
wait
on
this
gate
until
the
process
*/
/*
has
been
created
.
Then
we
return
from
the
constructor
.
*/
...
...
@@ -97,67 +108,82 @@ final class UNIXProcess extends Process {
}
UNIXProcess
(
final
byte
[]
prog
,
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
dir
,
final
boolean
redirectErrorStream
)
final
byte
[]
argBlock
,
final
int
argc
,
final
byte
[]
envBlock
,
final
int
envc
,
final
byte
[]
dir
,
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
final
Gate
gate
=
new
Gate
();
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* need no native code).
*/
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction
() {
public Object
run() {
Thread t = new Thread("process reaper") {
public void run() {
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* need no native code).
*/
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>
() {
public Void
run() {
Thread t = new Thread("process reaper") {
public void run() {
try {
pid = forkAndExec(prog,
argBlock, argc,
envBlock, envc,
dir,
redirectErrorStream
,
stdin_fd, stdout_fd, stderr_fd
);
argBlock, argc,
envBlock, envc,
dir,
std_fds
,
redirectErrorStream
);
} catch (IOException e) {
gate.setException(e); /*remember to rethrow later*/
gate.exit();
return;
}
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
stdin_stream = new BufferedOutputStream(new
FileOutputStream(stdin_fd));
stdout_stream = new BufferedInputStream(new
FileInputStream(stdout_fd));
new java.security.PrivilegedAction<Void>() {
public Void run() {
if (std_fds[0] == -1)
stdin_stream = new ProcessBuilder.NullOutputStream();
else {
FileDescriptor stdin_fd = new FileDescriptor();
fdAccess.set(stdin_fd, std_fds[0]);
stdin_stream = new BufferedOutputStream(
new FileOutputStream(stdin_fd));
}
if (std_fds[1] == -1)
stdout_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stdout_fd = new FileDescriptor();
fdAccess.set(stdout_fd, std_fds[1]);
stdout_stream = new BufferedInputStream(
new FileInputStream(stdout_fd));
}
if (std_fds[2] == -1)
stderr_stream = new ProcessBuilder.NullInputStream();
else {
FileDescriptor stderr_fd = new FileDescriptor();
fdAccess.set(stderr_fd, std_fds[2]);
stderr_stream = new FileInputStream(stderr_fd);
return null;
}
});
return null; }});
gate.exit(); /* exit from constructor */
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null;
}
});
return null; }});
gate.waitForExit();
IOException e = gate.getException();
if (e != null)
...
...
@@ -165,43 +191,43 @@ final class UNIXProcess extends Process {
}
public OutputStream getOutputStream() {
return stdin_stream;
return stdin_stream;
}
public InputStream getInputStream() {
return stdout_stream;
return stdout_stream;
}
public InputStream getErrorStream() {
return stderr_stream;
return stderr_stream;
}
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
wait();
}
return exitcode;
wait();
}
return exitcode;
}
public synchronized int exitValue() {
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
return exitcode;
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
return exitcode;
}
private static native void destroyProcess(int pid);
public void destroy() {
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
synchronized (this) {
if (!hasExited)
destroyProcess(pid);
}
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
synchronized (this) {
if (!hasExited)
destroyProcess(pid);
}
try {
stdin_stream.close();
stdout_stream.close();
...
...
@@ -215,6 +241,6 @@ final class UNIXProcess extends Process {
private static native void initIDs();
static {
initIDs();
initIDs();
}
}
src/solaris/classes/java/lang/UNIXProcess.java.solaris
浏览文件 @
73d65ed1
/*
*
Copyright
1995
-
200
6
Sun
Microsystems
,
Inc
.
All
Rights
Reserved
.
/*
*
Copyright
1995
-
200
8
Sun
Microsystems
,
Inc
.
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
...
...
@@ -33,129 +33,155 @@ import java.io.*;
*/
final
class
UNIXProcess
extends
Process
{
private
FileDescriptor
stdin_fd
;
private
FileDescriptor
stdout_fd
;
private
FileDescriptor
stderr_fd
;
private
int
pid
;
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
()
;
private
final
int
pid
;
private
int
exitcode
;
private
boolean
hasExited
;
private
OutputStream
stdin_stream
;
private
Buffered
InputStream
stdout_stream
;
private
InputStream
stdout_stream
;
private
DeferredCloseInputStream
stdout_inner_stream
;
private
DeferredClose
InputStream
stderr_stream
;
private
InputStream
stderr_stream
;
/*
this
is
for
the
reaping
thread
*/
private
native
int
waitForProcessExit
(
int
pid
);
/**
*
Create
a
process
using
fork
(
2
)
and
exec
(
2
).
*
*
@
param
std_fds
array
of
file
descriptors
.
Indexes
0
,
1
,
and
*
2
correspond
to
standard
input
,
standard
output
and
*
standard
error
,
respectively
.
On
input
,
a
value
of
-
1
*
means
to
create
a
pipe
to
connect
child
and
parent
*
processes
.
On
output
,
a
value
which
is
not
-
1
is
the
*
parent
pipe
fd
corresponding
to
the
pipe
which
has
*
been
created
.
An
element
of
this
array
is
-
1
on
input
*
if
and
only
if
it
is
<
em
>
not
</
em
>
-
1
on
output
.
*
@
return
the
pid
of
the
subprocess
*/
private
native
int
forkAndExec
(
byte
[]
prog
,
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
boolean
redirectErrorStream
,
FileDescriptor
stdin_fd
,
FileDescriptor
stdout_fd
,
FileDescriptor
stderr_fd
)
throws
IOException
;
byte
[]
argBlock
,
int
argc
,
byte
[]
envBlock
,
int
envc
,
byte
[]
dir
,
int
[]
std_fds
,
boolean
redirectErrorStream
)
throws
IOException
;
UNIXProcess
(
final
byte
[]
prog
,
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
dir
,
final
boolean
redirectErrorStream
)
final
byte
[]
argBlock
,
int
argc
,
final
byte
[]
envBlock
,
int
envc
,
final
byte
[]
dir
,
final
int
[]
std_fds
,
final
boolean
redirectErrorStream
)
throws
IOException
{
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
pid
=
forkAndExec
(
prog
,
argBlock
,
argc
,
envBlock
,
envc
,
dir
,
redirectErrorStream
,
stdin_fd
,
stdout_fd
,
stderr_fd
);
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
()
{
public
Object
run
()
{
stdin_stream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
return
null
;
}
});
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* need no native code).
*/
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction() {
public Object run() {
Thread t = new Thread("process reaper") {
public void run() {
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null;
}
});
pid
=
forkAndExec
(
prog
,
argBlock
,
argc
,
envBlock
,
envc
,
dir
,
std_fds
,
redirectErrorStream
);
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
if
(
std_fds
[
0
]
==
-
1
)
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
();
else
{
FileDescriptor
stdin_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stdin_fd
,
std_fds
[
0
]);
stdin_stream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
));
}
if
(
std_fds
[
1
]
==
-
1
)
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stdout_fd
,
std_fds
[
1
]);
stdout_inner_stream
=
new
DeferredCloseInputStream
(
stdout_fd
);
stdout_stream
=
new
BufferedInputStream
(
stdout_inner_stream
);
}
if
(
std_fds
[
2
]
==
-
1
)
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
set
(
stderr_fd
,
std_fds
[
2
]);
stderr_stream
=
new
DeferredCloseInputStream
(
stderr_fd
);
}
return
null
;
}});
/*
*
For
each
subprocess
forked
a
corresponding
reaper
thread
*
is
started
.
That
thread
is
the
only
thread
which
waits
*
for
the
subprocess
to
terminate
and
it
doesn
't hold any
* locks while doing so. This design allows waitFor() and
* exitStatus() to be safely executed in parallel (and they
* need no native code).
*/
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() { public Void run() {
Thread t = new Thread("process reaper") {
public void run() {
int res = waitForProcessExit(pid);
synchronized (UNIXProcess.this) {
hasExited = true;
exitcode = res;
UNIXProcess.this.notifyAll();
}
}
};
t.setDaemon(true);
t.start();
return null; }});
}
public OutputStream getOutputStream() {
return stdin_stream;
return stdin_stream;
}
public InputStream getInputStream() {
return stdout_stream;
return stdout_stream;
}
public InputStream getErrorStream() {
return stderr_stream;
return stderr_stream;
}
public synchronized int waitFor() throws InterruptedException {
while (!hasExited) {
wait();
}
return exitcode;
wait();
}
return exitcode;
}
public synchronized int exitValue() {
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
return exitcode;
if (!hasExited) {
throw new IllegalThreadStateException("process hasn'
t
exited
");
}
return exitcode;
}
private static native void destroyProcess(int pid);
public synchronized void destroy() {
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
if (!hasExited)
destroyProcess(pid);
try {
// There is a risk that pid will be recycled, causing us to
// kill the wrong process! So we only terminate processes
// that appear to still be running. Even with this check,
// there is an unavoidable race condition here, but the window
// is very small, and OSes try hard to not recycle pids too
// soon, so this is quite safe.
if (!hasExited)
destroyProcess(pid);
try {
stdin_stream.close();
stdout_inner_stream.closeDeferred(stdout_stream);
stderr_stream.closeDeferred(stderr_stream);
if (stdout_inner_stream != null)
stdout_inner_stream.closeDeferred(stdout_stream);
if (stderr_stream instanceof DeferredCloseInputStream)
((DeferredCloseInputStream) stderr_stream)
.closeDeferred(stderr_stream);
} catch (IOException e) {
// ignore
}
...
...
@@ -172,99 +198,99 @@ final class UNIXProcess extends Process {
// (EOF) as they did before.
//
private static class DeferredCloseInputStream
extends FileInputStream
extends FileInputStream
{
private DeferredCloseInputStream(FileDescriptor fd) {
super(fd);
}
private Object lock = new Object();
// For the following fields
private boolean closePending = false;
private int useCount = 0;
private InputStream streamToClose;
private void raise() {
synchronized (lock) {
useCount++;
}
}
private void lower() throws IOException {
synchronized (lock) {
useCount--;
if (useCount == 0 && closePending) {
streamToClose.close();
}
}
}
// stc is the actual stream to be closed; it might be this object, or
// it might be an upstream object for which this object is downstream.
//
private void closeDeferred(InputStream stc) throws IOException {
synchronized (lock) {
if (useCount == 0) {
stc.close();
} else {
closePending = true;
streamToClose = stc;
}
}
}
public void close() throws IOException {
synchronized (lock) {
useCount = 0;
closePending = false;
}
super.close();
}
public int read() throws IOException {
raise();
try {
return super.read();
} finally {
lower();
}
}
public int read(byte[] b) throws IOException {
raise();
try {
return super.read(b);
} finally {
lower();
}
}
public int read(byte[] b, int off, int len) throws IOException {
raise();
try {
return super.read(b, off, len);
} finally {
lower();
}
}
public long skip(long n) throws IOException {
raise();
try {
return super.skip(n);
} finally {
lower();
}
}
public int available() throws IOException {
raise();
try {
return super.available();
} finally {
lower();
}
}
private DeferredCloseInputStream(FileDescriptor fd) {
super(fd);
}
private Object lock = new Object();
// For the following fields
private boolean closePending = false;
private int useCount = 0;
private InputStream streamToClose;
private void raise() {
synchronized (lock) {
useCount++;
}
}
private void lower() throws IOException {
synchronized (lock) {
useCount--;
if (useCount == 0 && closePending) {
streamToClose.close();
}
}
}
// stc is the actual stream to be closed; it might be this object, or
// it might be an upstream object for which this object is downstream.
//
private void closeDeferred(InputStream stc) throws IOException {
synchronized (lock) {
if (useCount == 0) {
stc.close();
} else {
closePending = true;
streamToClose = stc;
}
}
}
public void close() throws IOException {
synchronized (lock) {
useCount = 0;
closePending = false;
}
super.close();
}
public int read() throws IOException {
raise();
try {
return super.read();
} finally {
lower();
}
}
public int read(byte[] b) throws IOException {
raise();
try {
return super.read(b);
} finally {
lower();
}
}
public int read(byte[] b, int off, int len) throws IOException {
raise();
try {
return super.read(b, off, len);
} finally {
lower();
}
}
public long skip(long n) throws IOException {
raise();
try {
return super.skip(n);
} finally {
lower();
}
}
public int available() throws IOException {
raise();
try {
return super.available();
} finally {
lower();
}
}
}
...
...
@@ -272,6 +298,6 @@ final class UNIXProcess extends Process {
private static native void initIDs();
static {
initIDs();
initIDs();
}
}
src/solaris/native/java/io/FileOutputStream_md.c
浏览文件 @
73d65ed1
...
...
@@ -53,13 +53,10 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) {
*/
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
);
}
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_openAppend
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
,
jboolean
append
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
(
append
?
O_APPEND
:
O_TRUNC
));
}
JNIEXPORT
void
JNICALL
...
...
src/solaris/native/java/lang/UNIXProcess_md.c
浏览文件 @
73d65ed1
/*
* Copyright 1995-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-200
8
Sun Microsystems, Inc. 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
...
...
@@ -479,6 +479,37 @@ closeSafely(int fd)
close
(
fd
);
}
/*
* Reads nbyte bytes from file descriptor fd into buf,
* The read operation is retried in case of EINTR or partial reads.
*
* Returns number of bytes read (normally nbyte, but may be less in
* case of EOF). In case of read errors, returns -1 and sets errno.
*/
static
ssize_t
readFully
(
int
fd
,
void
*
buf
,
size_t
nbyte
)
{
ssize_t
remaining
=
nbyte
;
for
(;;)
{
ssize_t
n
=
read
(
fd
,
buf
,
remaining
);
if
(
n
==
0
)
{
return
nbyte
-
remaining
;
}
else
if
(
n
>
0
)
{
remaining
-=
n
;
if
(
remaining
<=
0
)
return
nbyte
;
/* We were interrupted in the middle of reading the bytes.
* Unlikely, but possible. */
buf
=
(
void
*
)
(((
char
*
)
buf
)
+
n
);
}
else
if
(
errno
==
EINTR
)
{
/* Strange signals like SIGJVM1 are possible at any time.
* See http://www.dreamsongs.com/WorseIsBetter.html */
}
else
{
return
-
1
;
}
}
}
#ifndef __solaris__
#undef fork1
#define fork1() fork()
...
...
@@ -491,10 +522,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
jbyteArray
argBlock
,
jint
argc
,
jbyteArray
envBlock
,
jint
envc
,
jbyteArray
dir
,
jboolean
redirectErrorStream
,
jobject
stdin_fd
,
jobject
stdout_fd
,
jobject
stderr_fd
)
jintArray
std_fds
,
jboolean
redirectErrorStream
)
{
int
errnum
;
int
resultPid
=
-
1
;
...
...
@@ -505,6 +534,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
const
char
*
pargBlock
=
getBytes
(
env
,
argBlock
);
const
char
*
penvBlock
=
getBytes
(
env
,
envBlock
);
const
char
*
pdir
=
getBytes
(
env
,
dir
);
jint
*
fds
=
NULL
;
in
[
0
]
=
in
[
1
]
=
out
[
0
]
=
out
[
1
]
=
err
[
0
]
=
err
[
1
]
=
fail
[
0
]
=
fail
[
1
]
=
-
1
;
...
...
@@ -527,9 +557,13 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
initVectorFromBlock
(
envv
,
penvBlock
,
envc
);
}
if
((
pipe
(
in
)
<
0
)
||
(
pipe
(
out
)
<
0
)
||
(
pipe
(
err
)
<
0
)
||
assert
(
std_fds
!=
NULL
);
fds
=
(
*
env
)
->
GetIntArrayElements
(
env
,
std_fds
,
NULL
);
if
(
fds
==
NULL
)
goto
Catch
;
if
((
fds
[
0
]
==
-
1
&&
pipe
(
in
)
<
0
)
||
(
fds
[
1
]
==
-
1
&&
pipe
(
out
)
<
0
)
||
(
fds
[
2
]
==
-
1
&&
pipe
(
err
)
<
0
)
||
(
pipe
(
fail
)
<
0
))
{
throwIOException
(
env
,
errno
,
"Bad file descriptor"
);
goto
Catch
;
...
...
@@ -544,23 +578,26 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
if
(
resultPid
==
0
)
{
/* Child process */
/* Close the parent sides of the pipe.
Give the child sides of the pipes the right fileno's.
/* Close the parent sides of the pipes.
Closing pipe fds here is redundant, since closeDescriptors()
would do it anyways, but a little paranoia is a good thing. */
closeSafely
(
in
[
1
]);
closeSafely
(
out
[
0
]);
closeSafely
(
err
[
0
]);
closeSafely
(
fail
[
0
]);
/* Give the child sides of the pipes the right fileno's. */
/* Note: it is possible for in[0] == 0 */
close
(
in
[
1
]);
moveDescriptor
(
in
[
0
],
STDIN_FILENO
);
close
(
out
[
0
]);
moveDescriptor
(
out
[
1
],
STDOUT_FILENO
);
close
(
err
[
0
]);
moveDescriptor
(
in
[
0
]
!=
-
1
?
in
[
0
]
:
fds
[
0
],
STDIN_FILENO
);
moveDescriptor
(
out
[
1
]
!=
-
1
?
out
[
1
]
:
fds
[
1
],
STDOUT_FILENO
);
if
(
redirectErrorStream
)
{
close
(
err
[
1
]);
close
Safely
(
err
[
1
]);
dup2
(
STDOUT_FILENO
,
STDERR_FILENO
);
}
else
{
moveDescriptor
(
err
[
1
],
STDERR_FILENO
);
moveDescriptor
(
err
[
1
]
!=
-
1
?
err
[
1
]
:
fds
[
2
]
,
STDERR_FILENO
);
}
close
(
fail
[
0
]);
moveDescriptor
(
fail
[
1
],
FAIL_FILENO
);
/* close everything */
...
...
@@ -600,15 +637,21 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
/* parent process */
close
(
fail
[
1
]);
fail
[
1
]
=
-
1
;
/* See: WhyCantJohnnyExec */
if
(
read
(
fail
[
0
],
&
errnum
,
sizeof
(
errnum
))
!=
0
)
{
switch
(
readFully
(
fail
[
0
],
&
errnum
,
sizeof
(
errnum
)))
{
case
0
:
break
;
/* Exec succeeded */
case
sizeof
(
errnum
):
waitpid
(
resultPid
,
NULL
,
0
);
throwIOException
(
env
,
errnum
,
"Exec failed"
);
goto
Catch
;
default:
throwIOException
(
env
,
errno
,
"Read failed"
);
goto
Catch
;
}
(
*
env
)
->
SetIntField
(
env
,
stdin_fd
,
IO_fd_fdID
,
in
[
1
])
;
(
*
env
)
->
SetIntField
(
env
,
stdout_fd
,
IO_fd_fdID
,
out
[
0
])
;
(
*
env
)
->
SetIntField
(
env
,
stderr_fd
,
IO_fd_fdID
,
err
[
0
])
;
fds
[
0
]
=
(
in
[
1
]
!=
-
1
)
?
in
[
1
]
:
-
1
;
fds
[
1
]
=
(
out
[
0
]
!=
-
1
)
?
out
[
0
]
:
-
1
;
fds
[
2
]
=
(
err
[
0
]
!=
-
1
)
?
err
[
0
]
:
-
1
;
Finally:
/* Always clean up the child's side of the pipes */
...
...
@@ -628,6 +671,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
releaseBytes
(
env
,
envBlock
,
penvBlock
);
releaseBytes
(
env
,
dir
,
pdir
);
if
(
fds
!=
NULL
)
(
*
env
)
->
ReleaseIntArrayElements
(
env
,
std_fds
,
fds
,
0
);
return
resultPid
;
Catch:
...
...
src/windows/classes/java/io/FileDescriptor.java
浏览文件 @
73d65ed1
...
...
@@ -29,17 +29,14 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* Instances of the file descriptor class serve as an opaque handle
* to the underlying machine-specific structure representing an open
* file, an open socket, or another source or sink of bytes. The
* main practical use for a file descriptor is to create a
* <code>FileInputStream</code> or <code>FileOutputStream</code> to
* contain it.
* <p>
* Applications should not create their own file descriptors.
* to the underlying machine-specific structure representing an
* open file, an open socket, or another source or sink of bytes.
* The main practical use for a file descriptor is to create a
* {@link FileInputStream} or {@link FileOutputStream} to contain it.
*
* <p>Applications should not create their own file descriptors.
*
* @author Pavani Diwanji
* @see java.io.FileInputStream
* @see java.io.FileOutputStream
* @since JDK1.0
*/
public
final
class
FileDescriptor
{
...
...
@@ -81,6 +78,14 @@ public final class FileDescriptor {
public
int
get
(
FileDescriptor
obj
)
{
return
obj
.
fd
;
}
public
void
setHandle
(
FileDescriptor
obj
,
long
handle
)
{
obj
.
handle
=
handle
;
}
public
long
getHandle
(
FileDescriptor
obj
)
{
return
obj
.
handle
;
}
}
);
}
...
...
@@ -88,7 +93,7 @@ public final class FileDescriptor {
/**
* A handle to the standard input stream. Usually, this file
* descriptor is not used directly, but rather via the input stream
* known as
<code>System.in</code>
.
* known as
{@code System.in}
.
*
* @see java.lang.System#in
*/
...
...
@@ -97,7 +102,7 @@ public final class FileDescriptor {
/**
* A handle to the standard output stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.out</code>
.
* known as
{@code System.out}
.
* @see java.lang.System#out
*/
public
static
final
FileDescriptor
out
=
standardStream
(
1
);
...
...
@@ -105,7 +110,7 @@ public final class FileDescriptor {
/**
* A handle to the standard error stream. Usually, this file
* descriptor is not used directly, but rather via the output stream
* known as
<code>System.err</code>
.
* known as
{@code System.err}
.
*
* @see java.lang.System#err
*/
...
...
@@ -114,9 +119,9 @@ public final class FileDescriptor {
/**
* Tests if this file descriptor object is valid.
*
* @return
<code>true</code>
if the file descriptor object represents a
* @return
{@code true}
if the file descriptor object represents a
* valid, open file, socket, or other active I/O connection;
*
<code>false</code>
otherwise.
*
{@code false}
otherwise.
*/
public
boolean
valid
()
{
return
((
handle
!=
-
1
)
||
(
fd
!=
-
1
));
...
...
src/windows/classes/java/lang/ProcessImpl.java
浏览文件 @
73d65ed1
...
...
@@ -25,7 +25,16 @@
package
java.lang
;
import
java.io.*
;
import
java.io.IOException
;
import
java.io.File
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.io.FileInputStream
;
import
java.io.FileOutputStream
;
import
java.io.FileDescriptor
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedOutputStream
;
import
java.lang.ProcessBuilder.Redirect
;
/* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes.
...
...
@@ -35,30 +44,82 @@ import java.io.*;
*/
final
class
ProcessImpl
extends
Process
{
private
static
final
sun
.
misc
.
JavaIOFileDescriptorAccess
fdAccess
=
sun
.
misc
.
SharedSecrets
.
getJavaIOFileDescriptorAccess
();
// System-dependent portion of ProcessBuilder.start()
static
Process
start
(
String
cmdarray
[],
java
.
util
.
Map
<
String
,
String
>
environment
,
String
dir
,
ProcessBuilder
.
Redirect
[]
redirects
,
boolean
redirectErrorStream
)
throws
IOException
{
String
envblock
=
ProcessEnvironment
.
toEnvironmentBlock
(
environment
);
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
redirectErrorStream
);
FileInputStream
f0
=
null
;
FileOutputStream
f1
=
null
;
FileOutputStream
f2
=
null
;
try
{
long
[]
stdHandles
;
if
(
redirects
==
null
)
{
stdHandles
=
new
long
[]
{
-
1L
,
-
1L
,
-
1L
};
}
else
{
stdHandles
=
new
long
[
3
];
if
(
redirects
[
0
]
==
Redirect
.
PIPE
)
stdHandles
[
0
]
=
-
1L
;
else
if
(
redirects
[
0
]
==
Redirect
.
INHERIT
)
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
in
);
else
{
f0
=
new
FileInputStream
(
redirects
[
0
].
file
());
stdHandles
[
0
]
=
fdAccess
.
getHandle
(
f0
.
getFD
());
}
if
(
redirects
[
1
]
==
Redirect
.
PIPE
)
stdHandles
[
1
]
=
-
1L
;
else
if
(
redirects
[
1
]
==
Redirect
.
INHERIT
)
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
out
);
else
{
f1
=
redirects
[
1
].
toFileOutputStream
();
stdHandles
[
1
]
=
fdAccess
.
getHandle
(
f1
.
getFD
());
}
if
(
redirects
[
2
]
==
Redirect
.
PIPE
)
stdHandles
[
2
]
=
-
1L
;
else
if
(
redirects
[
2
]
==
Redirect
.
INHERIT
)
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
FileDescriptor
.
err
);
else
{
f2
=
redirects
[
2
].
toFileOutputStream
();
stdHandles
[
2
]
=
fdAccess
.
getHandle
(
f2
.
getFD
());
}
}
return
new
ProcessImpl
(
cmdarray
,
envblock
,
dir
,
stdHandles
,
redirectErrorStream
);
}
finally
{
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
try
{
if
(
f0
!=
null
)
f0
.
close
();
}
finally
{
try
{
if
(
f1
!=
null
)
f1
.
close
();
}
finally
{
if
(
f2
!=
null
)
f2
.
close
();
}
}
}
}
private
long
handle
=
0
;
private
FileDescriptor
stdin_fd
;
private
FileDescriptor
stdout_fd
;
private
FileDescriptor
stderr_fd
;
private
OutputStream
stdin_stream
;
private
InputStream
stdout_stream
;
private
InputStream
stderr_stream
;
private
ProcessImpl
(
String
cmd
[],
String
envblock
,
String
path
,
boolean
redirectErrorStream
)
private
ProcessImpl
(
final
String
cmd
[],
final
String
envblock
,
final
String
path
,
final
long
[]
stdHandles
,
final
boolean
redirectErrorStream
)
throws
IOException
{
// Win32 CreateProcess requires cmd[0] to be normalized
...
...
@@ -91,25 +152,39 @@ final class ProcessImpl extends Process {
}
String
cmdstr
=
cmdbuf
.
toString
();
stdin_fd
=
new
FileDescriptor
();
stdout_fd
=
new
FileDescriptor
();
stderr_fd
=
new
FileDescriptor
();
handle
=
create
(
cmdstr
,
envblock
,
path
,
redirectErrorStream
,
stdin_fd
,
stdout_fd
,
stderr_fd
);
handle
=
create
(
cmdstr
,
envblock
,
path
,
stdHandles
,
redirectErrorStream
);
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
()
{
public
Object
run
()
{
stdin_stream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
)
);
stdout_stream
=
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
)
);
stderr_stream
=
new
FileInputStream
(
stderr_fd
);
return
null
;
new
java
.
security
.
PrivilegedAction
<
Void
>
()
{
public
Void
run
()
{
if
(
stdHandles
[
0
]
==
-
1L
)
stdin_stream
=
new
ProcessBuilder
.
NullOutputStream
(
);
else
{
FileDescriptor
stdin_fd
=
new
FileDescriptor
(
);
fdAccess
.
setHandle
(
stdin_fd
,
stdHandles
[
0
]);
stdin_stream
=
new
BufferedOutputStream
(
new
FileOutputStream
(
stdin_fd
))
;
}
});
if
(
stdHandles
[
1
]
==
-
1L
)
stdout_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stdout_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stdout_fd
,
stdHandles
[
1
]);
stdout_stream
=
new
BufferedInputStream
(
new
FileInputStream
(
stdout_fd
));
}
if
(
stdHandles
[
2
]
==
-
1L
)
stderr_stream
=
new
ProcessBuilder
.
NullInputStream
();
else
{
FileDescriptor
stderr_fd
=
new
FileDescriptor
();
fdAccess
.
setHandle
(
stderr_fd
,
stdHandles
[
2
]);
stderr_stream
=
new
FileInputStream
(
stderr_fd
);
}
return
null
;
}});
}
public
OutputStream
getOutputStream
()
{
...
...
@@ -150,13 +225,30 @@ final class ProcessImpl extends Process {
public
void
destroy
()
{
terminateProcess
(
handle
);
}
private
static
native
void
terminateProcess
(
long
handle
);
/**
* Create a process using the win32 function CreateProcess.
*
* @param cmdstr the Windows commandline
* @param envblock NUL-separated, double-NUL-terminated list of
* environment strings in VAR=VALUE form
* @param dir the working directory of the process, or null if
* inheriting the current directory from the parent process
* @param stdHandles array of windows HANDLEs. Indexes 0, 1, and
* 2 correspond to standard input, standard output and
* standard error, respectively. On input, a value of -1
* means to create a pipe to connect child and parent
* processes. On output, a value which is not -1 is the
* parent pipe handle corresponding to the pipe which has
* been created. An element of this array is -1 on input
* if and only if it is <em>not</em> -1 on output.
* @param redirectErrorStream redirectErrorStream attribute
* @return the native subprocess HANDLE returned by CreateProcess
*/
private
static
native
long
create
(
String
cmdstr
,
String
envblock
,
String
dir
,
boolean
redirectErrorStream
,
FileDescriptor
in_fd
,
FileDescriptor
out_fd
,
FileDescriptor
err_fd
)
long
[]
stdHandles
,
boolean
redirectErrorStream
)
throws
IOException
;
private
static
native
boolean
closeHandle
(
long
handle
);
...
...
src/windows/native/java/io/FileOutputStream_md.c
浏览文件 @
73d65ed1
...
...
@@ -39,8 +39,6 @@
jfieldID
fos_fd
;
/* id for jobject 'fd' in java.io.FileOutputStream */
jfieldID
fos_append
;
/**************************************************************
* static methods to store field ID's in initializers
*/
...
...
@@ -49,7 +47,6 @@ JNIEXPORT void JNICALL
Java_java_io_FileOutputStream_initIDs
(
JNIEnv
*
env
,
jclass
fosClass
)
{
fos_fd
=
(
*
env
)
->
GetFieldID
(
env
,
fosClass
,
"fd"
,
"Ljava/io/FileDescriptor;"
);
fos_append
=
(
*
env
)
->
GetFieldID
(
env
,
fosClass
,
"append"
,
"Z"
);
}
/**************************************************************
...
...
@@ -57,45 +54,20 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) {
*/
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
);
}
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_openAppend
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
O_APPEND
);
Java_java_io_FileOutputStream_open
(
JNIEnv
*
env
,
jobject
this
,
jstring
path
,
jboolean
append
)
{
fileOpen
(
env
,
this
,
path
,
fos_fd
,
O_WRONLY
|
O_CREAT
|
(
append
?
O_APPEND
:
O_TRUNC
));
}
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_write
(
JNIEnv
*
env
,
jobject
this
,
jint
byte
)
{
jboolean
append
=
(
*
env
)
->
GetBooleanField
(
env
,
this
,
fos_append
);
FD
fd
=
GET_FD
(
this
,
fos_fd
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
}
if
(
append
==
JNI_TRUE
)
{
if
(
IO_Lseek
(
fd
,
0L
,
SEEK_END
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"Append failed"
);
}
}
writeSingle
(
env
,
this
,
byte
,
fos_fd
);
}
JNIEXPORT
void
JNICALL
Java_java_io_FileOutputStream_writeBytes
(
JNIEnv
*
env
,
jobject
this
,
jbyteArray
bytes
,
jint
off
,
jint
len
)
{
jboolean
append
=
(
*
env
)
->
GetBooleanField
(
env
,
this
,
fos_append
);
FD
fd
=
GET_FD
(
this
,
fos_fd
);
if
(
fd
==
-
1
)
{
JNU_ThrowIOException
(
env
,
"Stream Closed"
);
return
;
}
if
(
append
==
JNI_TRUE
)
{
if
(
IO_Lseek
(
fd
,
0L
,
SEEK_END
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"Append failed"
);
}
}
writeBytes
(
env
,
this
,
bytes
,
off
,
len
,
fos_fd
);
}
...
...
src/windows/native/java/io/io_util_md.c
浏览文件 @
73d65ed1
...
...
@@ -42,7 +42,7 @@
extern
jboolean
onNT
=
JNI_FALSE
;
static
int
MAX_INPUT_EVENTS
=
2000
;
static
DWORD
MAX_INPUT_EVENTS
=
2000
;
void
initializeWindowsVersion
()
{
...
...
@@ -190,9 +190,16 @@ pathToNTPath(JNIEnv *env, jstring path, jboolean throwFNFE) {
jlong
winFileHandleOpen
(
JNIEnv
*
env
,
jstring
path
,
int
flags
)
{
/* To implement O_APPEND, we use the strategy from
http://msdn2.microsoft.com/en-us/library/aa363858.aspx
"You can get atomic append by opening a file with
FILE_APPEND_DATA access and _without_ FILE_WRITE_DATA access.
If you do this then all writes will ignore the current file
pointer and be done at the end-of file." */
const
DWORD
access
=
(
flags
&
O_
RDWR
)
?
(
GENERIC_WRITE
|
GENERIC_READ
)
:
(
flags
&
O_
APPEND
)
?
(
FILE_GENERIC_WRITE
&
~
FILE_WRITE_DATA
)
:
(
flags
&
O_WRONLY
)
?
GENERIC_WRITE
:
(
flags
&
O_RDWR
)
?
(
GENERIC_READ
|
GENERIC_WRITE
)
:
GENERIC_READ
;
const
DWORD
sharing
=
FILE_SHARE_READ
|
FILE_SHARE_WRITE
;
...
...
@@ -444,24 +451,6 @@ handleSetLength(jlong fd, jlong length) {
return
0
;
}
int
handleFileSizeFD
(
jlong
fd
,
jlong
*
size
)
{
DWORD
sizeLow
=
0
;
DWORD
sizeHigh
=
0
;
HANDLE
h
=
(
HANDLE
)
fd
;
if
(
h
==
INVALID_HANDLE_VALUE
)
{
return
-
1
;
}
sizeLow
=
GetFileSize
(
h
,
&
sizeHigh
);
if
(
sizeLow
==
((
DWORD
)
-
1
))
{
if
(
GetLastError
()
!=
ERROR_SUCCESS
)
{
return
-
1
;
}
}
return
(((
jlong
)
sizeHigh
)
<<
32
)
|
sizeLow
;
}
JNIEXPORT
size_t
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
)
...
...
@@ -513,7 +502,7 @@ handleClose(JNIEnv *env, jobject this, jfieldID fid)
FD
fd
=
GET_FD
(
this
,
fid
);
HANDLE
h
=
(
HANDLE
)
fd
;
if
(
fd
==
INVALID_HANDLE_VALUE
)
{
if
(
h
==
INVALID_HANDLE_VALUE
)
{
return
0
;
}
...
...
src/windows/native/java/io/io_util_md.h
浏览文件 @
73d65ed1
...
...
@@ -38,7 +38,6 @@ void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
int
handleAvailable
(
jlong
fd
,
jlong
*
pbytes
);
JNIEXPORT
int
handleSync
(
jlong
fd
);
int
handleSetLength
(
jlong
fd
,
jlong
length
);
int
handleFileSizeFD
(
jlong
fd
,
jlong
*
size
);
JNIEXPORT
size_t
handleRead
(
jlong
fd
,
void
*
buf
,
jint
len
);
JNIEXPORT
size_t
handleWrite
(
jlong
fd
,
const
void
*
buf
,
jint
len
);
jint
handleClose
(
JNIEnv
*
env
,
jobject
this
,
jfieldID
fid
);
...
...
src/windows/native/java/lang/ProcessImpl_md.c
浏览文件 @
73d65ed1
...
...
@@ -33,7 +33,12 @@
#include <windows.h>
#include <io.h>
#define PIPE_SIZE 4096
/* We try to make sure that we can read and write 4095 bytes (the
* fixed limit on Linux) to the pipe on all operating systems without
* deadlock. Windows 2000 inexplicably appears to need an extra 24
* bytes of slop to avoid deadlock.
*/
#define PIPE_SIZE (4096+24)
char
*
extractExecutablePath
(
JNIEnv
*
env
,
char
*
source
)
...
...
@@ -120,7 +125,7 @@ win32Error(JNIEnv *env, const char *functionName)
static
void
closeSafely
(
HANDLE
handle
)
{
if
(
handle
)
if
(
handle
!=
INVALID_HANDLE_VALUE
)
CloseHandle
(
handle
);
}
...
...
@@ -129,23 +134,22 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
jstring
cmd
,
jstring
envBlock
,
jstring
dir
,
jboolean
redirectErrorStream
,
jobject
in_fd
,
jobject
out_fd
,
jobject
err_fd
)
jlongArray
stdHandles
,
jboolean
redirectErrorStream
)
{
HANDLE
inRead
=
0
;
HANDLE
inWrite
=
0
;
HANDLE
outRead
=
0
;
HANDLE
outWrite
=
0
;
HANDLE
errRead
=
0
;
HANDLE
errWrite
=
0
;
HANDLE
inRead
=
INVALID_HANDLE_VALUE
;
HANDLE
inWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
outRead
=
INVALID_HANDLE_VALUE
;
HANDLE
outWrite
=
INVALID_HANDLE_VALUE
;
HANDLE
errRead
=
INVALID_HANDLE_VALUE
;
HANDLE
errWrite
=
INVALID_HANDLE_VALUE
;
SECURITY_ATTRIBUTES
sa
;
PROCESS_INFORMATION
pi
;
STARTUPINFO
si
;
LPTSTR
pcmd
=
NULL
;
LPCTSTR
pdir
=
NULL
;
LPVOID
penvBlock
=
NULL
;
jlong
*
handles
=
NULL
;
jlong
ret
=
0
;
OSVERSIONINFO
ver
;
jboolean
onNT
=
JNI_FALSE
;
...
...
@@ -156,17 +160,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
ver
.
dwPlatformId
==
VER_PLATFORM_WIN32_NT
)
onNT
=
JNI_TRUE
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
if
(
!
(
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
)
&&
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
)))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
assert
(
cmd
!=
NULL
);
pcmd
=
(
LPTSTR
)
JNU_GetStringPlatformChars
(
env
,
cmd
,
NULL
);
if
(
pcmd
==
NULL
)
goto
Catch
;
...
...
@@ -184,19 +177,62 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
if
(
penvBlock
==
NULL
)
goto
Catch
;
}
assert
(
stdHandles
!=
NULL
);
handles
=
(
*
env
)
->
GetLongArrayElements
(
env
,
stdHandles
,
NULL
);
if
(
handles
==
NULL
)
goto
Catch
;
memset
(
&
si
,
0
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
si
.
dwFlags
=
STARTF_USESTDHANDLES
;
si
.
hStdInput
=
inRead
;
si
.
hStdOutput
=
outWrite
;
si
.
hStdError
=
redirectErrorStream
?
outWrite
:
errWrite
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
)
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
)
;
sa
.
nLength
=
sizeof
(
sa
);
sa
.
lpSecurityDescriptor
=
0
;
sa
.
bInheritHandle
=
TRUE
;
if
(
redirectErrorStream
)
SetHandleInformation
(
errWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
if
(
handles
[
0
]
!=
(
jlong
)
-
1
)
{
si
.
hStdInput
=
(
HANDLE
)
handles
[
0
];
handles
[
0
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
inRead
,
&
inWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdInput
=
inRead
;
SetHandleInformation
(
inWrite
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
0
]
=
(
jlong
)
inWrite
;
}
SetHandleInformation
(
si
.
hStdInput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
handles
[
1
]
!=
(
jlong
)
-
1
)
{
si
.
hStdOutput
=
(
HANDLE
)
handles
[
1
];
handles
[
1
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
outRead
,
&
outWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdOutput
=
outWrite
;
SetHandleInformation
(
outRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
1
]
=
(
jlong
)
outRead
;
}
SetHandleInformation
(
si
.
hStdOutput
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
redirectErrorStream
)
{
si
.
hStdError
=
si
.
hStdOutput
;
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
if
(
handles
[
2
]
!=
(
jlong
)
-
1
)
{
si
.
hStdError
=
(
HANDLE
)
handles
[
2
];
handles
[
2
]
=
(
jlong
)
-
1
;
}
else
{
if
(
!
CreatePipe
(
&
errRead
,
&
errWrite
,
&
sa
,
PIPE_SIZE
))
{
win32Error
(
env
,
"CreatePipe"
);
goto
Catch
;
}
si
.
hStdError
=
errWrite
;
SetHandleInformation
(
errRead
,
HANDLE_FLAG_INHERIT
,
FALSE
);
handles
[
2
]
=
(
jlong
)
errRead
;
}
SetHandleInformation
(
si
.
hStdError
,
HANDLE_FLAG_INHERIT
,
TRUE
);
if
(
onNT
)
processFlag
=
CREATE_NO_WINDOW
|
CREATE_UNICODE_ENVIRONMENT
;
...
...
@@ -232,9 +268,6 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
CloseHandle
(
pi
.
hThread
);
ret
=
(
jlong
)
pi
.
hProcess
;
(
*
env
)
->
SetLongField
(
env
,
in_fd
,
IO_handle_fdID
,
(
jlong
)
inWrite
);
(
*
env
)
->
SetLongField
(
env
,
out_fd
,
IO_handle_fdID
,
(
jlong
)
outRead
);
(
*
env
)
->
SetLongField
(
env
,
err_fd
,
IO_handle_fdID
,
(
jlong
)
errRead
);
Finally:
/* Always clean up the child's side of the pipes */
...
...
@@ -252,6 +285,9 @@ Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
else
JNU_ReleaseStringPlatformChars
(
env
,
dir
,
(
char
*
)
penvBlock
);
}
if
(
handles
!=
NULL
)
(
*
env
)
->
ReleaseLongArrayElements
(
env
,
stdHandles
,
handles
,
0
);
return
ret
;
Catch:
...
...
src/windows/native/java/lang/java_props_md.c
浏览文件 @
73d65ed1
...
...
@@ -673,13 +673,13 @@ GetJavaProperties(JNIEnv* env)
/* OS properties */
{
char
buf
[
100
];
OSVERSIONINFO
ver
;
OSVERSIONINFO
EX
ver
;
ver
.
dwOSVersionInfoSize
=
sizeof
(
ver
);
GetVersionEx
(
&
ver
);
GetVersionEx
(
(
OSVERSIONINFO
*
)
&
ver
);
/*
* From msdn page on OSVERSIONINFOEX, current as of this
* writing decoding of dwMajorVersion and dwMinorVersion.
* writing
,
decoding of dwMajorVersion and dwMinorVersion.
*
* Operating system dwMajorVersion dwMinorVersion
* ================== ============== ==============
...
...
@@ -692,7 +692,7 @@ GetJavaProperties(JNIEnv* env)
* Windows 2000 5 0
* Windows XP 5 1
* Windows Server 2003 family 5 2
* Windows Vista
6 0
* Windows Vista
family
6 0
*
* This mapping will presumably be augmented as new Windows
* versions are released.
...
...
@@ -724,7 +724,20 @@ GetJavaProperties(JNIEnv* env)
default:
sprops
.
os_name
=
"Windows NT (unknown)"
;
break
;
}
}
else
if
(
ver
.
dwMajorVersion
==
6
)
{
sprops
.
os_name
=
"Windows Vista"
;
/*
* From MSDN OSVERSIONINFOEX documentation:
*
* "Because the version numbers for Windows Server 2008
* and Windows Vista are identical, you must also test
* whether the wProductType member is VER_NT_WORKSTATION.
* If wProductType is VER_NT_WORKSTATION, the operating
* system is Windows Vista; otherwise, it is Windows
* Server 2008."
*/
if
(
ver
.
wProductType
==
VER_NT_WORKSTATION
)
sprops
.
os_name
=
"Windows Vista"
;
else
sprops
.
os_name
=
"Windows Server 2008"
;
}
else
{
sprops
.
os_name
=
"Windows NT (unknown)"
;
}
...
...
test/java/io/FileOutputStream/AtomicAppend.java
0 → 100644
浏览文件 @
73d65ed1
/*
* Copyright 2007 Sun Microsystems, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6631352
* @summary Check that appends are atomic
*/
import
java.io.File
;
import
java.io.FileOutputStream
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.TimeUnit
;
public
class
AtomicAppend
{
// Before the fix for
// 6631352: Implement atomic append mode using FILE_APPEND_DATA (win)
// this would fail intermittently on windows
void
test
(
String
[]
args
)
throws
Throwable
{
final
int
nThreads
=
10
;
final
int
writes
=
1000
;
final
File
file
=
new
File
(
"foo"
);
file
.
delete
();
try
{
final
ExecutorService
es
=
Executors
.
newFixedThreadPool
(
nThreads
);
for
(
int
i
=
0
;
i
<
nThreads
;
i
++)
es
.
execute
(
new
Runnable
()
{
public
void
run
()
{
try
{
FileOutputStream
s
=
new
FileOutputStream
(
file
,
true
);
for
(
int
j
=
0
;
j
<
1000
;
j
++)
{
s
.
write
((
int
)
'x'
);
s
.
flush
();
}
s
.
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}}});
es
.
shutdown
();
es
.
awaitTermination
(
10L
,
TimeUnit
.
MINUTES
);
equal
(
file
.
length
(),
(
long
)
(
nThreads
*
writes
));
}
finally
{
file
.
delete
();
}
}
//--------------------- Infrastructure ---------------------------
volatile
int
passed
=
0
,
failed
=
0
;
void
pass
()
{
passed
++;}
void
fail
()
{
failed
++;
Thread
.
dumpStack
();}
void
fail
(
String
msg
)
{
System
.
err
.
println
(
msg
);
fail
();}
void
unexpected
(
Throwable
t
)
{
failed
++;
t
.
printStackTrace
();}
void
check
(
boolean
cond
)
{
if
(
cond
)
pass
();
else
fail
();}
void
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
null
?
y
==
null
:
x
.
equals
(
y
))
pass
();
else
fail
(
x
+
" not equal to "
+
y
);}
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
new
AtomicAppend
().
instanceMain
(
args
);}
void
instanceMain
(
String
[]
args
)
throws
Throwable
{
try
{
test
(
args
);}
catch
(
Throwable
t
)
{
unexpected
(
t
);}
System
.
out
.
printf
(
"%nPassed = %d, failed = %d%n%n"
,
passed
,
failed
);
if
(
failed
>
0
)
throw
new
AssertionError
(
"Some tests failed"
);}
}
test/java/lang/ProcessBuilder/Basic.java
浏览文件 @
73d65ed1
...
...
@@ -25,12 +25,15 @@
* @test
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031
* 6464154 6523983 6206031
4960438 6631352 6631966
* @summary Basic tests for Process and Environment Variable code
* @run main/othervm Basic
* @author Martin Buchholz
*/
import
java.lang.ProcessBuilder.Redirect
;
import
static
java
.
lang
.
ProcessBuilder
.
Redirect
.*;
import
java.io.*
;
import
java.util.*
;
import
java.security.*
;
...
...
@@ -257,7 +260,29 @@ public class Basic {
public
static
class
JavaChild
{
public
static
void
main
(
String
args
[])
throws
Throwable
{
String
action
=
args
[
0
];
if
(
action
.
equals
(
"System.getenv(String)"
))
{
if
(
action
.
equals
(
"testIO"
))
{
String
expected
=
"standard input"
;
char
[]
buf
=
new
char
[
expected
.
length
()+
1
];
int
n
=
new
InputStreamReader
(
System
.
in
).
read
(
buf
,
0
,
buf
.
length
);
if
(
n
!=
expected
.
length
())
System
.
exit
(
5
);
if
(!
new
String
(
buf
,
0
,
n
).
equals
(
expected
))
System
.
exit
(
5
);
System
.
err
.
print
(
"standard error"
);
System
.
out
.
print
(
"standard output"
);
}
else
if
(
action
.
equals
(
"testInheritIO"
))
{
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
pb
.
inheritIO
();
ProcessResults
r
=
run
(
pb
);
if
(!
r
.
out
().
equals
(
""
))
System
.
exit
(
7
);
if
(!
r
.
err
().
equals
(
""
))
System
.
exit
(
8
);
if
(
r
.
exitValue
()
!=
0
)
System
.
exit
(
9
);
}
else
if
(
action
.
equals
(
"System.getenv(String)"
))
{
String
val
=
System
.
getenv
(
args
[
1
]);
printUTF8
(
val
==
null
?
"null"
:
val
);
}
else
if
(
action
.
equals
(
"System.getenv(\\u1234)"
))
{
...
...
@@ -599,6 +624,333 @@ public class Basic {
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
static
void
checkRedirects
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
equal
(
pb
.
redirectInput
(),
in
);
equal
(
pb
.
redirectOutput
(),
out
);
equal
(
pb
.
redirectError
(),
err
);
}
static
void
redirectIO
(
ProcessBuilder
pb
,
Redirect
in
,
Redirect
out
,
Redirect
err
)
{
pb
.
redirectInput
(
in
);
pb
.
redirectOutput
(
out
);
pb
.
redirectError
(
err
);
}
static
void
setFileContents
(
File
file
,
String
contents
)
{
try
{
Writer
w
=
new
FileWriter
(
file
);
w
.
write
(
contents
);
w
.
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
static
String
fileContents
(
File
file
)
{
try
{
Reader
r
=
new
FileReader
(
file
);
StringBuilder
sb
=
new
StringBuilder
();
char
[]
buffer
=
new
char
[
1024
];
int
n
;
while
((
n
=
r
.
read
(
buffer
))
!=
-
1
)
sb
.
append
(
buffer
,
0
,
n
);
r
.
close
();
return
new
String
(
sb
);
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
""
;
}
}
static
void
testIORedirection
()
throws
Throwable
{
final
File
ifile
=
new
File
(
"ifile"
);
final
File
ofile
=
new
File
(
"ofile"
);
final
File
efile
=
new
File
(
"efile"
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
//----------------------------------------------------------------
// Check mutual inequality of different types of Redirect
//----------------------------------------------------------------
Redirect
[]
redirects
=
{
PIPE
,
INHERIT
,
Redirect
.
from
(
ifile
),
Redirect
.
to
(
ifile
),
Redirect
.
appendTo
(
ifile
),
Redirect
.
from
(
ofile
),
Redirect
.
to
(
ofile
),
Redirect
.
appendTo
(
ofile
),
};
for
(
int
i
=
0
;
i
<
redirects
.
length
;
i
++)
for
(
int
j
=
0
;
j
<
redirects
.
length
;
j
++)
equal
(
redirects
[
i
].
equals
(
redirects
[
j
]),
(
i
==
j
));
//----------------------------------------------------------------
// Check basic properties of different types of Redirect
//----------------------------------------------------------------
equal
(
PIPE
.
type
(),
Redirect
.
Type
.
PIPE
);
equal
(
PIPE
.
toString
(),
"PIPE"
);
equal
(
PIPE
.
file
(),
null
);
equal
(
INHERIT
.
type
(),
Redirect
.
Type
.
INHERIT
);
equal
(
INHERIT
.
toString
(),
"INHERIT"
);
equal
(
INHERIT
.
file
(),
null
);
equal
(
Redirect
.
from
(
ifile
).
type
(),
Redirect
.
Type
.
READ
);
equal
(
Redirect
.
from
(
ifile
).
toString
(),
"redirect to read from file \"ifile\""
);
equal
(
Redirect
.
from
(
ifile
).
file
(),
ifile
);
equal
(
Redirect
.
from
(
ifile
),
Redirect
.
from
(
ifile
));
equal
(
Redirect
.
from
(
ifile
).
hashCode
(),
Redirect
.
from
(
ifile
).
hashCode
());
equal
(
Redirect
.
to
(
ofile
).
type
(),
Redirect
.
Type
.
WRITE
);
equal
(
Redirect
.
to
(
ofile
).
toString
(),
"redirect to write to file \"ofile\""
);
equal
(
Redirect
.
to
(
ofile
).
file
(),
ofile
);
equal
(
Redirect
.
to
(
ofile
),
Redirect
.
to
(
ofile
));
equal
(
Redirect
.
to
(
ofile
).
hashCode
(),
Redirect
.
to
(
ofile
).
hashCode
());
equal
(
Redirect
.
appendTo
(
ofile
).
type
(),
Redirect
.
Type
.
APPEND
);
equal
(
Redirect
.
appendTo
(
efile
).
toString
(),
"redirect to append to file \"efile\""
);
equal
(
Redirect
.
appendTo
(
efile
).
file
(),
efile
);
equal
(
Redirect
.
appendTo
(
efile
),
Redirect
.
appendTo
(
efile
));
equal
(
Redirect
.
appendTo
(
efile
).
hashCode
(),
Redirect
.
appendTo
(
efile
).
hashCode
());
//----------------------------------------------------------------
// Check initial values of redirects
//----------------------------------------------------------------
List
<
String
>
childArgs
=
new
ArrayList
<
String
>(
javaChildArgs
);
childArgs
.
add
(
"testIO"
);
final
ProcessBuilder
pb
=
new
ProcessBuilder
(
childArgs
);
checkRedirects
(
pb
,
PIPE
,
PIPE
,
PIPE
);
//----------------------------------------------------------------
// Check inheritIO
//----------------------------------------------------------------
pb
.
inheritIO
();
checkRedirects
(
pb
,
INHERIT
,
INHERIT
,
INHERIT
);
//----------------------------------------------------------------
// Check setters and getters agree
//----------------------------------------------------------------
pb
.
redirectInput
(
ifile
);
equal
(
pb
.
redirectInput
().
file
(),
ifile
);
equal
(
pb
.
redirectInput
(),
Redirect
.
from
(
ifile
));
pb
.
redirectOutput
(
ofile
);
equal
(
pb
.
redirectOutput
().
file
(),
ofile
);
equal
(
pb
.
redirectOutput
(),
Redirect
.
to
(
ofile
));
pb
.
redirectError
(
efile
);
equal
(
pb
.
redirectError
().
file
(),
efile
);
equal
(
pb
.
redirectError
(),
Redirect
.
to
(
efile
));
THROWS
(
IllegalArgumentException
.
class
,
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
to
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectInput
(
Redirect
.
appendTo
(
ofile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectOutput
(
Redirect
.
from
(
ifile
));
}},
new
Fun
(){
void
f
()
{
pb
.
redirectError
(
Redirect
.
from
(
ifile
));
}});
THROWS
(
IOException
.
class
,
// Input file does not exist
new
Fun
(){
void
f
()
throws
Throwable
{
pb
.
start
();
}});
setFileContents
(
ifile
,
"standard input"
);
//----------------------------------------------------------------
// Writing to non-existent files
//----------------------------------------------------------------
{
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Both redirectErrorStream + redirectError
//----------------------------------------------------------------
{
pb
.
redirectErrorStream
(
true
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
""
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending to existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
Redirect
.
appendTo
(
ofile
));
pb
.
redirectError
(
Redirect
.
appendTo
(
efile
));
pb
.
redirectErrorStream
(
false
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
+
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Replacing existing files
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
pb
.
redirectOutput
(
ofile
);
pb
.
redirectError
(
Redirect
.
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Appending twice to the same file?
//----------------------------------------------------------------
{
setFileContents
(
ofile
,
"ofile-contents"
);
setFileContents
(
efile
,
"efile-contents"
);
Redirect
appender
=
Redirect
.
appendTo
(
ofile
);
pb
.
redirectOutput
(
appender
);
pb
.
redirectError
(
appender
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
exitValue
(),
0
);
equal
(
fileContents
(
ofile
),
"ofile-contents"
+
"standard error"
+
"standard output"
);
equal
(
fileContents
(
efile
),
"efile-contents"
);
equal
(
r
.
out
(),
""
);
equal
(
r
.
err
(),
""
);
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
//----------------------------------------------------------------
// Testing INHERIT is harder.
// Note that this requires __FOUR__ nested JVMs involved in one test,
// if you count the harness JVM.
//----------------------------------------------------------------
{
redirectIO
(
pb
,
PIPE
,
PIPE
,
PIPE
);
List
<
String
>
command
=
pb
.
command
();
command
.
set
(
command
.
size
()
-
1
,
"testInheritIO"
);
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
equal
(
r
.
exitValue
(),
0
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
//----------------------------------------------------------------
// Test security implications of I/O redirection
//----------------------------------------------------------------
// Read access to current directory is always granted;
// So create a tmpfile for input instead.
final
File
tmpFile
=
File
.
createTempFile
(
"Basic"
,
"tmp"
);
setFileContents
(
tmpFile
,
"standard input"
);
final
Policy
policy
=
new
Policy
();
Policy
.
setPolicy
(
policy
);
System
.
setSecurityManager
(
new
SecurityManager
());
try
{
final
Permission
xPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"execute"
);
final
Permission
rxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,execute"
);
final
Permission
wxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"write,execute"
);
final
Permission
rwxPermission
=
new
FilePermission
(
"<<ALL FILES>>"
,
"read,write,execute"
);
THROWS
(
SecurityException
.
class
,
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
xPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
PIPE
);
pb
.
start
();}},
new
Fun
()
{
void
f
()
throws
IOException
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
PIPE
,
PIPE
,
to
(
efile
));
pb
.
start
();}});
{
policy
.
setPermissions
(
rxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
PIPE
,
PIPE
);
ProcessResults
r
=
run
(
pb
);
equal
(
r
.
out
(),
"standard output"
);
equal
(
r
.
err
(),
"standard error"
);
}
{
policy
.
setPermissions
(
wxPermission
);
redirectIO
(
pb
,
PIPE
,
to
(
ofile
),
to
(
efile
));
Process
p
=
pb
.
start
();
new
PrintStream
(
p
.
getOutputStream
()).
print
(
"standard input"
);
p
.
getOutputStream
().
close
();
ProcessResults
r
=
run
(
p
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
{
policy
.
setPermissions
(
rwxPermission
);
redirectIO
(
pb
,
from
(
tmpFile
),
to
(
ofile
),
to
(
efile
));
ProcessResults
r
=
run
(
pb
);
policy
.
setPermissions
(
rwxPermission
);
equal
(
fileContents
(
ofile
),
"standard output"
);
equal
(
fileContents
(
efile
),
"standard error"
);
}
}
finally
{
policy
.
setPermissions
(
new
RuntimePermission
(
"setSecurityManager"
));
System
.
setSecurityManager
(
null
);
tmpFile
.
delete
();
ifile
.
delete
();
ofile
.
delete
();
efile
.
delete
();
}
}
private
static
void
realMain
(
String
[]
args
)
throws
Throwable
{
if
(
Windows
.
is
())
System
.
out
.
println
(
"This appears to be a Windows system."
);
...
...
@@ -607,6 +959,9 @@ public class Basic {
if
(
UnicodeOS
.
is
())
System
.
out
.
println
(
"This appears to be a Unicode-based OS."
);
try
{
testIORedirection
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
//----------------------------------------------------------------
// Basic tests for setting, replacing and deleting envvars
//----------------------------------------------------------------
...
...
@@ -1354,7 +1709,8 @@ public class Basic {
execPermission
);
ProcessBuilder
pb
=
new
ProcessBuilder
(
"env"
);
pb
.
environment
().
put
(
"foo"
,
"bar"
);
pb
.
start
();
Process
p
=
pb
.
start
();
closeStreams
(
p
);
}
catch
(
IOException
e
)
{
// OK
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
...
...
@@ -1378,6 +1734,14 @@ public class Basic {
}
static
void
closeStreams
(
Process
p
)
{
try
{
p
.
getOutputStream
().
close
();
p
.
getInputStream
().
close
();
p
.
getErrorStream
().
close
();
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
}
}
//----------------------------------------------------------------
// A Policy class designed to make permissions fiddling very easy.
//----------------------------------------------------------------
...
...
@@ -1432,10 +1796,19 @@ public class Basic {
}
}
catch
(
Throwable
t
)
{
throwable
=
t
;
}
finally
{
try
{
is
.
close
();
}
catch
(
Throwable
t
)
{
throwable
=
t
;
}
}
}
}
static
ProcessResults
run
(
ProcessBuilder
pb
)
{
try
{
return
run
(
pb
.
start
());
}
catch
(
Throwable
t
)
{
unexpected
(
t
);
return
null
;
}
}
private
static
ProcessResults
run
(
Process
p
)
{
Throwable
throwable
=
null
;
int
exitValue
=
-
1
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录