int GUIAction::copylog(std::string arg) { operation_start("Copy Log"); if (!simulate) { string dst; PartitionManager.Mount_Current_Storage(true); dst = DataManager::GetCurrentStoragePath() + "/recovery.log"; TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755); tw_set_default_metadata(dst.c_str()); sync(); gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str()); } else simulate_progress_bar(); operation_end(0); return 0; }
int TWFunc::Recursive_Mkdir(string Path) { string pathCpy = Path; string wholePath; size_t pos = pathCpy.find("/", 2); while (pos != string::npos) { wholePath = pathCpy.substr(0, pos); if (!TWFunc::Path_Exists(wholePath)) { if (mkdir(wholePath.c_str(), 0777)) { LOGERR("Unable to create folder: %s (errno=%d)\n", wholePath.c_str(), errno); return false; } else { tw_set_default_metadata(wholePath.c_str()); } } pos = pathCpy.find("/", pos + 1); } if (mkdir(wholePath.c_str(), 0777) && errno != EEXIST) return false; return true; }
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; }