SecureDirectoryStream.java 15.9 KB
Newer Older
1 2 3 4 5 6 7
/*
 * Copyright 2007-2009 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.  Sun designates this
8
 * particular file as subject to the "Classpath" exception as provided
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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.
 */
package java.nio.file;

import java.nio.file.attribute.*;
import java.nio.channels.SeekableByteChannel;
import java.util.Set;
import java.io.IOException;

/**
 * A {@code DirectoryStream} that defines operations on files that are located
 * relative to an open directory. A {@code SecureDirectoryStream} is intended
 * for use by sophisticated or security sensitive applications requiring to
 * traverse file trees or otherwise operate on directories in a race-free manner.
 * Race conditions can arise when a sequence of file operations cannot be
 * carried out in isolation. Each of the file operations defined by this
 * interface specify a relative {@link Path}. All access to the file is relative
 * to the open directory irrespective of if the directory is moved or replaced
 * by an attacker while the directory is open. A {@code SecureDirectoryStream}
 * may also be used as a virtual <em>working directory</em>.
 *
 * <p> A {@code SecureDirectoryStream} requires corresponding support from the
 * underlying operating system. Where an implementation supports this features
 * then the {@code DirectoryStream} returned by the {@link Path#newDirectoryStream
 * newDirectoryStream} method will be a {@code SecureDirectoryStream} and must
 * be cast to that type in order to invoke the methods defined by this interface.
 *
 * <p> As specified by {@code DirectoryStream}, the iterator's {@link
 * java.util.Iterator#remove() remove} method removes the directory entry for
 * the last element returned by the iterator. In the case of a {@code
 * SecureDirectoryStream} the {@code remove} method behaves as if by invoking
 * the {@link #deleteFile deleteFile} or {@link #deleteDirectory deleteDirectory}
 * methods defined by this interface. The {@code remove} may require to examine
 * the file to determine if the file is a directory, and consequently, it may
 * not be atomic with respect to other file system operations.
 *
 * <p> In the case of the default {@link java.nio.file.spi.FileSystemProvider
 * provider}, and a security manager is set, then the permission checks are
 * performed using the path obtained by resolving the given relative path
 * against the <i>original path</i> of the directory (irrespective of if the
 * directory is moved since it was opened).
 *
 * @since   1.7
 */

