示例#1
0
static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
    int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
    if (fd < 0) {
        SendSyncFailErrno(s, "open failed");
        return false;
    }

    syncmsg msg;
    msg.data.id = ID_DATA;
    while (true) {
        int r = adb_read(fd, &buffer[0], buffer.size());
        if (r <= 0) {
            if (r == 0) break;
            SendSyncFailErrno(s, "read failed");
            adb_close(fd);
            return false;
        }
        msg.data.size = r;
        if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
            adb_close(fd);
            return false;
        }
    }

    adb_close(fd);

    msg.data.id = ID_DONE;
    msg.data.size = 0;
    return WriteFdExactly(s, &msg.data, sizeof(msg.data));
}
static int get_target_device_size(int fd, const char *blk_device,
                                  uint64_t *device_size)
{
    int data_device;
    struct ext4_super_block sb;
    struct fs_info info;

    info.len = 0;  /* Only len is set to 0 to ask the device for real size. */

    data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
    if (data_device < 0) {
        write_console(fd, "Error opening block device (%s)\n", strerror(errno));
        return -1;
    }

    if (lseek64(data_device, 1024, SEEK_SET) < 0) {
        write_console(fd, "Error seeking to superblock\n");
        adb_close(data_device);
        return -1;
    }

    if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
        write_console(fd, "Error reading superblock\n");
        adb_close(data_device);
        return -1;
    }

    ext4_parse_sb(&sb, &info);
    *device_size = info.len;

    adb_close(data_device);
    return 0;
}
示例#3
0
static int restore(int argc, char** argv) {
    const char* filename;
    int fd, tarFd;

    if (argc != 2) return usage();

    filename = argv[1];
    tarFd = adb_open(filename, O_RDONLY);
    if (tarFd < 0) {
        fprintf(stderr, "adb: unable to open file %s\n", filename);
        return -1;
    }

    fd = adb_connect("restore:");
    if (fd < 0) {
        fprintf(stderr, "adb: unable to connect for backup\n");
        adb_close(tarFd);
        return -1;
    }

    printf("Now unlock your device and confirm the restore operation.\n");
    copy_to_file(tarFd, fd);

    adb_close(fd);
    adb_close(tarFd);
    return 0;
}
示例#4
0
static int write_data_file(int fd, const char *path, syncsendbuf *sbuf, int show_progress)
{
    int lfd, err = 0;
    unsigned long long size = 0;

    lfd = adb_open(path, O_RDONLY);
    if(lfd < 0) {
        fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));
        return -1;
    }

    if (show_progress) {
        // Determine local file size.
        struct stat st;
        if (fstat(lfd, &st)) {
            fprintf(stderr,"cannot stat '%s': %s\n", path, strerror(errno));
            return -1;
        }

        size = st.st_size;
    }

    sbuf->id = ID_DATA;
    for(;;) {
        int ret;

        ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);
        if(!ret)
            break;

        if(ret < 0) {
            if(errno == EINTR)
                continue;
            fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
            break;
        }

        sbuf->size = htoll(ret);
        if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
            err = -1;
            break;
        }
        total_bytes += ret;

        if (show_progress) {
            print_transfer_progress(total_bytes, size);
        }
    }

    adb_close(lfd);
    return err;
}
示例#5
0
static void init_subproc_child()
{
    setsid();

    // Set OOM score adjustment to prevent killing
    int fd = adb_open("/proc/self/oom_score_adj", O_WRONLY | O_CLOEXEC);
    if (fd >= 0) {
        adb_write(fd, "0", 1);
        adb_close(fd);
    } else {
       D("adb: unable to update oom_score_adj\n");
    }
}
TEST(adb_utils, set_file_block_mode) {
  int fd = adb_open("/dev/null", O_RDWR | O_APPEND);
  ASSERT_GE(fd, 0);
  int flags = fcntl(fd, F_GETFL, 0);
  ASSERT_EQ(O_RDWR | O_APPEND, (flags & (O_RDWR | O_APPEND)));
  ASSERT_TRUE(set_file_block_mode(fd, false));
  int new_flags = fcntl(fd, F_GETFL, 0);
  ASSERT_EQ(flags | O_NONBLOCK, new_flags);
  ASSERT_TRUE(set_file_block_mode(fd, true));
  new_flags = fcntl(fd, F_GETFL, 0);
  ASSERT_EQ(flags, new_flags);
  ASSERT_EQ(0, adb_close(fd));
}
static int sysfs_write(const char *node, const char *message)
{
    int fd;
    ssize_t to_write;
    int ret = 0;

    fd = adb_open(node, O_RDWR);
    if (!fd) {
        D("open '%s' failed: %s\n", node, strerror(errno));
        return -1;
    }

    to_write = strlen(message);
    if (adb_write(fd, message, to_write) != to_write) {
        D("write '%s' failed: %s\n", node, strerror(errno));
        ret = -1;
    }
    adb_close(fd);
    return ret;
}
static int write_data_file(int fd, const char *path, syncsendbuf *sbuf)
{
    int lfd, err = 0;

    lfd = adb_open(path, O_RDONLY);
    if(lfd < 0) {
        fprintf(stderr,"cannot open '%s': %s\n", path, strerror(errno));
        return -1;
    }

    sbuf->id = ID_DATA;
    for(;;) {
        int ret;

        ret = adb_read(lfd, sbuf->data, SYNC_DATA_MAX);
        if(!ret)
            break;

        if(ret < 0) {
            if(errno == EINTR)
                continue;
            fprintf(stderr,"cannot read '%s': %s\n", path, strerror(errno));
            break;
        }

        sbuf->size = htoll(ret);
        if(writex(fd, sbuf, sizeof(unsigned) * 2 + ret)){
            err = -1;
            break;
        }
        total_bytes += ret;
        STATUS();
    }

    adb_close(lfd);
    return err;
}
示例#9
0
static int do_send(int s, char *path, char *buffer)
{
    char *tmp;
    unsigned int mode;
    int is_link, ret;
    bool do_unlink;

    tmp = strrchr(path,',');
    if(tmp) {
        *tmp = 0;
        errno = 0;
        mode = strtoul(tmp + 1, NULL, 0);
#ifndef HAVE_SYMLINKS
        is_link = 0;
#else
        is_link = S_ISLNK((mode_t) mode);
#endif
        mode &= 0777;
    }
    if(!tmp || errno) {
        mode = 0644;
        is_link = 0;
        do_unlink = true;
    } else {
        struct stat st;
        /* Don't delete files before copying if they are not "regular" */
        do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
        if (do_unlink) {
            adb_unlink(path);
        }
    }

#ifdef HAVE_SYMLINKS
    if(is_link)
        ret = handle_send_link(s, path, buffer);
    else {
#else
    {
#endif
        uid_t uid = -1;
        gid_t gid = -1;
        uint64_t cap = 0;

        /* copy user permission bits to "group" and "other" permissions */
        mode |= ((mode >> 3) & 0070);
        mode |= ((mode >> 3) & 0007);

        tmp = path;
        if(*tmp == '/') {
            tmp++;
        }
        if (is_on_system(path) || is_on_vendor(path)) {
            fs_config(tmp, 0, &uid, &gid, &mode, &cap);
        }
        ret = handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
    }

    return ret;
}

static int do_recv(int s, const char *path, char *buffer)
{
    syncmsg msg;
    int fd, r;

    fd = adb_open(path, O_RDONLY | O_CLOEXEC);
    if(fd < 0) {
        if(fail_errno(s)) return -1;
        return 0;
    }

    msg.data.id = ID_DATA;
    for(;;) {
        if(syc_size_enabled == 1) {
            r = adb_read(fd, buffer, SYNC_DATA_MAX_CUSTOMIZE);
        } else {
        r = adb_read(fd, buffer, SYNC_DATA_MAX);
        }
        if(r <= 0) {
            if(r == 0) break;
            if(errno == EINTR) continue;
            r = fail_errno(s);
            adb_close(fd);
            return r;
        }
        msg.data.size = htoll(r);
        if(writex(s, &msg.data, sizeof(msg.data)) ||
           writex(s, buffer, r)) {
            adb_close(fd);
            return -1;
        }
    }

    adb_close(fd);

    msg.data.id = ID_DONE;
    msg.data.size = 0;
    if(writex(s, &msg.data, sizeof(msg.data))) {
        return -1;
    }

    return 0;
}
示例#10
0
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1, pid_t *pid)
{
#ifdef HAVE_WIN32_PROC
    D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
    return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if(grantpt(ptm) || unlockpt(ptm) ||
       ((devname = (char*) ptsname(ptm)) == 0)){
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if(*pid < 0) {
        printf("- fork failed: pid(%d) %s -\n", *pid, strerror(errno));
        XLOGV("- fork failed: pid(%d) %s -\n", *pid, strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if(*pid == 0){
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if(pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n", devname);
            XLOGV("child failed to open pseudo-term slave: %s\n", devname);
            exit(-1);
        }

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(pts);
        adb_close(ptm);

        // set OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
           D("adb: unable to open %s\n", text);
           XLOGW("adb: unable to open %s\n", text);
        }

        timer_t timerid;
        struct sigevent sev;
        /* Create the timer */
        sev.sigev_notify = SIGEV_SIGNAL;
        sev.sigev_signo = SIGALRM;
        sev.sigev_value.sival_ptr = &timerid;
        if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1)
        {
            D("adb: Call timer_create failed!\n");
            XLOGV("adb: Call timer_create failed!\n");
            exit(-1);
        }

        struct itimerspec its;
        /* Start the timer */
        its.it_value.tv_sec = 1;
        its.it_value.tv_nsec = 0;
        its.it_interval.tv_sec = 3;
        its.it_interval.tv_nsec = 0;

        if (timer_settime(timerid, 0, &its, NULL) == -1)
        {
            D("adb: Call timer_settime failed!\n");
            XLOGV("adb: Call timer_settime failed!\n");
            exit(-1);
        }

        sigset_t mask;
        struct sigaction sa;
        /* Establish handler for timer signal */
        sa.sa_flags = SA_SIGINFO;
        sa.sa_sigaction = catcher;
        sigemptyset(&sa.sa_mask);
        if (sigaction(SIGALRM, &sa, NULL) == -1)
        {
            D("adb: Call sigaction failed!\n");
            XLOGV("adb: Call sigaction failed!\n");
            exit(-1);
        }

        int nRet = execl(cmd, cmd, arg0, arg1, NULL);

        fprintf(stderr, "- exec '%s' failed: %s (%d) nRet(%d) -\n",
                cmd, strerror(errno), errno, nRet);
        XLOGV("- exec '%s' failed: %s (%d) nRet(%d) -\n",
                cmd, strerror(errno), errno, nRet);
        exit(-1);
    } else {
        // Don't set child's OOM adjustment to zero.
        // Let the child do it itself, as sometimes the parent starts
        // running before the child has a /proc/pid/oom_adj.
        // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
static int sync_send(int fd, const char *lpath, const char *rpath,
                     unsigned mtime, mode_t mode, int verifyApk)
{
    syncmsg msg;
    int len, r;
    syncsendbuf *sbuf = &send_buffer;
    char* file_buffer = NULL;
    int size = 0;
    char tmp[64];

    len = strlen(rpath);
    if(len > 1024) goto fail;

    snprintf(tmp, sizeof(tmp), ",%d", mode);
    r = strlen(tmp);

    if (verifyApk) {
        int lfd;
        zipfile_t zip;
        zipentry_t entry;
        int amt;

        // if we are transferring an APK file, then sanity check to make sure
        // we have a real zip file that contains an AndroidManifest.xml
        // this requires that we read the entire file into memory.
        lfd = adb_open(lpath, O_RDONLY);
        if(lfd < 0) {
            fprintf(stderr,"cannot open '%s': %s\n", lpath, strerror(errno));
            return -1;
        }

        size = adb_lseek(lfd, 0, SEEK_END);
        if (size == -1 || -1 == adb_lseek(lfd, 0, SEEK_SET)) {
            fprintf(stderr, "error seeking in file '%s'\n", lpath);
            adb_close(lfd);
            return 1;
        }

        file_buffer = (char *)malloc(size);
        if (file_buffer == NULL) {
            fprintf(stderr, "could not allocate buffer for '%s'\n",
                    lpath);
            adb_close(lfd);
            return 1;
        }
        amt = adb_read(lfd, file_buffer, size);
        if (amt != size) {
            fprintf(stderr, "error reading from file: '%s'\n", lpath);
            adb_close(lfd);
            free(file_buffer);
            return 1;
        }

        adb_close(lfd);

        zip = init_zipfile(file_buffer, size);
        if (zip == NULL) {
            fprintf(stderr, "file '%s' is not a valid zip file\n",
                    lpath);
            free(file_buffer);
            return 1;
        }

        entry = lookup_zipentry(zip, "AndroidManifest.xml");
        release_zipfile(zip);
        if (entry == NULL) {
            fprintf(stderr, "file '%s' does not contain AndroidManifest.xml\n",
                    lpath);
            free(file_buffer);
            return 1;
        }
    }

    msg.req.id = ID_SEND;
    msg.req.namelen = htoll(len + r);

    if(writex(fd, &msg.req, sizeof(msg.req)) ||
       writex(fd, rpath, len) || writex(fd, tmp, r)) {
        free(file_buffer);
        goto fail;
    }

    if (file_buffer) {
        write_data_buffer(fd, file_buffer, size, sbuf);
        free(file_buffer);
    } else if (S_ISREG(mode))
        write_data_file(fd, lpath, sbuf);
#ifdef HAVE_SYMLINKS
    else if (S_ISLNK(mode))
        write_data_link(fd, lpath, sbuf);
#endif
    else
        goto fail;

    msg.data.id = ID_DONE;
    msg.data.size = htoll(mtime);
    if(writex(fd, &msg.data, sizeof(msg.data)))
        goto fail;

    if(readx(fd, &msg.status, sizeof(msg.status)))
        return -1;

    if(msg.status.id != ID_OKAY) {
        if(msg.status.id == ID_FAIL) {
            len = ltohl(msg.status.msglen);
            if(len > 256) len = 256;
            if(readx(fd, sbuf->data, len)) {
                return -1;
            }
            sbuf->data[len] = 0;
        } else
            strcpy(sbuf->data, "unknown reason");

        fprintf(stderr,"failed to copy '%s' to '%s': %s\n", lpath, rpath, sbuf->data);
        return -1;
    }

    return 0;

fail:
    fprintf(stderr,"protocol failure\n");
    adb_close(fd);
    return -1;
}
/* Turn verity on/off */
static int set_verity_enabled_state(int fd, const char *block_device,
                                    const char* mount_point, bool enable)
{
    uint32_t magic_number;
    const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
                                      : VERITY_METADATA_MAGIC_DISABLE;
    uint64_t device_length = 0;
    int device = -1;
    int retval = -1;

    if (make_block_device_writable(block_device)) {
        write_console(fd, "Could not make block device %s writable (%s).\n",
                      block_device, strerror(errno));
        goto errout;
    }

    device = adb_open(block_device, O_RDWR | O_CLOEXEC);
    if (device == -1) {
        write_console(fd, "Could not open block device %s (%s).\n",
                      block_device, strerror(errno));
        write_console(fd, "Maybe run adb remount?\n");
        goto errout;
    }

    // find the start of the verity metadata
    if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
        write_console(fd, "Could not get target device size.\n");
        goto errout;
    }

    if (lseek64(device, device_length, SEEK_SET) < 0) {
        write_console(fd,
                      "Could not seek to start of verity metadata block.\n");
        goto errout;
    }

    // check the magic number
    if (adb_read(device, &magic_number, sizeof(magic_number))
             != sizeof(magic_number)) {
        write_console(fd, "Couldn't read magic number!\n");
        goto errout;
    }

    if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
        write_console(fd, "Verity already disabled on %s\n", mount_point);
        goto errout;
    }

    if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
        write_console(fd, "Verity already enabled on %s\n", mount_point);
        goto errout;
    }

    if (magic_number != VERITY_METADATA_MAGIC_NUMBER
            && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
        write_console(fd,
                      "Couldn't find verity metadata at offset %" PRIu64 "!\n",
                      device_length);
        goto errout;
    }

    if (lseek64(device, device_length, SEEK_SET) < 0) {
        write_console(fd,
                      "Could not seek to start of verity metadata block.\n");
        goto errout;
    }

    if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
        write_console(
            fd, "Could not set verity %s flag on device %s with error %s\n",
            enable ? "enabled" : "disabled",
            block_device, strerror(errno));
        goto errout;
    }

    write_console(fd, "Verity %s on %s\n",
                  enable ? "enabled" : "disabled",
                  mount_point);
    retval = 0;
