Пример #1
0
        /// <summary>
        /// Push a single file
        /// </summary>
        /// <param name="local">the local file to push</param>
        /// <param name="remotePath">the remote file (length max is 1024)</param>
        /// <param name="monitor">the monitor. The monitor must be started already.</param>
        /// <returns>a SyncResult object with a code and an optional message.</returns>
        /// <exception cref="ArgumentNullException">Throws if monitor is null</exception>
        private SyncResult DoPushFile(string local, string remotePath, ISyncProgressMonitor monitor)
        {
            if (monitor == null)
            {
                throw new ArgumentNullException("monitor", "Monitor cannot be null");
            }

            Log.I(TAG, "Pushing file '" + local + "' to '" + Device + remotePath + "'.");
            byte[] msg;

            int timeOut = DdmPreferences.Timeout;

            FileStream fs;

            try
            {
                byte[] remotePathContent = StringHelper.GetBytes(remotePath, AdbHelper.DEFAULT_ENCODING);

                if (remotePathContent.Length > REMOTE_PATH_MAX_LENGTH)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_REMOTE_PATH_LENGTH));
                }

                // this shouldn't happen but still...
                if (!File.Exists(local))
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_NO_LOCAL_FILE));
                }

                // create the stream to read the file
                fs = new FileStream(local, System.IO.FileMode.Open, FileAccess.Read);

                // create the header for the action
                msg = CreateSendFileRequest(StringHelper.GetBytes(SEND), remotePathContent, (FileMode)0644);
            }
            catch (EncoderFallbackException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_REMOTE_PATH_ENCODING, e));
            }
            catch (FileNotFoundException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_FILE_READ_ERROR, e));
            }

            // and send it. We use a custom try/catch block to make the difference between
            // file and network IO exceptions.
            try
            {
                AdbHelper.Instance.Write(Channel, msg, -1, timeOut);
            }
            catch (IOException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR, e));
            }

            // create the buffer used to read.
            // we read max SYNC_DATA_MAX, but we need 2 4 bytes at the beginning.
            if (DataBuffer == null)
            {
                DataBuffer = new byte[SYNC_DATA_MAX + 8];
            }
            byte[] bDATA = StringHelper.GetBytes(DATA);
            Array.Copy(bDATA, 0, DataBuffer, 0, bDATA.Length);

            // look while there is something to read
            while (true)
            {
                // check if we're canceled
                if (monitor.IsCanceled)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_CANCELED));
                }

                // read up to SYNC_DATA_MAX
                int readCount;
                try
                {
                    readCount = fs.Read(DataBuffer, 8, SYNC_DATA_MAX);
                }
                catch (IOException e)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_FILE_READ_ERROR, e));
                }

                if (readCount == 0)
                {
                    // we reached the end of the file
                    break;
                }

                // now send the data to the device
                // first write the amount read
                ArrayHelper.Swap32bitsToArray(readCount, DataBuffer, 4);

                // now write it
                try
                {
                    AdbHelper.Instance.Write(Channel, DataBuffer, readCount + 8, timeOut);
                }
                catch (IOException e)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR, e));
                }

                // and advance the monitor
                monitor.Advance(readCount);
            }
            // close the local file
            try
            {
                fs.Close();
                fs.Dispose();
            }
            catch (IOException e)
            {
                Log.E(TAG, e);
            }

            try
            {
                // create the DONE message
                long time = DateTimeHelper.CurrentTimeMillis(DateTime.Now) / 1000;
                msg = CreateRequest(DONE, (int)time);

                // and send it.
                AdbHelper.Instance.Write(Channel, msg, -1, timeOut);

                // read the result, in a byte array containing 2 ints
                // (id, size)
                byte[] result = new byte[8];
                AdbHelper.Instance.Read(Channel, result, -1 /* full length */);

                if (!CheckResult(result, StringHelper.GetBytes(OKAY)))
                {
                    if (CheckResult(result, StringHelper.GetBytes(FAIL)))
                    {
                        // read some error message...
                        int len = ArrayHelper.Swap32bitFromArray(result, 4);

                        AdbHelper.Instance.Read(Channel, DataBuffer, len);

                        // output the result?
                        string message = StringHelper.GetString(DataBuffer, 0, len);
                        Log.E(TAG, "transfer error: " + message);
                        return(new SyncResult(ErrorCodeHelper.RESULT_UNKNOWN_ERROR, message));
                    }

                    return(new SyncResult(ErrorCodeHelper.RESULT_UNKNOWN_ERROR));
                }
            }
            catch (IOException e)
            {
                return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR, e));
            }

            // files pushed have no permissions...
            this.Device.FileSystem.Chmod(remotePath, "0666");

            return(new SyncResult(ErrorCodeHelper.RESULT_OK));
        }
