1/*
2 * Copyright (c) 2002, 2013, 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 4759207 4403166 4165006 4403166 6182812 6274272 7160013
26   @summary Test to see if win32 path length can be greater than 260
27 */
28
29import java.io.*;
30import java.nio.file.Files;
31import java.nio.file.Path;
32import java.nio.file.DirectoryNotEmptyException;
33
34public class MaxPathLength {
35    private static String sep = File.separator;
36    private static String pathComponent = sep +
37        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
38    private static String fileName =
39                 "areallylongfilenamethatsforsur";
40    private static boolean isWindows = false;
41
42    private static final int MAX_LENGTH = 256;
43
44    private static int counter = 0;
45
46    public static void main(String[] args) throws Exception {
47        String osName = System.getProperty("os.name");
48        if (osName.startsWith("Windows")) {
49            isWindows = true;
50        }
51
52        for (int i = 4; i < 7; i++) {
53            String name = fileName;
54            while (name.length() < MAX_LENGTH) {
55                testLongPath (i, name, false);
56                testLongPath (i, name, true);
57                name = getNextName(name);
58            }
59        }
60
61        // test long paths on windows
62        // And these long pathes cannot be handled on Solaris and Mac platforms
63        if (isWindows) {
64            String name = fileName;
65            while (name.length() < MAX_LENGTH) {
66                testLongPath (20, name, false);
67                testLongPath (20, name, true);
68                name = getNextName(name);
69            }
70        }
71    }
72
73    private static String getNextName(String fName) {
74        return (fName.length() < MAX_LENGTH/2) ? fName + fName
75                                               : fName + "A";
76    }
77
78    static void testLongPath(int max, String fn,
79                             boolean tryAbsolute) throws Exception {
80        String[] created = new String[max];
81        String pathString = ".";
82        for (int i = 0; i < max -1; i++) {
83            pathString = pathString + pathComponent + (counter++);
84            created[max - 1 -i] = pathString;
85        }
86
87        File dirFile = new File(pathString);
88        File f = new File(pathString + sep + fn);
89
90        String tPath = f.getPath();
91        if (tryAbsolute) {
92            tPath = f.getCanonicalPath();
93        }
94        created[0] = tPath;
95
96        //for getCanonicalPath testing on win32
97        File fu = new File(pathString + sep + fn.toUpperCase());
98
99        if (dirFile.exists()) {
100            System.err.println("Warning: Test directory structure exists already!");
101            return;
102        }
103
104        try {
105            Files.createDirectories(dirFile.toPath());
106
107            if (tryAbsolute)
108                dirFile = new File(dirFile.getCanonicalPath());
109            if (!dirFile.isDirectory())
110                throw new RuntimeException ("File.isDirectory() failed");
111            f = new File(tPath);
112            if (!f.createNewFile()) {
113                throw new RuntimeException ("File.createNewFile() failed");
114            }
115
116            if (!f.exists())
117                throw new RuntimeException ("File.exists() failed");
118            if (!f.isFile())
119                throw new RuntimeException ("File.isFile() failed");
120            if (!f.canRead())
121                throw new RuntimeException ("File.canRead() failed");
122            if (!f.canWrite())
123                throw new RuntimeException ("File.canWrite() failed");
124
125            if (!f.delete())
126                throw new RuntimeException ("File.delete() failed");
127
128            FileOutputStream fos = new FileOutputStream(f);
129            fos.write(1);
130            fos.close();
131
132            if (f.length() != 1)
133                throw new RuntimeException ("File.length() failed");
134            long time = System.currentTimeMillis();
135            if (!f.setLastModified(time))
136                throw new RuntimeException ("File.setLastModified() failed");
137            if (f.lastModified() == 0) {
138                throw new RuntimeException ("File.lastModified() failed");
139            }
140            String[] list = dirFile.list();
141            if (list == null || !fn.equals(list[0])) {
142                throw new RuntimeException ("File.list() failed");
143            }
144
145            File[] flist = dirFile.listFiles();
146            if (flist == null || !fn.equals(flist[0].getName()))
147                throw new RuntimeException ("File.listFiles() failed");
148
149            if (isWindows &&
150                !fu.getCanonicalPath().equals(f.getCanonicalPath()))
151                throw new RuntimeException ("getCanonicalPath() failed");
152
153            char[] cc = tPath.toCharArray();
154            cc[cc.length-1] = 'B';
155            File nf = new File(new String(cc));
156            if (!f.renameTo(nf)) {
157                /*there is a known issue that renameTo fails if
158                  (1)the path is a UNC path and
159                  (2)the path length is bigger than 1092
160                  so don't stop if above are true
161                */
162                String abPath = f.getAbsolutePath();
163                if (!abPath.startsWith("\\\\") ||
164                    abPath.length() < 1093) {
165                    throw new RuntimeException ("File.renameTo() failed for lenth="
166                                                + abPath.length());
167                }
168            } else {
169                if (!nf.canRead())
170                    throw new RuntimeException ("Renamed file is not readable");
171                if (!nf.canWrite())
172                    throw new RuntimeException ("Renamed file is not writable");
173                if (nf.length() != 1)
174                    throw new RuntimeException ("Renamed file's size is not correct");
175                if (!nf.renameTo(f)) {
176                    created[0] = nf.getPath();
177                }
178                /* add a script to test these two if we got a regression later
179                if (!f.setReadOnly())
180                    throw new RuntimeException ("File.setReadOnly() failed");
181                f.deleteOnExit();
182                */
183            }
184        } finally {
185            // Clean up
186            for (int i = 0; i < max; i++) {
187                Path p = (new File(created[i])).toPath();
188                try {
189                    Files.deleteIfExists(p);
190                    // Test if the file is really deleted and wait for 1 second at most
191                    for (int j = 0; j < 10 && Files.exists(p); j++) {
192                        Thread.sleep(100);
193                    }
194                } catch (DirectoryNotEmptyException ex) {
195                    // Give up the clean-up, let jtreg handle it.
196                    System.err.println("Dir, " + p + ", is not empty");
197                    break;
198                }
199            }
200        }
201    }
202}
203