2 * Copyright (C) 2012-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "AndroidStorageProvider.h"
22 #include "android/activity/XBMCApp.h"
23 #include "guilib/LocalizeStrings.h"
24 #include "filesystem/File.h"
26 #include "utils/log.h"
27 #include "utils/RegExp.h"
28 #include "utils/StringUtils.h"
29 #include "utils/URIUtils.h"
35 CAndroidStorageProvider::CAndroidStorageProvider()
37 m_removableLength = 0;
38 PumpDriveChangeEvents(NULL);
41 std::string CAndroidStorageProvider::unescape(const std::string& str)
43 std::string retString;
44 for (uint32_t i=0; i < str.length(); ++i)
51 if (str[i] == 'u') // unicode
55 else if (str[i] >= '0' && str[i] <= '7') // octal
57 std::string octString;
58 while (str[i] >= '0' && str[i] <= '7')
63 if (octString.length() != 0)
66 for (int j=octString.length()-1; j>=0; --j)
68 val += ((uint8_t)(octString[j] - '0')) * (1 << ((octString.length() - (j+1)) * 3));
70 retString += (char)val;
79 void CAndroidStorageProvider::GetLocalDrives(VECSOURCES &localDrives)
85 if (CXBMCApp::GetExternalStorage(path) && !path.empty() && XFILE::CFile::Exists(path))
88 share.strName = g_localizeStrings.Get(21456);
89 share.m_ignore = true;
90 localDrives.push_back(share);
95 share.strName = g_localizeStrings.Get(21453);
96 localDrives.push_back(share);
99 void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES &removableDrives)
104 std::map<std::string, std::string> result;
106 reMount.RegComp("^(.+?)\\s+(.+?)\\s+(.+?)\\s");
108 /* /proc/mounts is only guaranteed atomic for the current read
109 * operation, so we need to read it all at once.
111 if ((pipe = fopen("/proc/mounts", "r")))
114 size_t buf_len = 4096;
116 while ((new_buf = (char*)realloc(buf, buf_len * sizeof(char))))
121 nread = fread(buf, sizeof(char), buf_len, pipe);
123 if (nread == buf_len)
145 CLog::Log(LOGERROR, "Cannot read mount points");
150 char* saveptr = NULL;
152 line = strtok_r(buf, "\n", &saveptr);
156 if (reMount.RegFind(line) != -1)
158 bool accepted = false;
159 std::string device = reMount.GetReplaceString("\\1");
160 std::string mountStr = reMount.GetReplaceString("\\2");
161 std::string fsStr = reMount.GetReplaceString("\\3");
162 const char* fs = fsStr.c_str();
164 // Here we choose which filesystems are approved
165 if (strcmp(fs, "fuseblk") == 0 || strcmp(fs, "vfat") == 0
166 || strcmp(fs, "ext2") == 0 || strcmp(fs, "ext3") == 0 || strcmp(fs, "ext4") == 0
167 || strcmp(fs, "reiserfs") == 0 || strcmp(fs, "xfs") == 0
168 || strcmp(fs, "ntfs-3g") == 0 || strcmp(fs, "iso9660") == 0
169 || strcmp(fs, "exfat") == 0
170 || strcmp(fs, "fusefs") == 0 || strcmp(fs, "hfs") == 0)
174 if (!StringUtils::StartsWith(device, "/dev/block/vold/") ||
175 mountStr.find("sdcard") != std::string::npos)
179 result[device] = mountStr;
181 line = strtok_r(NULL, "\n", &saveptr);
186 for (std::map<std::string, std::string>::const_iterator i = result.begin(); i != result.end(); ++i)
189 share.strPath = unescape(i->second);
190 share.strName = URIUtils::GetFileName(share.strPath);
191 share.m_ignore = true;
192 removableDrives.push_back(share);
196 std::vector<CStdString> CAndroidStorageProvider::GetDiskUsage()
198 std::vector<CStdString> result;
202 CXBMCApp::GetStorageUsage("", usage);
203 result.push_back(usage);
207 if (CXBMCApp::GetStorageUsage("/", usage) && !usage.empty())
208 result.push_back(usage);
211 // add external storage if available
213 if (CXBMCApp::GetExternalStorage(path) && !path.empty() &&
214 CXBMCApp::GetStorageUsage(path, usage) && !usage.empty())
215 result.push_back(usage);
217 // add removable storage
219 GetRemovableDrives(drives);
220 for (unsigned int i = 0; i < drives.size(); i++)
223 if (CXBMCApp::GetStorageUsage(drives[i].strPath, usage) && !usage.empty())
224 result.push_back(usage);
230 bool CAndroidStorageProvider::Eject(CStdString mountpath)
235 bool CAndroidStorageProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback)
238 GetRemovableDrives(drives);
239 bool changed = drives.size() != m_removableLength;
240 m_removableLength = drives.size();