diff --git a/app/src/main/java/com/termux/app/RunCommandService.java b/app/src/main/java/com/termux/app/RunCommandService.java
index bc4d6451..f54f1693 100644
--- a/app/src/main/java/com/termux/app/RunCommandService.java
+++ b/app/src/main/java/com/termux/app/RunCommandService.java
@@ -148,7 +148,6 @@ public class RunCommandService extends Service {
FileUtils.APP_EXECUTABLE_FILE_PERMISSIONS, true, true,
false);
if (error != null) {
- error.appendMessage("\n" + this.getString(R.string.msg_executable_absolute_path, executionCommand.executable));
executionCommand.setStateFailed(error);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
@@ -170,7 +169,6 @@ public class RunCommandService extends Service {
true, true, true,
false, true);
if (error != null) {
- error.appendMessage("\n" + this.getString(R.string.msg_working_directory_absolute_path, executionCommand.workingDirectory));
executionCommand.setStateFailed(error);
PluginUtils.processPluginExecutionCommandError(this, LOG_TAG, executionCommand, false);
return stopService();
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 6b37c06b..192eddd5 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -111,12 +111,6 @@
-
- Executable Absolute Path: \"%1$s\"
- Working Directory Absolute Path: \"%1$s\"
-
-
-
Save file in ~/downloads/
Edit
diff --git a/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java b/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java
index dd057e4c..c1b5b6fd 100644
--- a/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java
+++ b/termux-shared/src/main/java/com/termux/shared/file/FileUtils.java
@@ -10,6 +10,7 @@ import com.termux.shared.file.filesystem.FileType;
import com.termux.shared.file.filesystem.FileTypes;
import com.termux.shared.data.DataUtils;
import com.termux.shared.logger.Logger;
+import com.termux.shared.models.errors.Errno;
import com.termux.shared.models.errors.Error;
import com.termux.shared.models.errors.FileUtilsErrno;
import com.termux.shared.models.errors.FunctionErrno;
@@ -34,6 +35,7 @@ import java.nio.file.LinkOption;
import java.nio.file.StandardCopyOption;
import java.util.Calendar;
import java.util.Iterator;
+import java.util.List;
import java.util.regex.Pattern;
public class FileUtils {
@@ -260,7 +262,7 @@ public class FileUtils {
// If file exists but not a regular file
if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) {
- return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file");
+ return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file");
}
boolean isPathUnderParentDirPath = false;
@@ -283,7 +285,8 @@ public class FileUtils {
// If path is not a regular file
// Regular files cannot be automatically created so we do not ignore if missing
if (fileType != FileType.REGULAR) {
- return FileUtilsErrno.ERRNO_NO_REGULAR_FILE_FOUND.getError(label + "file");
+ label += "regular file";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label);
}
// If there is not parentDirPath restriction or path is not under parentDirPath or
@@ -341,7 +344,7 @@ public class FileUtils {
// If file exists but not a directory file
if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) {
- return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory");
+ return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory");
}
boolean isPathInParentDirPath = false;
@@ -380,7 +383,8 @@ public class FileUtils {
// If path is not a directory
// Directories can be automatically created so we can ignore if missing with above check
if (fileType != FileType.DIRECTORY) {
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "directory", filePath);
+ label += "directory";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label);
}
if (permissionsToCheck != null) {
@@ -455,7 +459,7 @@ public class FileUtils {
// If file exists but not a regular file
if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) {
- return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file");
+ return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file");
}
// If regular file already exists
@@ -645,8 +649,10 @@ public class FileUtils {
// If target file does not exist
if (targetFileType == FileType.NO_EXIST) {
// If dangling symlink should not be allowed, then return with error
- if (!allowDangling)
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "symlink target file", targetFileAbsolutePath);
+ if (!allowDangling) {
+ label += "symlink target file";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, targetFileAbsolutePath).setLabel(label);
+ }
}
// If destination exists
@@ -920,8 +926,10 @@ public class FileUtils {
if (ignoreNonExistentSrcFile)
return null;
// Else return with error
- else
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "source file", srcFilePath);
+ else {
+ label += "source file";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, srcFilePath).setLabel(label);
+ }
}
// If the file type of the source file does not exist in the allowedFileTypeFlags, then return with error
@@ -1121,8 +1129,10 @@ public class FileUtils {
if (ignoreNonExistentFile)
return null;
// Else return with error
- else
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be deleted", filePath);
+ else {
+ label += "file meant to be deleted";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label);
+ }
}
// If the file type of the file does not exist in the allowedFileTypeFlags
@@ -1224,7 +1234,7 @@ public class FileUtils {
// If file exists but not a directory file
if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) {
- return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory");
+ return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory");
}
// If directory exists, clear its contents
@@ -1288,7 +1298,7 @@ public class FileUtils {
// If file exists but not a directory file
if (fileType != FileType.NO_EXIST && fileType != FileType.DIRECTORY) {
- return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory");
+ return FileUtilsErrno.ERRNO_NON_DIRECTORY_FILE_FOUND.getError(label + "directory", filePath).setLabel(label + "directory");
}
// If file does not exist
@@ -1297,8 +1307,10 @@ public class FileUtils {
if (ignoreNonExistentFile)
return null;
// Else return with error
- else
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "directory under which files had to be deleted", filePath);
+ else {
+ label += "directory under which files had to be deleted";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label);
+ }
}
// If directory exists, delete its contents
@@ -1349,7 +1361,7 @@ public class FileUtils {
// If file exists but not a regular file
if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) {
- return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file");
+ return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file");
}
// If file does not exist
@@ -1358,8 +1370,10 @@ public class FileUtils {
if (ignoreNonExistentFile)
return null;
// Else return with error
- else
- return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be read", filePath);
+ else {
+ label += "file meant to be read";
+ return FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label);
+ }
}
if (charset == null) charset = Charset.defaultCharset();
@@ -1428,7 +1442,7 @@ public class FileUtils {
// If file exists but not a regular file
if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) {
- return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file"), null);
+ return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file"), null);
}
// If file does not exist
@@ -1437,8 +1451,10 @@ public class FileUtils {
if (ignoreNonExistentFile)
return new ReadSerializableObjectResult(null, null);
// Else return with error
- else
- return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label + "file meant to be read", filePath), null);
+ else {
+ label += "file meant to be read";
+ return new ReadSerializableObjectResult(FileUtilsErrno.ERRNO_FILE_NOT_FOUND_AT_PATH.getError(label, filePath).setLabel(label), null);
+ }
}
FileInputStream fileInputStream = null;
@@ -1556,7 +1572,7 @@ public class FileUtils {
// If file exists but not a regular file
if (fileType != FileType.NO_EXIST && fileType != FileType.REGULAR) {
- return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file");
+ return FileUtilsErrno.ERRNO_NON_REGULAR_FILE_FOUND.getError(label + "file", filePath).setLabel(label + "file");
}
// Create the file parent directory
@@ -1764,17 +1780,17 @@ public class FileUtils {
// If file is not readable
if (permissionsToCheck.contains("r") && !file.canRead()) {
- return FileUtilsErrno.ERRNO_FILE_NOT_READABLE.getError(label + "file");
+ return FileUtilsErrno.ERRNO_FILE_NOT_READABLE.getError(label + "file", filePath).setLabel(label + "file");
}
// If file is not writable
if (permissionsToCheck.contains("w") && !file.canWrite()) {
- return FileUtilsErrno.ERRNO_FILE_NOT_WRITABLE.getError(label + "file");
+ return FileUtilsErrno.ERRNO_FILE_NOT_WRITABLE.getError(label + "file", filePath).setLabel(label + "file");
}
// If file is not executable
// This canExecute() will give "avc: granted { execute }" warnings for target sdk 29
else if (permissionsToCheck.contains("x") && !file.canExecute() && !ignoreIfNotExecutable) {
- return FileUtilsErrno.ERRNO_FILE_NOT_EXECUTABLE.getError(label + "file");
+ return FileUtilsErrno.ERRNO_FILE_NOT_EXECUTABLE.getError(label + "file", filePath).setLabel(label + "file");
}
return null;
@@ -1794,4 +1810,26 @@ public class FileUtils {
return Pattern.compile("^([r-])[w-][x-]$", 0).matcher(string).matches();
}
+
+
+ /**
+ * Get a {@link Error} that contains a shorter version of {@link Errno} message.
+ *
+ * @param error The original {@link Error} returned by one of the {@link FileUtils} functions.
+ * @return Returns the shorter {@link Error} if one exists, otherwise original {@code error}.
+ */
+ public static Error getShortFileUtilsError(final Error error) {
+ String type = error.getType();
+ if (!FileUtilsErrno.TYPE.equals(type)) return error;
+
+ Errno shortErrno = FileUtilsErrno.ERRNO_SHORT_MAPPING.get(Errno.valueOf(type, error.getCode()));
+ if (shortErrno == null) return error;
+
+ List throwables = error.getThrowablesList();
+ if (throwables.isEmpty())
+ return shortErrno.getError(DataUtils.getDefaultIfNull(error.getLabel(), "file"));
+ else
+ return shortErrno.getError(throwables, error.getLabel(), "file");
+ }
+
}
diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java b/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java
index ce4c702d..d330787c 100644
--- a/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java
+++ b/termux-shared/src/main/java/com/termux/shared/models/errors/Errno.java
@@ -8,11 +8,14 @@ import com.termux.shared.logger.Logger;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
/** The {@link Class} that defines error messages and codes. */
public class Errno {
+ private static final HashMap map = new HashMap<>();
+
public static final String TYPE = "Error";
@@ -35,6 +38,7 @@ public class Errno {
this.type = type;
this.code = code;
this.message = message;
+ map.put(type + ":" + code, this);
}
@NonNull
@@ -56,6 +60,17 @@ public class Errno {
return code;
}
+ /**
+ * Get the {@link Errno} of a specific type and code.
+ *
+ * @param type The unique type of the {@link Errno}.
+ * @param code The unique code of the {@link Errno}.
+ */
+ public static Errno valueOf(String type, Integer code) {
+ if (type == null || type.isEmpty() || code == null) return null;
+ return map.get(type + ":" + code);
+ }
+
public Error getError() {
@@ -73,12 +88,18 @@ public class Errno {
}
public Error getError(Throwable throwable, Object... args) {
- return getError(Collections.singletonList(throwable), args);
+ if (throwable == null)
+ return getError(args);
+ else
+ return getError(Collections.singletonList(throwable), args);
}
public Error getError(List throwablesList, Object... args) {
try {
- return new Error(getType(), getCode(), String.format(getMessage(), args), throwablesList);
+ if (throwablesList == null)
+ return new Error(getType(), getCode(), String.format(getMessage(), args));
+ else
+ return new Error(getType(), getCode(), String.format(getMessage(), args), throwablesList);
} catch (Exception e) {
Logger.logWarn(LOG_TAG, "Exception raised while calling String.format() for error message of errno " + this + " with args" + Arrays.toString(args) + "\n" + e.getMessage());
// Return unformatted message as a backup
diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java b/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java
index b9dba33f..f74f4485 100644
--- a/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java
+++ b/termux-shared/src/main/java/com/termux/shared/models/errors/Error.java
@@ -12,6 +12,8 @@ import java.util.List;
public class Error implements Serializable {
+ /** The optional error label. */
+ private String label;
/** The error type. */
private String type;
/** The error code. */
@@ -76,7 +78,18 @@ public class Error implements Serializable {
this.code = Errno.ERRNO_SUCCESS.getCode();
this.message = message;
- this.throwablesList = throwablesList;
+
+ if (throwablesList != null)
+ this.throwablesList = throwablesList;
+ }
+
+ public Error setLabel(String label) {
+ this.label = label;
+ return this;
+ }
+
+ public String getLabel() {
+ return label;
}
diff --git a/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java b/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java
index 48b4b096..f8c701d8 100644
--- a/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java
+++ b/termux-shared/src/main/java/com/termux/shared/models/errors/FileUtilsErrno.java
@@ -1,5 +1,8 @@
package com.termux.shared.models.errors;
+import java.util.HashMap;
+import java.util.Map;
+
/** The {@link Class} that defines FileUtils error messages and codes. */
public class FileUtilsErrno extends Errno {
@@ -18,19 +21,20 @@ public class FileUtilsErrno extends Errno {
/* Errors for invalid or not found files at path (150-200) */
- public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH = new Errno(TYPE, 150, "The %1$s is not found at path \"%2$s\".");
+ public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH = new Errno(TYPE, 150, "The %1$s not found at path \"%2$s\".");
+ public static final Errno ERRNO_FILE_NOT_FOUND_AT_PATH_SHORT = new Errno(TYPE, 151, "The %1$s not found at path.");
- public static final Errno ERRNO_NO_REGULAR_FILE_FOUND = new Errno(TYPE, 151, "Regular file not found at %1$s path.");
- public static final Errno ERRNO_NOT_A_REGULAR_FILE = new Errno(TYPE, 152, "The %1$s at path \"%2$s\" is not a regular file.");
+ public static final Errno ERRNO_NON_REGULAR_FILE_FOUND = new Errno(TYPE, 152, "Non-regular file found at %1$s path \"%2$s\".");
+ public static final Errno ERRNO_NON_REGULAR_FILE_FOUND_SHORT = new Errno(TYPE, 153, "Non-regular file found at %1$s path.");
+ public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND = new Errno(TYPE, 154, "Non-directory file found at %1$s path \"%2$s\".");
+ public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND_SHORT = new Errno(TYPE, 155, "Non-directory file found at %1$s path.");
+ public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND = new Errno(TYPE, 156, "Non-symlink file found at %1$s path \"%2$s\".");
+ public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND_SHORT = new Errno(TYPE, 157, "Non-symlink file found at %1$s path.");
- public static final Errno ERRNO_NON_REGULAR_FILE_FOUND = new Errno(TYPE, 153, "Non-regular file found at %1$s path.");
- public static final Errno ERRNO_NON_DIRECTORY_FILE_FOUND = new Errno(TYPE, 154, "Non-directory file found at %1$s path.");
- public static final Errno ERRNO_NON_SYMLINK_FILE_FOUND = new Errno(TYPE, 155, "Non-symlink file found at %1$s path.");
+ public static final Errno ERRNO_FILE_NOT_AN_ALLOWED_FILE_TYPE = new Errno(TYPE, 158, "The %1$s found at path \"%2$s\" is not one of allowed file types \"%3$s\".");
- public static final Errno ERRNO_FILE_NOT_AN_ALLOWED_FILE_TYPE = new Errno(TYPE, 156, "The %1$s found at path \"%2$s\" is not one of allowed file types \"%3$s\".");
-
- public static final Errno ERRNO_VALIDATE_FILE_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 157, "Validating file existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s");
- public static final Errno ERRNO_VALIDATE_DIRECTORY_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 158, "Validating directory existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s");
+ public static final Errno ERRNO_VALIDATE_FILE_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 159, "Validating file existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s");
+ public static final Errno ERRNO_VALIDATE_DIRECTORY_EXISTENCE_AND_PERMISSIONS_FAILED_WITH_EXCEPTION = new Errno(TYPE, 160, "Validating directory existence and permissions of %1$s at path \"%2$s\" failed.\nException: %3$s");
@@ -72,13 +76,31 @@ public class FileUtilsErrno extends Errno {
/* Errors for invalid file permissions (400-450) */
public static final Errno ERRNO_INVALID_FILE_PERMISSIONS_STRING_TO_CHECK = new Errno(TYPE, 400, "The file permission string to check is invalid.");
- public static final Errno ERRNO_FILE_NOT_READABLE = new Errno(TYPE, 401, "The %1$s at path is not readable. Permission Denied.");
- public static final Errno ERRNO_FILE_NOT_WRITABLE = new Errno(TYPE, 402, "The %1$s at path is not writable. Permission Denied.");
- public static final Errno ERRNO_FILE_NOT_EXECUTABLE = new Errno(TYPE, 403, "The %1$s at path is not executable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_READABLE = new Errno(TYPE, 401, "The %1$s at path \"%2$s\" is not readable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_READABLE_SHORT = new Errno(TYPE, 402, "The %1$s at path is not readable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_WRITABLE = new Errno(TYPE, 403, "The %1$s at path \"%2$s\" is not writable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_WRITABLE_SHORT = new Errno(TYPE, 404, "The %1$s at path is not writable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_EXECUTABLE = new Errno(TYPE, 405, "The %1$s at path \"%2$s\" is not executable. Permission Denied.");
+ public static final Errno ERRNO_FILE_NOT_EXECUTABLE_SHORT = new Errno(TYPE, 406, "The %1$s at path is not executable. Permission Denied.");
FileUtilsErrno(final String type, final int code, final String message) {
super(type, code, message);
}
+
+
+ /** Defines the {@link Errno} mapping to get a shorter version of {@link FileUtilsErrno}. */
+ public static Map ERRNO_SHORT_MAPPING = new HashMap() {{
+ put(ERRNO_FILE_NOT_FOUND_AT_PATH, ERRNO_FILE_NOT_FOUND_AT_PATH_SHORT);
+
+ put(ERRNO_NON_REGULAR_FILE_FOUND, ERRNO_NON_REGULAR_FILE_FOUND_SHORT);
+ put(ERRNO_NON_DIRECTORY_FILE_FOUND, ERRNO_NON_DIRECTORY_FILE_FOUND_SHORT);
+ put(ERRNO_NON_SYMLINK_FILE_FOUND, ERRNO_NON_SYMLINK_FILE_FOUND_SHORT);
+
+ put(ERRNO_FILE_NOT_READABLE, ERRNO_FILE_NOT_READABLE_SHORT);
+ put(ERRNO_FILE_NOT_WRITABLE, ERRNO_FILE_NOT_WRITABLE_SHORT);
+ put(ERRNO_FILE_NOT_EXECUTABLE, ERRNO_FILE_NOT_EXECUTABLE_SHORT);
+ }};
+
}