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); }
// 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; }