/*
* Copyright (C) 2012 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.cyanogenmod.filemanager.commands.shell;
import android.util.Log;
import com.cyanogenmod.filemanager.commands.SyncResultExecutable;
import com.cyanogenmod.filemanager.commands.WritableExecutable;
import com.cyanogenmod.filemanager.console.CommandNotFoundException;
import com.cyanogenmod.filemanager.console.ExecutionException;
import com.cyanogenmod.filemanager.console.InsufficientPermissionsException;
import com.cyanogenmod.filemanager.console.NoSuchFileOrDirectory;
import com.cyanogenmod.filemanager.console.ReadOnlyFilesystemException;
/**
* An abstract class that represents a command to wrap others commands,
* like <code>sh</code> or <code>su</code> commands.
*/
public abstract class Shell extends Command {
private int mPid;
private final static String TAG = "Shell"; //$NON-NLS-1$
/**
* @Constructor of <code>Shell</code>
*
* @param id The resource identifier of the command
* @param args Arguments of the command (will be formatted with the arguments from
* the command definition)
* @throws InvalidCommandDefinitionException If the command has an invalid definition
*/
public Shell(String id, String... args) throws InvalidCommandDefinitionException {
super(id, args);
this.mPid = -1;
}
/**
* Method that returns the process identifier of the console
*
* @return int The process identifier
*/
public final int getPid() {
return this.mPid;
}
/**
* Method that sets the process identifier of the console
*
* @param pid The process identifier
*/
public final void setPid(int pid) {
this.mPid = pid;
}
/**
* {@inheritDoc}
*/
@Override
public void checkExitCode(int exitCode)
throws InsufficientPermissionsException, CommandNotFoundException, ExecutionException {
//Command not found
if (exitCode == 127) {
Log.w(TAG, String.format(
"CommandNotFound: %s %s", //$NON-NLS-1$
getCommand(),
getArguments()));
throw new CommandNotFoundException(getId());
}
//No exit code
if (exitCode == 255) {
throw new ExecutionException(getId());
}
}
/**
* Method that checks if the standard errors has exceptions.
*
* @param program The program
* @param exitCode Program exit code
* @param err Standard Error buffer
* @throws InsufficientPermissionsException If an operation requires elevated permissions
* @throws NoSuchFileOrDirectory If the file or directory was not found
* @throws CommandNotFoundException If the command was not found
* @throws ExecutionException If the another exception is detected in the standard error
* @throws ReadOnlyFilesystemException If the operation writes in a read-only filesystem
* @hide
*/
@SuppressWarnings({ "static-method", "unused" })
public void checkStdErr(Program program, int exitCode, String err)
throws InsufficientPermissionsException, NoSuchFileOrDirectory,
CommandNotFoundException, ExecutionException, ReadOnlyFilesystemException {
//Check problems in the standard error
if (exitCode != 0 && err.indexOf("No such file or directory") != -1) { //$NON-NLS-1$
throw new NoSuchFileOrDirectory();
}
//Normally usage code is generated for invalid commands, but let's assume
//that the invalid command is generated for and error caused for non
//existing directory
if (err.indexOf("Usage:") != -1) { //$NON-NLS-1$
throw new NoSuchFileOrDirectory();
}
if (err.indexOf("Permission denied") != -1) { //$NON-NLS-1$
if (program instanceof SyncResultExecutable) {
throw new InsufficientPermissionsException((SyncResultExecutable)program);
}
throw new InsufficientPermissionsException();
}
if (exitCode != 0 && err.indexOf("Operation not permitted") != -1) { //$NON-NLS-1$
if (program instanceof SyncResultExecutable) {
throw new InsufficientPermissionsException((SyncResultExecutable)program);
}
throw new InsufficientPermissionsException();
}
if (err.indexOf("Read-only file system") != -1) { //$NON-NLS-1$
if (program instanceof WritableExecutable) {
// This error could be caused by dst or src. No matter which. Use dst.
throw new ReadOnlyFilesystemException(
((WritableExecutable)program).getDstWritableMountPoint());
}
throw new ExecutionException("Read-only file system"); //$NON-NLS-1$
}
}
}