• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * [The "BSD licence"]
3  * Copyright (c) 2010 Ben Gruver
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 package com.android.tools.smali.util;
29 
30 import com.google.common.collect.Lists;
31 
32 import java.io.File;
33 import java.io.FileNotFoundException;
34 import java.io.FileReader;
35 import java.io.FileWriter;
36 import java.io.IOException;
37 import java.nio.CharBuffer;
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 public class PathUtil {
PathUtil()42     private PathUtil() {
43     }
44 
getRelativeFile(File baseFile, File fileToRelativize)45     public static File getRelativeFile(File baseFile, File fileToRelativize) throws IOException {
46         if (baseFile.isFile()) {
47             baseFile = baseFile.getParentFile();
48         }
49 
50         return new File(getRelativeFileInternal(baseFile.getCanonicalFile(), fileToRelativize.getCanonicalFile()));
51     }
52 
getRelativeFileInternal(File canonicalBaseFile, File canonicalFileToRelativize)53     static String getRelativeFileInternal(File canonicalBaseFile, File canonicalFileToRelativize) {
54         List<String> basePath = getPathComponents(canonicalBaseFile);
55         List<String> pathToRelativize = getPathComponents(canonicalFileToRelativize);
56 
57         //if the roots aren't the same (i.e. different drives on a windows machine), we can't construct a relative
58         //path from one to the other, so just return the canonical file
59         if (!basePath.get(0).equals(pathToRelativize.get(0))) {
60             return canonicalFileToRelativize.getPath();
61         }
62 
63         int commonDirs;
64         StringBuilder sb = new StringBuilder();
65 
66         for (commonDirs=1; commonDirs<basePath.size() && commonDirs<pathToRelativize.size(); commonDirs++) {
67             if (!basePath.get(commonDirs).equals(pathToRelativize.get(commonDirs))) {
68                 break;
69             }
70         }
71 
72         boolean first = true;
73         for (int i=commonDirs; i<basePath.size(); i++) {
74             if (!first) {
75                 sb.append(File.separatorChar);
76             } else {
77                 first = false;
78             }
79 
80             sb.append("..");
81         }
82 
83         first = true;
84         for (int i=commonDirs; i<pathToRelativize.size(); i++) {
85             if (first) {
86                 if (sb.length() != 0) {
87                     sb.append(File.separatorChar);
88                 }
89                 first = false;
90             } else {
91                 sb.append(File.separatorChar);
92             }
93 
94             sb.append(pathToRelativize.get(i));
95         }
96 
97         if (sb.length() == 0) {
98             return ".";
99         }
100 
101         return sb.toString();
102     }
103 
getPathComponents(File file)104     private static List<String> getPathComponents(File file) {
105         ArrayList<String> path = new ArrayList<String>();
106 
107         while (file != null) {
108             File parentFile = file.getParentFile();
109 
110             if (parentFile == null) {
111                 path.add(file.getPath());
112             } else {
113                 path.add(file.getName());
114             }
115 
116             file = parentFile;
117         }
118 
119         return Lists.reverse(path);
120     }
121 
testCaseSensitivity(File path)122     public static boolean testCaseSensitivity(File path) throws IOException {
123         int num = 1;
124         File f, f2;
125         do {
126             f = new File(path, "test." + num);
127             f2 = new File(path, "TEST." + num++);
128         } while(f.exists() || f2.exists());
129 
130         try {
131             try {
132                 FileWriter writer = new FileWriter(f);
133                 writer.write("test");
134                 writer.flush();
135                 writer.close();
136             } catch (IOException ex) {
137                 try {f.delete();} catch (Exception ex2) {}
138                 throw ex;
139             }
140 
141             if (f2.exists()) {
142                 return false;
143             }
144 
145             if (f2.createNewFile()) {
146                 return true;
147             }
148 
149             //the above 2 tests should catch almost all cases. But maybe there was a failure while creating f2
150             //that isn't related to case sensitivity. Let's see if we can open the file we just created using
151             //f2
152             try {
153                 CharBuffer buf = CharBuffer.allocate(32);
154                 FileReader reader = new FileReader(f2);
155 
156                 while (reader.read(buf) != -1 && buf.length() < 4);
157                 if (buf.length() == 4 && buf.toString().equals("test")) {
158                     return false;
159                 } else {
160                     //we probably shouldn't get here. If the filesystem was case-sensetive, creating a new
161                     //FileReader should have thrown a FileNotFoundException. Otherwise, we should have opened
162                     //the file and read in the string "test". It's remotely possible that someone else modified
163                     //the file after we created it. Let's be safe and return false here as well
164                     assert(false);
165                     return false;
166                 }
167             } catch (FileNotFoundException ex) {
168                 return true;
169             }
170         } finally {
171             try { f.delete(); } catch (Exception ex) {}
172             try { f2.delete(); } catch (Exception ex) {}
173         }
174     }
175 }
176