Example #1
0
void file_close(void * fd)
{
#ifdef WIN32
  win32_close(fd);
#else
  unix_close(fd);
#endif
}
bool make_block_device_writable(const std::string& dev) {
    int fd = unix_open(dev.c_str(), O_RDONLY | O_CLOEXEC);
    if (fd == -1) {
        return false;
    }

    int OFF = 0;
    bool result = (ioctl(fd, BLKROSET, &OFF) != -1);
    unix_close(fd);
    return result;
}
void close_stdin() {
    int fd = unix_open(kNullFileName, O_RDONLY);
    if (fd == -1) {
        fatal_errno("failed to open %s", kNullFileName);
    }

    if (TEMP_FAILURE_RETRY(dup2(fd, STDIN_FILENO)) == -1) {
        fatal_errno("failed to redirect stdin to %s", kNullFileName);
    }
    unix_close(fd);
}
void start_device_log(void) {
    int fd = unix_open(get_log_file_name().c_str(),
                       O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
    if (fd == -1) {
        return;
    }

    // Redirect stdout and stderr to the log file.
    dup2(fd, STDOUT_FILENO);
    dup2(fd, STDERR_FILENO);
    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
    unix_close(fd);
}
static void setup_daemon_logging(void) {
    const std::string log_file_path(GetLogFilePath());
    int fd = unix_open(log_file_path.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0640);
    if (fd == -1) {
        fatal("cannot open '%s': %s", log_file_path.c_str(), strerror(errno));
    }
    if (dup2(fd, STDOUT_FILENO) == -1) {
        fatal("cannot redirect stdout: %s", strerror(errno));
    }
    if (dup2(fd, STDERR_FILENO) == -1) {
        fatal("cannot redirect stderr: %s", strerror(errno));
    }
    unix_close(fd);

    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
    LOG(INFO) << adb_version();
}
void log_service(int fd, void *cookie)
{
    /* get the name of the log filepath to read */
    char * log_filepath = cookie;

    /* open the log file. */
    int logfd = unix_open(log_filepath, O_RDONLY);
    if (logfd < 0) {
        goto done;
    }

    // temp buffer to read the entries
    unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1] __attribute__((aligned(4)));
    struct logger_entry *entry = (struct logger_entry *) buf;

    while (1) {
        int ret;

        ret = unix_read(logfd, entry, LOGGER_ENTRY_MAX_LEN);
        if (ret < 0) {
            if (errno == EINTR || errno == EAGAIN)
                continue;
            // perror("logcat read");
            goto done;
        }
        else if (!ret) {
            // fprintf(stderr, "read: Unexpected EOF!\n");
            goto done;
        }

        /* NOTE: driver guarantees we read exactly one full entry */

        entry->msg[entry->len] = '\0';

        write_log_entry(fd, entry);
    }

done:
    unix_close(fd);
    free(log_filepath);
}
Example #7
0
// Read from a pipe (that we take ownership of) and write the result to stdout/stderr. Return on
// error or when the pipe is closed. Internally makes inheritable handles, so this should not be
// called if subprocesses may be started concurrently.
static unsigned _redirect_pipe_thread(HANDLE h, DWORD nStdHandle) {
    // Take ownership of the HANDLE and close when we're done.
    unique_handle   read_pipe(h);
    const char*     output_name = nStdHandle == STD_OUTPUT_HANDLE ? "stdout" : "stderr";
    const int       original_fd = fileno(nStdHandle == STD_OUTPUT_HANDLE ? stdout : stderr);
    std::unique_ptr<FILE, decltype(&fclose)> stream(nullptr, fclose);

    if (original_fd == -1) {
        fprintf(stderr, "Failed to get file descriptor for %s: %s\n", output_name, strerror(errno));
        return EXIT_FAILURE;
    }

    // If fileno() is -2, stdout/stderr is not associated with an output stream, so we should read,
    // but don't write. Otherwise, make a FILE* identical to stdout/stderr except that it is in
    // binary mode with no CR/LR translation since we're reading raw.
    if (original_fd >= 0) {
        // This internally makes a duplicate file handle that is inheritable, so callers should not
        // call this function if subprocesses may be started concurrently.
        const int fd = dup(original_fd);
        if (fd == -1) {
            fprintf(stderr, "Failed to duplicate file descriptor for %s: %s\n", output_name,
                    strerror(errno));
            return EXIT_FAILURE;
        }

        // Note that although we call fdopen() below with a binary flag, it may not adhere to that
        // flag, so we have to set the mode manually.
        if (_setmode(fd, _O_BINARY) == -1) {
            fprintf(stderr, "Failed to set binary mode for duplicate of %s: %s\n", output_name,
                    strerror(errno));
            unix_close(fd);
            return EXIT_FAILURE;
        }

        stream.reset(fdopen(fd, "wb"));
        if (stream.get() == nullptr) {
            fprintf(stderr, "Failed to open duplicate stream for %s: %s\n", output_name,
                    strerror(errno));
            unix_close(fd);
            return EXIT_FAILURE;
        }

        // Unbuffer the stream because it will be buffered by default and we want subprocess output
        // to be shown immediately.
        if (setvbuf(stream.get(), NULL, _IONBF, 0) == -1) {
            fprintf(stderr, "Failed to unbuffer %s: %s\n", output_name, strerror(errno));
            return EXIT_FAILURE;
        }

        // fd will be closed when stream is closed.
    }

    while (true) {
        char    buf[64 * 1024];
        DWORD   bytes_read = 0;
        if (!ReadFile(read_pipe.get(), buf, sizeof(buf), &bytes_read, NULL)) {
            const DWORD err = GetLastError();
            // ERROR_BROKEN_PIPE is expected when the subprocess closes
            // the other end of the pipe.
            if (err == ERROR_BROKEN_PIPE) {
                return EXIT_SUCCESS;
            } else {
                fprintf(stderr, "Failed to read from %s: %s\n", output_name,
                        android::base::SystemErrorCodeToString(err).c_str());
                return EXIT_FAILURE;
            }
        }

        // Don't try to write if our stdout/stderr was not setup by the parent process.
        if (stream) {
            // fwrite() actually calls adb_fwrite() which can write UTF-8 to the console.
            const size_t bytes_written = fwrite(buf, 1, bytes_read, stream.get());
            if (bytes_written != bytes_read) {
                fprintf(stderr, "Only wrote %zu of %lu bytes to %s\n", bytes_written, bytes_read,
                        output_name);
                return EXIT_FAILURE;
            }
        }
    }
}
int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) {
#if defined(_WIN32)
    // adb start-server starts us up with stdout and stderr hooked up to
    // anonymous pipes. When the C Runtime sees this, it makes stderr and
    // stdout buffered, but to improve the chance that error output is seen,
    // unbuffer stdout and stderr just like if we were run at the console.
    // This also keeps stderr unbuffered when it is redirected to adb.log.
    if (is_daemon) {
        if (setvbuf(stdout, NULL, _IONBF, 0) == -1) {
            fatal("cannot make stdout unbuffered: %s", strerror(errno));
        }
        if (setvbuf(stderr, NULL, _IONBF, 0) == -1) {
            fatal("cannot make stderr unbuffered: %s", strerror(errno));
        }
    }

    SetConsoleCtrlHandler(ctrlc_handler, TRUE);
#endif

    init_transport_registration();

    usb_init();
    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
    adb_auth_init();

    std::string error;
    std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
    if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
        fatal("could not install *smartsocket* listener: %s", error.c_str());
    }

    // Inform our parent that we are up and running.
    if (is_daemon) {
        close_stdin();
        setup_daemon_logging();

        // Any error output written to stderr now goes to adb.log. We could
        // keep around a copy of the stderr fd and use that to write any errors
        // encountered by the following code, but that is probably overkill.
#if defined(_WIN32)
        const HANDLE ack_reply_handle = cast_int_to_handle(ack_reply_fd);
        const CHAR ack[] = "OK\n";
        const DWORD bytes_to_write = arraysize(ack) - 1;
        DWORD written = 0;
        if (!WriteFile(ack_reply_handle, ack, bytes_to_write, &written, NULL)) {
            fatal("adb: cannot write ACK to handle 0x%p: %s", ack_reply_handle,
                  SystemErrorCodeToString(GetLastError()).c_str());
        }
        if (written != bytes_to_write) {
            fatal("adb: cannot write %lu bytes of ACK: only wrote %lu bytes",
                  bytes_to_write, written);
        }
        CloseHandle(ack_reply_handle);
#else
        // TODO(danalbert): Can't use SendOkay because we're sending "OK\n", not
        // "OKAY".
        if (!android::base::WriteStringToFd("OK\n", ack_reply_fd)) {
            fatal_errno("error writing ACK to fd %d", ack_reply_fd);
        }
        unix_close(ack_reply_fd);
#endif
    }

    D("Event loop starting");
    fdevent_loop();

    return 0;
}