MtpResponseCode MtpServer::doGetObject() { if (!hasStorage()) return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpString pathBuf; int64_t fileLength; MtpObjectFormat format; int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format); if (result != MTP_RESPONSE_OK) return result; 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 = 0; mfr.length = fileLength; 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); LOGV("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::doSetObjectPropValue() { if (!hasStorage()) return MTP_RESPONSE_INVALID_OBJECT_HANDLE; MtpObjectHandle handle = mRequest.getParameter(1); MtpObjectProperty property = mRequest.getParameter(2); LOGV("SetObjectPropValue %d %s\n", handle, MtpDebug::getObjectPropCodeName(property)); return mDatabase->setObjectPropertyValue(handle, property, mData); }
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::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(); MtpResponseCode result = mDatabase->setObjectReferences(handle, references); 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::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); LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n", handle, MtpDebug::getFormatCodeName(format), MtpDebug::getObjectPropCodeName(property), groupCode, depth); return mDatabase->getObjectPropertyList(handle, format, property, groupCode, depth, mData); }
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; MtpObjectHandleList* handles = mDatabase->getObjectList(storageID, format, parent); mData.putAUInt32(handles); delete handles; return MTP_RESPONSE_OK; }
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 MtpObjectHandleList* handles = mDatabase->getObjectReferences(handle); if (handles) { mData.putAUInt32(handles); delete handles; } else { mData.putEmptyArray(); } return MTP_RESPONSE_OK; }
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::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; int count = mDatabase->getNumObjects(storageID, format, parent); if (count >= 0) { mResponse.setParameter(1, count); return MTP_RESPONSE_OK; } else { mResponse.setParameter(1, 0); return MTP_RESPONSE_INVALID_OBJECT_HANDLE; } }
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; int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format); if (result == MTP_RESPONSE_OK) { LOGV("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); } } return result; }
bool hasDenseLeadingDimension(blas::matrix_expression<Mat> const& m){ if(!isTransposed(m)) return hasStorage(m)&& leadingDimension(m)==(int)m().size2(); else return hasStorage(m)&& leadingDimension(m)==(int)m().size1(); }
MtpResponseCode MtpServer::doSendObject() { if (!hasStorage()) return MTP_RESPONSE_GENERAL_ERROR; MtpResponseCode result = MTP_RESPONSE_OK; mode_t mask; int ret, initialData; if (mSendObjectHandle == kInvalidObjectHandle) { LOGE("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) { 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); if (mfr.fd < 0) { result = MTP_RESPONSE_GENERAL_ERROR; 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; } LOGV("receiving %s\n", (const char *)mSendObjectFilePath); // transfer the file ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr); LOGV("MTP_RECEIVE_FILE returned %d\n", ret); } close(mfr.fd); if (ret < 0) { unlink(mSendObjectFilePath); if (errno == ECANCELED) result = MTP_RESPONSE_TRANSACTION_CANCELLED; else result = MTP_RESPONSE_GENERAL_ERROR; } done: // reset so we don't attempt to send the data back mData.reset(); mDatabase->endSendObject(mSendObjectFilePath, mSendObjectHandle, mSendObjectFormat, result == MTP_RESPONSE_OK); mSendObjectHandle = kInvalidObjectHandle; mSendObjectFormat = 0; return result; }
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) { LOGE("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) { LOGD("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; LOGV("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); LOGV("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; }
bool Plot::hasManipulatorFile() const { return hasStorage() && manipulatorFilePath(storageUuid()).exists(); }
bool Plot::hasValidStorage() const { return hasStorage() && snapshotFilePath().exists(); }