Пример #2
0
        /// <summary>
        /// Pulls a remote file
        /// </summary>
        /// <param name="remotePath">the remote file (length max is 1024)</param>
        /// <param name="localPath">the local destination</param>
        /// <param name="monitor">the monitor. The monitor must be started already.</param>
        /// <returns>a SyncResult object with a code and an optional message.</returns>
        /// <exception cref="ArgumentNullException">Throws if monitor is null</exception>
        private SyncResult DoPullFile(string remotePath, string localPath, ISyncProgressMonitor monitor)
        {
            if (monitor == null)
            {
                throw new ArgumentNullException("monitor", "Monitor cannot be null");
            }

            Log.I(TAG, "Pulling file '" + localPath + "' from '" + Device + remotePath + "'.");
            byte[] pullResult = new byte[8];

            int timeOut = DdmPreferences.Timeout;

            try
            {
                byte[] remotePathContent = StringHelper.GetBytes(remotePath, AdbHelper.DEFAULT_ENCODING);

                if (remotePathContent.Length > REMOTE_PATH_MAX_LENGTH)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_REMOTE_PATH_LENGTH));
                }

                // create the full request message
                byte[] msg = CreateFileRequest(StringHelper.GetBytes(RECV), remotePathContent);

                // and send it.
                AdbHelper.Instance.Write(Channel, msg, -1, timeOut);

                // read the result, in a byte array containing 2 ints
                // (id, size)
                AdbHelper.Instance.Read(Channel, pullResult, -1);

                // check we have the proper data back
                if (CheckResult(pullResult, StringHelper.GetBytes(DATA)) == false &&
                    CheckResult(pullResult, StringHelper.GetBytes(DONE)) == false)
                {
                    return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR));
                }
            }
            catch (EncoderFallbackException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_REMOTE_PATH_ENCODING, e));
            }
            catch (IOException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR, e));
            }

            // access the destination file
            FileInfo f = new FileInfo(localPath);

            // create the stream to write in the file. We use a new try/catch block to differentiate
            // between file and network io exceptions.
            FileStream fos;

            try
            {
                fos = new FileStream(f.FullName, System.IO.FileMode.Create, FileAccess.Write);
            }
            catch (FileNotFoundException e)
            {
                Log.E(TAG, e);
                return(new SyncResult(ErrorCodeHelper.RESULT_FILE_WRITE_ERROR, e));
            }

            // the buffer to read the data
            byte[] data = new byte[SYNC_DATA_MAX];
            using (fos)
            {
                // loop to get data until we're done.
                while (true)
                {
                    // check if we're cancelled
                    if (monitor.IsCanceled)
                    {
                        return(new SyncResult(ErrorCodeHelper.RESULT_CANCELED));
                    }

                    // if we're done, we stop the loop
                    if (CheckResult(pullResult, StringHelper.GetBytes(DONE)))
                    {
                        break;
                    }
                    if (CheckResult(pullResult, StringHelper.GetBytes(DATA)) == false)
                    {
                        // hmm there's an error
                        return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR));
                    }
                    int length = ArrayHelper.Swap32bitFromArray(pullResult, 4);
                    if (length > SYNC_DATA_MAX)
                    {
                        // buffer overrun!
                        // error and exit
                        return(new SyncResult(ErrorCodeHelper.RESULT_BUFFER_OVERRUN));
                    }

                    try
                    {
                        // now read the length we received
                        AdbHelper.Instance.Read(Channel, data, length);

                        // get the header for the next packet.
                        AdbHelper.Instance.Read(Channel, pullResult, -1);
                    }
                    catch (IOException e)
                    {
                        Log.E(TAG, e);
                        return(new SyncResult(ErrorCodeHelper.RESULT_CONNECTION_ERROR, e));
                    }
                    // write the content in the file
                    try
                    {
                        fos.Write(data, 0, data.Length);
                    }
                    catch (IOException e)
                    {
                        Log.E(TAG, e);
                        return(new SyncResult(ErrorCodeHelper.RESULT_FILE_WRITE_ERROR, e));
                    }

                    monitor.Advance(length);
                }

                try
                {
                    fos.Flush();
                }
                catch (IOException e)
                {
                    Log.E(TAG, e);
                    return(new SyncResult(ErrorCodeHelper.RESULT_FILE_WRITE_ERROR, e));
                }

                try
                {
                    fos.Close();
                    fos.Dispose();
                }
                catch (IOException e)
                {
                    Log.E(TAG, e);
                }
            }
            return(new SyncResult(ErrorCodeHelper.RESULT_OK));
        }