errout:
    if (device != -1)
        adb_close(device);
    return retval;
}
示例#13
0
static int create_subprocess(const char *cmd, const char *arg0,
                             const char *arg1, pid_t * pid)
{
#ifdef HAVE_WIN32_PROC
    D("create_subprocess(cmd=%s, arg0=%s, arg1=%s)\n", cmd, arg0, arg1);
    fprintf(stderr,
            "error: create_subprocess not implemented on Win32 (%s %s %s)\n",
            cmd, arg0, arg1);
    return -1;
#else                           /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;

    ptm = unix_open("/dev/ptmx", O_RDWR);   // | O_NOCTTY);
    if (ptm < 0) {
        printf("[ cannot open /dev/ptmx - %s ]\n", strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if (grantpt(ptm) || unlockpt(ptm) ||
        ((devname = (char *) ptsname(ptm)) == 0)) {
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    *pid = fork();
    if (*pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        adb_close(ptm);
        return -1;
    }

    if (*pid == 0) {
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if (pts < 0) {
            fprintf(stderr, "child failed to open pseudo-term slave: %s\n",
                    devname);
            exit(-1);
        }

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(pts);
        adb_close(ptm);

        // set OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", getpid());
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
            D("adb: unable to open %s\n", text);
        }
        execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
        // Don't set child's OOM adjustment to zero.
        // Let the child do it itself, as sometimes the parent starts
        // running before the child has a /proc/pid/oom_adj.
        // """adb: unable to open /proc/644/oom_adj""" seen in some logs.
        return ptm;
    }
#endif                          /* !HAVE_WIN32_PROC */
}
示例#14
0
static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
{
#ifdef HAVE_WIN32_PROC
	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
	return -1;
#else /* !HAVE_WIN32_PROC */
    char *devname;
    int ptm;
    pid_t pid;

    ptm = unix_open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
    if(ptm < 0){
        printf("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
        return -1;
    }
    fcntl(ptm, F_SETFD, FD_CLOEXEC);

    if(grantpt(ptm) || unlockpt(ptm) ||
       ((devname = (char*) ptsname(ptm)) == 0)){
        printf("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
        return -1;
    }

    pid = fork();
    if(pid < 0) {
        printf("- fork failed: %s -\n", strerror(errno));
        return -1;
    }

    if(pid == 0){
        int pts;

        setsid();

        pts = unix_open(devname, O_RDWR);
        if(pts < 0) exit(-1);

        dup2(pts, 0);
        dup2(pts, 1);
        dup2(pts, 2);

        adb_close(ptm);

        execl(cmd, cmd, arg0, arg1, NULL);
        fprintf(stderr, "- exec '%s' failed: %s (%d) -\n",
                cmd, strerror(errno), errno);
        exit(-1);
    } else {
#if !ADB_HOST
        // set child's OOM adjustment to zero
        char text[64];
        snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
        int fd = adb_open(text, O_WRONLY);
        if (fd >= 0) {
            adb_write(fd, "0", 1);
            adb_close(fd);
        } else {
           D("adb: unable to open %s\n", text);
        }
#endif
        return ptm;
    }
#endif /* !HAVE_WIN32_PROC */
}
static int do_send(int s, char *path, char *buffer)
{
    char *tmp;
    mode_t mode;
    int is_link, ret;

    tmp = strrchr(path,',');
    if(tmp) {
        *tmp = 0;
        errno = 0;
        mode = strtoul(tmp + 1, NULL, 0);
#ifndef HAVE_SYMLINKS
        is_link = 0;
#else
        is_link = S_ISLNK(mode);
#endif
        mode &= 0777;
    }
    if(!tmp || errno) {
        mode = 0644;
        is_link = 0;
    }

    adb_unlink(path);


#ifdef HAVE_SYMLINKS
    if(is_link)
        ret = handle_send_link(s, path, buffer);
    else {
#else
    {
#endif
        /* copy user permission bits to "group" and "other" permissions */
        mode |= ((mode >> 3) & 0070);
        mode |= ((mode >> 3) & 0007);

        ret = handle_send_file(s, path, mode, buffer);
    }

    return ret;
}

static int do_recv(int s, const char *path, char *buffer)
{
    syncmsg msg;
    int fd, r;

    fd = adb_open(path, O_RDONLY);
    if(fd < 0) {
        if(fail_errno(s)) return -1;
        return 0;
    }

    msg.data.id = ID_DATA;
    for(;;) {
        r = adb_read(fd, buffer, SYNC_DATA_MAX);
        if(r <= 0) {
            if(r == 0) break;
            if(errno == EINTR) continue;
            r = fail_errno(s);
            adb_close(fd);
            return r;
        }
        msg.data.size = htoll(r);
        if(writex(s, &msg.data, sizeof(msg.data)) ||
           writex(s, buffer, r)) {
            adb_close(fd);
            return -1;
        }
    }

    adb_close(fd);

    msg.data.id = ID_DONE;
    msg.data.size = 0;
    if(writex(s, &msg.data, sizeof(msg.data))) {
        return -1;
    }

    return 0;
}
int adb_main(int is_daemon)
{
#if !ADB_HOST
    int secure = 0;
    char value[PROPERTY_VALUE_MAX];

    // prevent the OOM killer from killing us
    char text[64];
    snprintf(text, sizeof text, "/proc/%d/oom_adj", (int)getpid());
    int fd = adb_open(text, O_WRONLY);
    if (fd >= 0) {
        // -17 should make us immune to OOM
        snprintf(text, sizeof text, "%d", -17);
        adb_write(fd, text, strlen(text));
        adb_close(fd);
    } else {
        D("adb: unable to open %s\n", text);
    }
#endif

    atexit(adb_cleanup);
#ifdef HAVE_WIN32_PROC
    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
#elif defined(HAVE_FORKEXEC)
    signal(SIGCHLD, sigchld_handler);
    signal(SIGPIPE, SIG_IGN);
#endif

    init_transport_registration();


#if ADB_HOST
    HOST = 1;
    usb_init();
    local_init();

    if(install_listener("tcp:5037", "*smartsocket*", NULL)) {
        exit(1);
    }
#else
    /* run adbd in secure mode if ro.secure is set and
    ** we are not in the emulator
    */
    property_get("ro.kernel.qemu", value, "");
    if (strcmp(value, "1") != 0) {
        property_get("ro.secure", value, "");
        if (strcmp(value, "1") == 0) {
            // don't run as root if ro.secure is set...
            secure = 1;

            // ... except we allow running as root in userdebug builds if the
            // service.adb.root property has been set by the "adb root" command
            property_get("ro.debuggable", value, "");
            if (strcmp(value, "1") == 0) {
                property_get("service.adb.root", value, "");
                if (strcmp(value, "1") == 0) {
                    secure = 0;
                }
            }
        }
    }

    /* don't listen on port 5037 if we are running in secure mode */
    /* don't run as root if we are running in secure mode */
    if (secure) {
        /* add extra groups:
        ** AID_ADB to access the USB driver
        ** AID_LOG to read system logs (adb logcat)
        ** AID_INPUT to diagnose input issues (getevent)
        ** AID_INET to diagnose network issues (netcfg, ping)
        ** AID_GRAPHICS to access the frame buffer
        ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
        */
        gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
                           AID_NET_BT, AID_NET_BT_ADMIN
                         };
        setgroups(sizeof(groups)/sizeof(groups[0]), groups);

        /* then switch user and group to "shell" */
        setgid(AID_SHELL);
        setuid(AID_SHELL);

        D("Local port 5037 disabled\n");
    } else {
        if(install_listener("tcp:5037", "*smartsocket*", NULL)) {
            exit(1);
        }
    }

    /* for the device, start the usb transport if the
    ** android usb device exists, otherwise start the
    ** network transport.
    */
    if(access("/dev/android_adb", F_OK) == 0 ||
            access("/dev/android", F_OK) == 0) {
        usb_init();
    } else {
        local_init();
    }
    init_jdwp();
#endif

    if (is_daemon)
    {
        // inform our parent that we are up and running.
#ifdef HAVE_WIN32_PROC
        DWORD  count;
        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
#elif defined(HAVE_FORKEXEC)
        fprintf(stderr, "OK\n");
#endif
        start_logging();
    }

    fdevent_loop();

    usb_cleanup();

    return 0;
}