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