MTP: Return error if user tries to copy a file >= 4GB to a FAT32 file system

Bug: 4561836

Change-Id: I2bffb93b032038f6c220c24c752ccd7ca66c23a0
Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
Mike Lockwood
2011-07-11 09:18:03 -04:00
parent b7440a140b
commit 7a59dd2ce3
9 changed files with 62 additions and 10 deletions

View File

@@ -34,6 +34,8 @@ public class StorageVolume implements Parcelable {
private final int mMtpReserveSpace;
private final boolean mAllowMassStorage;
private int mStorageId;
// maximum file size for the storage, or zero for no limit
private final long mMaxFileSize;
// StorageVolume extra for ACTION_MEDIA_REMOVED, ACTION_MEDIA_UNMOUNTED, ACTION_MEDIA_CHECKING,
// ACTION_MEDIA_NOFS, ACTION_MEDIA_MOUNTED, ACTION_MEDIA_SHARED, ACTION_MEDIA_UNSHARED,
@@ -41,18 +43,20 @@ public class StorageVolume implements Parcelable {
public static final String EXTRA_STORAGE_VOLUME = "storage_volume";
public StorageVolume(String path, String description, boolean removable,
boolean emulated, int mtpReserveSpace, boolean allowMassStorage) {
boolean emulated, int mtpReserveSpace, boolean allowMassStorage, long maxFileSize) {
mPath = path;
mDescription = description;
mRemovable = removable;
mEmulated = emulated;
mMtpReserveSpace = mtpReserveSpace;
mAllowMassStorage = allowMassStorage;
mMaxFileSize = maxFileSize;
}
// for parcelling only
private StorageVolume(String path, String description, boolean removable,
boolean emulated, int mtpReserveSpace, int storageId, boolean allowMassStorage) {
boolean emulated, int mtpReserveSpace, int storageId,
boolean allowMassStorage, long maxFileSize) {
mPath = path;
mDescription = description;
mRemovable = removable;
@@ -60,6 +64,7 @@ public class StorageVolume implements Parcelable {
mMtpReserveSpace = mtpReserveSpace;
mAllowMassStorage = allowMassStorage;
mStorageId = storageId;
mMaxFileSize = maxFileSize;
}
/**
@@ -142,6 +147,15 @@ public class StorageVolume implements Parcelable {
return mAllowMassStorage;
}
/**
* Returns maximum file size for the volume, or zero if it is unbounded.
*
* @return maximum file size
*/
public long getMaxFileSize() {
return mMaxFileSize;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof StorageVolume && mPath != null) {
@@ -171,9 +185,10 @@ public class StorageVolume implements Parcelable {
int storageId = in.readInt();
int mtpReserveSpace = in.readInt();
int allowMassStorage = in.readInt();
long maxFileSize = in.readLong();
return new StorageVolume(path, description,
removable == 1, emulated == 1,
mtpReserveSpace, storageId, allowMassStorage == 1);
removable == 1, emulated == 1, mtpReserveSpace,
storageId, allowMassStorage == 1, maxFileSize);
}
public StorageVolume[] newArray(int size) {
@@ -193,5 +208,6 @@ public class StorageVolume implements Parcelable {
parcel.writeInt(mStorageId);
parcel.writeInt(mMtpReserveSpace);
parcel.writeInt(mAllowMassStorage ? 1 : 0);
parcel.writeLong(mMaxFileSize);
}
}

View File

@@ -5318,6 +5318,8 @@
<attr name="mtpReserve" format="integer" />
<!-- true if the storage can be shared via USB mass storage -->
<attr name="allowMassStorage" format="boolean" />
<!-- maximum file size for the volume in megabytes, zero or unspecified if it is unbounded -->
<attr name="maxFileSize" format="integer" />
</declare-styleable>
<declare-styleable name="SwitchPreference">

View File

@@ -330,7 +330,6 @@ class MtpPropertyGroup {
}
int count = (c == null ? 1 : c.getCount());
Log.d(TAG, "count: " + count);
MtpPropertyList result = new MtpPropertyList(count * mProperties.length,
MtpConstants.RESPONSE_OK);

View File

@@ -32,6 +32,7 @@ public class MtpStorage {
private final String mDescription;
private final long mReserveSpace;
private final boolean mRemovable;
private final long mMaxFileSize;
public MtpStorage(StorageVolume volume) {
mStorageId = volume.getStorageId();
@@ -39,6 +40,7 @@ public class MtpStorage {
mDescription = volume.getDescription();
mReserveSpace = volume.getMtpReserveSpace();
mRemovable = volume.isRemovable();
mMaxFileSize = volume.getMaxFileSize();
}
/**
@@ -98,4 +100,13 @@ public class MtpStorage {
public final boolean isRemovable() {
return mRemovable;
}
/**
* Returns maximum file size for the storage, or zero if it is unbounded.
*
* @return maximum file size
*/
public long getMaxFileSize() {
return mMaxFileSize;
}
}

View File

@@ -48,6 +48,7 @@ static jfieldID field_MtpStorage_path;
static jfieldID field_MtpStorage_description;
static jfieldID field_MtpStorage_reserveSpace;
static jfieldID field_MtpStorage_removable;
static jfieldID field_MtpStorage_maxFileSize;
static Mutex sMutex;
@@ -228,12 +229,14 @@ android_mtp_MtpServer_add_storage(JNIEnv *env, jobject thiz, jobject jstorage)
jstring description = (jstring)env->GetObjectField(jstorage, field_MtpStorage_description);
jlong reserveSpace = env->GetLongField(jstorage, field_MtpStorage_reserveSpace);
jboolean removable = env->GetBooleanField(jstorage, field_MtpStorage_removable);
jlong maxFileSize = env->GetLongField(jstorage, field_MtpStorage_maxFileSize);
const char *pathStr = env->GetStringUTFChars(path, NULL);
if (pathStr != NULL) {
const char *descriptionStr = env->GetStringUTFChars(description, NULL);
if (descriptionStr != NULL) {
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr, reserveSpace, removable);
MtpStorage* storage = new MtpStorage(storageID, pathStr, descriptionStr,
reserveSpace, removable, maxFileSize);
thread->addStorage(storage);
env->ReleaseStringUTFChars(path, pathStr);
env->ReleaseStringUTFChars(description, descriptionStr);
@@ -312,6 +315,11 @@ int register_android_mtp_MtpServer(JNIEnv *env)
LOGE("Can't find MtpStorage.mRemovable");
return -1;
}
field_MtpStorage_maxFileSize = env->GetFieldID(clazz, "mMaxFileSize", "J");
if (field_MtpStorage_maxFileSize == NULL) {
LOGE("Can't find MtpStorage.mMaxFileSize");
return -1;
}
clazz_MtpStorage = (jclass)env->NewGlobalRef(clazz);
clazz = env->FindClass("android/mtp/MtpServer");

View File

@@ -871,6 +871,14 @@ MtpResponseCode MtpServer::doSendObjectInfo() {
// check space first
if (mSendObjectFileSize > storage->getFreeSpace())
return MTP_RESPONSE_STORAGE_FULL;
uint64_t maxFileSize = storage->getMaxFileSize();
// check storage max file size
if (maxFileSize != 0) {
// if mSendObjectFileSize is 0xFFFFFFFF, then all we know is the file size
// is >= 0xFFFFFFFF
if (mSendObjectFileSize > maxFileSize || mSendObjectFileSize == 0xFFFFFFFF)
return MTP_RESPONSE_OBJECT_TOO_LARGE;
}
LOGD("path: %s parent: %d storageID: %08X", (const char*)path, parent, storageID);
MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,

View File

@@ -33,11 +33,13 @@
namespace android {
MtpStorage::MtpStorage(MtpStorageID id, const char* filePath,
const char* description, uint64_t reserveSpace, bool removable)
const char* description, uint64_t reserveSpace,
bool removable, uint64_t maxFileSize)
: mStorageID(id),
mFilePath(filePath),
mDescription(description),
mMaxCapacity(0),
mMaxFileSize(maxFileSize),
mReserveSpace(reserveSpace),
mRemovable(removable)
{

View File

@@ -31,6 +31,7 @@ private:
MtpString mFilePath;
MtpString mDescription;
uint64_t mMaxCapacity;
uint64_t mMaxFileSize;
// amount of free space to leave unallocated
uint64_t mReserveSpace;
bool mRemovable;
@@ -38,7 +39,7 @@ private:
public:
MtpStorage(MtpStorageID id, const char* filePath,
const char* description, uint64_t reserveSpace,
bool removable);
bool removable, uint64_t maxFileSize);
virtual ~MtpStorage();
inline MtpStorageID getStorageID() const { return mStorageID; }
@@ -50,6 +51,7 @@ public:
const char* getDescription() const;
inline const char* getPath() const { return (const char *)mFilePath; }
inline bool isRemovable() const { return mRemovable; }
inline uint64_t getMaxFileSize() const { return mMaxFileSize; }
};
}; // namespace android

View File

@@ -1075,18 +1075,22 @@ class MountService extends IMountService.Stub implements INativeDaemonConnectorC
com.android.internal.R.styleable.Storage_mtpReserve, 0);
boolean allowMassStorage = a.getBoolean(
com.android.internal.R.styleable.Storage_allowMassStorage, false);
// resource parser does not support longs, so XML value is in megabytes
long maxFileSize = a.getInt(
com.android.internal.R.styleable.Storage_maxFileSize, 0) * 1024L * 1024L;
Slog.d(TAG, "got storage path: " + path + " description: " + description +
" primary: " + primary + " removable: " + removable +
" emulated: " + emulated + " mtpReserve: " + mtpReserve +
" allowMassStorage: " + allowMassStorage);
" allowMassStorage: " + allowMassStorage +
" maxFileSize: " + maxFileSize);
if (path == null || description == null) {
Slog.e(TAG, "path or description is null in readStorageList");
} else {
String pathString = path.toString();
StorageVolume volume = new StorageVolume(pathString,
description.toString(), removable, emulated,
mtpReserve, allowMassStorage);
mtpReserve, allowMassStorage, maxFileSize);
if (primary) {
if (mPrimaryVolume == null) {
mPrimaryVolume = volume;