| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 
 | // Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// MtabWatcherLinux implementation.
#include "components/storage_monitor/mtab_watcher_linux.h"
#include <mntent.h>
#include <stdio.h>
#include "base/bind.h"
#include "content/public/browser/browser_thread.h"
namespace {
// List of file systems we care about.
const char* const kKnownFileSystems[] = {
  "btrfs",
  "ext2",
  "ext3",
  "ext4",
  "fat",
  "hfsplus",
  "iso9660",
  "msdos",
  "ntfs",
  "udf",
  "vfat",
};
}  // namespace
namespace storage_monitor {
MtabWatcherLinux::MtabWatcherLinux(const base::FilePath& mtab_path,
                                   base::WeakPtr<Delegate> delegate)
    : mtab_path_(mtab_path),
      delegate_(delegate),
      weak_ptr_factory_(this) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  bool ret = file_watcher_.Watch(
      mtab_path_, false,
      base::Bind(&MtabWatcherLinux::OnFilePathChanged,
                 weak_ptr_factory_.GetWeakPtr()));
  if (!ret) {
    LOG(ERROR) << "Adding watch for " << mtab_path_.value() << " failed";
    return;
  }
  ReadMtab();
}
MtabWatcherLinux::~MtabWatcherLinux() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
}
void MtabWatcherLinux::ReadMtab() const {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  FILE* fp = setmntent(mtab_path_.value().c_str(), "r");
  if (!fp)
    return;
  MountPointDeviceMap device_map;
  mntent entry;
  char buf[512];
  // We return the same device mounted to multiple locations, but hide
  // devices that have been mounted over.
  while (getmntent_r(fp, &entry, buf, sizeof(buf))) {
    // We only care about real file systems.
    for (size_t i = 0; i < arraysize(kKnownFileSystems); ++i) {
      if (strcmp(kKnownFileSystems[i], entry.mnt_type) == 0) {
        device_map[base::FilePath(entry.mnt_dir)] =
            base::FilePath(entry.mnt_fsname);
        break;
      }
    }
  }
  endmntent(fp);
  content::BrowserThread::PostTask(
      content::BrowserThread::UI, FROM_HERE,
      base::Bind(&Delegate::UpdateMtab, delegate_, device_map));
}
void MtabWatcherLinux::OnFilePathChanged(
    const base::FilePath& path, bool error) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
  if (path != mtab_path_) {
    // This cannot happen unless FilePathWatcher is buggy. Just ignore this
    // notification and do nothing.
    NOTREACHED();
    return;
  }
  if (error) {
    LOG(ERROR) << "Error watching " << mtab_path_.value();
    return;
  }
  ReadMtab();
}
}  // namespace storage_monitor
 |