Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20a96c7d authored by Josh Gao's avatar Josh Gao
Browse files

adbd: restore the old error handling behavior.

Restore the previous file sync error handling behavior of reporting
failure, and then consuming packets from the other end until receiving a
DONE packet.

Bug: http://b/26816782
Change-Id: I9708f2a36c072547e191fa0b6b42dffc31f8a2f2
parent 69469c4e
Loading
Loading
Loading
Loading
+35 −20
Original line number Diff line number Diff line
@@ -183,8 +183,6 @@ static bool handle_send_file(int s, const char* path, uid_t uid,
    }

    while (true) {
        unsigned int len;

        if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;

        if (msg.data.id != ID_DATA) {
@@ -193,17 +191,17 @@ static bool handle_send_file(int s, const char* path, uid_t uid,
                break;
            }
            SendSyncFail(s, "invalid data message");
            goto fail;
            goto abort;
        }
        len = msg.data.size;
        if (len > buffer.size()) { // TODO: resize buffer?

        if (msg.data.size > buffer.size()) {  // TODO: resize buffer?
            SendSyncFail(s, "oversize data message");
            goto fail;
            goto abort;
        }

        if (!ReadFdExactly(s, &buffer[0], len)) goto fail;
        if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;

        if (!WriteFdExactly(fd, &buffer[0], len)) {
        if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) {
            SendSyncFailErrno(s, "write failed");
            goto fail;
        }
@@ -221,6 +219,35 @@ static bool handle_send_file(int s, const char* path, uid_t uid,
    return WriteFdExactly(s, &msg.status, sizeof(msg.status));

fail:
    // If there's a problem on the device, we'll send an ID_FAIL message and
    // close the socket. Unfortunately the kernel will sometimes throw that
    // data away if the other end keeps writing without reading (which is
    // the case with old versions of adb). To maintain compatibility, keep
    // reading and throwing away ID_DATA packets until the other side notices
    // that we've reported an error.
    while (true) {
        if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;

        if (msg.data.id == ID_DONE) {
            goto abort;
        } else if (msg.data.id != ID_DATA) {
            char id[5];
            memcpy(id, &msg.data.id, sizeof(msg.data.id));
            id[4] = '\0';
            D("handle_send_fail received unexpected id '%s' during failure", id);
            goto abort;
        }

        if (msg.data.size > buffer.size()) {
            D("handle_send_fail received oversized packet of length '%u' during failure",
              msg.data.size);
            goto abort;
        }

        if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;
    }

abort:
    if (fd >= 0) adb_close(fd);
    if (do_unlink) adb_unlink(path);
    return false;
@@ -403,18 +430,6 @@ static bool handle_sync_command(int fd, std::vector<char>& buffer) {
void file_sync_service(int fd, void* cookie) {
    std::vector<char> buffer(SYNC_DATA_MAX);

    // If there's a problem on the device, we'll send an ID_FAIL message and
    // close the socket. Unfortunately the kernel will sometimes throw that
    // data away if the other end keeps writing without reading (which is
    // the normal case with our protocol --- they won't read until the end).
    // So set SO_LINGER to give the client 20s to get around to reading our
    // failure response. Without this, the other side's ability to report
    // useful errors is reduced.
    struct linger l;
    l.l_onoff = 1;
    l.l_linger = 20;
    adb_setsockopt(fd, SOL_SOCKET, SO_LINGER, &l, sizeof(l));

    while (handle_sync_command(fd, buffer)) {
    }