Пример #3
0
        /// <summary>
        /// Executes a shell command on the remote device
        /// </summary>
        /// <param name="endPoint">The socket end point</param>
        /// <param name="command">The command to execute</param>
        /// <param name="device">The device to execute on</param>
        /// <param name="rcvr">The shell output receiver</param>
        /// <exception cref="FileNotFoundException">Throws if the result is 'command': not found</exception>
        /// <exception cref="IOException">Throws if there is a problem reading / writing to the socket</exception>
        /// <exception cref="OperationCanceledException">Throws if the execution was canceled</exception>
        /// <exception cref="EndOfStreamException">Throws if the Socket.Receice ever returns -1</exception>
        public void ExecuteRemoteCommand(IPEndPoint endPoint, string command, Device device, IShellOutputReceiver rcvr)
        {
            Log.I(TAG, "executing '" + command + "' on '" + device + "'.");
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            if (!device.IsOnline)
            {
                return;
            }

            try
            {
                socket.ReceiveTimeout = SOCKET_TIMEOUT;
                socket.SendTimeout    = SOCKET_TIMEOUT;
                socket.Connect(endPoint);
                socket.Blocking = true;

                SetDevice(socket, device);

                byte[] request = FormAdbRequest("shell:" + command);
                if (!Write(socket, request))
                {
                    throw new AdbException("failed submitting shell command");
                }

                AdbResponse resp = ReadAdbResponse(socket, false /* readDiagstring */);
                if (!resp.IOSuccess || !resp.Okay)
                {
                    throw new AdbException("sad result from adb: " + resp.Message);
                }

                byte[] data  = new byte[16384];
                int    count = -1;
                socket.ReceiveTimeout = SOCKET_TIMEOUT_SHELLCOMMAND;
                while (count != 0)
                {
                    if (rcvr != null && rcvr.IsCancelled)
                    {
                        Log.W(TAG, "execute: cancelled");
                        throw new OperationCanceledException();
                    }

                    count = socket.Receive(data);
                    if (count < 0)
                    {
                        // we're at the end, we flush the output
                        rcvr.Flush();
                        Log.W(TAG, "execute '" + command + "' on '" + device + "' : EOF hit. Read: " + count);
                        throw new EndOfStreamException();
                    }
                    else if (count == 0)
                    {
                        // do nothing
                    }
                    else
                    {
                        string[] cmd          = command.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        string   sdata        = StringHelper.GetString(data, 0, count, AdbHelper.DEFAULT_ENCODING);
                        var      sdataTrimmed = sdata.Trim();
                        if (sdataTrimmed.EndsWith(string.Format("{0}: not found", cmd[0])))
                        {
                            Log.W("AdbHelper", "The remote execution returned: '{0}: not found'", cmd[0]);
                            throw new FileNotFoundException(string.Format("The remote execution returned: '{0}: not found'", cmd[0]));
                        }

                        if (sdataTrimmed.EndsWith("No such file or directory"))
                        {
                            Log.W("AdbHelper", "The remote execution returned: {0}", sdataTrimmed);
                            throw new FileNotFoundException(string.Format("The remote execution returned: {0}", sdataTrimmed));
                        }

                        // for busybox applets
                        // cmd: applet not found
                        if (cmd.Length > 1 && sdataTrimmed.EndsWith(string.Format("{0}: applet not found", cmd[1])))
                        {
                            Log.W("AdbHelper", "The remote execution returned: '{0}'", sdataTrimmed);
                            throw new FileNotFoundException(string.Format("The remote execution returned: '{0}'", sdataTrimmed));
                        }

                        // checks if the permission to execute the command was denied.
                        // workitem: 16822
                        if (sdataTrimmed.EndsWith(string.Format("{0}: permission denied", cmd[0])) ||
                            sdataTrimmed.EndsWith(string.Format("{0}: access denied", cmd[0])))
                        {
                            Log.W("AdbHelper", "The remote execution returned: '{0}'", sdataTrimmed);
                            throw new PermissionDeniedException(string.Format("The remote execution returned: '{0}'", sdataTrimmed));
                        }

                        // Add the data to the receiver
                        if (rcvr != null)
                        {
                            rcvr.AddOutput(data, 0, count);
                        }
                    }
                }
            }             /*catch ( Exception e ) {
                           *    Log.e ( "AdbHelper", e );
                           *    throw;
                           * }*/
            finally
            {
                if (socket != null)
                {
                    socket.Close();
                }
                rcvr.Flush();
            }
        }