1111import android .view .WindowManager ;
1212
1313import com .termux .R ;
14+ import com .termux .app .file .FileUtils ;
1415import com .termux .app .utils .Logger ;
1516
1617import java .io .BufferedReader ;
1718import java .io .ByteArrayInputStream ;
1819import java .io .File ;
1920import java .io .FileOutputStream ;
20- import java .io .IOException ;
2121import java .io .InputStreamReader ;
2222import java .util .ArrayList ;
2323import java .util .List ;
3232 * <p/>
3333 * (2) A progress dialog is shown with "Installing..." message and a spinner.
3434 * <p/>
35- * (3) A staging directory, $STAGING_PREFIX, is {@link #deleteDirectory(File)} if left over from broken installation below.
35+ * (3) A staging directory, $STAGING_PREFIX, is cleared if left over from broken installation below.
3636 * <p/>
3737 * (4) The zip file is loaded from a shared library.
3838 * <p/>
@@ -47,10 +47,8 @@ final class TermuxInstaller {
4747
4848 private static final String LOG_TAG = "TermuxInstaller" ;
4949
50- /** Performs setup if necessary. */
51- static void setupIfNeeded (final Activity activity , final Runnable whenDone ) {
52- Logger .logInfo (LOG_TAG , "Installing " + TermuxConstants .TERMUX_APP_NAME + " bootstrap packages." );
53-
50+ /** Performs bootstrap setup if necessary. */
51+ static void setupBootstrapIfNeeded (final Activity activity , final Runnable whenDone ) {
5452 // Termux can only be run as the primary user (device owner) since only that
5553 // account has the expected file system paths. Verify that:
5654 UserManager um = (UserManager ) activity .getSystemService (Context .USER_SERVICE );
@@ -63,7 +61,6 @@ static void setupIfNeeded(final Activity activity, final Runnable whenDone) {
6361 return ;
6462 }
6563
66- Logger .logInfo (LOG_TAG , "Creating prefix directory \" " + TermuxConstants .TERMUX_PREFIX_DIR_PATH + "\" ." );
6764 final File PREFIX_FILE = TermuxConstants .TERMUX_PREFIX_DIR ;
6865 if (PREFIX_FILE .isDirectory ()) {
6966 whenDone .run ();
@@ -75,12 +72,16 @@ static void setupIfNeeded(final Activity activity, final Runnable whenDone) {
7572 @ Override
7673 public void run () {
7774 try {
75+ Logger .logInfo (LOG_TAG , "Installing " + TermuxConstants .TERMUX_APP_NAME + " bootstrap packages." );
76+
77+ String errmsg ;
78+
7879 final String STAGING_PREFIX_PATH = TermuxConstants .TERMUX_STAGING_PREFIX_DIR_PATH ;
7980 final File STAGING_PREFIX_FILE = new File (STAGING_PREFIX_PATH );
8081
81- if ( STAGING_PREFIX_FILE . exists ()) {
82- Logger . logInfo ( LOG_TAG , "Deleting prefix staging directory \" " + TermuxConstants . TERMUX_STAGING_PREFIX_DIR_PATH + " \" ." );
83- deleteDirectory ( STAGING_PREFIX_FILE );
82+ errmsg = FileUtils . clearDirectory ( activity , "prefix staging directory" , STAGING_PREFIX_PATH );
83+ if ( errmsg != null ) {
84+ throw new RuntimeException ( errmsg );
8485 }
8586
8687 Logger .logInfo (LOG_TAG , "Extracting bootstrap zip to prefix staging directory \" " + TermuxConstants .TERMUX_STAGING_PREFIX_DIR_PATH + "\" ." );
@@ -103,14 +104,14 @@ public void run() {
103104 String newPath = STAGING_PREFIX_PATH + "/" + parts [1 ];
104105 symlinks .add (Pair .create (oldPath , newPath ));
105106
106- ensureDirectoryExists (new File (newPath ).getParentFile ());
107+ ensureDirectoryExists (activity , new File (newPath ).getParentFile ());
107108 }
108109 } else {
109110 String zipEntryName = zipEntry .getName ();
110111 File targetFile = new File (STAGING_PREFIX_PATH , zipEntryName );
111112 boolean isDirectory = zipEntry .isDirectory ();
112113
113- ensureDirectoryExists (isDirectory ? targetFile : targetFile .getParentFile ());
114+ ensureDirectoryExists (activity , isDirectory ? targetFile : targetFile .getParentFile ());
114115
115116 if (!isDirectory ) {
116117 try (FileOutputStream outStream = new FileOutputStream (targetFile )) {
@@ -151,7 +152,7 @@ public void run() {
151152 activity .finish ();
152153 }).setPositiveButton (R .string .bootstrap_error_try_again , (dialog , which ) -> {
153154 dialog .dismiss ();
154- TermuxInstaller .setupIfNeeded (activity , whenDone );
155+ TermuxInstaller .setupBootstrapIfNeeded (activity , whenDone );
155156 }).show ();
156157 } catch (WindowManager .BadTokenException e1 ) {
157158 // Activity already dismissed - ignore.
@@ -170,37 +171,6 @@ public void run() {
170171 }.start ();
171172 }
172173
173- private static void ensureDirectoryExists (File directory ) {
174- if (!directory .isDirectory () && !directory .mkdirs ()) {
175- throw new RuntimeException ("Unable to create directory: " + directory .getAbsolutePath ());
176- }
177- }
178-
179- public static byte [] loadZipBytes () {
180- // Only load the shared library when necessary to save memory usage.
181- System .loadLibrary ("termux-bootstrap" );
182- return getZip ();
183- }
184-
185- public static native byte [] getZip ();
186-
187- /** Delete a directory and all its content or throw. Don't follow symlinks. */
188- static void deleteDirectory (File fileOrDirectory ) throws IOException {
189- if (fileOrDirectory .getCanonicalPath ().equals (fileOrDirectory .getAbsolutePath ()) && fileOrDirectory .isDirectory ()) {
190- File [] children = fileOrDirectory .listFiles ();
191-
192- if (children != null ) {
193- for (File child : children ) {
194- deleteDirectory (child );
195- }
196- }
197- }
198-
199- if (!fileOrDirectory .delete ()) {
200- throw new RuntimeException ("Unable to delete " + (fileOrDirectory .isDirectory () ? "directory " : "file " ) + fileOrDirectory .getAbsolutePath ());
201- }
202- }
203-
204174 static void setupStorageSymlinks (final Context context ) {
205175 final String LOG_TAG = "termux-storage" ;
206176
@@ -209,19 +179,12 @@ static void setupStorageSymlinks(final Context context) {
209179 new Thread () {
210180 public void run () {
211181 try {
182+ String errmsg ;
212183 File storageDir = TermuxConstants .TERMUX_STORAGE_HOME_DIR ;
213184
214- if (storageDir .exists ()) {
215- try {
216- deleteDirectory (storageDir );
217- } catch (IOException e ) {
218- Logger .logStackTraceWithMessage (LOG_TAG , "Failed to delete old ~/storage directory" , e );
219- return ;
220- }
221- }
222-
223- if (!storageDir .mkdirs ()) {
224- Logger .logError (LOG_TAG , "Unable to create ~/storage directory." );
185+ errmsg = FileUtils .clearDirectory (context , "~/storage" , storageDir .getAbsolutePath ());
186+ if (errmsg != null ) {
187+ Logger .logErrorAndShowToast (context , LOG_TAG , errmsg );
225188 return ;
226189 }
227190
@@ -264,4 +227,21 @@ public void run() {
264227 }.start ();
265228 }
266229
230+ private static void ensureDirectoryExists (Context context , File directory ) {
231+ String errmsg ;
232+
233+ errmsg = FileUtils .createDirectoryFile (context , directory .getAbsolutePath ());
234+ if (errmsg != null ) {
235+ throw new RuntimeException (errmsg );
236+ }
237+ }
238+
239+ public static byte [] loadZipBytes () {
240+ // Only load the shared library when necessary to save memory usage.
241+ System .loadLibrary ("termux-bootstrap" );
242+ return getZip ();
243+ }
244+
245+ public static native byte [] getZip ();
246+
267247}
0 commit comments