summaryrefslogtreecommitdiffstats
path: root/mtp/MtpServer.cpp
diff options
context:
space:
mode:
authorbigbiff bigbiff <bigbiff@teamw.in>2018-12-19 00:39:53 +0100
committerEthan Yonker <dees_troy@teamw.in>2019-03-20 20:28:21 +0100
commitaf32bb9c4f4f06e92de3435ed2db3153c0701094 (patch)
tree622948fb3167dc17bb436c948d61df581d2e75f7 /mtp/MtpServer.cpp
parentAdding Edl button in reboot menu (diff)
downloadandroid_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar.gz
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar.bz2
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar.lz
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar.xz
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.tar.zst
android_bootable_recovery-af32bb9c4f4f06e92de3435ed2db3153c0701094.zip
Diffstat (limited to 'mtp/MtpServer.cpp')
-rw-r--r--mtp/MtpServer.cpp1379
1 files changed, 0 insertions, 1379 deletions
diff --git a/mtp/MtpServer.cpp b/mtp/MtpServer.cpp
deleted file mode 100644
index 11eca86bc..000000000
--- a/mtp/MtpServer.cpp
+++ /dev/null
@@ -1,1379 +0,0 @@
-/*
- * Copyright (C) 2017 TeamWin
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include "../twcommon.h"
-#include "../set_metadata.h"
-#include <cutils/properties.h>
-
-#include "MtpTypes.h"
-#include "MtpDebug.h"
-#include "MtpDatabase.h"
-#include "MtpObjectInfo.h"
-#include "MtpProperty.h"
-#include "MtpServer.h"
-#include "MtpStorage.h"
-#include "MtpStringBuffer.h"
-
-#include <linux/usb/f_mtp.h>
-
-static const MtpOperationCode kSupportedOperationCodes[] = {
- MTP_OPERATION_GET_DEVICE_INFO,
- MTP_OPERATION_OPEN_SESSION,
- MTP_OPERATION_CLOSE_SESSION,
- MTP_OPERATION_GET_STORAGE_IDS,
- MTP_OPERATION_GET_STORAGE_INFO,
- MTP_OPERATION_GET_NUM_OBJECTS,
- MTP_OPERATION_GET_OBJECT_HANDLES,
- MTP_OPERATION_GET_OBJECT_INFO,
- MTP_OPERATION_GET_OBJECT,
- MTP_OPERATION_GET_THUMB,
- MTP_OPERATION_DELETE_OBJECT,
- MTP_OPERATION_SEND_OBJECT_INFO,
- MTP_OPERATION_SEND_OBJECT,
-// MTP_OPERATION_INITIATE_CAPTURE,
-// MTP_OPERATION_FORMAT_STORE,
-// MTP_OPERATION_RESET_DEVICE,
-// MTP_OPERATION_SELF_TEST,
-// MTP_OPERATION_SET_OBJECT_PROTECTION,
-// MTP_OPERATION_POWER_DOWN,
- MTP_OPERATION_GET_DEVICE_PROP_DESC,
- MTP_OPERATION_GET_DEVICE_PROP_VALUE,
- MTP_OPERATION_SET_DEVICE_PROP_VALUE,
- MTP_OPERATION_RESET_DEVICE_PROP_VALUE,
-// MTP_OPERATION_TERMINATE_OPEN_CAPTURE,
-// MTP_OPERATION_MOVE_OBJECT,
-// MTP_OPERATION_COPY_OBJECT,
- MTP_OPERATION_GET_PARTIAL_OBJECT,
-// MTP_OPERATION_INITIATE_OPEN_CAPTURE,
- MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED,
- MTP_OPERATION_GET_OBJECT_PROP_DESC,
- MTP_OPERATION_GET_OBJECT_PROP_VALUE,
- MTP_OPERATION_SET_OBJECT_PROP_VALUE,
- MTP_OPERATION_GET_OBJECT_PROP_LIST,
-// MTP_OPERATION_SET_OBJECT_PROP_LIST,
-// MTP_OPERATION_GET_INTERDEPENDENT_PROP_DESC,
-// MTP_OPERATION_SEND_OBJECT_PROP_LIST,
- MTP_OPERATION_GET_OBJECT_REFERENCES,
- MTP_OPERATION_SET_OBJECT_REFERENCES,
-// MTP_OPERATION_SKIP,
- // Android extension for direct file IO
- MTP_OPERATION_GET_PARTIAL_OBJECT_64,
- MTP_OPERATION_SEND_PARTIAL_OBJECT,
- MTP_OPERATION_TRUNCATE_OBJECT,
- MTP_OPERATION_BEGIN_EDIT_OBJECT,
- MTP_OPERATION_END_EDIT_OBJECT,
-};
-
-static const MtpEventCode kSupportedEventCodes[] = {
- MTP_EVENT_OBJECT_ADDED,
- MTP_EVENT_OBJECT_REMOVED,
- MTP_EVENT_STORE_ADDED,
- MTP_EVENT_STORE_REMOVED,
- MTP_EVENT_OBJECT_PROP_CHANGED,
-};
-
-MtpServer::MtpServer(MtpDatabase* database, bool ptp,
- int fileGroup, int filePerm, int directoryPerm)
- : mDatabase(database),
- mPtp(ptp),
- mFileGroup(fileGroup),
- mFilePermission(filePerm),
- mDirectoryPermission(directoryPerm),
- mSessionID(0),
- mSessionOpen(false),
- mSendObjectHandle(kInvalidObjectHandle),
- mSendObjectFormat(0),
- mSendObjectFileSize(0)
-{
- mFD = -1;
-}
-
-MtpServer::~MtpServer() {
-}
-
-void MtpServer::addStorage(MtpStorage* storage) {
- android::Mutex::Autolock autoLock(mMutex);
- MTPD("addStorage(): storage: %x\n", storage);
- if (getStorage(storage->getStorageID()) != NULL) {
- MTPE("MtpServer::addStorage Storage for storage ID %i already exists.\n", storage->getStorageID());
- return;
- }
- mDatabase->createDB(storage, storage->getStorageID());
- mStorages.push(storage);
- sendStoreAdded(storage->getStorageID());
-}
-
-void MtpServer::removeStorage(MtpStorage* storage) {
- android::Mutex::Autolock autoLock(mMutex);
-
- for (size_t i = 0; i < mStorages.size(); i++) {
- if (mStorages[i] == storage) {
- MTPD("MtpServer::removeStorage calling sendStoreRemoved\n");
- // First lock the mutex so that the inotify thread and main
- // thread do not do anything while we remove the storage
- // item, and to make sure we don't remove the item while an
- // operation is in progress
- mDatabase->lockMutex();
- // Grab the storage ID before we delete the item from the
- // database
- MtpStorageID storageID = storage->getStorageID();
- // Remove the item from the mStorages from the vector. At
- // this point the main thread will no longer be able to find
- // this storage item anymore.
- mStorages.removeAt(i);
- // Destroy the storage item, free up all the memory, kill
- // the inotify thread.
- mDatabase->destroyDB(storageID);
- // Tell the host OS that the storage item is gone.
- sendStoreRemoved(storageID);
- // Unlock any remaining mutexes on other storage devices.
- // If no storage devices exist anymore this will do nothing.
- mDatabase->unlockMutex();
- break;
- }
- }
- MTPD("MtpServer::removeStorage DONE\n");
-}
-
-MtpStorage* MtpServer::getStorage(MtpStorageID id) {
- MTPD("getStorage\n");
- if (id == 0) {
- MTPD("mStorages\n");
- return mStorages[0];
- }
- for (size_t i = 0; i < mStorages.size(); i++) {
- MtpStorage* storage = mStorages[i];
- MTPD("id: %d\n", id);
- MTPD("storage: %d\n", storage->getStorageID());
- if (storage->getStorageID() == id) {
- return storage;
- }
- }
- return NULL;
-}
-
-bool MtpServer::hasStorage(MtpStorageID id) {
- MTPD("in hasStorage\n");
- if (id == 0 || id == 0xFFFFFFFF)
- return mStorages.size() > 0;
- return (getStorage(id) != NULL);
-}
-
-void MtpServer::run(int fd) {
- if (fd < 0)
- return;
-
- mFD = fd;
- MTPI("MtpServer::run fd: %d\n", fd);
-
- while (1) {
- MTPD("About to read device...\n");
- int ret = mRequest.read(fd);
- if (ret < 0) {
- if (errno == ECANCELED) {
- // return to top of loop and wait for next command
- MTPD("request read returned %d ECANCELED, starting over\n", ret);
- continue;
- }
- MTPE("request read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
- break;
- }
- MtpOperationCode operation = mRequest.getOperationCode();
- MtpTransactionID transaction = mRequest.getTransactionID();
-
- MTPD("operation: %s", MtpDebug::getOperationCodeName(operation));
- mRequest.dump();
-
- // FIXME need to generalize this
- bool dataIn = (operation == MTP_OPERATION_SEND_OBJECT_INFO
- || operation == MTP_OPERATION_SET_OBJECT_REFERENCES
- || operation == MTP_OPERATION_SET_OBJECT_PROP_VALUE
- || operation == MTP_OPERATION_SET_DEVICE_PROP_VALUE);
- if (dataIn) {
- int ret = mData.read(fd);
- if (ret < 0) {
- if (errno == ECANCELED) {
- // return to top of loop and wait for next command
- MTPD("data read returned %d ECANCELED, starting over\n", ret);
- continue;
- }
- MTPD("data read returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
- break;
- }
- MTPD("received data:");
- mData.dump();
- } else {
- mData.reset();
- }
-
- if (handleRequest()) {
- if (!dataIn && mData.hasData()) {
- mData.setOperationCode(operation);
- mData.setTransactionID(transaction);
- MTPD("sending data:");
- mData.dump();
- ret = mData.write(fd);
- if (ret < 0) {
- if (errno == ECANCELED) {
- // return to top of loop and wait for next command
- MTPD("data write returned %d ECANCELED, starting over\n", ret);
- continue;
- }
- MTPE("data write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
- break;
- }
- }
-
- mResponse.setTransactionID(transaction);
- MTPD("sending response %04X\n", mResponse.getResponseCode());
- ret = mResponse.write(fd);
- MTPD("ret: %d\n", ret);
- mResponse.dump();
- if (ret < 0) {
- if (errno == ECANCELED) {
- // return to top of loop and wait for next command
- MTPD("response write returned %d ECANCELED, starting over\n", ret);
- continue;
- }
- MTPE("response write returned %d, errno: %d, exiting MtpServer::run loop\n", ret, errno);
- break;
- }
- } else {
- MTPD("skipping response\n");
- }
- }
-
- // commit any open edits
- int count = mObjectEditList.size();
- for (int i = 0; i < count; i++) {
- ObjectEdit* edit = mObjectEditList[i];
- commitEdit(edit);
- delete edit;
- }
- mObjectEditList.clear();
-
- if (mSessionOpen)
- mDatabase->sessionEnded(); // This doesn't actually do anything but was carry over from AOSP
- close(fd);
- mFD = -1;
-}
-
-void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
- MTPD("sendObjectAdded %d\n", handle);
- sendEvent(MTP_EVENT_OBJECT_ADDED, handle);
-}
-
-void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
- MTPD("sendObjectRemoved %d\n", handle);
- sendEvent(MTP_EVENT_OBJECT_REMOVED, handle);
-}
-
-void MtpServer::sendObjectUpdated(MtpObjectHandle handle) {
- MTPD("sendObjectUpdated %d\n", handle);
- sendEvent(MTP_EVENT_OBJECT_PROP_CHANGED, handle);
-}
-
-void MtpServer::sendStoreAdded(MtpStorageID id) {
- MTPD("sendStoreAdded %08X\n", id);
- sendEvent(MTP_EVENT_STORE_ADDED, id);
-}
-
-void MtpServer::sendStoreRemoved(MtpStorageID id) {
- MTPD("sendStoreRemoved %08X\n", id);
- sendEvent(MTP_EVENT_STORE_REMOVED, id);
- MTPD("MtpServer::sendStoreRemoved done\n");
-}
-
-void MtpServer::sendEvent(MtpEventCode code, uint32_t param1) {
- MTPD("MtpServer::sendEvent sending event code: %x\n", code);
- if (mSessionOpen) {
- mEvent.setEventCode(code);
- mEvent.setTransactionID(mRequest.getTransactionID());
- mEvent.setParameter(1, param1);
- int ret = mEvent.write(mFD);
- MTPD("mEvent.write returned %d\n", ret);
- }
-}
-
-void MtpServer::addEditObject(MtpObjectHandle handle, MtpString& path,
- uint64_t size, MtpObjectFormat format, int fd) {
- ObjectEdit* edit = new ObjectEdit(handle, path, size, format, fd);
- mObjectEditList.add(edit);
-}
-
-MtpServer::ObjectEdit* MtpServer::getEditObject(MtpObjectHandle handle) {
- int count = mObjectEditList.size();
- for (int i = 0; i < count; i++) {
- ObjectEdit* edit = mObjectEditList[i];
- if (edit->mHandle == handle) return edit;
- }
- return NULL;
-}
-
-void MtpServer::removeEditObject(MtpObjectHandle handle) {
- int count = mObjectEditList.size();
- for (int i = 0; i < count; i++) {
- ObjectEdit* edit = mObjectEditList[i];
- if (edit->mHandle == handle) {
- delete edit;
- mObjectEditList.removeAt(i);
- return;
- }
- }
- MTPE("ObjectEdit not found in removeEditObject");
-}
-
-void MtpServer::commitEdit(ObjectEdit* edit) {
- mDatabase->endSendObject((const char *)edit->mPath, edit->mHandle, edit->mFormat, true);
-}
-
-
-bool MtpServer::handleRequest() {
- android::Mutex::Autolock autoLock(mMutex);
-
- MtpOperationCode operation = mRequest.getOperationCode();
- MtpResponseCode response;
-
- mResponse.reset();
-
- if (mSendObjectHandle != kInvalidObjectHandle && operation != MTP_OPERATION_SEND_OBJECT) {
- // FIXME - need to delete mSendObjectHandle from the database
- MTPE("expected SendObject after SendObjectInfo");
- mSendObjectHandle = kInvalidObjectHandle;
- }
-
- switch (operation) {
- case MTP_OPERATION_GET_DEVICE_INFO:
- MTPD("doGetDeviceInfo()\n");
- response = doGetDeviceInfo();
- break;
- case MTP_OPERATION_OPEN_SESSION:
- MTPD("doOpenSesion()\n");
- response = doOpenSession();
- break;
- case MTP_OPERATION_CLOSE_SESSION:
- MTPD("doCloseSession()\n");
- response = doCloseSession();
- break;
- case MTP_OPERATION_GET_STORAGE_IDS:
- MTPD("doGetStorageIDs()\n");
- response = doGetStorageIDs();
- break;
- case MTP_OPERATION_GET_STORAGE_INFO:
- MTPD("about to call doGetStorageInfo()\n");
- response = doGetStorageInfo();
- break;
- case MTP_OPERATION_GET_OBJECT_PROPS_SUPPORTED:
- MTPD("about to call doGetObjectPropsSupported()\n");
- response = doGetObjectPropsSupported();
- break;
- case MTP_OPERATION_GET_OBJECT_HANDLES:
- MTPD("about to call doGetObjectHandles()\n");
- response = doGetObjectHandles();
- break;
- case MTP_OPERATION_GET_NUM_OBJECTS:
- MTPD("about to call doGetNumbObjects()\n");
- response = doGetNumObjects();
- break;
- case MTP_OPERATION_GET_OBJECT_REFERENCES:
- MTPD("about to call doGetObjectReferences()\n");
- response = doGetObjectReferences();
- break;
- case MTP_OPERATION_SET_OBJECT_REFERENCES:
- MTPD("about to call doSetObjectReferences()\n");
- response = doSetObjectReferences();
- break;
- case MTP_OPERATION_GET_OBJECT_PROP_VALUE:
- MTPD("about to call doGetObjectPropValue()\n");
- response = doGetObjectPropValue();
- break;
- case MTP_OPERATION_SET_OBJECT_PROP_VALUE:
- MTPD("about to call doSetObjectPropValue()\n");
- response = doSetObjectPropValue();
- break;
- case MTP_OPERATION_GET_DEVICE_PROP_VALUE:
- MTPD("about to call doGetDevicPropValue()\n");
- response = doGetDevicePropValue();
- break;
- case MTP_OPERATION_SET_DEVICE_PROP_VALUE:
- MTPD("about to call doSetDevicePropVaue()\n");
- response = doSetDevicePropValue();
- break;
- case MTP_OPERATION_RESET_DEVICE_PROP_VALUE:
- MTPD("about to call doResetDevicePropValue()\n");
- response = doResetDevicePropValue();
- break;
- case MTP_OPERATION_GET_OBJECT_PROP_LIST:
- MTPD("calling doGetObjectPropList()\n");
- response = doGetObjectPropList();
- break;
- case MTP_OPERATION_GET_OBJECT_INFO:
- MTPD("calling doGetObjectInfo()\n");
- response = doGetObjectInfo();
- break;
- case MTP_OPERATION_GET_OBJECT:
- MTPD("about to call doGetObject()\n");
- response = doGetObject();
- break;
- case MTP_OPERATION_GET_THUMB:
- response = doGetThumb();
- break;
- case MTP_OPERATION_GET_PARTIAL_OBJECT:
- case MTP_OPERATION_GET_PARTIAL_OBJECT_64:
- response = doGetPartialObject(operation);
- break;
- case MTP_OPERATION_SEND_OBJECT_INFO:
- MTPD("about to call doSendObjectInfo()\n");
- response = doSendObjectInfo();
- break;
- case MTP_OPERATION_SEND_OBJECT:
- MTPD("about to call doSendObject()\n");
- response = doSendObject();
- break;
- case MTP_OPERATION_DELETE_OBJECT:
- response = doDeleteObject();
- break;
- case MTP_OPERATION_GET_OBJECT_PROP_DESC:
- MTPD("about to call doGetObjectPropDesc()\n");
- response = doGetObjectPropDesc();
- break;
- case MTP_OPERATION_GET_DEVICE_PROP_DESC:
- MTPD("about to call doGetDevicePropDesc()\n");
- response = doGetDevicePropDesc();
- break;
- case MTP_OPERATION_SEND_PARTIAL_OBJECT:
- response = doSendPartialObject();
- break;
- case MTP_OPERATION_TRUNCATE_OBJECT:
- response = doTruncateObject();
- break;
- case MTP_OPERATION_BEGIN_EDIT_OBJECT:
- response = doBeginEditObject();
- break;
- case MTP_OPERATION_END_EDIT_OBJECT:
- response = doEndEditObject();
- break;
- default:
- MTPE("got unsupported command %s", MtpDebug::getOperationCodeName(operation));
- response = MTP_RESPONSE_OPERATION_NOT_SUPPORTED;
- break;
- }
-
- if (response == MTP_RESPONSE_TRANSACTION_CANCELLED)
- return false;
- mResponse.setResponseCode(response);
- return true;
-}
-
-MtpResponseCode MtpServer::doGetDeviceInfo() {
- MtpStringBuffer string;
- char prop_value[PROPERTY_VALUE_MAX];
-
- MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
- MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
- MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();
-
- // fill in device info
- mData.putUInt16(MTP_STANDARD_VERSION);
- if (mPtp) {
- MTPD("doGetDeviceInfo putting 0\n");
- mData.putUInt32(0);
- } else {
- // MTP Vendor Extension ID
- MTPD("doGetDeviceInfo putting 6\n");
- mData.putUInt32(6);
- }
- mData.putUInt16(MTP_STANDARD_VERSION);
- if (mPtp) {
- // no extensions
- MTPD("doGetDeviceInfo no extensions\n");
- string.set("");
- } else {
- // MTP extensions
- MTPD("doGetDeviceInfo microsoft.com: 1.0; android.com: 1.0;\n");
- string.set("microsoft.com: 1.0; android.com: 1.0;");
- }
- mData.putString(string); // MTP Extensions
- mData.putUInt16(0); //Functional Mode
- MTPD("doGetDeviceInfo opcodes, %i\n", sizeof(kSupportedOperationCodes) / sizeof(uint16_t));
- MTPD("doGetDeviceInfo eventcodes, %i\n", sizeof(kSupportedEventCodes) / sizeof(uint16_t));
- mData.putAUInt16(kSupportedOperationCodes,
- sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
- mData.putAUInt16(kSupportedEventCodes,
- sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
- mData.putAUInt16(deviceProperties); // Device Properties Supported
- mData.putAUInt16(captureFormats); // Capture Formats
- mData.putAUInt16(playbackFormats); // Playback Formats
-
- property_get("ro.product.manufacturer", prop_value, "unknown manufacturer");
- MTPD("prop: %s\n", prop_value);
- string.set(prop_value);
- mData.putString(string); // Manufacturer
-
- property_get("ro.product.model", prop_value, "MTP Device");
- string.set(prop_value);
- mData.putString(string); // Model
- string.set("1.0");
- mData.putString(string); // Device Version
-
- property_get("ro.serialno", prop_value, "????????");
- MTPD("sn: %s\n", prop_value);
- string.set(prop_value);
- mData.putString(string); // Serial Number
-
- delete playbackFormats;
- delete captureFormats;
- delete deviceProperties;
-
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doOpenSession() {
- if (mSessionOpen) {
- mResponse.setParameter(1, mSessionID);
- return MTP_RESPONSE_SESSION_ALREADY_OPEN;
- }
- mSessionID = mRequest.getParameter(1);
- mSessionOpen = true;
-
- mDatabase->sessionStarted();
-
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doCloseSession() {
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- mSessionID = 0;
- mSessionOpen = false;
- mDatabase->sessionEnded();
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetStorageIDs() {
- MTPD("doGetStorageIDs()\n");
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- int count = mStorages.size();
- mData.putUInt32(count);
- for (int i = 0; i < count; i++) {
- MTPD("getting storageid %d\n", mStorages[i]->getStorageID());
- mData.putUInt32(mStorages[i]->getStorageID());
- }
-
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetStorageInfo() {
- MtpStringBuffer string;
- MTPD("doGetStorageInfo()\n");
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- MtpStorageID id = mRequest.getParameter(1);
- MtpStorage* storage = getStorage(id);
- if (!storage) {
- MTPE("invalid storage id\n");
- return MTP_RESPONSE_INVALID_STORAGE_ID;
- }
-
- mData.putUInt16(storage->getType());
- mData.putUInt16(storage->getFileSystemType());
- mData.putUInt16(storage->getAccessCapability());
- mData.putUInt64(storage->getMaxCapacity());
- mData.putUInt64(storage->getFreeSpace());
- mData.putUInt32(1024*1024*1024); // Free Space in Objects
- string.set(storage->getDescription());
- mData.putString(string);
- mData.putEmptyString(); // Volume Identifier
-
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetObjectPropsSupported() {
- MTPD("doGetObjectPropsSupported()\n");
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- MtpObjectFormat format = mRequest.getParameter(1);
- mDatabase->lockMutex();
- MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
- mData.putAUInt16(properties);
- delete properties;
- mDatabase->unlockMutex();
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetObjectHandles() {
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
- MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
- MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
- // 0x00000000 for all objects
-
- if (!hasStorage(storageID))
- return MTP_RESPONSE_INVALID_STORAGE_ID;
-
- MTPD("calling MtpDatabase->getObjectList()\n");
- mDatabase->lockMutex();
- MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent);
- mData.putAUInt32(handles);
- delete handles;
- mDatabase->unlockMutex();
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetNumObjects() {
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
- MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
- MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
- // 0x00000000 for all objects
- if (!hasStorage(storageID))
- return MTP_RESPONSE_INVALID_STORAGE_ID;
-
- mDatabase->lockMutex();
- int count = mDatabase->getNumObjects(storageID, format, parent);
- mDatabase->unlockMutex();
- if (count >= 0) {
- mResponse.setParameter(1, count);
- return MTP_RESPONSE_OK;
- } else {
- mResponse.setParameter(1, 0);
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- }
-}
-
-MtpResponseCode MtpServer::doGetObjectReferences() {
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
-
- // FIXME - check for invalid object handle
- mDatabase->lockMutex();
- MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle);
- if (handles) {
- mData.putAUInt32(handles);
- delete handles;
- } else {
- MTPD("MtpServer::doGetObjectReferences putEmptyArray\n");
- mData.putEmptyArray();
- }
- mDatabase->unlockMutex();
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doSetObjectReferences() {
- if (!mSessionOpen)
- return MTP_RESPONSE_SESSION_NOT_OPEN;
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpStorageID handle = mRequest.getParameter(1);
-
- MtpObjectHandleList* references = mData.getAUInt32();
- mDatabase->lockMutex();
- MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
- mDatabase->unlockMutex();
- delete references;
- return result;
-}
-
-MtpResponseCode MtpServer::doGetObjectPropValue() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- MtpObjectProperty property = mRequest.getParameter(2);
- MTPD("GetObjectPropValue %d %s\n", handle,
- MtpDebug::getObjectPropCodeName(property));
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->getObjectPropertyValue(handle, property, mData);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doSetObjectPropValue() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- MtpObjectProperty property = mRequest.getParameter(2);
- MTPD("SetObjectPropValue %d %s\n", handle,
- MtpDebug::getObjectPropCodeName(property));
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->setObjectPropertyValue(handle, property, mData);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doGetDevicePropValue() {
- MtpDeviceProperty property = mRequest.getParameter(1);
- MTPD("GetDevicePropValue %s\n",
- MtpDebug::getDevicePropCodeName(property));
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->getDevicePropertyValue(property, mData);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doSetDevicePropValue() {
- MtpDeviceProperty property = mRequest.getParameter(1);
- MTPD("SetDevicePropValue %s\n",
- MtpDebug::getDevicePropCodeName(property));
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->setDevicePropertyValue(property, mData);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doResetDevicePropValue() {
- MtpDeviceProperty property = mRequest.getParameter(1);
- MTPD("ResetDevicePropValue %s\n",
- MtpDebug::getDevicePropCodeName(property));
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->resetDeviceProperty(property);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doGetObjectPropList() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
-
- MtpObjectHandle handle = mRequest.getParameter(1);
- // use uint32_t so we can support 0xFFFFFFFF
- uint32_t format = mRequest.getParameter(2);
- uint32_t property = mRequest.getParameter(3);
- int groupCode = mRequest.getParameter(4);
- int depth = mRequest.getParameter(5);
- MTPD("GetObjectPropList %d format: %s property: %x group: %d depth: %d\n",
- handle, MtpDebug::getFormatCodeName(format),
- property, groupCode, depth);
-
- mDatabase->lockMutex();
- MtpResponseCode res = mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData);
- mDatabase->unlockMutex();
- return res;
-}
-
-MtpResponseCode MtpServer::doGetObjectInfo() {
- MTPD("inside doGetObjectInfo()\n");
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- MtpObjectInfo info(handle);
- MTPD("calling mtpdatabase getObjectInfo()\n");
- mDatabase->lockMutex();
- MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
- mDatabase->unlockMutex();
- if (result == MTP_RESPONSE_OK) {
- char date[20];
-
- mData.putUInt32(info.mStorageID);
- mData.putUInt16(info.mFormat);
- mData.putUInt16(info.mProtectionStatus);
-
- // if object is being edited the database size may be out of date
- uint32_t size = info.mCompressedSize;
- ObjectEdit* edit = getEditObject(handle);
- if (edit)
- size = (edit->mSize > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)edit->mSize);
- mData.putUInt32(size);
-
- mData.putUInt16(info.mThumbFormat);
- mData.putUInt32(info.mThumbCompressedSize);
- mData.putUInt32(info.mThumbPixWidth);
- mData.putUInt32(info.mThumbPixHeight);
- mData.putUInt32(info.mImagePixWidth);
- mData.putUInt32(info.mImagePixHeight);
- mData.putUInt32(info.mImagePixDepth);
- mData.putUInt32(info.mParent);
- mData.putUInt16(info.mAssociationType);
- mData.putUInt32(info.mAssociationDesc);
- mData.putUInt32(info.mSequenceNumber);
- MTPD("info.mName: %s\n", info.mName);
- mData.putString(info.mName);
- mData.putEmptyString(); // date created
- formatDateTime(info.mDateModified, date, sizeof(date));
- mData.putString(date); // date modified
- mData.putEmptyString(); // keywords
- }
- return result;
-}
-
-MtpResponseCode MtpServer::doGetObject() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- MtpString pathBuf;
- int64_t fileLength;
- MtpObjectFormat format;
- MTPD("MtpServer::doGetObject calling getObjectFilePath\n");
- mDatabase->lockMutex();
- int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
- mDatabase->unlockMutex();
- if (result != MTP_RESPONSE_OK)
- return result;
-
- const char* filePath = (const char *)pathBuf;
- MTPD("filePath: %s\n", filePath);
- mtp_file_range mfr;
- mfr.fd = open(filePath, O_RDONLY);
- if (mfr.fd < 0) {
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- mfr.offset = 0;
- mfr.length = fileLength;
- MTPD("mfr.length: %lld\n", mfr.length);
- mfr.command = mRequest.getOperationCode();
- mfr.transaction_id = mRequest.getTransactionID();
-
- // then transfer the file
- int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
- MTPD("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
- close(mfr.fd);
- if (ret < 0) {
- if (errno == ECANCELED)
- return MTP_RESPONSE_TRANSACTION_CANCELLED;
- else
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetThumb() {
- MtpObjectHandle handle = mRequest.getParameter(1);
- size_t thumbSize;
- mDatabase->lockMutex();
- void* thumb = mDatabase->getThumbnail(handle, thumbSize);
- mDatabase->unlockMutex();
- if (thumb) {
- // send data
- mData.setOperationCode(mRequest.getOperationCode());
- mData.setTransactionID(mRequest.getTransactionID());
- mData.writeData(mFD, thumb, thumbSize);
- free(thumb);
- return MTP_RESPONSE_OK;
- } else {
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-}
-
-MtpResponseCode MtpServer::doGetPartialObject(MtpOperationCode operation) {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- uint64_t offset;
- uint32_t length;
- offset = mRequest.getParameter(2);
- if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {
- // android extension with 64 bit offset
- uint64_t offset2 = mRequest.getParameter(3);
- offset = offset | (offset2 << 32);
- length = mRequest.getParameter(4);
- } else {
- // standard GetPartialObject
- length = mRequest.getParameter(3);
- }
- MtpString pathBuf;
- int64_t fileLength;
- MtpObjectFormat format;
- MTPD("MtpServer::doGetPartialObject calling getObjectFilePath\n");
- mDatabase->lockMutex();
- int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
- mDatabase->unlockMutex();
- if (result != MTP_RESPONSE_OK) {
- return result;
- }
- if (offset + length > (uint64_t)fileLength)
- length = fileLength - offset;
-
- const char* filePath = (const char *)pathBuf;
- mtp_file_range mfr;
- mfr.fd = open(filePath, O_RDONLY);
- if (mfr.fd < 0) {
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- mfr.offset = offset;
- mfr.length = length;
- mfr.command = mRequest.getOperationCode();
- mfr.transaction_id = mRequest.getTransactionID();
- mResponse.setParameter(1, length);
-
- // transfer the file
- int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
- MTPD("MTP_SEND_FILE_WITH_HEADER returned %d\n", ret);
- close(mfr.fd);
- if (ret < 0) {
- if (errno == ECANCELED)
- return MTP_RESPONSE_TRANSACTION_CANCELLED;
- else
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doSendObjectInfo() {
- MTPD("MtpServer::doSendObjectInfo starting\n");
- MtpString path;
- MtpStorageID storageID = mRequest.getParameter(1);
- MtpStorage* storage = getStorage(storageID);
- MtpObjectHandle parent = mRequest.getParameter(2);
- if (!storage)
- return MTP_RESPONSE_INVALID_STORAGE_ID;
-
- // special case the root
- if (parent == MTP_PARENT_ROOT) {
- MTPD("MtpServer::doSendObjectInfo special case root\n");
- path = storage->getPath();
- parent = 0;
- } else {
- int64_t length;
- MtpObjectFormat format;
- MTPD("MtpServer::doSendObjectInfo calling getObjectFilePath\n");
- mDatabase->lockMutex();
- int result = mDatabase->getObjectFilePath(parent, path, length, format);
- mDatabase->unlockMutex();
- if (result != MTP_RESPONSE_OK) {
- return result;
- }
- if (format != MTP_FORMAT_ASSOCIATION)
- return MTP_RESPONSE_INVALID_PARENT_OBJECT;
- }
-
- // read only the fields we need
- mData.getUInt32(); // storage ID
- MtpObjectFormat format = mData.getUInt16();
- mData.getUInt16(); // protection status
- mSendObjectFileSize = mData.getUInt32();
- mData.getUInt16(); // thumb format
- mData.getUInt32(); // thumb compressed size
- mData.getUInt32(); // thumb pix width
- mData.getUInt32(); // thumb pix height
- mData.getUInt32(); // image pix width
- mData.getUInt32(); // image pix height
- mData.getUInt32(); // image bit depth
- mData.getUInt32(); // parent
- uint16_t associationType = mData.getUInt16();
- uint32_t associationDesc = mData.getUInt32(); // association desc
- mData.getUInt32(); // sequence number
- MtpStringBuffer name, created, modified;
- mData.getString(name); // file name
- mData.getString(created); // date created
- mData.getString(modified); // date modified
- // keywords follow
-
- MTPD("name: %s format: %04X\n", (const char *)name, format);
- time_t modifiedTime;
- if (!parseDateTime(modified, modifiedTime)) {
- modifiedTime = 0;
- }
- if (path[path.size() - 1] != '/') {
- path += "/";
- }
- path += (const char *)name;
-
- // check space first
- if (mSendObjectFileSize > storage->getFreeSpace())
- return MTP_RESPONSE_STORAGE_FULL;
- uint64_t maxFileSize = storage->getMaxFileSize();
- // check storage max file size
- MTPD("maxFileSize: %ld\n", maxFileSize);
- 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;
- }
-
- MTPD("MtpServer::doSendObjectInfo path: %s parent: %d storageID: %08X\n", (const char*)path, parent, storageID);
- mDatabase->lockMutex();
- MtpObjectHandle handle = mDatabase->beginSendObject((const char*)path,
- format, parent, storageID, mSendObjectFileSize, modifiedTime);
- mDatabase->unlockMutex();
- if (handle == kInvalidObjectHandle) {
- MTPE("MtpServer::doSendObjectInfo returning MTP_RESPONSE_GENERAL_ERROR, handle == kInvalidObjectHandle\n");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- if (format == MTP_FORMAT_ASSOCIATION) {
- mode_t mask = umask(0);
- MTPD("MtpServer::doSendObjectInfo mkdir '%s'\n", (const char *)path);
- int ret = mkdir((const char *)path, mDirectoryPermission);
- umask(mask);
- if (ret && ret != -EEXIST) {
- MTPE("MtpServer::doSendObjectInfo returning MTP_RESPONSE_GENERAL_ERROR, ret && ret != -EEXIST\n");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
- chown((const char *)path, getuid(), mFileGroup);
- tw_set_default_metadata((const char *)path);
-
- // SendObject does not get sent for directories, so call endSendObject here instead
- mDatabase->lockMutex();
- mDatabase->endSendObject(path, handle, MTP_FORMAT_ASSOCIATION, MTP_RESPONSE_OK);
- mDatabase->unlockMutex();
- } else {
- mSendObjectFilePath = path;
- // save the handle for the SendObject call, which should follow
- mSendObjectHandle = handle;
- mSendObjectFormat = format;
- }
-
- mResponse.setParameter(1, storageID);
- mResponse.setParameter(2, parent);
- mResponse.setParameter(3, handle);
- MTPD("MtpServer::doSendObjectInfo returning MTP_RESPONSE_OK\n");
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doSendObject() {
- if (!hasStorage())
- return MTP_RESPONSE_GENERAL_ERROR;
- MtpResponseCode result = MTP_RESPONSE_OK;
- mode_t mask;
- int ret = 0, initialData;
-
- if (mSendObjectHandle == kInvalidObjectHandle) {
- MTPE("Expected SendObjectInfo before SendObject");
- result = MTP_RESPONSE_NO_VALID_OBJECT_INFO;
- goto done;
- }
-
- // read the header, and possibly some data
- ret = mData.read(mFD);
- if (ret < MTP_CONTAINER_HEADER_SIZE) {
- MTPE("MTP_RESPONSE_GENERAL_ERROR\n");
- result = MTP_RESPONSE_GENERAL_ERROR;
- goto done;
- }
- initialData = ret - MTP_CONTAINER_HEADER_SIZE;
-
- mtp_file_range mfr;
- mfr.fd = open(mSendObjectFilePath, O_RDWR | O_CREAT | O_TRUNC, 0640);
- if (mfr.fd < 0) {
- result = MTP_RESPONSE_GENERAL_ERROR;
- MTPE("fd error\n");
- goto done;
- }
- fchown(mfr.fd, getuid(), mFileGroup);
- // set permissions
- mask = umask(0);
- fchmod(mfr.fd, mFilePermission);
- umask(mask);
-
- if (initialData > 0)
- ret = write(mfr.fd, mData.getData(), initialData);
-
- if (mSendObjectFileSize - initialData > 0) {
- mfr.offset = initialData;
- if (mSendObjectFileSize == 0xFFFFFFFF) {
- // tell driver to read until it receives a short packet
- mfr.length = 0xFFFFFFFF;
- } else {
- mfr.length = mSendObjectFileSize - initialData;
- }
-
- MTPD("receiving %s\n", (const char *)mSendObjectFilePath);
- // transfer the file
- ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
- }
- close(mfr.fd);
- tw_set_default_metadata((const char *)mSendObjectFilePath);
-
- if (ret < 0) {
- unlink(mSendObjectFilePath);
- if (errno == ECANCELED)
- result = MTP_RESPONSE_TRANSACTION_CANCELLED;
- else {
- MTPD("errno: %d\n", errno);
- result = MTP_RESPONSE_GENERAL_ERROR;
- }
- }
-
-done:
- // reset so we don't attempt to send the data back
- MTPD("MTP_RECEIVE_FILE returned %d\n", ret);
- mData.reset();
- mDatabase->lockMutex();
- mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat,
- result == MTP_RESPONSE_OK);
- mDatabase->unlockMutex();
- mSendObjectHandle = kInvalidObjectHandle;
- MTPD("result: %d\n", result);
- mSendObjectFormat = 0;
- return result;
-}
-
-static void deleteRecursive(const char* path) {
- char pathbuf[PATH_MAX];
- size_t pathLength = strlen(path);
- if (pathLength >= sizeof(pathbuf) - 1) {
- MTPE("path too long: %s\n", path);
- }
- strcpy(pathbuf, path);
- if (pathbuf[pathLength - 1] != '/') {
- pathbuf[pathLength++] = '/';
- }
- char* fileSpot = pathbuf + pathLength;
- int pathRemaining = sizeof(pathbuf) - pathLength - 1;
-
- DIR* dir = opendir(path);
- if (!dir) {
- MTPE("opendir %s failed: %s", path, strerror(errno));
- return;
- }
-
- struct dirent* entry;
- while ((entry = readdir(dir))) {
- const char* name = entry->d_name;
-
- // ignore "." and ".."
- if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
- continue;
- }
-
- int nameLength = strlen(name);
- if (nameLength > pathRemaining) {
- MTPE("path %s/%s too long\n", path, name);
- continue;
- }
- strcpy(fileSpot, name);
-
- int type = entry->d_type;
- struct stat st;
- if (lstat(pathbuf, &st)) {
- MTPE("Failed to lstat '%s'\n", pathbuf);
- continue;
- }
- if (st.st_mode & S_IFDIR) {
- deleteRecursive(pathbuf);
- rmdir(pathbuf);
- } else {
- unlink(pathbuf);
- }
- }
- closedir(dir);
-}
-
-static void deletePath(const char* path) {
- struct stat statbuf;
- if (stat(path, &statbuf) == 0) {
- if (S_ISDIR(statbuf.st_mode)) {
- deleteRecursive(path);
- rmdir(path);
- } else {
- unlink(path);
- }
- } else {
- MTPE("deletePath stat failed for %s: %s", path, strerror(errno));
- }
-}
-
-MtpResponseCode MtpServer::doDeleteObject() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- MtpObjectFormat format = mRequest.getParameter(2);
- // FIXME - support deleting all objects if handle is 0xFFFFFFFF
- // FIXME - implement deleting objects by format
-
- MtpString filePath;
- int64_t fileLength;
- MTPD("MtpServer::doDeleteObject calling getObjectFilePath\n");
- mDatabase->lockMutex();
- int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
- if (result == MTP_RESPONSE_OK) {
- MTPD("deleting %s", (const char *)filePath);
- result = mDatabase->deleteFile(handle);
- // Don't delete the actual files unless the database deletion is allowed
- if (result == MTP_RESPONSE_OK) {
- deletePath((const char *)filePath);
- }
- }
- mDatabase->unlockMutex();
- return result;
-}
-
-MtpResponseCode MtpServer::doGetObjectPropDesc() {
- MtpObjectProperty propCode = mRequest.getParameter(1);
- MtpObjectFormat format = mRequest.getParameter(2);
- MTPD("MtpServer::doGetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
- MtpDebug::getFormatCodeName(format));
- mDatabase->lockMutex();
- MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
- mDatabase->unlockMutex();
- if (!property) {
- MTPE("MtpServer::doGetObjectPropDesc propery not supported\n");
- return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
- }
- property->write(mData);
- delete property;
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doGetDevicePropDesc() {
- MtpDeviceProperty propCode = mRequest.getParameter(1);
- MTPD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
- mDatabase->lockMutex();
- MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
- mDatabase->unlockMutex();
- if (!property) {
- MTPE("MtpServer::doGetDevicePropDesc property not supported\n");
- return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
- }
- property->write(mData);
- delete property;
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doSendPartialObject() {
- if (!hasStorage())
- return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
- MtpObjectHandle handle = mRequest.getParameter(1);
- uint64_t offset = mRequest.getParameter(2);
- uint64_t offset2 = mRequest.getParameter(3);
- offset = offset | (offset2 << 32);
- uint32_t length = mRequest.getParameter(4);
-
- ObjectEdit* edit = getEditObject(handle);
- if (!edit) {
- MTPE("object not open for edit in doSendPartialObject");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- // can't start writing past the end of the file
- if (offset > edit->mSize) {
- MTPE("writing past end of object, offset: %lld, edit->mSize: %lld", offset, edit->mSize);
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- const char* filePath = (const char *)edit->mPath;
- MTPD("receiving partial %s %lld %lld\n", filePath, offset, length);
-
- // read the header, and possibly some data
- int ret = mData.read(mFD);
- if (ret < MTP_CONTAINER_HEADER_SIZE)
- return MTP_RESPONSE_GENERAL_ERROR;
- int initialData = ret - MTP_CONTAINER_HEADER_SIZE;
-
- if (initialData > 0) {
- ret = write(edit->mFD, mData.getData(), initialData);
- offset += initialData;
- length -= initialData;
- }
-
- if (length > 0) {
- mtp_file_range mfr;
- mfr.fd = edit->mFD;
- mfr.offset = offset;
- mfr.length = length;
-
- // transfer the file
- ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
- MTPD("MTP_RECEIVE_FILE returned %d", ret);
- }
- if (ret < 0) {
- mResponse.setParameter(1, 0);
- if (errno == ECANCELED)
- return MTP_RESPONSE_TRANSACTION_CANCELLED;
- else
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- // reset so we don't attempt to send this back
- mData.reset();
- mResponse.setParameter(1, length);
- uint64_t end = offset + length;
- if (end > edit->mSize) {
- edit->mSize = end;
- }
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doTruncateObject() {
- MtpObjectHandle handle = mRequest.getParameter(1);
- ObjectEdit* edit = getEditObject(handle);
- if (!edit) {
- MTPE("object not open for edit in doTruncateObject");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- uint64_t offset = mRequest.getParameter(2);
- uint64_t offset2 = mRequest.getParameter(3);
- offset |= (offset2 << 32);
- if (ftruncate(edit->mFD, offset) != 0) {
- return MTP_RESPONSE_GENERAL_ERROR;
- } else {
- edit->mSize = offset;
- return MTP_RESPONSE_OK;
- }
-}
-
-MtpResponseCode MtpServer::doBeginEditObject() {
- MtpObjectHandle handle = mRequest.getParameter(1);
- if (getEditObject(handle)) {
- MTPE("object already open for edit in doBeginEditObject");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- MtpString path;
- int64_t fileLength;
- MtpObjectFormat format;
- MTPD("MtpServer::doBeginEditObject calling getObjectFilePath\n");
- mDatabase->lockMutex();
- int result = mDatabase->getObjectFilePath(handle, path, fileLength, format);
- mDatabase->unlockMutex();
- if (result != MTP_RESPONSE_OK)
- return result;
-
- int fd = open((const char *)path, O_RDWR | O_EXCL);
- if (fd < 0) {
- MTPE("open failed for %s in doBeginEditObject (%d)", (const char *)path, errno);
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- addEditObject(handle, path, fileLength, format, fd);
- return MTP_RESPONSE_OK;
-}
-
-MtpResponseCode MtpServer::doEndEditObject() {
- MtpObjectHandle handle = mRequest.getParameter(1);
- ObjectEdit* edit = getEditObject(handle);
- if (!edit) {
- MTPE("object not open for edit in doEndEditObject");
- return MTP_RESPONSE_GENERAL_ERROR;
- }
-
- commitEdit(edit);
- removeEditObject(handle);
- return MTP_RESPONSE_OK;
-}