* limitations under the License.
*/
-#ifndef _VOLUMEMANAGER_H
-#define _VOLUMEMANAGER_H
+#ifndef ANDROID_VOLD_VOLUME_MANAGER_H
+#define ANDROID_VOLD_VOLUME_MANAGER_H
#include <pthread.h>
+#include <fnmatch.h>
+#include <stdlib.h>
#ifdef __cplusplus
+
+#include <list>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+
+#include <cutils/multiuser.h>
#include <utils/List.h>
+#include <utils/Timers.h>
#include <sysutils/SocketListener.h>
+#include <sysutils/NetlinkEvent.h>
-#include "Volume.h"
+#include "Disk.h"
+#include "VolumeBase.h"
/* The length of an MD5 hash when encoded into ASCII hex characters */
#define MD5_ASCII_LENGTH_PLUS_NULL ((MD5_DIGEST_LENGTH*2)+1)
typedef android::List<ContainerData*> AsecIdCollection;
class VolumeManager {
+public:
+ static const char *SEC_ASECDIR_EXT;
+ static const char *SEC_ASECDIR_INT;
+ static const char *ASECDIR;
+ static const char *LOOPDIR;
+
private:
static VolumeManager *sInstance;
-private:
SocketListener *mBroadcaster;
- VolumeCollection *mVolumes;
AsecIdCollection *mActiveContainers;
bool mDebug;
public:
virtual ~VolumeManager();
+ // TODO: pipe all requests through VM to avoid exposing this lock
+ std::mutex& getLock() { return mLock; }
+
int start();
int stop();
void handleBlockEvent(NetlinkEvent *evt);
- int addVolume(Volume *v);
+ class DiskSource {
+ public:
+ DiskSource(const std::string& sysPattern, const std::string& nickname, int flags) :
+ mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {
+ }
+
+ bool matches(const std::string& sysPath) {
+ return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
+ }
+
+ const std::string& getNickname() { return mNickname; }
+ int getFlags() { return mFlags; }
+
+ private:
+ std::string mSysPattern;
+ std::string mNickname;
+ int mFlags;
+ };
+
+ void addDiskSource(const std::shared_ptr<DiskSource>& diskSource);
+
+ std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
+ std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
- int listVolumes(SocketClient *cli);
- int mountVolume(const char *label);
- int unmountVolume(const char *label, bool force);
- int shareVolume(const char *label, const char *method);
- int unshareVolume(const char *label, const char *method);
- int shareEnabled(const char *path, const char *method, bool *enabled);
- int formatVolume(const char *label);
+ void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
+
+ nsecs_t benchmarkPrivate(const std::string& id);
+
+ int forgetPartition(const std::string& partGuid);
+
+ int onUserAdded(userid_t userId, int userSerialNumber);
+ int onUserRemoved(userid_t userId);
+ int onUserStarted(userid_t userId);
+ int onUserStopped(userid_t userId);
+
+ int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
+
+ int remountUid(uid_t uid, const std::string& mode);
+
+ /* Reset all internal state, typically during framework boot */
+ int reset();
+ /* Prepare for device shutdown, safely unmounting all devices */
+ int shutdown();
+ /* Unmount all volumes, usually for encryption */
+ int unmountAll();
/* ASEC */
+ int findAsec(const char *id, char *asecPath = NULL, size_t asecPathLen = 0,
+ const char **directory = NULL) const;
int createAsec(const char *id, unsigned numSectors, const char *fstype,
- const char *key, int ownerUid);
+ const char *key, const int ownerUid, bool isExternal);
+ int resizeAsec(const char *id, unsigned numSectors, const char *key);
int finalizeAsec(const char *id);
+
+ /**
+ * Fixes ASEC permissions on a filesystem that has owners and permissions.
+ * This currently means EXT4-based ASEC containers.
+ *
+ * There is a single file that can be marked as "private" and will not have
+ * world-readable permission. The group for that file will be set to the gid
+ * supplied.
+ *
+ * Returns 0 on success.
+ */
+ int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename);
int destroyAsec(const char *id, bool force);
- int mountAsec(const char *id, const char *key, int ownerUid);
+ int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly);
int unmountAsec(const char *id, bool force);
int renameAsec(const char *id1, const char *id2);
int getAsecMountPath(const char *id, char *buffer, int maxlen);
int unmountLoopImage(const char *containerId, const char *loopId,
const char *fileName, const char *mountPoint, bool force);
- void setDebug(bool enable);
-
- // XXX: Post froyo this should be moved and cleaned up
- int cleanupAsec(Volume *v, bool force);
+ int setDebug(bool enable);
void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
SocketListener *getBroadcaster() { return mBroadcaster; }
static char *asecHash(const char *id, char *buffer, size_t len);
- Volume *lookupVolume(const char *label);
- int getNumDirectVolumes(void);
- int getDirectVolumeList(struct volume_info *vol_list);
+ /*
+ * Ensure that all directories along given path exist, creating parent
+ * directories as needed. Validates that given path is absolute and that
+ * it contains no relative "." or ".." paths or symlinks. Last path segment
+ * is treated as filename and ignored, unless the path ends with "/". Also
+ * ensures that path belongs to a volume managed by vold.
+ */
+ int mkdirs(char* path);
private:
VolumeManager();
void readInitialState();
bool isMountpointMounted(const char *mp);
+ bool isAsecInDirectory(const char *dir, const char *asec) const;
+ bool isLegalAsecId(const char *id) const;
+
+ int linkPrimary(userid_t userId);
+
+ std::mutex mLock;
+
+ std::list<std::shared_ptr<DiskSource>> mDiskSources;
+ std::list<std::shared_ptr<android::vold::Disk>> mDisks;
+
+ std::unordered_map<userid_t, int> mAddedUsers;
+ std::unordered_set<userid_t> mStartedUsers;
+
+ std::shared_ptr<android::vold::VolumeBase> mInternalEmulated;
+ std::shared_ptr<android::vold::VolumeBase> mPrimary;
};
extern "C" {
#endif /* __cplusplus */
#define UNMOUNT_NOT_MOUNTED_ERR -2
- int vold_unmountVol(const char *label);
- int vold_getNumDirectVolumes(void);
- int vold_getDirectVolumeList(struct volume_info *v);
+ int vold_unmountAll(void);
#ifdef __cplusplus
}
#endif