Home | History | Annotate | Download | only in jni
      1 // Copyright 2017 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "file_utils.h"
      6 
      7 #include <ctype.h>
      8 #include <errno.h>
      9 #include <fcntl.h>
     10 #include <stdio.h>
     11 #include <string.h>
     12 #include <sys/stat.h>
     13 #include <sys/types.h>
     14 
     15 namespace {
     16 
     17 bool IsNumeric(const char* str) {
     18   if (!str[0])
     19     return false;
     20   for (const char* c = str; *c; c++) {
     21     if (!isdigit(*c))
     22       return false;
     23   }
     24   return true;
     25 }
     26 
     27 }  // namespace
     28 
     29 namespace file_utils {
     30 
     31 void ForEachPidInProcPath(const char* proc_path,
     32                           std::function<void(int)> predicate) {
     33   DIR* root_dir = opendir(proc_path);
     34   ScopedDir autoclose(root_dir);
     35   struct dirent* child_dir;
     36   while ((child_dir = readdir(root_dir))) {
     37     if (child_dir->d_type != DT_DIR || !IsNumeric(child_dir->d_name))
     38       continue;
     39     predicate(atoi(child_dir->d_name));
     40   }
     41 }
     42 
     43 ssize_t ReadFile(const char* path, char* buf, size_t length) {
     44   buf[0] = '\0';
     45   int fd = open(path, O_RDONLY);
     46   if (fd < 0 && errno == ENOENT)
     47     return -1;
     48   ScopedFD autoclose(fd);
     49   size_t tot_read = 0;
     50   do {
     51     ssize_t rsize = read(fd, buf + tot_read, length - tot_read);
     52     if (rsize == 0)
     53       break;
     54     if (rsize == -1 && errno == EINTR)
     55       continue;
     56     else if (rsize < 0)
     57       return -1;
     58     tot_read += static_cast<size_t>(rsize);
     59   } while (tot_read < length);
     60   buf[tot_read < length ? tot_read : length - 1] = '\0';
     61   return tot_read;
     62 }
     63 
     64 bool ReadFileTrimmed(const char* path, char* buf, size_t length) {
     65   ssize_t rsize = ReadFile(path, buf, length);
     66   if (rsize < 0)
     67     return false;
     68   for (ssize_t i = 0; i < rsize; i++) {
     69     const char c = buf[i];
     70     if (c == '\0' || c == '\r' || c == '\n') {
     71       buf[i] = '\0';
     72       break;
     73     }
     74     buf[i] = isprint(c) ? c : '?';
     75   }
     76   return true;
     77 }
     78 
     79 ssize_t ReadProcFile(int pid, const char* proc_file, char* buf, size_t length) {
     80   char proc_path[128];
     81   snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
     82   return ReadFile(proc_path, buf, length);
     83 }
     84 
     85 // Reads a single-line proc file, stripping out any \0, \r, \n and replacing
     86 // non-printable charcters with '?'.
     87 bool ReadProcFileTrimmed(int pid,
     88                          const char* proc_file,
     89                          char* buf,
     90                          size_t length) {
     91   char proc_path[128];
     92   snprintf(proc_path, sizeof(proc_path), "/proc/%d/%s", pid, proc_file);
     93   return ReadFileTrimmed(proc_path, buf, length);
     94 }
     95 
     96 LineReader::LineReader(char* buf, size_t size)
     97     : ptr_(buf), end_(buf + size) {
     98 }
     99 
    100 LineReader::~LineReader() {
    101 }
    102 
    103 const char* LineReader::NextLine() {
    104   if (ptr_ >= end_)
    105     return nullptr;
    106   const char* cur = ptr_;
    107   char* next = strchr(ptr_, '\n');
    108   if (next) {
    109     *next = '\0';
    110     ptr_ = next + 1;
    111   } else {
    112     ptr_ = end_;
    113   }
    114   return cur;
    115 }
    116 
    117 }  // namespace file_utils
    118