public abstract class SecureDirectoryStream
    implements DirectoryStream<Path>
{
    /**
     * Initialize a new instance of this class.
     */
    protected SecureDirectoryStream() { }

    /**
     * Opens the directory identified by the given path, returning a {@code
     * SecureDirectoryStream} to iterate over the entries in the directory.
     *
     * <p> This method works in exactly the manner specified by the {@link
     * Path#newDirectoryStream newDirectoryStream} method for the case that
     * the {@code path} parameter is an {@link Path#isAbsolute absolute} path.
     * When the parameter is a relative path then the directory to open is
     * relative to this open directory. The {@code followLinks} parameter
     * determines if links should be followed. If this parameter is {@code
     * false} and the file is a symbolic link then this method fails (by
     * throwing an I/O exception).
     *
     * <p> The new directory stream, once created, is not dependent upon the
     * directory stream used to create it. Closing this directory stream has no
     * effect upon newly created directory stream.
     *
     * @param   path
94
     *          the path to the directory to open
95 96 97
     * @param   followLinks
     *          {@code true} if the links should be followed
     * @param   filter
98
     *          the directory stream filter or {@code null}.
99
     *
100
     * @return  a new and open {@code SecureDirectoryStream} object
101 102
     *
     * @throws  ClosedDirectoryStreamException
103
     *          if the directory stream is closed
104
     * @throws  NotDirectoryException
105
     *          if the file could not otherwise be opened because it is not
106 107
     *          a directory <i>(optional specific exception)</i>
     * @throws  IOException
108
     *          if an I/O error occurs
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
     *          method is invoked to check read access to the directory.
     */
    public abstract SecureDirectoryStream newDirectoryStream(Path path,
                                                             boolean followLinks,
                                                             DirectoryStream.Filter<? super Path> filter)
        throws IOException;

    /**
     * Opens or creates a file in this directory, returning a seekable byte
     * channel to access the file.
     *
     * <p> This method works in exactly the manner specified by the {@link
     * Path#newByteChannel Path.newByteChannel} method for the
     * case that the {@code path} parameter is an {@link Path#isAbsolute absolute}
     * path. When the parameter is a relative path then the file to open or
     * create is relative to this open directory. In addition to the options
     * defined by the {@code Path.newByteChannel} method, the {@link
     * LinkOption#NOFOLLOW_LINKS NOFOLLOW_LINKS} option may be used to
     * ensure that this method fails if the file is a symbolic link.
     *
     * <p> The channel, once created, is not dependent upon the directory stream
     * used to create it. Closing this directory stream has no effect upon the
     * channel.
     *
     * @param   path
137
     *          the path of the file to open open or create
138
     * @param   options
139
     *          options specifying how the file is opened
140
     * @param   attrs
141
     *          an optional list of attributes to set atomically when creating
142 143 144
     *          the file
     *
     * @throws  ClosedDirectoryStreamException
145
     *          if the directory stream is closed
146
     * @throws  IllegalArgumentException
147
     *          if the set contains an invalid combination of options
148
     * @throws  UnsupportedOperationException
149
     *          if an unsupported open option is specified or the array contains
150 151
     *          attributes that cannot be set atomically when creating the file
     * @throws  FileAlreadyExistsException
152
     *          if a file of that name already exists and the {@link
153 154 155
     *          StandardOpenOption#CREATE_NEW CREATE_NEW} option is specified
     *          <i>(optional specific exception)</i>
     * @throws  IOException
156
     *          if an I/O error occurs
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, the {@link SecurityManager#checkRead(String) checkRead}
     *          method is invoked to check read access to the path if the file
     *          is opened for reading. The {@link SecurityManager#checkWrite(String)
     *          checkWrite} method is invoked to check write access to the path
     *          if the file is opened for writing.
     */
    public abstract SeekableByteChannel newByteChannel(Path path,
                                                       Set<? extends OpenOption> options,
                                                       FileAttribute<?>... attrs)
        throws IOException;

    /**
     * Deletes a file.
     *
     * <p> Unlike the {@link FileRef#delete delete()} method, this method
     * does not first examine the file to determine if the file is a directory.
     * Whether a directory is deleted by this method is system dependent and
     * therefore not specified. If the file is a symbolic-link then the link is
     * deleted (not the final target of the link). When the parameter is a
     * relative path then the file to delete is relative to this open directory.
     *
     * @param   path
181
     *          the path of the file to delete
182 183
     *
     * @throws  ClosedDirectoryStreamException
184
     *          if the directory stream is closed
185
     * @throws  NoSuchFileException
186
     *          if the file does not exist <i>(optional specific exception)</i>
187
     * @throws  IOException
188
     *          if an I/O error occurs
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, the {@link SecurityManager#checkDelete(String) checkDelete}
     *          method is invoked to check delete access to the file
     */
    public abstract void deleteFile(Path path) throws IOException;

    /**
     * Deletes a directory.
     *
     * <p> Unlike the {@link FileRef#delete delete()} method, this method
     * does not first examine the file to determine if the file is a directory.
     * Whether non-directories are deleted by this method is system dependent and
     * therefore not specified. When the parameter is a relative path then the
     * directory to delete is relative to this open directory.
     *
     * @param   path
206
     *          the path of the directory to delete
207 208
     *
     * @throws  ClosedDirectoryStreamException
209
     *          if the directory stream is closed
210
     * @throws  NoSuchFileException
211
     *          if the the directory does not exist <i>(optional specific exception)</i>
212
     * @throws  DirectoryNotEmptyException
213
     *          if the directory could not otherwise be deleted because it is
214 215
     *          not empty <i>(optional specific exception)</i>
     * @throws  IOException
216
     *          if an I/O error occurs
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, the {@link SecurityManager#checkDelete(String) checkDelete}
     *          method is invoked to check delete access to the directory
     */
    public abstract void deleteDirectory(Path path) throws IOException;

    /**
     * Move a file from this directory to another directory.
     *
     * <p> This method works in a similar manner to {@link Path#moveTo moveTo}
     * method when the {@link StandardCopyOption#ATOMIC_MOVE ATOMIC_MOVE} option
     * is specified. That is, this method moves a file as an atomic file system
     * operation. If the {@code srcpath} parameter is an {@link Path#isAbsolute
     * absolute} path then it locates the source file. If the parameter is a
     * relative path then it is located relative to this open directory. If
     * the {@code targetpath} parameter is absolute then it locates the target
     * file (the {@code targetdir} parameter is ignored). If the parameter is
     * a relative path it is located relative to the open directory identified
     * by the {@code targetdir} parameter. In all cases, if the target file
     * exists then it is implementation specific if it is replaced or this
     * method fails.
     *
     * @param   srcpath
241
     *          the name of the file to move
242
     * @param   targetdir
243
     *          the destination directory
244
     * @param   targetpath
245
     *          the name to give the file in the destination directory
246 247
     *
     * @throws  ClosedDirectoryStreamException
248
     *          if this or the target directory stream is closed
249
     * @throws  FileAlreadyExistsException
250
     *          if the file already exists in the target directory and cannot
251 252
     *          be replaced <i>(optional specific exception)</i>
     * @throws  AtomicMoveNotSupportedException
253
     *          if the file cannot be moved as an atomic file system operation
254
     * @throws  IOException
255
     *          if an I/O error occurs
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
     * @throws  SecurityException
     *          In the case of the default provider, and a security manager is
     *          installed, the {@link SecurityManager#checkWrite(String) checkWrite}
     *          method is invoked to check write access to both the source and
     *          target file.
     */
    public abstract void move(Path srcpath, SecureDirectoryStream targetdir, Path targetpath)
        throws IOException;

    /**
     * Returns a new file attribute view to access the file attributes of this
     * directory.
     *
     * <p> The resulting file attribute view can be used to read or update the
     * attributes of this (open) directory. The {@code type} parameter specifies
     * the type of the attribute view and the method returns an instance of that
     * type if supported. Invoking this method to obtain a {@link
     * BasicFileAttributeView} always returns an instance of that class that is
     * bound to this open directory.
     *
     * <p> The state of resulting file attribute view is intimately connected
     * to this directory stream. Once the directory stream is {@link #close closed},
     * then all methods to read or update attributes will throw {@link
     * ClosedDirectoryStreamException ClosedDirectoryStreamException}.
     *
     * @param   type
282
     *          the {@code Class} object corresponding to the file attribute view
283
     *
284
     * @return  a new file attribute view of the specified type bound to
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
     *          this directory stream, or {@code null} if the attribute view
     *          type is not available
     */
    public abstract <V extends FileAttributeView> V getFileAttributeView(Class<V> type);

    /**
     * Returns a new file attribute view to access the file attributes of a file
     * in this directory.
     *
     * <p> The resulting file attribute view can be used to read or update the
     * attributes of file in this directory. The {@code type} parameter specifies
     * the type of the attribute view and the method returns an instance of that
     * type if supported. Invoking this method to obtain a {@link
     * BasicFileAttributeView} always returns an instance of that class that is
     * bound to the file in the directory.
     *
     * <p> The state of resulting file attribute view is intimately connected
     * to this directory stream. Once the directory stream {@link #close closed},
     * then all methods to read or update attributes will throw {@link
     * ClosedDirectoryStreamException ClosedDirectoryStreamException}. The
     * file is not required to exist at the time that the file attribute view
     * is created but methods to read or update attributes of the file will
     * fail when invoked and the file does not exist.
     *
     * @param   path
310
     *          the path of the file
311
     * @param   type
312
     *          the {@code Class} object corresponding to the file attribute view
313
     * @param   options
314
     *          options indicating how symbolic links are handled
315
     *
316
     * @return  a new file attribute view of the specified type bound to a
317 318 319 320 321 322 323 324
     *          this directory stream, or {@code null} if the attribute view
     *          type is not available
     *
     */
    public abstract <V extends FileAttributeView> V getFileAttributeView(Path path,
                                                                         Class<V> type,
                                                                         LinkOption... options);
}