1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ANDROID_VOLD_VOLUME_MANAGER_H
18#define ANDROID_VOLD_VOLUME_MANAGER_H
19
20#include <pthread.h>
21#include <fnmatch.h>
22#include <stdlib.h>
23
24#ifdef __cplusplus
25
26#include <list>
27#include <mutex>
28#include <string>
29#include <unordered_map>
30#include <unordered_set>
31
32#include <cutils/multiuser.h>
33#include <utils/List.h>
34#include <utils/Timers.h>
35#include <sysutils/SocketListener.h>
36#include <sysutils/NetlinkEvent.h>
37
38#include "Disk.h"
39#include "VolumeBase.h"
40
41/* The length of an MD5 hash when encoded into ASCII hex characters */
42#define MD5_ASCII_LENGTH_PLUS_NULL ((MD5_DIGEST_LENGTH*2)+1)
43
44typedef enum { ASEC, OBB } container_type_t;
45
46class ContainerData {
47public:
48    ContainerData(char* _id, container_type_t _type)
49            : id(_id)
50            , type(_type)
51    {}
52
53    ~ContainerData() {
54        if (id != NULL) {
55            free(id);
56            id = NULL;
57        }
58    }
59
60    char *id;
61    container_type_t type;
62};
63
64typedef android::List<ContainerData*> AsecIdCollection;
65
66class VolumeManager {
67public:
68    static const char *SEC_ASECDIR_EXT;
69    static const char *SEC_ASECDIR_INT;
70    static const char *ASECDIR;
71    static const char *LOOPDIR;
72
73private:
74    static VolumeManager *sInstance;
75
76    SocketListener        *mBroadcaster;
77
78    AsecIdCollection      *mActiveContainers;
79    bool                   mDebug;
80
81    // for adjusting /proc/sys/vm/dirty_ratio when UMS is active
82    int                    mUmsSharingCount;
83    int                    mSavedDirtyRatio;
84    int                    mUmsDirtyRatio;
85
86public:
87    virtual ~VolumeManager();
88
89    // TODO: pipe all requests through VM to avoid exposing this lock
90    std::mutex& getLock() { return mLock; }
91
92    int start();
93    int stop();
94
95    void handleBlockEvent(NetlinkEvent *evt);
96
97    class DiskSource {
98    public:
99        DiskSource(const std::string& sysPattern, const std::string& nickname, int flags) :
100                mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {
101        }
102
103        bool matches(const std::string& sysPath) {
104            return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
105        }
106
107        const std::string& getNickname() { return mNickname; }
108        int getFlags() { return mFlags; }
109
110    private:
111        std::string mSysPattern;
112        std::string mNickname;
113        int mFlags;
114    };
115
116    void addDiskSource(const std::shared_ptr<DiskSource>& diskSource);
117
118    std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
119    std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
120
121    void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
122
123    nsecs_t benchmarkPrivate(const std::string& id);
124
125    int forgetPartition(const std::string& partGuid);
126
127    int onUserAdded(userid_t userId, int userSerialNumber);
128    int onUserRemoved(userid_t userId);
129    int onUserStarted(userid_t userId);
130    int onUserStopped(userid_t userId);
131
132    int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
133
134    int remountUid(uid_t uid, const std::string& mode);
135
136    /* Reset all internal state, typically during framework boot */
137    int reset();
138    /* Prepare for device shutdown, safely unmounting all devices */
139    int shutdown();
140    /* Unmount all volumes, usually for encryption */
141    int unmountAll();
142
143    /* ASEC */
144    int findAsec(const char *id, char *asecPath = NULL, size_t asecPathLen = 0,
145            const char **directory = NULL) const;
146    int createAsec(const char *id, unsigned numSectors, const char *fstype,
147                   const char *key, const int ownerUid, bool isExternal);
148    int resizeAsec(const char *id, unsigned numSectors, const char *key);
149    int finalizeAsec(const char *id);
150
151    /**
152     * Fixes ASEC permissions on a filesystem that has owners and permissions.
153     * This currently means EXT4-based ASEC containers.
154     *
155     * There is a single file that can be marked as "private" and will not have
156     * world-readable permission. The group for that file will be set to the gid
157     * supplied.
158     *
159     * Returns 0 on success.
160     */
161    int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename);
162    int destroyAsec(const char *id, bool force);
163    int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly);
164    int unmountAsec(const char *id, bool force);
165    int renameAsec(const char *id1, const char *id2);
166    int getAsecMountPath(const char *id, char *buffer, int maxlen);
167    int getAsecFilesystemPath(const char *id, char *buffer, int maxlen);
168
169    /* Loopback images */
170    int listMountedObbs(SocketClient* cli);
171    int mountObb(const char *fileName, const char *key, int ownerUid);
172    int unmountObb(const char *fileName, bool force);
173    int getObbMountPath(const char *id, char *buffer, int maxlen);
174
175    /* Shared between ASEC and Loopback images */
176    int unmountLoopImage(const char *containerId, const char *loopId,
177            const char *fileName, const char *mountPoint, bool force);
178
179    int setDebug(bool enable);
180
181    void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
182    SocketListener *getBroadcaster() { return mBroadcaster; }
183
184    static VolumeManager *Instance();
185
186    static char *asecHash(const char *id, char *buffer, size_t len);
187
188    /*
189     * Ensure that all directories along given path exist, creating parent
190     * directories as needed.  Validates that given path is absolute and that
191     * it contains no relative "." or ".." paths or symlinks.  Last path segment
192     * is treated as filename and ignored, unless the path ends with "/".  Also
193     * ensures that path belongs to a volume managed by vold.
194     */
195    int mkdirs(char* path);
196
197private:
198    VolumeManager();
199    void readInitialState();
200    bool isMountpointMounted(const char *mp);
201    bool isAsecInDirectory(const char *dir, const char *asec) const;
202    bool isLegalAsecId(const char *id) const;
203
204    int linkPrimary(userid_t userId);
205
206    std::mutex mLock;
207
208    std::list<std::shared_ptr<DiskSource>> mDiskSources;
209    std::list<std::shared_ptr<android::vold::Disk>> mDisks;
210
211    std::unordered_map<userid_t, int> mAddedUsers;
212    std::unordered_set<userid_t> mStartedUsers;
213
214    std::shared_ptr<android::vold::VolumeBase> mInternalEmulated;
215    std::shared_ptr<android::vold::VolumeBase> mPrimary;
216};
217
218extern "C" {
219#endif /* __cplusplus */
220#define UNMOUNT_NOT_MOUNTED_ERR -2
221    int vold_unmountAll(void);
222#ifdef __cplusplus
223}
224#endif
225
226#endif
227