Пример #1
0
dev_t DirectVolume::getShareDevice() {
    if (mPartIdx != -1) {
#ifdef VOLD_DISC_HAS_MULTIPLE_MAJORS
        int major = getMajorNumberForBadPartition(mPartIdx);
        if(major != -1) {
            SLOGE("getShareDevice() returning correct major: %d, minor: %d", major, mPartMinors[mPartIdx - 1]);
            return MKDEV(major, mPartMinors[mPartIdx - 1]);
        }
        else
#endif
        return MKDEV(mDiskMajor, mPartIdx);
    } else {
        return MKDEV(mDiskMajor, mDiskMinor);
    }
}
Пример #2
0
int VolumeManager::unmountAsec(const char *id, bool force) {
    char asecFileName[255];
    char mountPoint[255];

    snprintf(asecFileName, sizeof(asecFileName), "%s/%s.asec", Volume::SEC_ASECDIR, id);
    snprintf(mountPoint, sizeof(mountPoint), "%s/%s", Volume::ASECDIR, id);

    char idHash[33];
    if (!asecHash(id, idHash, sizeof(idHash))) {
        SLOGE("Hash of '%s' failed (%s)", id, strerror(errno));
        return -1;
    }

    return unmountLoopImage(id, idHash, asecFileName, mountPoint, force);
}
Пример #3
0
int NetlinkManager::stop()
{
    if (mHandler->stop())
    {
        SLOGE("Unable to stop NetlinkHandler: %s", strerror(errno));
        return -1;
    }
    delete mHandler;
    mHandler = NULL;

    close(mSock);
    mSock = -1;

    return 0;
}
Пример #4
0
static int load_qseecom_library()
{
    const char *error = NULL;
    if (loaded_library)
        return loaded_library;

    void * handle = dlopen(QSEECOM_LIBRARY_PATH, RTLD_NOW);
    if(handle) {
        dlerror(); /* Clear any existing error */
        *(void **) (&qseecom_create_key) = dlsym(handle,"QSEECom_create_key");

        if((error = dlerror()) == NULL) {
            SLOGD("Success loading QSEECom_create_key \n");
            *(void **) (&qseecom_update_key) = dlsym(handle,"QSEECom_update_key_user_info");
            if ((error = dlerror()) == NULL) {
                SLOGD("Success loading QSEECom_update_key_user_info\n");
                *(void **) (&qseecom_wipe_key) = dlsym(handle,"QSEECom_wipe_key");
                if ((error = dlerror()) == NULL) {
                    loaded_library = 1;
                    SLOGD("Success loading QSEECom_wipe_key \n");
                }
                else
                    SLOGE("Error %s loading symbols for QSEECom APIs \n", error);
            }
            else
                SLOGE("Error %s loading symbols for QSEECom APIs \n", error);
        }
    } else {
        SLOGE("Could not load libQSEEComAPI.so \n");
    }

    if(error)
        dlclose(handle);

    return loaded_library;
}
bool SocketClient::decRef() {
    bool deleteSelf = false;
    pthread_mutex_lock(&mRefCountMutex);
    mRefCount--;
    if (mRefCount == 0) {
        deleteSelf = true;
    } else if (mRefCount < 0) {
        SLOGE("SocketClient refcount went negative!");
    }
    pthread_mutex_unlock(&mRefCountMutex);
    if (deleteSelf) {
        delete this;
    }
    return deleteSelf;
}
Пример #6
0
int main(int argc, char **argv) {
    if (argc != 2 || argv[1][0] != '/') {
        usage(argv[0]);
        return -1;
    }
    SLOGD("Running: %s %s", argv[0], argv[1]);
    std::string target(argv[1]);
    destroy_key(target);
    if (unlink(argv[1]) != 0 && errno != ENOENT) {
        SLOGE("Unable to delete %s: %s",
            argv[1], strerror(errno));
        return -1;
    }
    return 0;
}
int SsServerDeleteFile(int sender_pid, const char* data_filepath, ssm_flag flag, const char* cookie, const char* group_id)
{
	const char* in_filepath = data_filepath;
	char out_filepath[MAX_FILENAME_LEN] = {0, };

	//0. privilege check and get directory name
	if(check_privilege(cookie, group_id) != 0)
	{
		SLOGE("[%s] permission denied\n", __func__);
		return SS_PERMISSION_DENIED;
	}

	// 1. create out file name
	ConvertFileName(sender_pid, out_filepath, in_filepath, flag, group_id);
	
	// 2. delete designated file
	if(unlink(out_filepath) != 0)	// unlink fail?
	{
		SLOGE("[%s] error occured while deleting file\n", __func__);
		return SS_FILE_WRITE_ERROR;
	}
	
	return 1;
}
Пример #8
0
int Volume::doUnmount(const char *path, bool force) {
    int retries = 3;
    int need_to_wait_count = 0;
    bool need_to_wait = false;

    bool isHotPlug = mVm->getHotPlug();
    if (isHotPlug == true) {
        retries = 5;        
    }

    SLOGD("doUnmount: %s retries = %d, isHotPlug=%d", path, retries, isHotPlug);

    if (mDebug) {
        SLOGD("Unmounting {%s}, force = %d", path, force);
    }

    while (retries--) {
        if (!umount(path) || errno == EINVAL || errno == ENOENT) {
            SLOGI("%s sucessfully unmounted", path);
            return 0;
        }

        int action = 0;

        if (force) {
            if (retries == 1) {
                action = 2; // SIGKILL
            } else if (retries == 2) {
                action = 1; // SIGHUP
            }
        }

        SLOGW("Failed to unmount %s (%s, retries %d, action %d)",
                path, strerror(errno), retries, action);

        Process::killProcessesWithOpenFiles(path, action);
        if (retries > 0) 
          usleep(1000*1000);
        
        if(isHotPlug && (retries == 1))
            usleep(1000*1000);

    }
    errno = EBUSY;
    SLOGE("Giving up on unmount %s (%s)", path, strerror(errno));
    Process::FindProcessesWithOpenFiles(path);
    return -1;
}
Пример #9
0
static int e4crypt_install_key(const ext4_encryption_key &ext4_key, const std::string &ref)
{
    key_serial_t device_keyring = e4crypt_keyring();
    SLOGI("Found device_keyring - id is %d", device_keyring);
    key_serial_t key_id = add_key("logon", ref.c_str(),
                                  (void*)&ext4_key, sizeof(ext4_key),
                                  device_keyring);
    if (key_id == -1) {
        SLOGE("Failed to insert key into keyring with error %s",
              strerror(errno));
        return -1;
    }
    SLOGI("Added key %d (%s) to keyring %d in process %d",
          key_id, ref.c_str(), device_keyring, getpid());
    return 0;
}
Пример #10
0
void DirectVolume::handlePartitionAdded(const char *devpath, NetlinkEvent *evt) {
    int major = atoi(evt->findParam("MAJOR"));
    int minor = atoi(evt->findParam("MINOR"));

    int part_num;

    const char *tmp = evt->findParam("PARTN");

    if (tmp) {
        part_num = atoi(tmp);
    } else {
        SLOGW("Kernel block uevent missing 'PARTN'");
        part_num = 1;
    }

    if (part_num > MAX_PARTITIONS || part_num < 1) {
        SLOGW("Invalid 'PARTN' value");
        part_num = 1;
    }

    if (part_num > mDiskNumParts) {
        mDiskNumParts = part_num;
    }

    if (major != mDiskMajor) {
        SLOGE("Partition '%s' has a different major than its disk!", devpath);
        return;
    }
#ifdef PARTITION_DEBUG
    SLOGD("Dv:partAdd: part_num = %d, minor = %d\n", part_num, minor);
#endif
    mPartMinors[part_num -1] = minor;

    mPendingPartMap &= ~(1 << part_num);
    if (!mPendingPartMap) {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: Got all partitions - ready to rock!");
#endif
        if (getState() != Volume::State_Formatting) {
            setState(Volume::State_Idle);
        }
    } else {
#ifdef PARTITION_DEBUG
        SLOGD("Dv:partAdd: pending mask now = 0x%x", mPendingPartMap);
#endif
    }
}
// hunt down and kill processes that have files open on the given mount point
void killProcessesWithOpenFiles(const char *path, int action)
{
    DIR *dir;
    struct dirent *de;

    if (!(dir = opendir("/proc"))) {
        SLOGE("opendir failed (%s)", strerror(errno));
        return;
    }

    while ((de = readdir(dir))) {
        int pid = getPid(de->d_name);
        char name[PATH_MAX];

        if (pid == -1)
            continue;
        getProcessName(pid, name, sizeof(name));

        char openfile[PATH_MAX];

        if (checkfileDescriptorSymLinks
                (pid, path, openfile, sizeof(openfile))) {
            SLOGE("Process %s (%d) has open file %s", name, pid,
                  openfile);
        } else if (checkfileMaps(pid, path, openfile, sizeof(openfile))) {
            SLOGE("Process %s (%d) has open filemap for %s", name,
                  pid, openfile);
        } else if (checkSymLink(pid, path, "cwd")) {
            SLOGE("Process %s (%d) has cwd within %s", name, pid,
                  path);
        } else if (checkSymLink(pid, path, "root")) {
            SLOGE("Process %s (%d) has chroot within %s", name, pid,
                  path);
        } else if (checkSymLink(pid, path, "exe")) {
            SLOGE("Process %s (%d) has executable path within %s",
                  name, pid, path);
        } else {
            continue;
        }
        if (action == 1) {
            SLOGW("Sending SIGHUP to process %d", pid);
            kill(pid, SIGTERM);
        } else if (action == 2) {
            SLOGE("Sending SIGKILL to process %d", pid);
            kill(pid, SIGKILL);
        }
    }
    closedir(dir);
}
Пример #12
0
int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
    char asecFileName[255];

    if (findAsec(id, asecFileName, sizeof(asecFileName))) {
        SLOGE("Couldn't find ASEC %s", id);
        return -1;
    }

    memset(buffer, 0, maxlen);
    if (access(asecFileName, F_OK)) {
        errno = ENOENT;
        return -1;
    }

    snprintf(buffer, maxlen, "%s", asecFileName);
    return 0;
}
Пример #13
0
int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
    char idHash[33];
    if (!asecHash(sourceFile, idHash, sizeof(idHash))) {
        SLOGE("Hash of '%s' failed (%s)", sourceFile, strerror(errno));
        return -1;
    }

    memset(mountPath, 0, mountPathLen);
    snprintf(mountPath, mountPathLen, "%s/%s", Volume::LOOPDIR, idHash);

    if (access(mountPath, F_OK)) {
        errno = ENOENT;
        return -1;
    }

    return 0;
}
Пример #14
0
// BLKSECDISCARD all content in "path", if it's small enough.
static void destroy_key(const std::string &path) {
    uint64_t range[2];
    if (file_device_range(path, range) < 0) {
        return;
    }
    int fs_fd = open_block_device_for_path(path);
    if (fs_fd < 0) {
        return;
    }
    if (ioctl(fs_fd, BLKSECDISCARD, range) != 0) {
        SLOGE("Unable to BLKSECDISCARD %s: %s", path.c_str(), strerror(errno));
        close(fs_fd);
        return;
    }
    close(fs_fd);
    SLOGD("Discarded %s", path.c_str());
}
bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
    int dirfd = open(dir, O_DIRECTORY);
    if (dirfd < 0) {
        SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
        return -1;
    }

    bool ret = false;

    if (!faccessat(dirfd, asecName, F_OK, AT_SYMLINK_NOFOLLOW)) {
        ret = true;
    }

    close(dirfd);

    return ret;
}
int IsDirExist(char* dirpath)
{
	DIR* dp = NULL;
	
	if((dp = opendir(dirpath)) == NULL) // dir is not exist
	{
		SLOGE("[%s] directory [%s] is not exist.\n", __func__, dirpath);
		return 0; // return value '0' represents dir is not exist
	}
	else
	{
		closedir(dp);
		return 1;
	}

	return -1;
}
Пример #17
0
bool LogAudit::onDataAvailable(SocketClient *cli) {
    prctl(PR_SET_NAME, "logd.auditd");

    struct audit_message rep;

    rep.nlh.nlmsg_type = 0;
    rep.nlh.nlmsg_len = 0;
    rep.data[0] = '\0';

    if (audit_get_reply(cli->getSocket(), &rep, GET_REPLY_BLOCKING, 0) < 0) {
        SLOGE("Failed on audit_get_reply with error: %s", strerror(errno));
        return false;
    }

    logPrint("type=%d %.*s", rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);

    return true;
}
Пример #18
0
void Volume::protectFromAutorunStupidity() {
    char filename[255];

    snprintf(filename, sizeof(filename), "%s/autorun.inf", SEC_STGDIR);
    if (!access(filename, F_OK)) {
        SLOGW("Volume contains an autorun.inf! - removing");
        /*
         * Ensure the filename is all lower-case so
         * the process killer can find the inode.
         * Probably being paranoid here but meh.
         */
        rename(filename, filename);
        Process::killProcessesWithOpenFiles(filename, 2);
        if (unlink(filename)) {
            SLOGE("Failed to remove %s (%s)", filename, strerror(errno));
        }
    }
}
/* Should we use keymaster? */
static int keymaster_check_compatibility_old()
{
    keymaster0_device_t *keymaster0_dev = 0;
    keymaster1_device_t *keymaster1_dev = 0;
    int rc = 0;

    if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) {
        SLOGE("Failed to init keymaster");
        rc = -1;
        goto out;
    }

    if (keymaster1_dev) {
        rc = 1;
        goto out;
    }

    if (!keymaster0_dev || !keymaster0_dev->common.module) {
        rc = -1;
        goto out;
    }

    // TODO(swillden): Check to see if there's any reason to require v0.3.  I think v0.1 and v0.2
    // should work.
    if (keymaster0_dev->common.module->module_api_version
            < KEYMASTER_MODULE_API_VERSION_0_3) {
        rc = 0;
        goto out;
    }

    if (!(keymaster0_dev->flags & KEYMASTER_SOFTWARE_ONLY) &&
        (keymaster0_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE)) {
        rc = 1;
    }

