1 /*
   2  * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25  * @bug 8139133
  26  * @summary Verify ability to set time attributes of socket files with no device
  27  * @requires os.family == "linux"
  28  */
  29 
  30 import java.io.File;
  31 import java.io.InputStream;
  32 import java.io.IOException;
  33 import java.nio.file.FileSystem;
  34 import java.nio.file.FileSystems;
  35 import java.nio.file.Files;
  36 import java.nio.file.Path;
  37 import java.nio.file.Paths;
  38 import java.nio.file.StandardWatchEventKinds;
  39 import java.nio.file.WatchKey;
  40 import java.nio.file.WatchService;
  41 import java.nio.file.attribute.BasicFileAttributeView;
  42 import java.nio.file.attribute.BasicFileAttributes;
  43 import java.nio.file.attribute.FileTime;
  44 
  45 public class UnixSocketFile {
  46     private static final String TEST_SUB_DIR = "UnixSocketFile";
  47     private static final String SOCKET_FILE_NAME = "mysocket";
  48     private static final String CMD_BASE = "nc -lU";
  49 
  50     public static void main(String[] args)
  51         throws InterruptedException, IOException {
  52 
  53         // Use 'which' to verify that 'nc' is available and skip the test
  54         // if it is not.
  55         Process proc = Runtime.getRuntime().exec("which nc");
  56         InputStream stdout = proc.getInputStream();
  57         int b = stdout.read();
  58         proc.destroy();
  59         if (b == -1) {
  60             System.err.println("Netcat command unavailable; skipping test.");
  61             return;
  62         }
  63 
  64         // Create a new sub-directory of the nominal test directory in which
  65         // 'nc' will create the socket file.
  66         String testSubDir = System.getProperty("test.dir", ".")
  67             + File.separator + TEST_SUB_DIR;
  68         Path socketTestDir = Paths.get(testSubDir);
  69         Files.createDirectory(socketTestDir);
  70 
  71         // Set the path of the socket file.
  72         String socketFilePath = testSubDir + File.separator
  73             + SOCKET_FILE_NAME;
  74 
  75         // Create a process which executes the nc (netcat) utility to create
  76         // a socket file at the indicated location.
  77         FileSystem fs = FileSystems.getDefault();
  78         try (WatchService ws = fs.newWatchService()) {
  79             // Watch the test sub-directory to receive notification when an
  80             // entry, i.e., the socket file, is added to the sub-directory.
  81             WatchKey wk = socketTestDir.register(ws,
  82                     StandardWatchEventKinds.ENTRY_CREATE);
  83 
  84             // Execute the 'nc' command.
  85             proc = Runtime.getRuntime().exec(CMD_BASE + " " + socketFilePath);
  86 
  87             // Wait until the socket file is created.
  88             WatchKey key = ws.take();
  89             if (key != wk) {
  90                 throw new RuntimeException("Unknown entry created - expected: "
  91                     + wk.watchable() + ", actual: " + key.watchable());
  92             }
  93             wk.cancel();
  94         }
  95 
  96         // Verify that the socket file in fact exists.
  97         Path socketPath = fs.getPath(socketFilePath);
  98         if (!Files.exists(socketPath)) {
  99             throw new RuntimeException("Socket file " + socketFilePath
 100                 + " was not created by \"nc\" command.");
 101         }
 102 
 103         // Retrieve the most recent access and modification times of the
 104         // socket file; print the values.
 105         BasicFileAttributeView attributeView = Files.getFileAttributeView(
 106                 socketPath, BasicFileAttributeView.class);
 107         BasicFileAttributes oldAttributes = attributeView.readAttributes();
 108         FileTime oldAccessTime = oldAttributes.lastAccessTime();
 109         FileTime oldModifiedTime = oldAttributes.lastModifiedTime();
 110         System.out.println("Old times: " + oldAccessTime
 111             + " " + oldModifiedTime);
 112 
 113         // Calculate the time to which the access and modification times of the
 114         // socket file will be changed.
 115         FileTime newFileTime =
 116             FileTime.fromMillis(oldAccessTime.toMillis() + 1066);
 117 
 118         try {
 119             // Set the access and modification times of the socket file.
 120             attributeView.setTimes(newFileTime, newFileTime, null);
 121 
 122             // Retrieve the updated access and modification times of the
 123             // socket file; print the values.
 124             FileTime newAccessTime = null;
 125             FileTime newModifiedTime = null;
 126             BasicFileAttributes newAttributes = attributeView.readAttributes();
 127             newAccessTime = newAttributes.lastAccessTime();
 128             newModifiedTime = newAttributes.lastModifiedTime();
 129             System.out.println("New times: " + newAccessTime + " "
 130                 + newModifiedTime);
 131 
 132             // Verify that the updated times have the expected values.
 133             if ((newAccessTime != null && !newAccessTime.equals(newFileTime))
 134                 || (newModifiedTime != null
 135                     && !newModifiedTime.equals(newFileTime))) {
 136                 throw new RuntimeException("Failed to set correct times.");
 137             }
 138         } finally {
 139             // Destry the process running netcat and delete the socket file.
 140             proc.destroy();
 141             Files.delete(socketPath);
 142         }
 143     }
 144 }