out:
    if (keymaster1_dev) {
        keymaster1_close(keymaster1_dev);
    }
    if (keymaster0_dev) {
        keymaster0_close(keymaster0_dev);
    }
    return rc;
}
int VolumeManager::listMountedObbs(SocketClient* cli) {
    char device[256];
    char mount_path[256];
    char rest[256];
    FILE *fp;
    char line[1024];

    if (!(fp = fopen("/proc/mounts", "r"))) {
        SLOGE("Error opening /proc/mounts (%s)", strerror(errno));
        return -1;
    }

    // Create a string to compare against that has a trailing slash
    int loopDirLen = strlen(Volume::LOOPDIR);
    char loopDir[loopDirLen + 2];
    strcpy(loopDir, Volume::LOOPDIR);
    loopDir[loopDirLen++] = '/';
    loopDir[loopDirLen] = '\0';

    while(fgets(line, sizeof(line), fp)) {
        line[strlen(line)-1] = '\0';

        /*
         * Should look like:
         * /dev/block/loop0 /mnt/obb/fc99df1323fd36424f864dcb76b76d65 ...
         */
        sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);

        if (!strncmp(mount_path, loopDir, loopDirLen)) {
            int fd = open(device, O_RDONLY);
            if (fd >= 0) {
                struct loop_info64 li;
                if (ioctl(fd, LOOP_GET_STATUS64, &li) >= 0) {
                    cli->sendMsg(ResponseCode::AsecListResult,
                            (const char*) li.lo_file_name, false);
                }
                close(fd);
            }
        }
    }

    fclose(fp);
    return 0;
}
Пример #21
0
// Given a file path, look for the corresponding
// block device in /proc/mounts and open it.
static int open_block_device_for_path(const std::string &path)
{
    std::string mountsfile("/proc/mounts");
    std::string mounts;
    if (read_file_as_string_atomically(mountsfile, mounts) < 0) {
        return -1;
    }
    std::string block_device;
    if (find_block_device_for_path(mounts, path, block_device) < 0) {
        return -1;
    }
    SLOGD("For path %s block device is %s", path.c_str(), block_device.c_str());
    int res = open(block_device.c_str(), O_RDWR | O_LARGEFILE | O_CLOEXEC);
    if (res < 0) {
        SLOGE("Failed to open device %s: %s", block_device.c_str(), strerror(errno));
        return -1;
    }
    return res;
}
Пример #22
0
int Volume::formatVol() {

    if (getState() == Volume::State_NoMedia) {
        errno = ENODEV;
        return -1;
    } else if (getState() != Volume::State_Idle) {
        errno = EBUSY;
        return -1;
    }

    if (isMountpointMounted(getMountpoint())) {
        SLOGW("Volume is idle but appears to be mounted - fixing");
        setState(Volume::State_Mounted);
        // mCurrentlyMountedKdev = XXX
        errno = EBUSY;
        return -1;
    }

    // Just format one partition but not the whole disk
    if (devicePath[0] == 0)
    {
        dev_t diskNode = getDiskDevice();
        dev_t partNode = MKDEV(MAJOR(diskNode), 1); // XXX: Hmmm

        sprintf(devicePath, "/dev/block/vold/%d:%d",
                MAJOR(diskNode), MINOR(diskNode));
    }

    if (mDebug) {
        SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
    }
    setState(Volume::State_Formatting);

    if (Fat::format(devicePath, 0)) {
        SLOGE("Failed to format (%s)", strerror(errno));
        goto err;
    }

    setState(Volume::State_Idle);
    return 0;
err:
    return -1;
}
char* get_preserved_dir()
{
	FILE* fp_conf = NULL;
	char buf[128];
	char* retbuf = NULL;
	char seps[] = " :\n\r\t";
	char* token = NULL;

	retbuf = (char*)malloc(sizeof(char) * 128);
	memset(buf, 0x00, 128);
	memset(retbuf, 0x00, 128);

	if(!(fp_conf = fopen(CONF_FILE_PATH, "r")))
	{
		SLOGE("[%s] Configuration file is not exist\n", __func__);
		free(retbuf);
		return NULL;
	}
	
	while(fgets(buf, 128, fp_conf))
	{
		token = strtok(buf, seps);
		if(!strncmp(token, "PRESERVE_DIR", 12))	// preserve directory?
		{
			token = strtok(NULL, seps);	// real path
			break;
		}

		token = NULL;
	}
	fclose(fp_conf);

	if(token)
		strncpy(retbuf, token, 127);
	else {
		if(retbuf != NULL)
			free(retbuf);
		return NULL;
	}

	return retbuf;
}
/* This signs the given object using the keymaster key. */
static int keymaster_sign_object_new(struct crypt_mnt_ftr *ftr,
                                 const unsigned char *object,
                                 const size_t object_size,
                                 unsigned char **signature,
                                 size_t *signature_size)
{
    unsigned char to_sign[RSA_KEY_SIZE_BYTES];
    size_t to_sign_size = sizeof(to_sign);
    memset(to_sign, 0, RSA_KEY_SIZE_BYTES);

    // To sign a message with RSA, the message must satisfy two
    // constraints:
    //
    // 1. The message, when interpreted as a big-endian numeric value, must
    //    be strictly less than the public modulus of the RSA key.  Note
    //    that because the most significant bit of the public modulus is
    //    guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit
    //    key), an n-bit message with most significant bit 0 always
    //    satisfies this requirement.
    //
    // 2. The message must have the same length in bits as the public
    //    modulus of the RSA key.  This requirement isn't mathematically
    //    necessary, but is necessary to ensure consistency in
    //    implementations.
    switch (ftr->kdf_type) {
        case KDF_SCRYPT_KEYMASTER:
            // This ensures the most significant byte of the signed message
            // is zero.  We could have zero-padded to the left instead, but
            // this approach is slightly more robust against changes in
            // object size.  However, it's still broken (but not unusably
            // so) because we really should be using a proper deterministic
            // RSA padding function, such as PKCS1.
            memcpy(to_sign + 1, object, min(RSA_KEY_SIZE_BYTES - 1, object_size));
            SLOGI("Signing safely-padded object");
            break;
        default:
            SLOGE("Unknown KDF type %d", ftr->kdf_type);
            return -1;
    }
    return keymaster_sign_object_for_cryptfs_scrypt(ftr->keymaster_blob, ftr->keymaster_blob_size,
            KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign, to_sign_size, signature, signature_size);
}
Пример #25
0
int main(void)
{
  /* Library initialization.  Must be called only once. */
  SLOG_Init(SLOG_STDERR, "example02-log.txt");

  /* Setting log levels: all messages to console and all to the file.
   * Default settings are: all messages to file and >= INFO to console. */
  SLOG_SetLevel(SLOG_DEBUG, SLOG_DEBUG);

  SLOGD(TAG, "debug message");
  SLOGI(TAG, "info");
  SLOGW(TAG, "warning");
  SLOGE(TAG, "error");

  SLOGI(TAG, "formatted message (%d, %s)", 123, "bar");

  /* Library deinitialization. */
  SLOG_Deinit();
  return 0;
}
bool NotificationManager::onDataAvailable(NuSocketClient *cli)
{
    int socket = cli->getSocket();
    ssize_t count;

    count = TEMP_FAILURE_RETRY(read(socket, mBuffer, sizeof(mBuffer)));
    if (count < 0 || count > 4) {
        SLOGE("recvmsg failed (%s)", strerror(errno));
        return false;
    } else if (count == 0){
        LOGD("count = 0, client closed!");
        return false;
    }
    

    int *value = (int *)&mBuffer[0];
    onCommand(*value); 

    return true;
}
Пример #27
0
int Ext::format(const char *fsPath) {
    int fd;
    const char *args[3];
    int rc;

    args[0] = MKEXTFS_PATH;
    args[1] = fsPath;
    args[2] = NULL;
    rc = logwrap(3, args, 1);

    if (rc == 0) {
        SLOGI("Filesystem formatted OK");
        return 0;
    } else {
        SLOGE("Format failed (unknown exit code %d)", rc);
        errno = EIO;
        return -1;
    }
    return 0;
}
Пример #28
0
int main (int argc, char* argv[]) {
  int ret;
  if (argc != 2) {
    fprintf(stderr, "Usage: %s <flush-frequency-in-seconds>\n", argv[0]);
    ret = -1;
  } else {
    hw_module_t* module;
    ret = hw_get_module(MRKNLOG_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
    if (ret == 0) {
      struct mrknlog_device_t *dev;
      ret = module->methods->open(module, 0, (struct hw_device_t **) &dev);
      if (ret == 0) {
        int frequency = atoi(argv[1]);
        int totalSize = dev->get_total_log_size(dev);
        int usedSize;
        int count = 1;
        while(runFlag) {
          usedSize = dev->get_used_log_size(dev);
          if (dev->flush_log(dev) == 0) {
            SLOGI("Flushed log (%d, %d of %d bytes). Waiting %d seconds before the next flush.", 
              count, usedSize, totalSize, frequency);
          } else {
            SLOGE("Failed to flush log. Bailing out");
            break;
          }
          count++;
          sleep(frequency);
        }
        SLOGI("Done after %d iterations.", count);
        dev->common.close((struct hw_device_t *)dev);
      } else {
        fprintf(stderr, "Failed to open device: %d", ret);
        ret = -2;
      }
    } else {
      fprintf(stderr, "Failed to get module: %s", MRKNLOG_HARDWARE_MODULE_ID);
      ret = -3;    
    }
  }
  return ret;
}
int VolumeManager::mkdirs(char* path) {
    // Require that path lives under a volume we manage
    const char* emulated_source = getenv("EMULATED_STORAGE_SOURCE");
    const char* root = NULL;
    if (emulated_source && !strncmp(path, emulated_source, strlen(emulated_source))) {
        root = emulated_source;
    } else {
        Volume* vol = getVolumeForFile(path);
        if (vol) {
            root = vol->getMountpoint();
        }
    }

    if (!root) {
        SLOGE("Failed to find volume for %s", path);
        return -EINVAL;
    }

    /* fs_mkdirs() does symlink checking and relative path enforcement */
    return fs_mkdirs(path, 0700);
}
Пример #30
0
bool FrameworkListener::onDataAvailable(SocketClient *c) {
    char buffer[255];
    int len;

    if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
        SLOGE("read() failed (%s)", strerror(errno));
        return false;
    } else if (!len)
        return false;

    int offset = 0;
    int i;

    for (i = 0; i < len; i++) {
        if (buffer[i] == '\0') {
            dispatchCommand(c, buffer + offset);
            offset = i + 1;
        }
    }
    return true;
}