mtp

Merge lp:~phablet-team/mtp/aosp-update into lp:mtp

Proposed by Alfonso Sanchez-Beato
Status: Merged
Approved by: Konrad Zapałowicz
Approved revision: 74
Merged at revision: 70
Proposed branch: lp:~phablet-team/mtp/aosp-update
Merge into: lp:mtp
Diff against target: 2258 lines (+634/-357)
25 files modified
CMakeLists.txt (+1/-1)
include/MtpDataPacket.h (+13/-12)
include/MtpDevice.h (+1/-1)
include/MtpDeviceInfo.h (+2/-2)
include/MtpObjectInfo.h (+1/-1)
include/MtpPacket.h (+4/-4)
include/MtpProperty.h (+7/-7)
include/MtpRequestPacket.h (+4/-0)
include/MtpServer.h (+1/-0)
include/MtpStorageInfo.h (+1/-1)
include/MtpStringBuffer.h (+5/-2)
server/UbuntuMtpDatabase.h (+48/-37)
server/server.cpp (+25/-23)
src/MtpDataPacket.cpp (+129/-55)
src/MtpDevice.cpp (+33/-14)
src/MtpDeviceInfo.cpp (+19/-12)
src/MtpObjectInfo.cpp (+22/-20)
src/MtpPacket.cpp (+1/-1)
src/MtpProperty.cpp (+63/-42)
src/MtpRequestPacket.cpp (+17/-4)
src/MtpServer.cpp (+170/-64)
src/MtpStorageInfo.cpp (+11/-9)
src/MtpStringBuffer.cpp (+36/-24)
src/MtpUtils.cpp (+19/-20)
tests/TestMtpUtils.cpp (+1/-1)
To merge this branch: bzr merge lp:~phablet-team/mtp/aosp-update
Reviewer Review Type Date Requested Status
Konrad Zapałowicz (community) code Approve
Simon Fels Approve
Review via email: mp+291626@code.launchpad.net

Commit message

* Update to latest AOSP code (Marshallow)
* Make MTP work for file > 4GB (LP: #1472789). This involved adding O_LARGEFILE flag when opening a file (the flag is automatically added by bionic, but not by glibc) and fixing parts of the MTP database implementation.

Description of the change

* Update to latest AOSP code (Marshallow)
* Make MTP work for file > 4GB (LP: #1472789). This involved adding O_LARGEFILE flag when opening a file (the flag is automatically added by bionic, but not by glibc) and fixing parts of the MTP database implementation.

To post a comment you must log in.
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

Minor issues mostly related to type-safety

review: Needs Fixing (code)
Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Thanks for the thorough review. However, most of the code comes directly from AOSP, and I have preferred in many cases to minimize the difference between our project and "upstream" to ease future merges. AOSP code can be found in:

https://android.googlesource.com/platform/frameworks/av/

lp:~phablet-team/mtp/aosp-update updated
74. By Alfonso Sanchez-Beato

Address review comments

Revision history for this message
Alfonso Sanchez-Beato (alfonsosanchezbeato) wrote :

Branch refreshed after addressing review comments.

Revision history for this message
Simon Fels (morphis) wrote :

LGTM

review: Approve
Revision history for this message
Konrad Zapałowicz (kzapalowicz) wrote :

Approved

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-09-04 01:11:14 +0000
+++ CMakeLists.txt 2016-04-12 16:15:02 +0000
@@ -7,7 +7,7 @@
77
8set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")8set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
99
10add_definitions(-DMTP_DEVICE -DMTP_HOST)10add_definitions(-DMTP_DEVICE -DMTP_HOST -D_FILE_OFFSET_BITS=64)
1111
12set(MTP_VERSION_MAJOR 1)12set(MTP_VERSION_MAJOR 1)
13set(MTP_VERSION_MINOR 0)13set(MTP_VERSION_MINOR 0)
1414
=== modified file 'include/MtpDataPacket.h'
--- include/MtpDataPacket.h 2013-06-13 10:22:21 +0000
+++ include/MtpDataPacket.h 2016-04-12 16:15:02 +0000
@@ -30,7 +30,7 @@
30class MtpDataPacket : public MtpPacket {30class MtpDataPacket : public MtpPacket {
31private:31private:
32 // current offset for get/put methods32 // current offset for get/put methods
33 int mOffset;33 size_t mOffset;
3434
35public:35public:
36 MtpDataPacket();36 MtpDataPacket();
@@ -42,17 +42,18 @@
42 void setTransactionID(MtpTransactionID id);42 void setTransactionID(MtpTransactionID id);
4343
44 inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }44 inline const uint8_t* getData() const { return mBuffer + MTP_CONTAINER_HEADER_SIZE; }
45 inline uint8_t getUInt8() { return (uint8_t)mBuffer[mOffset++]; }45
46 inline int8_t getInt8() { return (int8_t)mBuffer[mOffset++]; }46 bool getUInt8(uint8_t& value);
47 uint16_t getUInt16();47 inline bool getInt8(int8_t& value) { return getUInt8((uint8_t&)value); }
48 inline int16_t getInt16() { return (int16_t)getUInt16(); }48 bool getUInt16(uint16_t& value);
49 uint32_t getUInt32();49 inline bool getInt16(int16_t& value) { return getUInt16((uint16_t&)value); }
50 inline int32_t getInt32() { return (int32_t)getUInt32(); }50 bool getUInt32(uint32_t& value);
51 uint64_t getUInt64();51 inline bool getInt32(int32_t& value) { return getUInt32((uint32_t&)value); }
52 inline int64_t getInt64() { return (int64_t)getUInt64(); }52 bool getUInt64(uint64_t& value);
53 void getUInt128(uint128_t& value);53 inline bool getInt64(int64_t& value) { return getUInt64((uint64_t&)value); }
54 inline void getInt128(int128_t& value) { getUInt128((uint128_t&)value); }54 bool getUInt128(uint128_t& value);
55 void getString(MtpStringBuffer& string);55 inline bool getInt128(int128_t& value) { return getUInt128((uint128_t&)value); }
56 bool getString(MtpStringBuffer& string);
5657
57 Int8List* getAInt8();58 Int8List* getAInt8();
58 UInt8List* getAUInt8();59 UInt8List* getAUInt8();
5960
=== modified file 'include/MtpDevice.h'
--- include/MtpDevice.h 2013-06-13 10:22:21 +0000
+++ include/MtpDevice.h 2016-04-12 16:15:02 +0000
@@ -96,7 +96,7 @@
96 bool readObject(MtpObjectHandle handle,96 bool readObject(MtpObjectHandle handle,
97 bool (* callback)(void* data, int offset,97 bool (* callback)(void* data, int offset,
98 int length, void* clientData),98 int length, void* clientData),
99 int objectSize, void* clientData);99 size_t objectSize, void* clientData);
100 bool readObject(MtpObjectHandle handle, const char* destPath, int group,100 bool readObject(MtpObjectHandle handle, const char* destPath, int group,
101 int perm);101 int perm);
102102
103103
=== modified file 'include/MtpDeviceInfo.h'
--- include/MtpDeviceInfo.h 2013-06-13 10:22:21 +0000
+++ include/MtpDeviceInfo.h 2016-04-12 16:15:02 +0000
@@ -29,7 +29,7 @@
29 uint32_t mVendorExtensionID;29 uint32_t mVendorExtensionID;
30 uint16_t mVendorExtensionVersion;30 uint16_t mVendorExtensionVersion;
31 char* mVendorExtensionDesc;31 char* mVendorExtensionDesc;
32 uint16_t mFunctionalCode;32 uint16_t mFunctionalMode;
33 UInt16List* mOperations;33 UInt16List* mOperations;
34 UInt16List* mEvents;34 UInt16List* mEvents;
35 MtpDevicePropertyList* mDeviceProperties;35 MtpDevicePropertyList* mDeviceProperties;
@@ -44,7 +44,7 @@
44 MtpDeviceInfo();44 MtpDeviceInfo();
45 virtual ~MtpDeviceInfo();45 virtual ~MtpDeviceInfo();
4646
47 void read(MtpDataPacket& packet);47 bool read(MtpDataPacket& packet);
4848
49 void print();49 void print();
50};50};
5151
=== modified file 'include/MtpObjectInfo.h'
--- include/MtpObjectInfo.h 2013-06-13 10:22:21 +0000
+++ include/MtpObjectInfo.h 2016-04-12 16:15:02 +0000
@@ -50,7 +50,7 @@
50 MtpObjectInfo(MtpObjectHandle handle);50 MtpObjectInfo(MtpObjectHandle handle);
51 virtual ~MtpObjectInfo();51 virtual ~MtpObjectInfo();
5252
53 void read(MtpDataPacket& packet);53 bool read(MtpDataPacket& packet);
5454
55 void print();55 void print();
56};56};
5757
=== modified file 'include/MtpPacket.h'
--- include/MtpPacket.h 2013-06-13 10:22:21 +0000
+++ include/MtpPacket.h 2016-04-12 16:15:02 +0000
@@ -28,11 +28,11 @@
28protected:28protected:
29 uint8_t* mBuffer;29 uint8_t* mBuffer;
30 // current size of the buffer30 // current size of the buffer
31 int mBufferSize;31 size_t mBufferSize;
32 // number of bytes to add when resizing the buffer32 // number of bytes to add when resizing the buffer
33 int mAllocationIncrement;33 size_t mAllocationIncrement;
34 // size of the data in the packet34 // size of the data in the packet
35 int mPacketSize;35 size_t mPacketSize;
3636
37public:37public:
38 MtpPacket(int bufferSize);38 MtpPacket(int bufferSize);
@@ -41,7 +41,7 @@
41 // sets packet size to the default container size and sets buffer to zero41 // sets packet size to the default container size and sets buffer to zero
42 virtual void reset();42 virtual void reset();
4343
44 void allocate(int length);44 void allocate(size_t length);
45 void dump();45 void dump();
46 void copyFrom(const MtpPacket& src);46 void copyFrom(const MtpPacket& src);
4747
4848
=== modified file 'include/MtpProperty.h'
--- include/MtpProperty.h 2013-06-13 10:22:21 +0000
+++ include/MtpProperty.h 2016-04-12 16:15:02 +0000
@@ -49,9 +49,9 @@
49 MtpPropertyValue mCurrentValue;49 MtpPropertyValue mCurrentValue;
5050
51 // for array types51 // for array types
52 int mDefaultArrayLength;52 uint32_t mDefaultArrayLength;
53 MtpPropertyValue* mDefaultArrayValues;53 MtpPropertyValue* mDefaultArrayValues;
54 int mCurrentArrayLength;54 uint32_t mCurrentArrayLength;
55 MtpPropertyValue* mCurrentArrayValues;55 MtpPropertyValue* mCurrentArrayValues;
5656
57 enum {57 enum {
@@ -70,7 +70,7 @@
70 MtpPropertyValue mStepSize;70 MtpPropertyValue mStepSize;
7171
72 // for enum form72 // for enum form
73 int mEnumLength;73 uint16_t mEnumLength;
74 MtpPropertyValue* mEnumValues;74 MtpPropertyValue* mEnumValues;
7575
76public:76public:
@@ -83,7 +83,7 @@
8383
84 inline MtpPropertyCode getPropertyCode() const { return mCode; }84 inline MtpPropertyCode getPropertyCode() const { return mCode; }
8585
86 void read(MtpDataPacket& packet);86 bool read(MtpDataPacket& packet);
87 void write(MtpDataPacket& packet);87 void write(MtpDataPacket& packet);
8888
89 void setDefaultValue(const uint16_t* string);89 void setDefaultValue(const uint16_t* string);
@@ -102,11 +102,11 @@
102 }102 }
103103
104private:104private:
105 void readValue(MtpDataPacket& packet, MtpPropertyValue& value);105 bool readValue(MtpDataPacket& packet, MtpPropertyValue& value);
106 void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);106 void writeValue(MtpDataPacket& packet, MtpPropertyValue& value);
107 MtpPropertyValue* readArrayValues(MtpDataPacket& packet, int& length);107 MtpPropertyValue* readArrayValues(MtpDataPacket& packet, uint32_t& length);
108 void writeArrayValues(MtpDataPacket& packet,108 void writeArrayValues(MtpDataPacket& packet,
109 MtpPropertyValue* values, int length);109 MtpPropertyValue* values, uint32_t length);
110};110};
111111
112}; // namespace android112}; // namespace android
113113
=== modified file 'include/MtpRequestPacket.h'
--- include/MtpRequestPacket.h 2013-06-13 10:22:21 +0000
+++ include/MtpRequestPacket.h 2016-04-12 16:15:02 +0000
@@ -43,6 +43,10 @@
43 inline MtpOperationCode getOperationCode() const { return getContainerCode(); }43 inline MtpOperationCode getOperationCode() const { return getContainerCode(); }
44 inline void setOperationCode(MtpOperationCode code)44 inline void setOperationCode(MtpOperationCode code)
45 { return setContainerCode(code); }45 { return setContainerCode(code); }
46 inline int getParameterCount() const { return mParameterCount; }
47
48private:
49 int mParameterCount;
46};50};
4751
48}; // namespace android52}; // namespace android
4953
=== modified file 'include/MtpServer.h'
--- include/MtpServer.h 2014-10-29 18:46:35 +0000
+++ include/MtpServer.h 2016-04-12 16:15:02 +0000
@@ -108,6 +108,7 @@
108108
109 void sendObjectAdded(MtpObjectHandle handle);109 void sendObjectAdded(MtpObjectHandle handle);
110 void sendObjectRemoved(MtpObjectHandle handle);110 void sendObjectRemoved(MtpObjectHandle handle);
111 void sendDevicePropertyChanged(MtpDeviceProperty property);
111 void sendObjectInfoChanged(MtpObjectHandle handle);112 void sendObjectInfoChanged(MtpObjectHandle handle);
112 void sendObjectPropChanged(MtpObjectHandle handle,113 void sendObjectPropChanged(MtpObjectHandle handle,
113 MtpObjectProperty prop);114 MtpObjectProperty prop);
114115
=== modified file 'include/MtpStorageInfo.h'
--- include/MtpStorageInfo.h 2013-06-13 10:22:21 +0000
+++ include/MtpStorageInfo.h 2016-04-12 16:15:02 +0000
@@ -39,7 +39,7 @@
39 MtpStorageInfo(MtpStorageID id);39 MtpStorageInfo(MtpStorageID id);
40 virtual ~MtpStorageInfo();40 virtual ~MtpStorageInfo();
4141
42 void read(MtpDataPacket& packet);42 bool read(MtpDataPacket& packet);
4343
44 void print();44 void print();
45};45};
4646
=== modified file 'include/MtpStringBuffer.h'
--- include/MtpStringBuffer.h 2013-06-13 10:22:21 +0000
+++ include/MtpStringBuffer.h 2016-04-12 16:15:02 +0000
@@ -19,6 +19,9 @@
1919
20#include <stdint.h>20#include <stdint.h>
2121
22// Max Character number of a MTP String
23#define MTP_STRING_MAX_CHARACTER_NUMBER 255
24
22namespace android {25namespace android {
2326
24class MtpDataPacket;27class MtpDataPacket;
@@ -29,7 +32,7 @@
29private:32private:
30 // mBuffer contains string in UTF8 format33 // mBuffer contains string in UTF8 format
31 // maximum 3 bytes/character, with 1 extra for zero termination34 // maximum 3 bytes/character, with 1 extra for zero termination
32 uint8_t mBuffer[255 * 3 + 1];35 uint8_t mBuffer[MTP_STRING_MAX_CHARACTER_NUMBER * 3 + 1];
33 int mCharCount;36 int mCharCount;
34 int mByteCount;37 int mByteCount;
3538
@@ -43,7 +46,7 @@
43 void set(const char* src);46 void set(const char* src);
44 void set(const uint16_t* src);47 void set(const uint16_t* src);
4548
46 void readFromPacket(MtpDataPacket* packet);49 bool readFromPacket(MtpDataPacket* packet);
47 void writeToPacket(MtpDataPacket* packet) const;50 void writeToPacket(MtpDataPacket* packet) const;
4851
49 inline int getCharCount() const { return mCharCount; }52 inline int getCharCount() const { return mCharCount; }
5053
=== modified file 'server/UbuntuMtpDatabase.h'
--- server/UbuntuMtpDatabase.h 2015-01-26 19:35:23 +0000
+++ server/UbuntuMtpDatabase.h 2016-04-12 16:15:02 +0000
@@ -63,7 +63,7 @@
63 MtpStorageID storage_id;63 MtpStorageID storage_id;
64 MtpObjectFormat object_format;64 MtpObjectFormat object_format;
65 MtpObjectHandle parent;65 MtpObjectHandle parent;
66 size_t object_size;66 uint64_t object_size;
67 std::string display_name;67 std::string display_name;
68 std::string path;68 std::string path;
69 int watch_fd;69 int watch_fd;
@@ -117,7 +117,7 @@
117 IN_MODIFY | IN_CREATE | IN_DELETE);117 IN_MODIFY | IN_CREATE | IN_DELETE);
118 }118 }
119119
120 120
121 void add_file_entry(path p, MtpObjectHandle parent, MtpStorageID storage)121 void add_file_entry(path p, MtpObjectHandle parent, MtpStorageID storage)
122 {122 {
123 MtpObjectHandle handle = counter;123 MtpObjectHandle handle = counter;
@@ -246,16 +246,16 @@
246 std::size_t transferred)246 std::size_t transferred)
247 {247 {
248 size_t processed = 0;248 size_t processed = 0;
249 249
250 while(transferred - processed >= sizeof(inotify_event))250 while(transferred - processed >= sizeof(inotify_event))
251 {251 {
252 const char* cdata = processed + asio::buffer_cast<const char*>(buf.data());252 const char* cdata = processed + asio::buffer_cast<const char*>(buf.data());
253 const inotify_event* ievent = reinterpret_cast<const inotify_event*>(cdata);253 const inotify_event* ievent = reinterpret_cast<const inotify_event*>(cdata);
254 MtpObjectHandle parent;254 MtpObjectHandle parent;
255 path p;255 path p;
256 256
257 processed += sizeof(inotify_event) + ievent->len;257 processed += sizeof(inotify_event) + ievent->len;
258 258
259 BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {259 BOOST_FOREACH(MtpObjectHandle i, db | boost::adaptors::map_keys) {
260 if (db.at(i).watch_fd == ievent->wd) {260 if (db.at(i).watch_fd == ievent->wd) {
261 parent = i;261 parent = i;
@@ -329,7 +329,7 @@
329 }329 }
330 }330 }
331 }331 }
332 332
333 read_more_notify();333 read_more_notify();
334 }334 }
335335
@@ -411,7 +411,7 @@
411411
412 counter++;412 counter++;
413413
414 return handle; 414 return handle;
415 }415 }
416416
417 // called to report success or failure of the SendObject file transfer417 // called to report success or failure of the SendObject file transfer
@@ -470,7 +470,7 @@
470 {470 {
471 list = new MtpObjectHandleList();471 list = new MtpObjectHandleList();
472 }472 }
473 473
474 return list;474 return list;
475 }475 }
476476
@@ -491,7 +491,7 @@
491 } catch(...)491 } catch(...)
492 {492 {
493 }493 }
494 494
495 return result;495 return result;
496 }496 }
497497
@@ -540,14 +540,14 @@
540540
541 return new MtpObjectFormatList{list};541 return new MtpObjectFormatList{list};
542 }542 }
543 543
544 virtual MtpObjectFormatList* getSupportedCaptureFormats()544 virtual MtpObjectFormatList* getSupportedCaptureFormats()
545 {545 {
546 VLOG(1) << __PRETTY_FUNCTION__;546 VLOG(1) << __PRETTY_FUNCTION__;
547 static const MtpObjectFormatList list = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};547 static const MtpObjectFormatList list = {MTP_FORMAT_ASSOCIATION, MTP_FORMAT_PNG};
548 return new MtpObjectFormatList{list};548 return new MtpObjectFormatList{list};
549 }549 }
550 550
551 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)551 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format)
552 {552 {
553 VLOG(1) << __PRETTY_FUNCTION__;553 VLOG(1) << __PRETTY_FUNCTION__;
@@ -555,8 +555,8 @@
555 if (format != MTP_FORMAT_PNG)555 if (format != MTP_FORMAT_PNG)
556 return nullptr;556 return nullptr;
557 */557 */
558 558
559 static const MtpObjectPropertyList list = 559 static const MtpObjectPropertyList list =
560 {560 {
561 MTP_PROPERTY_STORAGE_ID,561 MTP_PROPERTY_STORAGE_ID,
562 MTP_PROPERTY_PARENT_OBJECT,562 MTP_PROPERTY_PARENT_OBJECT,
@@ -574,16 +574,16 @@
574 MTP_PROPERTY_NON_CONSUMABLE,574 MTP_PROPERTY_NON_CONSUMABLE,
575575
576 };576 };
577 577
578 return new MtpObjectPropertyList{list};578 return new MtpObjectPropertyList{list};
579 }579 }
580 580
581 virtual MtpDevicePropertyList* getSupportedDeviceProperties()581 virtual MtpDevicePropertyList* getSupportedDeviceProperties()
582 {582 {
583 VLOG(1) << __PRETTY_FUNCTION__;583 VLOG(1) << __PRETTY_FUNCTION__;
584 static const MtpDevicePropertyList list = {584 static const MtpDevicePropertyList list = {
585 MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,585 MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
586 MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, 586 MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
587 };587 };
588 return new MtpDevicePropertyList{list};588 return new MtpDevicePropertyList{list};
589 }589 }
@@ -592,7 +592,7 @@
592 MtpObjectHandle handle,592 MtpObjectHandle handle,
593 MtpObjectProperty property,593 MtpObjectProperty property,
594 MtpDataPacket& packet)594 MtpDataPacket& packet)
595 { 595 {
596 char date[20];596 char date[20];
597597
598 VLOG(1) << __PRETTY_FUNCTION__598 VLOG(1) << __PRETTY_FUNCTION__
@@ -605,10 +605,10 @@
605 try {605 try {
606 switch(property)606 switch(property)
607 {607 {
608 case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break; 608 case MTP_PROPERTY_STORAGE_ID: packet.putUInt32(db.at(handle).storage_id); break;
609 case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break; 609 case MTP_PROPERTY_PARENT_OBJECT: packet.putUInt32(db.at(handle).parent); break;
610 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt16(db.at(handle).object_format); break;610 case MTP_PROPERTY_OBJECT_FORMAT: packet.putUInt16(db.at(handle).object_format); break;
611 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt32(db.at(handle).object_size); break;611 case MTP_PROPERTY_OBJECT_SIZE: packet.putUInt64(db.at(handle).object_size); break;
612 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;612 case MTP_PROPERTY_DISPLAY_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
613 case MTP_PROPERTY_OBJECT_FILE_NAME: packet.putString(db.at(handle).display_name.c_str()); break;613 case MTP_PROPERTY_OBJECT_FILE_NAME: packet.putString(db.at(handle).display_name.c_str()); break;
614 case MTP_PROPERTY_PERSISTENT_UID: packet.putUInt128(handle); break;614 case MTP_PROPERTY_PERSISTENT_UID: packet.putUInt128(handle); break;
@@ -637,9 +637,9 @@
637 else637 else
638 packet.putUInt16(1); // files can usually be played.638 packet.putUInt16(1); // files can usually be played.
639 break;639 break;
640 default: return MTP_RESPONSE_GENERAL_ERROR; break; 640 default: return MTP_RESPONSE_GENERAL_ERROR; break;
641 }641 }
642 642
643 return MTP_RESPONSE_OK;643 return MTP_RESPONSE_OK;
644 }644 }
645 catch (...) {645 catch (...) {
@@ -676,7 +676,10 @@
676 try {676 try {
677 entry = db.at(handle);677 entry = db.at(handle);
678678
679 packet.getString(buffer);679 if (!packet.getString(buffer)) {
680 LOG(ERROR) << "Cannot read packet";
681 return MTP_RESPONSE_GENERAL_ERROR;
682 }
680 newname = strdup(buffer);683 newname = strdup(buffer);
681684
682 oldpath /= entry.path;685 oldpath /= entry.path;
@@ -701,7 +704,10 @@
701 case MTP_PROPERTY_PARENT_OBJECT:704 case MTP_PROPERTY_PARENT_OBJECT:
702 try {705 try {
703 entry = db.at(handle);706 entry = db.at(handle);
704 entry.parent = packet.getUInt32();707 if (!packet.getUInt32(entry.parent)) {
708 LOG(ERROR) << "Cannot read packet";
709 return MTP_RESPONSE_GENERAL_ERROR;
710 }
705 }711 }
706 catch (...) {712 catch (...) {
707 LOG(ERROR) << "Could not change parent object for handle "713 LOG(ERROR) << "Could not change parent object for handle "
@@ -710,7 +716,7 @@
710 }716 }
711 default: return MTP_RESPONSE_OPERATION_NOT_SUPPORTED; break;717 default: return MTP_RESPONSE_OPERATION_NOT_SUPPORTED; break;
712 }718 }
713 719
714 return MTP_RESPONSE_OK;720 return MTP_RESPONSE_OK;
715 }721 }
716722
@@ -727,7 +733,7 @@
727 break;733 break;
728 default: return MTP_RESPONSE_OPERATION_NOT_SUPPORTED; break;734 default: return MTP_RESPONSE_OPERATION_NOT_SUPPORTED; break;
729 }735 }
730 736
731 return MTP_RESPONSE_OK;737 return MTP_RESPONSE_OK;
732 }738 }
733739
@@ -748,9 +754,9 @@
748754
749 virtual MtpResponseCode getObjectPropertyList(755 virtual MtpResponseCode getObjectPropertyList(
750 MtpObjectHandle handle,756 MtpObjectHandle handle,
751 uint32_t format, 757 uint32_t format,
752 uint32_t property,758 uint32_t property,
753 int groupCode, 759 int groupCode,
754 int depth,760 int depth,
755 MtpDataPacket& packet)761 MtpDataPacket& packet)
756 {762 {
@@ -841,8 +847,8 @@
841 if (property == ALL_PROPERTIES || property == MTP_PROPERTY_OBJECT_SIZE) {847 if (property == ALL_PROPERTIES || property == MTP_PROPERTY_OBJECT_SIZE) {
842 packet.putUInt32(i);848 packet.putUInt32(i);
843 packet.putUInt16(MTP_PROPERTY_OBJECT_SIZE);849 packet.putUInt16(MTP_PROPERTY_OBJECT_SIZE);
844 packet.putUInt16(MTP_TYPE_UINT32);850 packet.putUInt16(MTP_TYPE_UINT64);
845 packet.putUInt32(entry.object_size);851 packet.putUInt64(entry.object_size);
846 }852 }
847853
848 // Object File Name854 // Object File Name
@@ -944,11 +950,16 @@
944 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;950 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
945951
946 try {952 try {
953 uint64_t object_size = db.at(handle).object_size;
954
947 info.mHandle = handle;955 info.mHandle = handle;
948 info.mStorageID = db.at(handle).storage_id;956 info.mStorageID = db.at(handle).storage_id;
949 info.mFormat = db.at(handle).object_format;957 info.mFormat = db.at(handle).object_format;
950 info.mProtectionStatus = 0x0;958 info.mProtectionStatus = 0x0;
951 info.mCompressedSize = db.at(handle).object_size;959 if (object_size > UINT64_C(0xFFFFFFFF))
960 info.mCompressedSize = UINT64_C(0xFFFFFFFF);
961 else
962 info.mCompressedSize = object_size;
952 info.mImagePixWidth = 0;963 info.mImagePixWidth = 0;
953 info.mImagePixHeight = 0;964 info.mImagePixHeight = 0;
954 info.mImagePixDepth = 0;965 info.mImagePixDepth = 0;
@@ -1116,7 +1127,7 @@
1116 case MTP_PROPERTY_STORAGE_ID: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;1127 case MTP_PROPERTY_STORAGE_ID: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;
1117 case MTP_PROPERTY_PARENT_OBJECT: result = new MtpProperty(property, MTP_TYPE_UINT32, true); break;1128 case MTP_PROPERTY_PARENT_OBJECT: result = new MtpProperty(property, MTP_TYPE_UINT32, true); break;
1118 case MTP_PROPERTY_OBJECT_FORMAT: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;1129 case MTP_PROPERTY_OBJECT_FORMAT: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;
1119 case MTP_PROPERTY_OBJECT_SIZE: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;1130 case MTP_PROPERTY_OBJECT_SIZE: result = new MtpProperty(property, MTP_TYPE_UINT64, false); break;
1120 case MTP_PROPERTY_WIDTH: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;1131 case MTP_PROPERTY_WIDTH: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;
1121 case MTP_PROPERTY_HEIGHT: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;1132 case MTP_PROPERTY_HEIGHT: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;
1122 case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;1133 case MTP_PROPERTY_IMAGE_BIT_DEPTH: result = new MtpProperty(property, MTP_TYPE_UINT32, false); break;
@@ -1130,9 +1141,9 @@
1130 case MTP_PROPERTY_DATE_MODIFIED: result = new MtpProperty(property, MTP_TYPE_STR, false); break;1141 case MTP_PROPERTY_DATE_MODIFIED: result = new MtpProperty(property, MTP_TYPE_STR, false); break;
1131 case MTP_PROPERTY_HIDDEN: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;1142 case MTP_PROPERTY_HIDDEN: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;
1132 case MTP_PROPERTY_NON_CONSUMABLE: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;1143 case MTP_PROPERTY_NON_CONSUMABLE: result = new MtpProperty(property, MTP_TYPE_UINT16, false); break;
1133 default: break; 1144 default: break;
1134 }1145 }
1135 1146
1136 return result;1147 return result;
1137 }1148 }
11381149
@@ -1146,12 +1157,12 @@
1146 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:1157 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1147 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:1158 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
1148 result = new MtpProperty(property, MTP_TYPE_STR, false); break;1159 result = new MtpProperty(property, MTP_TYPE_STR, false); break;
1149 default: break; 1160 default: break;
1150 }1161 }
1151 1162
1152 return result;1163 return result;
1153 }1164 }
1154 1165
1155 virtual void sessionStarted(MtpServer* server)1166 virtual void sessionStarted(MtpServer* server)
1156 {1167 {
1157 VLOG(1) << __PRETTY_FUNCTION__;1168 VLOG(1) << __PRETTY_FUNCTION__;
11581169
=== modified file 'server/server.cpp'
--- server/server.cpp 2015-02-13 15:19:49 +0000
+++ server/server.cpp 2016-04-12 16:15:02 +0000
@@ -21,6 +21,7 @@
21#include <MtpStorage.h>21#include <MtpStorage.h>
2222
23#include <iostream>23#include <iostream>
24#include <stdint.h>
2425
25#include <signal.h>26#include <signal.h>
26#include <sys/types.h>27#include <sys/types.h>
@@ -39,7 +40,7 @@
39#include <core/dbus/property.h>40#include <core/dbus/property.h>
40#include <core/dbus/service.h>41#include <core/dbus/service.h>
41#include <core/dbus/signal.h>42#include <core/dbus/signal.h>
42 43
43#include <core/dbus/asio/executor.h>44#include <core/dbus/asio/executor.h>
44#include <core/dbus/types/stl/tuple.h>45#include <core/dbus/types/stl/tuple.h>
45#include <core/dbus/types/stl/vector.h>46#include <core/dbus/types/stl/vector.h>
@@ -76,23 +77,23 @@
76};77};
77}78}
7879
79namespace core 80namespace core
80{ 81{
81namespace dbus 82namespace dbus
82{ 83{
83namespace traits84namespace traits
84{ 85{
85template<> 86template<>
86struct Service<core::UnityGreeter> 87struct Service<core::UnityGreeter>
87{ 88{
88 inline static const std::string& interface_name()89 inline static const std::string& interface_name()
89 {90 {
90 static const std::string s91 static const std::string s
91 {92 {
92 "com.canonical.UnityGreeter"93 "com.canonical.UnityGreeter"
93 }; 94 };
94 return s;95 return s;
95 } 96 }
96};97};
97}98}
98}99}
@@ -148,13 +149,14 @@
148 {149 {
149 static int storageID = MTP_STORAGE_REMOVABLE_RAM;150 static int storageID = MTP_STORAGE_REMOVABLE_RAM;
150151
152 /* TODO check removable file system type to set maximum file size */
151 MtpStorage *removable = new MtpStorage(153 MtpStorage *removable = new MtpStorage(
152 storageID, 154 storageID,
153 path,155 path,
154 name,156 name,
155 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */157 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */
156 true,158 true,
157 1024 * 1024 * 1024 * 2 /* 2GB arbitrary max file size */);159 UINT64_C(4294967295) /* 4GB-1, we assume vfat here */);
158160
159 storageID++;161 storageID++;
160162
@@ -195,15 +197,15 @@
195 std::size_t transferred)197 std::size_t transferred)
196 {198 {
197 size_t processed = 0;199 size_t processed = 0;
198 200
199 while(transferred - processed >= sizeof(inotify_event))201 while(transferred - processed >= sizeof(inotify_event))
200 {202 {
201 const char* cdata = processed + asio::buffer_cast<const char*>(buf.data());203 const char* cdata = processed + asio::buffer_cast<const char*>(buf.data());
202 const inotify_event* ievent = reinterpret_cast<const inotify_event*>(cdata);204 const inotify_event* ievent = reinterpret_cast<const inotify_event*>(cdata);
203 path storage_path ("/media");205 path storage_path ("/media");
204 206
205 processed += sizeof(inotify_event) + ievent->len;207 processed += sizeof(inotify_event) + ievent->len;
206 208
207 storage_path /= userdata->pw_name;209 storage_path /= userdata->pw_name;
208210
209 if (ievent->len > 0 && ievent->mask & IN_CREATE)211 if (ievent->len > 0 && ievent->mask & IN_CREATE)
@@ -277,11 +279,11 @@
277279
278 // MTP server280 // MTP server
279 server = new MtpServer(281 server = new MtpServer(
280 fd, 282 fd,
281 mtp_database,283 mtp_database,
282 false, 284 false,
283 userdata->pw_gid, 285 userdata->pw_gid,
284 FileSystemConfig::file_perm, 286 FileSystemConfig::file_perm,
285 FileSystemConfig::directory_perm);287 FileSystemConfig::directory_perm);
286288
287 // security / screen locking289 // security / screen locking
@@ -302,12 +304,12 @@
302 property_get ("ro.product.model", product_name, "Ubuntu Touch device");304 property_get ("ro.product.model", product_name, "Ubuntu Touch device");
303305
304 home_storage = new MtpStorage(306 home_storage = new MtpStorage(
305 MTP_STORAGE_FIXED_RAM, 307 MTP_STORAGE_FIXED_RAM,
306 userdata->pw_dir,308 userdata->pw_dir,
307 product_name,309 product_name,
308 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */310 1024 * 1024 * 100, /* 100 MB reserved space, to avoid filling the disk */
309 false,311 false,
310 1024 * 1024 * 1024 * 2 /* 2GB arbitrary max file size */);312 0 /* Do not check sizes for internal storage */);
311 mtp_database->addStoragePath(std::string(userdata->pw_dir) + "/Documents",313 mtp_database->addStoragePath(std::string(userdata->pw_dir) + "/Documents",
312 gettext("Documents"),314 gettext("Documents"),
313 MTP_STORAGE_FIXED_RAM, false);315 MTP_STORAGE_FIXED_RAM, false);
@@ -424,7 +426,7 @@
424 LOG(ERROR) << "Error opening /dev/mtp_usb, aborting now...";426 LOG(ERROR) << "Error opening /dev/mtp_usb, aborting now...";
425 return 1;427 return 1;
426 }428 }
427 429
428 try {430 try {
429 MtpDaemon *d = new MtpDaemon(fd);431 MtpDaemon *d = new MtpDaemon(fd);
430432
431433
=== modified file 'src/MtpDataPacket.cpp'
--- src/MtpDataPacket.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpDataPacket.cpp 2016-04-12 16:15:02 +0000
@@ -53,104 +53,178 @@
53 MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);53 MtpPacket::putUInt32(MTP_CONTAINER_TRANSACTION_ID_OFFSET, id);
54}54}
5555
56uint16_t MtpDataPacket::getUInt16() {56bool MtpDataPacket::getUInt8(uint8_t& value) {
57 int offset = mOffset;57 if (mPacketSize - mOffset < sizeof(value))
58 uint16_t result = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);58 return false;
59 mOffset += 2;59 value = mBuffer[mOffset++];
60 return result;60 return true;
61}61}
6262
63uint32_t MtpDataPacket::getUInt32() {63bool MtpDataPacket::getUInt16(uint16_t& value) {
64 int offset = mOffset;64 if (mPacketSize - mOffset < sizeof(value))
65 uint32_t result = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |65 return false;
66 size_t offset = mOffset;
67 value = (uint16_t)mBuffer[offset] | ((uint16_t)mBuffer[offset + 1] << 8);
68 mOffset += sizeof(value);
69 return true;
70}
71
72bool MtpDataPacket::getUInt32(uint32_t& value) {
73 if (mPacketSize - mOffset < sizeof(value))
74 return false;
75 size_t offset = mOffset;
76 value = (uint32_t)mBuffer[offset] | ((uint32_t)mBuffer[offset + 1] << 8) |
66 ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);77 ((uint32_t)mBuffer[offset + 2] << 16) | ((uint32_t)mBuffer[offset + 3] << 24);
67 mOffset += 4;78 mOffset += sizeof(value);
68 return result;79 return true;
69}80}
7081
71uint64_t MtpDataPacket::getUInt64() {82bool MtpDataPacket::getUInt64(uint64_t& value) {
72 int offset = mOffset;83 if (mPacketSize - mOffset < sizeof(value))
73 uint64_t result = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |84 return false;
85 size_t offset = mOffset;
86 value = (uint64_t)mBuffer[offset] | ((uint64_t)mBuffer[offset + 1] << 8) |
74 ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |87 ((uint64_t)mBuffer[offset + 2] << 16) | ((uint64_t)mBuffer[offset + 3] << 24) |
75 ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |88 ((uint64_t)mBuffer[offset + 4] << 32) | ((uint64_t)mBuffer[offset + 5] << 40) |
76 ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);89 ((uint64_t)mBuffer[offset + 6] << 48) | ((uint64_t)mBuffer[offset + 7] << 56);
77 mOffset += 8;90 mOffset += sizeof(value);
78 return result;91 return true;
79}92}
8093
81void MtpDataPacket::getUInt128(uint128_t& value) {94bool MtpDataPacket::getUInt128(uint128_t& value) {
82 value[0] = getUInt32();95 return getUInt32(value[0]) && getUInt32(value[1]) && getUInt32(value[2]) && getUInt32(value[3]);
83 value[1] = getUInt32();96}
84 value[2] = getUInt32();97
85 value[3] = getUInt32();98bool MtpDataPacket::getString(MtpStringBuffer& string)
86}
87
88void MtpDataPacket::getString(MtpStringBuffer& string)
89{99{
90 string.readFromPacket(this);100 return string.readFromPacket(this);
91}101}
92102
93Int8List* MtpDataPacket::getAInt8() {103Int8List* MtpDataPacket::getAInt8() {
104 uint32_t count;
105 if (!getUInt32(count))
106 return NULL;
94 Int8List* result = new Int8List;107 Int8List* result = new Int8List;
95 int count = getUInt32();108 for (uint32_t i = 0; i < count; i++) {
96 for (int i = 0; i < count; i++)109 int8_t value;
97 result->push_back(getInt8());110 if (!getInt8(value)) {
111 delete result;
112 return NULL;
113 }
114 result->push_back(value);
115 }
98 return result;116 return result;
99}117}
100118
101UInt8List* MtpDataPacket::getAUInt8() {119UInt8List* MtpDataPacket::getAUInt8() {
120 uint32_t count;
121 if (!getUInt32(count))
122 return NULL;
102 UInt8List* result = new UInt8List;123 UInt8List* result = new UInt8List;
103 int count = getUInt32();124 for (uint32_t i = 0; i < count; i++) {
104 for (int i = 0; i < count; i++)125 uint8_t value;
105 result->push_back(getUInt8());126 if (!getUInt8(value)) {
127 delete result;
128 return NULL;
129 }
130 result->push_back(value);
131 }
106 return result;132 return result;
107}133}
108134
109Int16List* MtpDataPacket::getAInt16() {135Int16List* MtpDataPacket::getAInt16() {
136 uint32_t count;
137 if (!getUInt32(count))
138 return NULL;
110 Int16List* result = new Int16List;139 Int16List* result = new Int16List;
111 int count = getUInt32();140 for (uint32_t i = 0; i < count; i++) {
112 for (int i = 0; i < count; i++)141 int16_t value;
113 result->push_back(getInt16());142 if (!getInt16(value)) {
143 delete result;
144 return NULL;
145 }
146 result->push_back(value);
147 }
114 return result;148 return result;
115}149}
116150
117UInt16List* MtpDataPacket::getAUInt16() {151UInt16List* MtpDataPacket::getAUInt16() {
152 uint32_t count;
153 if (!getUInt32(count))
154 return NULL;
118 UInt16List* result = new UInt16List;155 UInt16List* result = new UInt16List;
119 int count = getUInt32();156 for (uint32_t i = 0; i < count; i++) {
120 for (int i = 0; i < count; i++)157 uint16_t value;
121 result->push_back(getUInt16());158 if (!getUInt16(value)) {
159 delete result;
160 return NULL;
161 }
162 result->push_back(value);
163 }
122 return result;164 return result;
123}165}
124166
125Int32List* MtpDataPacket::getAInt32() {167Int32List* MtpDataPacket::getAInt32() {
168 uint32_t count;
169 if (!getUInt32(count))
170 return NULL;
126 Int32List* result = new Int32List;171 Int32List* result = new Int32List;
127 int count = getUInt32();172 for (uint32_t i = 0; i < count; i++) {
128 for (int i = 0; i < count; i++)173 int32_t value;
129 result->push_back(getInt32());174 if (!getInt32(value)) {
175 delete result;
176 return NULL;
177 }
178 result->push_back(value);
179 }
130 return result;180 return result;
131}181}
132182
133UInt32List* MtpDataPacket::getAUInt32() {183UInt32List* MtpDataPacket::getAUInt32() {
184 uint32_t count;
185 if (!getUInt32(count))
186 return NULL;
134 UInt32List* result = new UInt32List;187 UInt32List* result = new UInt32List;
135 int count = getUInt32();188 for (uint32_t i = 0; i < count; i++) {
136 for (int i = 0; i < count; i++)189 uint32_t value;
137 result->push_back(getUInt32());190 if (!getUInt32(value)) {
191 delete result;
192 return NULL;
193 }
194 result->push_back(value);
195 }
138 return result;196 return result;
139}197}
140198
141Int64List* MtpDataPacket::getAInt64() {199Int64List* MtpDataPacket::getAInt64() {
200 uint32_t count;
201 if (!getUInt32(count))
202 return NULL;
142 Int64List* result = new Int64List;203 Int64List* result = new Int64List;
143 int count = getUInt32();204 for (uint32_t i = 0; i < count; i++) {
144 for (int i = 0; i < count; i++)205 int64_t value;
145 result->push_back(getInt64());206 if (!getInt64(value)) {
207 delete result;
208 return NULL;
209 }
210 result->push_back(value);
211 }
146 return result;212 return result;
147}213}
148214
149UInt64List* MtpDataPacket::getAUInt64() {215UInt64List* MtpDataPacket::getAUInt64() {
216 uint32_t count;
217 if (!getUInt32(count))
218 return NULL;
150 UInt64List* result = new UInt64List;219 UInt64List* result = new UInt64List;
151 int count = getUInt32();220 for (uint32_t i = 0; i < count; i++) {
152 for (int i = 0; i < count; i++)221 uint64_t value;
153 result->push_back(getUInt64());222 if (!getUInt64(value)) {
223 delete result;
224 return NULL;
225 }
226 result->push_back(value);
227 }
154 return result;228 return result;
155}229}
156230
@@ -333,7 +407,7 @@
333407
334void MtpDataPacket::putString(const uint16_t* string) {408void MtpDataPacket::putString(const uint16_t* string) {
335 int count = 0;409 int count = 0;
336 for (int i = 0; i < 256; i++) {410 for (int i = 0; i <= MTP_STRING_MAX_CHARACTER_NUMBER; i++) {
337 if (string[i])411 if (string[i])
338 count++;412 count++;
339 else413 else
@@ -365,7 +439,7 @@
365}439}
366440
367int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {441int MtpDataPacket::writeData(int fd, void* data, uint32_t length) {
368 allocate(length);442 allocate(length + MTP_CONTAINER_HEADER_SIZE);
369 memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);443 memcpy(mBuffer + MTP_CONTAINER_HEADER_SIZE, data, length);
370 length += MTP_CONTAINER_HEADER_SIZE;444 length += MTP_CONTAINER_HEADER_SIZE;
371 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);445 MtpPacket::putUInt32(MTP_CONTAINER_LENGTH_OFFSET, length);
@@ -420,7 +494,7 @@
420// Queue a read request. Call readDataWait to wait for result494// Queue a read request. Call readDataWait to wait for result
421int MtpDataPacket::readDataAsync(struct usb_request *req) {495int MtpDataPacket::readDataAsync(struct usb_request *req) {
422 if (usb_request_queue(req)) {496 if (usb_request_queue(req)) {
423 PLOG(ERROR) << "usb_endpoint_queue failed";497 PLOG(ERROR) << "usb_endpoint_queue failed, errno: " << errno;
424 return -1;498 return -1;
425 }499 }
426 return 0;500 return 0;
427501
=== modified file 'src/MtpDevice.cpp'
--- src/MtpDevice.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpDevice.cpp 2016-04-12 16:15:02 +0000
@@ -135,13 +135,22 @@
135 struct usb_endpoint_descriptor *ep_in_desc = NULL;135 struct usb_endpoint_descriptor *ep_in_desc = NULL;
136 struct usb_endpoint_descriptor *ep_out_desc = NULL;136 struct usb_endpoint_descriptor *ep_out_desc = NULL;
137 struct usb_endpoint_descriptor *ep_intr_desc = NULL;137 struct usb_endpoint_descriptor *ep_intr_desc = NULL;
138 //USB3 add USB_DT_SS_ENDPOINT_COMP as companion descriptor;
139 struct usb_ss_ep_comp_descriptor *ep_ss_ep_comp_desc = NULL;
138 for (int i = 0; i < 3; i++) {140 for (int i = 0; i < 3; i++) {
139 ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);141 ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
142 if (ep && ep->bDescriptorType == USB_DT_SS_ENDPOINT_COMP) {
143 VLOG(2) << "Descriptor type is USB_DT_SS_ENDPOINT_COMP for USB3 \n";
144 ep_ss_ep_comp_desc = (usb_ss_ep_comp_descriptor*)ep;
145 ep = (struct usb_endpoint_descriptor *)usb_descriptor_iter_next(&iter);
146 }
147
140 if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {148 if (!ep || ep->bDescriptorType != USB_DT_ENDPOINT) {
141 LOG(ERROR) << "endpoints not found";149 LOG(ERROR) << "endpoints not found";
142 usb_device_close(device);150 usb_device_close(device);
143 return NULL;151 return NULL;
144 }152 }
153
145 if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {154 if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK) {
146 if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)155 if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
147 ep_in_desc = ep;156 ep_in_desc = ep;
@@ -199,7 +208,7 @@
199208
200MtpDevice::~MtpDevice() {209MtpDevice::~MtpDevice() {
201 close();210 close();
202 for (int i = 0; i < mDeviceProperties.size(); i++)211 for (size_t i = 0; i < mDeviceProperties.size(); i++)
203 delete mDeviceProperties[i];212 delete mDeviceProperties[i];
204 usb_request_free(mRequestIn1);213 usb_request_free(mRequestIn1);
205 usb_request_free(mRequestIn2);214 usb_request_free(mRequestIn2);
@@ -257,7 +266,7 @@
257 VLOG(2) << "*** FORMAT: " << MtpDebug::getFormatCodeName(format);266 VLOG(2) << "*** FORMAT: " << MtpDebug::getFormatCodeName(format);
258 MtpObjectPropertyList* props = getObjectPropsSupported(format);267 MtpObjectPropertyList* props = getObjectPropsSupported(format);
259 if (props) {268 if (props) {
260 for (int j = 0; j < props->size(); j++) {269 for (size_t j = 0; j < props->size(); j++) {
261 MtpObjectProperty prop = (*props)[j];270 MtpObjectProperty prop = (*props)[j];
262 MtpProperty* property = getObjectPropDesc(prop, format);271 MtpProperty* property = getObjectPropDesc(prop, format);
263 if (property) {272 if (property) {
@@ -317,8 +326,10 @@
317 MtpResponseCode ret = readResponse();326 MtpResponseCode ret = readResponse();
318 if (ret == MTP_RESPONSE_OK) {327 if (ret == MTP_RESPONSE_OK) {
319 MtpDeviceInfo* info = new MtpDeviceInfo;328 MtpDeviceInfo* info = new MtpDeviceInfo;
320 info->read(mData);329 if (info->read(mData))
321 return info;330 return info;
331 else
332 delete info;
322 }333 }
323 return NULL;334 return NULL;
324}335}
@@ -350,8 +361,10 @@
350 MtpResponseCode ret = readResponse();361 MtpResponseCode ret = readResponse();
351 if (ret == MTP_RESPONSE_OK) {362 if (ret == MTP_RESPONSE_OK) {
352 MtpStorageInfo* info = new MtpStorageInfo(storageID);363 MtpStorageInfo* info = new MtpStorageInfo(storageID);
353 info->read(mData);364 if (info->read(mData))
354 return info;365 return info;
366 else
367 delete info;
355 }368 }
356 return NULL;369 return NULL;
357}370}
@@ -389,8 +402,10 @@
389 MtpResponseCode ret = readResponse();402 MtpResponseCode ret = readResponse();
390 if (ret == MTP_RESPONSE_OK) {403 if (ret == MTP_RESPONSE_OK) {
391 MtpObjectInfo* info = new MtpObjectInfo(handle);404 MtpObjectInfo* info = new MtpObjectInfo(handle);
392 info->read(mData);405 if (info->read(mData))
393 return info;406 return info;
407 else
408 delete info;
394 }409 }
395 return NULL;410 return NULL;
396}411}
@@ -551,8 +566,10 @@
551 MtpResponseCode ret = readResponse();566 MtpResponseCode ret = readResponse();
552 if (ret == MTP_RESPONSE_OK) {567 if (ret == MTP_RESPONSE_OK) {
553 MtpProperty* property = new MtpProperty;568 MtpProperty* property = new MtpProperty;
554 property->read(mData);569 if (property->read(mData))
555 return property;570 return property;
571 else
572 delete property;
556 }573 }
557 return NULL;574 return NULL;
558}575}
@@ -570,15 +587,17 @@
570 MtpResponseCode ret = readResponse();587 MtpResponseCode ret = readResponse();
571 if (ret == MTP_RESPONSE_OK) {588 if (ret == MTP_RESPONSE_OK) {
572 MtpProperty* property = new MtpProperty;589 MtpProperty* property = new MtpProperty;
573 property->read(mData);590 if (property->read(mData))
574 return property;591 return property;
592 else
593 delete property;
575 }594 }
576 return NULL;595 return NULL;
577}596}
578597
579bool MtpDevice::readObject(MtpObjectHandle handle,598bool MtpDevice::readObject(MtpObjectHandle handle,
580 bool (* callback)(void* data, int offset, int length, void* clientData),599 bool (* callback)(void* data, int offset, int length, void* clientData),
581 int objectSize, void* clientData) {600 size_t objectSize, void* clientData) {
582 MtpAutolock autoLock(mMutex);601 MtpAutolock autoLock(mMutex);
583 bool result = false;602 bool result = false;
584603
@@ -671,7 +690,7 @@
671// reads the object's data and writes it to the specified file path690// reads the object's data and writes it to the specified file path
672bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {691bool MtpDevice::readObject(MtpObjectHandle handle, const char* destPath, int group, int perm) {
673 VLOG(2) << "readObject: " << destPath;692 VLOG(2) << "readObject: " << destPath;
674 int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);693 int fd = ::open(destPath, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR);
675 if (fd < 0) {694 if (fd < 0) {
676 LOG(ERROR) << "open failed for " << destPath;695 LOG(ERROR) << "open failed for " << destPath;
677 return false;696 return false;
678697
=== modified file 'src/MtpDeviceInfo.cpp'
--- src/MtpDeviceInfo.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpDeviceInfo.cpp 2016-04-12 16:15:02 +0000
@@ -32,7 +32,7 @@
32 mVendorExtensionID(0),32 mVendorExtensionID(0),
33 mVendorExtensionVersion(0),33 mVendorExtensionVersion(0),
34 mVendorExtensionDesc(NULL),34 mVendorExtensionDesc(NULL),
35 mFunctionalCode(0),35 mFunctionalMode(0),
36 mOperations(NULL),36 mOperations(NULL),
37 mEvents(NULL),37 mEvents(NULL),
38 mDeviceProperties(NULL),38 mDeviceProperties(NULL),
@@ -63,32 +63,39 @@
63 free(mSerial);63 free(mSerial);
64}64}
6565
66void MtpDeviceInfo::read(MtpDataPacket& packet) {66bool MtpDeviceInfo::read(MtpDataPacket& packet) {
67 MtpStringBuffer string;67 MtpStringBuffer string;
6868
69 // read the device info69 // read the device info
70 mStandardVersion = packet.getUInt16();70 if (!packet.getUInt16(mStandardVersion)) return false;
71 mVendorExtensionID = packet.getUInt32();71 if (!packet.getUInt32(mVendorExtensionID)) return false;
72 mVendorExtensionVersion = packet.getUInt16();72 if (!packet.getUInt16(mVendorExtensionVersion)) return false;
7373
74 packet.getString(string);74 if (!packet.getString(string)) return false;
75 mVendorExtensionDesc = strdup((const char *)string);75 mVendorExtensionDesc = strdup((const char *)string);
7676
77 mFunctionalCode = packet.getUInt16();77 if (!packet.getUInt16(mFunctionalMode)) return false;
78 mOperations = packet.getAUInt16();78 mOperations = packet.getAUInt16();
79 if (!mOperations) return false;
79 mEvents = packet.getAUInt16();80 mEvents = packet.getAUInt16();
81 if (!mEvents) return false;
80 mDeviceProperties = packet.getAUInt16();82 mDeviceProperties = packet.getAUInt16();
83 if (!mDeviceProperties) return false;
81 mCaptureFormats = packet.getAUInt16();84 mCaptureFormats = packet.getAUInt16();
85 if (!mCaptureFormats) return false;
82 mPlaybackFormats = packet.getAUInt16();86 mPlaybackFormats = packet.getAUInt16();
87 if (!mCaptureFormats) return false;
8388
84 packet.getString(string);89 if (!packet.getString(string)) return false;
85 mManufacturer = strdup((const char *)string);90 mManufacturer = strdup((const char *)string);
86 packet.getString(string);91 if (!packet.getString(string)) return false;
87 mModel = strdup((const char *)string);92 mModel = strdup((const char *)string);
88 packet.getString(string);93 if (!packet.getString(string)) return false;
89 mVersion = strdup((const char *)string);94 mVersion = strdup((const char *)string);
90 packet.getString(string);95 if (!packet.getString(string)) return false;
91 mSerial = strdup((const char *)string);96 mSerial = strdup((const char *)string);
97
98 return true;
92}99}
93100
94void MtpDeviceInfo::print() {101void MtpDeviceInfo::print() {
@@ -97,7 +104,7 @@
97 << "\n\tmVendorExtensionID: " << mVendorExtensionID104 << "\n\tmVendorExtensionID: " << mVendorExtensionID
98 << "\n\tmVendorExtensionVersion: " << mVendorExtensionVersion105 << "\n\tmVendorExtensionVersion: " << mVendorExtensionVersion
99 << "\n\tmVendorExtensionDesc: " << mVendorExtensionDesc106 << "\n\tmVendorExtensionDesc: " << mVendorExtensionDesc
100 << "\n\tmFunctionalCode: " << mFunctionalCode107 << "\n\tmFunctionalCode: " << mFunctionalMode
101 << "\n\tmManufacturer: " << mManufacturer108 << "\n\tmManufacturer: " << mManufacturer
102 << "\n\tmModel: " << mModel109 << "\n\tmModel: " << mModel
103 << "\n\tmVersion: " << mVersion110 << "\n\tmVersion: " << mVersion
104111
=== modified file 'src/MtpObjectInfo.cpp'
--- src/MtpObjectInfo.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpObjectInfo.cpp 2016-04-12 16:15:02 +0000
@@ -60,39 +60,41 @@
60 free(mKeywords);60 free(mKeywords);
61}61}
6262
63void MtpObjectInfo::read(MtpDataPacket& packet) {63bool MtpObjectInfo::read(MtpDataPacket& packet) {
64 MtpStringBuffer string;64 MtpStringBuffer string;
65 time_t time;65 time_t time;
6666
67 mStorageID = packet.getUInt32();67 if (!packet.getUInt32(mStorageID)) return false;
68 mFormat = packet.getUInt16();68 if (!packet.getUInt16(mFormat)) return false;
69 mProtectionStatus = packet.getUInt16();69 if (!packet.getUInt16(mProtectionStatus)) return false;
70 mCompressedSize = packet.getUInt32();70 if (!packet.getUInt32(mCompressedSize)) return false;
71 mThumbFormat = packet.getUInt16();71 if (!packet.getUInt16(mThumbFormat)) return false;
72 mThumbCompressedSize = packet.getUInt32();72 if (!packet.getUInt32(mThumbCompressedSize)) return false;
73 mThumbPixWidth = packet.getUInt32();73 if (!packet.getUInt32(mThumbPixWidth)) return false;
74 mThumbPixHeight = packet.getUInt32();74 if (!packet.getUInt32(mThumbPixHeight)) return false;
75 mImagePixWidth = packet.getUInt32();75 if (!packet.getUInt32(mImagePixWidth)) return false;
76 mImagePixHeight = packet.getUInt32();76 if (!packet.getUInt32(mImagePixHeight)) return false;
77 mImagePixDepth = packet.getUInt32();77 if (!packet.getUInt32(mImagePixDepth)) return false;
78 mParent = packet.getUInt32();78 if (!packet.getUInt32(mParent)) return false;
79 mAssociationType = packet.getUInt16();79 if (!packet.getUInt16(mAssociationType)) return false;
80 mAssociationDesc = packet.getUInt32();80 if (!packet.getUInt32(mAssociationDesc)) return false;
81 mSequenceNumber = packet.getUInt32();81 if (!packet.getUInt32(mSequenceNumber)) return false;
8282
83 packet.getString(string);83 if (!packet.getString(string)) return false;
84 mName = strdup((const char *)string);84 mName = strdup((const char *)string);
8585
86 packet.getString(string);86 if (!packet.getString(string)) return false;
87 if (parseDateTime((const char*)string, time))87 if (parseDateTime((const char*)string, time))
88 mDateCreated = time;88 mDateCreated = time;
8989
90 packet.getString(string);90 if (!packet.getString(string)) return false;
91 if (parseDateTime((const char*)string, time))91 if (parseDateTime((const char*)string, time))
92 mDateModified = time;92 mDateModified = time;
9393
94 packet.getString(string);94 if (!packet.getString(string)) return false;
95 mKeywords = strdup((const char *)string);95 mKeywords = strdup((const char *)string);
96
97 return true;
96}98}
9799
98void MtpObjectInfo::print() {100void MtpObjectInfo::print() {
99101
=== modified file 'src/MtpPacket.cpp'
--- src/MtpPacket.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpPacket.cpp 2016-04-12 16:15:02 +0000
@@ -52,7 +52,7 @@
52 memset(mBuffer, 0, mBufferSize);52 memset(mBuffer, 0, mBufferSize);
53}53}
5454
55void MtpPacket::allocate(int length) {55void MtpPacket::allocate(size_t length) {
56 if (length > mBufferSize) {56 if (length > mBufferSize) {
57 int newLength = length + mAllocationIncrement;57 int newLength = length + mAllocationIncrement;
58 mBuffer = (uint8_t *)realloc(mBuffer, newLength);58 mBuffer = (uint8_t *)realloc(mBuffer, newLength);
5959
=== modified file 'src/MtpProperty.cpp'
--- src/MtpProperty.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpProperty.cpp 2016-04-12 16:15:02 +0000
@@ -112,15 +112,15 @@
112 free(mMinimumValue.str);112 free(mMinimumValue.str);
113 free(mMaximumValue.str);113 free(mMaximumValue.str);
114 if (mDefaultArrayValues) {114 if (mDefaultArrayValues) {
115 for (int i = 0; i < mDefaultArrayLength; i++)115 for (uint32_t i = 0; i < mDefaultArrayLength; i++)
116 free(mDefaultArrayValues[i].str);116 free(mDefaultArrayValues[i].str);
117 }117 }
118 if (mCurrentArrayValues) {118 if (mCurrentArrayValues) {
119 for (int i = 0; i < mCurrentArrayLength; i++)119 for (uint32_t i = 0; i < mCurrentArrayLength; i++)
120 free(mCurrentArrayValues[i].str);120 free(mCurrentArrayValues[i].str);
121 }121 }
122 if (mEnumValues) {122 if (mEnumValues) {
123 for (int i = 0; i < mEnumLength; i++)123 for (uint16_t i = 0; i < mEnumLength; i++)
124 free(mEnumValues[i].str);124 free(mEnumValues[i].str);
125 }125 }
126 }126 }
@@ -129,11 +129,14 @@
129 delete[] mEnumValues;129 delete[] mEnumValues;
130}130}
131131
132void MtpProperty::read(MtpDataPacket& packet) {132bool MtpProperty::read(MtpDataPacket& packet) {
133 mCode = packet.getUInt16();133 uint8_t temp8;
134
135 if (!packet.getUInt16(mCode)) return false;
134 bool deviceProp = isDeviceProperty();136 bool deviceProp = isDeviceProperty();
135 mType = packet.getUInt16();137 if (!packet.getUInt16(mType)) return false;
136 mWriteable = (packet.getUInt8() == 1);138 if (!packet.getUInt8(temp8)) return false;
139 mWriteable = (temp8 == 1);
137 switch (mType) {140 switch (mType) {
138 case MTP_TYPE_AINT8:141 case MTP_TYPE_AINT8:
139 case MTP_TYPE_AUINT8:142 case MTP_TYPE_AUINT8:
@@ -146,28 +149,36 @@
146 case MTP_TYPE_AINT128:149 case MTP_TYPE_AINT128:
147 case MTP_TYPE_AUINT128:150 case MTP_TYPE_AUINT128:
148 mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);151 mDefaultArrayValues = readArrayValues(packet, mDefaultArrayLength);
149 if (deviceProp)152 if (!mDefaultArrayValues) return false;
153 if (deviceProp) {
150 mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);154 mCurrentArrayValues = readArrayValues(packet, mCurrentArrayLength);
155 if (!mCurrentArrayValues) return false;
156 }
151 break;157 break;
152 default:158 default:
153 readValue(packet, mDefaultValue);159 if (!readValue(packet, mDefaultValue)) return false;
154 if (deviceProp)160 if (deviceProp) {
155 readValue(packet, mCurrentValue);161 if (!readValue(packet, mCurrentValue)) return false;
156 }162 }
157 if (!deviceProp)163 }
158 mGroupCode = packet.getUInt32();164 if (!deviceProp) {
159 mFormFlag = packet.getUInt8();165 if (!packet.getUInt32(mGroupCode)) return false;
166 }
167 if (!packet.getUInt8(mFormFlag)) return false;
160168
161 if (mFormFlag == kFormRange) {169 if (mFormFlag == kFormRange) {
162 readValue(packet, mMinimumValue);170 if (!readValue(packet, mMinimumValue)) return false;
163 readValue(packet, mMaximumValue);171 if (!readValue(packet, mMaximumValue)) return false;
164 readValue(packet, mStepSize);172 if (!readValue(packet, mStepSize)) return false;
165 } else if (mFormFlag == kFormEnum) {173 } else if (mFormFlag == kFormEnum) {
166 mEnumLength = packet.getUInt16();174 if (!packet.getUInt16(mEnumLength)) return false;
167 mEnumValues = new MtpPropertyValue[mEnumLength];175 mEnumValues = new MtpPropertyValue[mEnumLength];
168 for (int i = 0; i < mEnumLength; i++)176 for (int i = 0; i < mEnumLength; i++) {
169 readValue(packet, mEnumValues[i]);177 if (!readValue(packet, mEnumValues[i])) return false;
178 }
170 }179 }
180
181 return true;
171}182}
172183
173void MtpProperty::write(MtpDataPacket& packet) {184void MtpProperty::write(MtpDataPacket& packet) {
@@ -197,9 +208,9 @@
197 if (deviceProp)208 if (deviceProp)
198 writeValue(packet, mCurrentValue);209 writeValue(packet, mCurrentValue);
199 }210 }
200 packet.putUInt32(mGroupCode);
201 if (!deviceProp)211 if (!deviceProp)
202 packet.putUInt8(mFormFlag);212 packet.putUInt32(mGroupCode);
213 packet.putUInt8(mFormFlag);
203 if (mFormFlag == kFormRange) {214 if (mFormFlag == kFormRange) {
204 writeValue(packet, mMinimumValue);215 writeValue(packet, mMinimumValue);
205 writeValue(packet, mMaximumValue);216 writeValue(packet, mMaximumValue);
@@ -423,52 +434,52 @@
423 buffer += ss.str();434 buffer += ss.str();
424}435}
425436
426void MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {437bool MtpProperty::readValue(MtpDataPacket& packet, MtpPropertyValue& value) {
427 MtpStringBuffer stringBuffer;438 MtpStringBuffer stringBuffer;
428439
429 switch (mType) {440 switch (mType) {
430 case MTP_TYPE_INT8:441 case MTP_TYPE_INT8:
431 case MTP_TYPE_AINT8:442 case MTP_TYPE_AINT8:
432 value.u.i8 = packet.getInt8();443 if (!packet.getInt8(value.u.i8)) return false;
433 break;444 break;
434 case MTP_TYPE_UINT8:445 case MTP_TYPE_UINT8:
435 case MTP_TYPE_AUINT8:446 case MTP_TYPE_AUINT8:
436 value.u.u8 = packet.getUInt8();447 if (!packet.getUInt8(value.u.u8)) return false;
437 break;448 break;
438 case MTP_TYPE_INT16:449 case MTP_TYPE_INT16:
439 case MTP_TYPE_AINT16:450 case MTP_TYPE_AINT16:
440 value.u.i16 = packet.getInt16();451 if (!packet.getInt16(value.u.i16)) return false;
441 break;452 break;
442 case MTP_TYPE_UINT16:453 case MTP_TYPE_UINT16:
443 case MTP_TYPE_AUINT16:454 case MTP_TYPE_AUINT16:
444 value.u.u16 = packet.getUInt16();455 if (!packet.getUInt16(value.u.u16)) return false;
445 break;456 break;
446 case MTP_TYPE_INT32:457 case MTP_TYPE_INT32:
447 case MTP_TYPE_AINT32:458 case MTP_TYPE_AINT32:
448 value.u.i32 = packet.getInt32();459 if (!packet.getInt32(value.u.i32)) return false;
449 break;460 break;
450 case MTP_TYPE_UINT32:461 case MTP_TYPE_UINT32:
451 case MTP_TYPE_AUINT32:462 case MTP_TYPE_AUINT32:
452 value.u.u32 = packet.getUInt32();463 if (!packet.getUInt32(value.u.u32)) return false;
453 break;464 break;
454 case MTP_TYPE_INT64:465 case MTP_TYPE_INT64:
455 case MTP_TYPE_AINT64:466 case MTP_TYPE_AINT64:
456 value.u.i64 = packet.getInt64();467 if (!packet.getInt64(value.u.i64)) return false;
457 break;468 break;
458 case MTP_TYPE_UINT64:469 case MTP_TYPE_UINT64:
459 case MTP_TYPE_AUINT64:470 case MTP_TYPE_AUINT64:
460 value.u.u64 = packet.getUInt64();471 if (!packet.getUInt64(value.u.u64)) return false;
461 break;472 break;
462 case MTP_TYPE_INT128:473 case MTP_TYPE_INT128:
463 case MTP_TYPE_AINT128:474 case MTP_TYPE_AINT128:
464 packet.getInt128(value.u.i128);475 if (!packet.getInt128(value.u.i128)) return false;
465 break;476 break;
466 case MTP_TYPE_UINT128:477 case MTP_TYPE_UINT128:
467 case MTP_TYPE_AUINT128:478 case MTP_TYPE_AUINT128:
468 packet.getUInt128(value.u.u128);479 if (!packet.getUInt128(value.u.u128)) return false;
469 break;480 break;
470 case MTP_TYPE_STR:481 case MTP_TYPE_STR:
471 packet.getString(stringBuffer);482 if (!packet.getString(stringBuffer)) return false;
472 value.str = strdup(stringBuffer);483 value.str = strdup(stringBuffer);
473 break;484 break;
474 default:485 default:
@@ -476,6 +487,7 @@
476 << std::hex << mType << std::dec487 << std::hex << mType << std::dec
477 << " in MtpProperty::readValue";488 << " in MtpProperty::readValue";
478 }489 }
490 return true;
479}491}
480492
481void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {493void MtpProperty::writeValue(MtpDataPacket& packet, MtpPropertyValue& value) {
@@ -535,19 +547,28 @@
535 }547 }
536}548}
537549
538MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, int& length) {550MtpPropertyValue* MtpProperty::readArrayValues(MtpDataPacket& packet, uint32_t& length) {
539 length = packet.getUInt32();551 if (!packet.getUInt32(length)) return NULL;
540 if (length == 0)552
553 // Fail if resulting array is over 2GB. This is because the maximum array
554 // size may be less than SIZE_MAX on some platforms.
555 if (length == 0 ||
556 length >= INT32_MAX / sizeof(MtpPropertyValue)) {
557 length = 0;
541 return NULL;558 return NULL;
559 }
542 MtpPropertyValue* result = new MtpPropertyValue[length];560 MtpPropertyValue* result = new MtpPropertyValue[length];
543 for (int i = 0; i < length; i++)561 for (uint32_t i = 0; i < length; i++)
544 readValue(packet, result[i]);562 if (!readValue(packet, result[i])) {
563 delete result;
564 return NULL;
565 }
545 return result;566 return result;
546}567}
547568
548void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, int length) {569void MtpProperty::writeArrayValues(MtpDataPacket& packet, MtpPropertyValue* values, uint32_t length) {
549 packet.putUInt32(length);570 packet.putUInt32(length);
550 for (int i = 0; i < length; i++)571 for (uint32_t i = 0; i < length; i++)
551 writeValue(packet, values[i]);572 writeValue(packet, values[i]);
552}573}
553574
554575
=== modified file 'src/MtpRequestPacket.cpp'
--- src/MtpRequestPacket.cpp 2013-06-13 10:22:21 +0000
+++ src/MtpRequestPacket.cpp 2016-04-12 16:15:02 +0000
@@ -24,11 +24,13 @@
24#include "MtpRequestPacket.h"24#include "MtpRequestPacket.h"
2525
26#include <usbhost/usbhost.h>26#include <usbhost/usbhost.h>
27#include <glog/logging.h>
2728
28namespace android {29namespace android {
2930
30MtpRequestPacket::MtpRequestPacket()31MtpRequestPacket::MtpRequestPacket()
31 : MtpPacket(512)32 : MtpPacket(512),
33 mParameterCount(0)
32{34{
33}35}
3436
@@ -38,10 +40,21 @@
38#ifdef MTP_DEVICE40#ifdef MTP_DEVICE
39int MtpRequestPacket::read(int fd) {41int MtpRequestPacket::read(int fd) {
40 int ret = ::read(fd, mBuffer, mBufferSize);42 int ret = ::read(fd, mBuffer, mBufferSize);
41 if (ret >= 0)43 if (ret < 0) {
44 // file read error
45 return ret;
46 }
47
48 // request packet should have 12 byte header followed by 0 to 5 32-bit arguments
49 if (ret >= MTP_CONTAINER_HEADER_SIZE
50 && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
51 && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
42 mPacketSize = ret;52 mPacketSize = ret;
43 else53 mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
44 mPacketSize = 0;54 } else {
55 PLOG(ERROR) << "Malformed MTP request packet";
56 ret = -1;
57 }
45 return ret;58 return ret;
46}59}
47#endif60#endif
4861
=== modified file 'src/MtpServer.cpp'
--- src/MtpServer.cpp 2014-10-31 15:56:55 +0000
+++ src/MtpServer.cpp 2016-04-12 16:15:02 +0000
@@ -27,6 +27,7 @@
27#include <sys/stat.h>27#include <sys/stat.h>
28#include <dirent.h>28#include <dirent.h>
29#include <unistd.h>29#include <unistd.h>
30#include <errno.h>
3031
31#define LOG_TAG "MtpServer"32#define LOG_TAG "MtpServer"
3233
@@ -99,6 +100,7 @@
99 MTP_EVENT_OBJECT_REMOVED,100 MTP_EVENT_OBJECT_REMOVED,
100 MTP_EVENT_STORE_ADDED,101 MTP_EVENT_STORE_ADDED,
101 MTP_EVENT_STORE_REMOVED,102 MTP_EVENT_STORE_REMOVED,
103 MTP_EVENT_DEVICE_PROP_CHANGED,
102 MTP_EVENT_OBJECT_INFO_CHANGED,104 MTP_EVENT_OBJECT_INFO_CHANGED,
103 MTP_EVENT_OBJECT_PROP_CHANGED,105 MTP_EVENT_OBJECT_PROP_CHANGED,
104};106};
@@ -132,7 +134,7 @@
132void MtpServer::removeStorage(MtpStorage* storage) {134void MtpServer::removeStorage(MtpStorage* storage) {
133 MtpAutolock autoLock(mMutex);135 MtpAutolock autoLock(mMutex);
134136
135 for (int i = 0; i < mStorages.size(); i++) {137 for (size_t i = 0; i < mStorages.size(); i++) {
136 if (mStorages[i] == storage) {138 if (mStorages[i] == storage) {
137 mStorages.erase(mStorages.begin()+i);139 mStorages.erase(mStorages.begin()+i);
138 sendStoreRemoved(storage->getStorageID());140 sendStoreRemoved(storage->getStorageID());
@@ -144,7 +146,7 @@
144MtpStorage* MtpServer::getStorage(MtpStorageID id) {146MtpStorage* MtpServer::getStorage(MtpStorageID id) {
145 if (id == 0)147 if (id == 0)
146 return mStorages[0];148 return mStorages[0];
147 for (int i = 0; i < mStorages.size(); i++) {149 for (size_t i = 0; i < mStorages.size(); i++) {
148 MtpStorage* storage = mStorages[i];150 MtpStorage* storage = mStorages[i];
149 if (storage->getStorageID() == id)151 if (storage->getStorageID() == id)
150 return storage;152 return storage;
@@ -226,10 +228,12 @@
226 VLOG(2) << "sending response "228 VLOG(2) << "sending response "
227 << std::hex << mResponse.getResponseCode() << std::dec;229 << std::hex << mResponse.getResponseCode() << std::dec;
228 ret = mResponse.write(fd);230 ret = mResponse.write(fd);
231 const int savedErrno = errno;
229 mResponse.dump();232 mResponse.dump();
230 if (ret < 0) {233 if (ret < 0) {
231 PLOG(ERROR) << "request write returned " << ret;234 PLOG(ERROR) << "request write returned " << ret
232 if (errno == ECANCELED) {235 << ", errno: " << savedErrno;
236 if (savedErrno == ECANCELED) {
233 // return to top of loop and wait for next command237 // return to top of loop and wait for next command
234 continue;238 continue;
235 }239 }
@@ -348,6 +352,15 @@
348 mSendObjectHandle = kInvalidObjectHandle;352 mSendObjectHandle = kInvalidObjectHandle;
349 }353 }
350354
355 int containertype = mRequest.getContainerType();
356 if (containertype != MTP_CONTAINER_TYPE_COMMAND) {
357 LOG(ERROR) << "wrong container type " << containertype;
358 return false;
359 }
360
361 VLOG(2) << "got command " << MtpDebug::getOperationCodeName(operation)
362 << ", " << std::hex << operation << std::dec;
363
351 switch (operation) {364 switch (operation) {
352 case MTP_OPERATION_GET_DEVICE_INFO:365 case MTP_OPERATION_GET_DEVICE_INFO:
353 response = doGetDeviceInfo();366 response = doGetDeviceInfo();
@@ -513,6 +526,9 @@
513 mResponse.setParameter(1, mSessionID);526 mResponse.setParameter(1, mSessionID);
514 return MTP_RESPONSE_SESSION_ALREADY_OPEN;527 return MTP_RESPONSE_SESSION_ALREADY_OPEN;
515 }528 }
529 if (mRequest.getParameterCount() < 1)
530 return MTP_RESPONSE_INVALID_PARAMETER;
531
516 mSessionID = mRequest.getParameter(1);532 mSessionID = mRequest.getParameter(1);
517 mSessionOpen = true;533 mSessionOpen = true;
518534
@@ -547,6 +563,9 @@
547563
548 if (!mSessionOpen)564 if (!mSessionOpen)
549 return MTP_RESPONSE_SESSION_NOT_OPEN;565 return MTP_RESPONSE_SESSION_NOT_OPEN;
566 if (mRequest.getParameterCount() < 1)
567 return MTP_RESPONSE_INVALID_PARAMETER;
568
550 MtpStorageID id = mRequest.getParameter(1);569 MtpStorageID id = mRequest.getParameter(1);
551 MtpStorage* storage = getStorage(id);570 MtpStorage* storage = getStorage(id);
552 if (!storage)571 if (!storage)
@@ -568,6 +587,8 @@
568MtpResponseCode MtpServer::doGetObjectPropsSupported() {587MtpResponseCode MtpServer::doGetObjectPropsSupported() {
569 if (!mSessionOpen)588 if (!mSessionOpen)
570 return MTP_RESPONSE_SESSION_NOT_OPEN;589 return MTP_RESPONSE_SESSION_NOT_OPEN;
590 if (mRequest.getParameterCount() < 1)
591 return MTP_RESPONSE_INVALID_PARAMETER;
571 MtpObjectFormat format = mRequest.getParameter(1);592 MtpObjectFormat format = mRequest.getParameter(1);
572 MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);593 MtpObjectPropertyList* properties = mDatabase->getSupportedObjectProperties(format);
573 mData.putAUInt16(properties);594 mData.putAUInt16(properties);
@@ -578,6 +599,8 @@
578MtpResponseCode MtpServer::doGetObjectHandles() {599MtpResponseCode MtpServer::doGetObjectHandles() {
579 if (!mSessionOpen)600 if (!mSessionOpen)
580 return MTP_RESPONSE_SESSION_NOT_OPEN;601 return MTP_RESPONSE_SESSION_NOT_OPEN;
602 if (mRequest.getParameterCount() < 3)
603 return MTP_RESPONSE_INVALID_PARAMETER;
581 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage604 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
582 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats605 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
583 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent606 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
@@ -595,6 +618,8 @@
595MtpResponseCode MtpServer::doGetNumObjects() {618MtpResponseCode MtpServer::doGetNumObjects() {
596 if (!mSessionOpen)619 if (!mSessionOpen)
597 return MTP_RESPONSE_SESSION_NOT_OPEN;620 return MTP_RESPONSE_SESSION_NOT_OPEN;
621 if (mRequest.getParameterCount() < 3)
622 return MTP_RESPONSE_INVALID_PARAMETER;
598 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage623 MtpStorageID storageID = mRequest.getParameter(1); // 0xFFFFFFFF for all storage
599 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats624 MtpObjectFormat format = mRequest.getParameter(2); // 0 for all formats
600 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent625 MtpObjectHandle parent = mRequest.getParameter(3); // 0xFFFFFFFF for objects with no parent
@@ -617,6 +642,8 @@
617 return MTP_RESPONSE_SESSION_NOT_OPEN;642 return MTP_RESPONSE_SESSION_NOT_OPEN;
618 if (!hasStorage())643 if (!hasStorage())
619 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;644 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
645 if (mRequest.getParameterCount() < 1)
646 return MTP_RESPONSE_INVALID_PARAMETER;
620 MtpObjectHandle handle = mRequest.getParameter(1);647 MtpObjectHandle handle = mRequest.getParameter(1);
621648
622 // FIXME - check for invalid object handle649 // FIXME - check for invalid object handle
@@ -635,9 +662,13 @@
635 return MTP_RESPONSE_SESSION_NOT_OPEN;662 return MTP_RESPONSE_SESSION_NOT_OPEN;
636 if (!hasStorage())663 if (!hasStorage())
637 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;664 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
665 if (mRequest.getParameterCount() < 1)
666 return MTP_RESPONSE_INVALID_PARAMETER;
638 MtpStorageID handle = mRequest.getParameter(1);667 MtpStorageID handle = mRequest.getParameter(1);
639668
640 MtpObjectHandleList* references = mData.getAUInt32();669 MtpObjectHandleList* references = mData.getAUInt32();
670 if (!references)
671 return MTP_RESPONSE_INVALID_PARAMETER;
641 MtpResponseCode result = mDatabase->setObjectReferences(handle, references);672 MtpResponseCode result = mDatabase->setObjectReferences(handle, references);
642 delete references;673 delete references;
643 return result;674 return result;
@@ -646,6 +677,8 @@
646MtpResponseCode MtpServer::doGetObjectPropValue() {677MtpResponseCode MtpServer::doGetObjectPropValue() {
647 if (!hasStorage())678 if (!hasStorage())
648 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;679 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
680 if (mRequest.getParameterCount() < 2)
681 return MTP_RESPONSE_INVALID_PARAMETER;
649 MtpObjectHandle handle = mRequest.getParameter(1);682 MtpObjectHandle handle = mRequest.getParameter(1);
650 MtpObjectProperty property = mRequest.getParameter(2);683 MtpObjectProperty property = mRequest.getParameter(2);
651 VLOG(2) << "GetObjectPropValue " << handle684 VLOG(2) << "GetObjectPropValue " << handle
@@ -659,6 +692,8 @@
659692
660 if (!hasStorage())693 if (!hasStorage())
661 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;694 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
695 if (mRequest.getParameterCount() < 2)
696 return MTP_RESPONSE_INVALID_PARAMETER;
662 MtpObjectHandle handle = mRequest.getParameter(1);697 MtpObjectHandle handle = mRequest.getParameter(1);
663 MtpObjectProperty property = mRequest.getParameter(2);698 MtpObjectProperty property = mRequest.getParameter(2);
664 VLOG(2) << "SetObjectPropValue " << handle699 VLOG(2) << "SetObjectPropValue " << handle
@@ -672,6 +707,8 @@
672}707}
673708
674MtpResponseCode MtpServer::doGetDevicePropValue() {709MtpResponseCode MtpServer::doGetDevicePropValue() {
710 if (mRequest.getParameterCount() < 1)
711 return MTP_RESPONSE_INVALID_PARAMETER;
675 MtpDeviceProperty property = mRequest.getParameter(1);712 MtpDeviceProperty property = mRequest.getParameter(1);
676 VLOG(1) << "GetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);713 VLOG(1) << "GetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);
677714
@@ -679,6 +716,8 @@
679}716}
680717
681MtpResponseCode MtpServer::doSetDevicePropValue() {718MtpResponseCode MtpServer::doSetDevicePropValue() {
719 if (mRequest.getParameterCount() < 1)
720 return MTP_RESPONSE_INVALID_PARAMETER;
682 MtpDeviceProperty property = mRequest.getParameter(1);721 MtpDeviceProperty property = mRequest.getParameter(1);
683 VLOG(1) << "SetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);722 VLOG(1) << "SetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);
684723
@@ -686,6 +725,8 @@
686}725}
687726
688MtpResponseCode MtpServer::doResetDevicePropValue() {727MtpResponseCode MtpServer::doResetDevicePropValue() {
728 if (mRequest.getParameterCount() < 1)
729 return MTP_RESPONSE_INVALID_PARAMETER;
689 MtpDeviceProperty property = mRequest.getParameter(1);730 MtpDeviceProperty property = mRequest.getParameter(1);
690 VLOG(1) << "ResetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);731 VLOG(1) << "ResetDevicePropValue " << MtpDebug::getDevicePropCodeName(property);
691732
@@ -695,6 +736,8 @@
695MtpResponseCode MtpServer::doGetObjectPropList() {736MtpResponseCode MtpServer::doGetObjectPropList() {
696 if (!hasStorage())737 if (!hasStorage())
697 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;738 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
739 if (mRequest.getParameterCount() < 5)
740 return MTP_RESPONSE_INVALID_PARAMETER;
698741
699 MtpObjectHandle handle = mRequest.getParameter(1);742 MtpObjectHandle handle = mRequest.getParameter(1);
700 // use uint32_t so we can support 0xFFFFFFFF743 // use uint32_t so we can support 0xFFFFFFFF
@@ -714,6 +757,8 @@
714MtpResponseCode MtpServer::doGetObjectInfo() {757MtpResponseCode MtpServer::doGetObjectInfo() {
715 if (!hasStorage())758 if (!hasStorage())
716 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;759 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
760 if (mRequest.getParameterCount() < 1)
761 return MTP_RESPONSE_INVALID_PARAMETER;
717 MtpObjectHandle handle = mRequest.getParameter(1);762 MtpObjectHandle handle = mRequest.getParameter(1);
718 MtpObjectInfo info(handle);763 MtpObjectInfo info(handle);
719 MtpResponseCode result = mDatabase->getObjectInfo(handle, info);764 MtpResponseCode result = mDatabase->getObjectInfo(handle, info);
@@ -754,6 +799,8 @@
754MtpResponseCode MtpServer::doGetObject() {799MtpResponseCode MtpServer::doGetObject() {
755 if (!hasStorage())800 if (!hasStorage())
756 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;801 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
802 if (mRequest.getParameterCount() < 1)
803 return MTP_RESPONSE_INVALID_PARAMETER;
757 MtpObjectHandle handle = mRequest.getParameter(1);804 MtpObjectHandle handle = mRequest.getParameter(1);
758 MtpString pathBuf;805 MtpString pathBuf;
759 int64_t fileLength;806 int64_t fileLength;
@@ -763,7 +810,7 @@
763 return result;810 return result;
764811
765 mtp_file_range mfr;812 mtp_file_range mfr;
766 mfr.fd = open(pathBuf.c_str(), O_RDONLY);813 mfr.fd = open(pathBuf.c_str(), O_RDONLY | O_LARGEFILE);
767 if (mfr.fd < 0) {814 if (mfr.fd < 0) {
768 return MTP_RESPONSE_GENERAL_ERROR;815 return MTP_RESPONSE_GENERAL_ERROR;
769 }816 }
@@ -774,18 +821,24 @@
774821
775 // then transfer the file822 // then transfer the file
776 int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);823 int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
824 if (ret < 0) {
825 if (errno == ECANCELED) {
826 result = MTP_RESPONSE_TRANSACTION_CANCELLED;
827 } else {
828 result = MTP_RESPONSE_GENERAL_ERROR;
829 }
830 } else {
831 result = MTP_RESPONSE_OK;
832 }
833
777 VLOG(2) << "MTP_SEND_FILE_WITH_HEADER returned " << ret;834 VLOG(2) << "MTP_SEND_FILE_WITH_HEADER returned " << ret;
778 close(mfr.fd);835 close(mfr.fd);
779 if (ret < 0) {836 return result;
780 if (errno == ECANCELED)
781 return MTP_RESPONSE_TRANSACTION_CANCELLED;
782 else
783 return MTP_RESPONSE_GENERAL_ERROR;
784 }
785 return MTP_RESPONSE_OK;
786}837}
787838
788MtpResponseCode MtpServer::doGetThumb() {839MtpResponseCode MtpServer::doGetThumb() {
840 if (mRequest.getParameterCount() < 1)
841 return MTP_RESPONSE_INVALID_PARAMETER;
789 MtpObjectHandle handle = mRequest.getParameter(1);842 MtpObjectHandle handle = mRequest.getParameter(1);
790 size_t thumbSize;843 size_t thumbSize;
791 void* thumb = mDatabase->getThumbnail(handle, thumbSize);844 void* thumb = mDatabase->getThumbnail(handle, thumbSize);
@@ -809,11 +862,19 @@
809 uint32_t length;862 uint32_t length;
810 offset = mRequest.getParameter(2);863 offset = mRequest.getParameter(2);
811 if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {864 if (operation == MTP_OPERATION_GET_PARTIAL_OBJECT_64) {
865 // MTP_OPERATION_GET_PARTIAL_OBJECT_64 takes 4 arguments
866 if (mRequest.getParameterCount() < 4)
867 return MTP_RESPONSE_INVALID_PARAMETER;
868
812 // android extension with 64 bit offset869 // android extension with 64 bit offset
813 uint64_t offset2 = mRequest.getParameter(3);870 uint64_t offset2 = mRequest.getParameter(3);
814 offset = offset | (offset2 << 32);871 offset = offset | (offset2 << 32);
815 length = mRequest.getParameter(4);872 length = mRequest.getParameter(4);
816 } else {873 } else {
874 // MTP_OPERATION_GET_PARTIAL_OBJECT takes 3 arguments
875 if (mRequest.getParameterCount() < 3)
876 return MTP_RESPONSE_INVALID_PARAMETER;
877
817 // standard GetPartialObject878 // standard GetPartialObject
818 length = mRequest.getParameter(3);879 length = mRequest.getParameter(3);
819 }880 }
@@ -823,11 +884,11 @@
823 int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);884 int result = mDatabase->getObjectFilePath(handle, pathBuf, fileLength, format);
824 if (result != MTP_RESPONSE_OK)885 if (result != MTP_RESPONSE_OK)
825 return result;886 return result;
826 if (offset + length > fileLength)887 if (offset + length > (uint64_t)fileLength)
827 length = fileLength - offset;888 length = fileLength - offset;
828889
829 mtp_file_range mfr;890 mtp_file_range mfr;
830 mfr.fd = open(pathBuf.c_str(), O_RDONLY);891 mfr.fd = open(pathBuf.c_str(), O_RDONLY | O_LARGEFILE);
831 if (mfr.fd < 0) {892 if (mfr.fd < 0) {
832 return MTP_RESPONSE_GENERAL_ERROR;893 return MTP_RESPONSE_GENERAL_ERROR;
833 }894 }
@@ -840,18 +901,24 @@
840 // transfer the file901 // transfer the file
841 int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);902 int ret = ioctl(mFD, MTP_SEND_FILE_WITH_HEADER, (unsigned long)&mfr);
842 VLOG(2) << "MTP_SEND_FILE_WITH_HEADER returned " << ret;903 VLOG(2) << "MTP_SEND_FILE_WITH_HEADER returned " << ret;
843 close(mfr.fd);904 result = MTP_RESPONSE_OK;
844 if (ret < 0) {905 if (ret < 0) {
845 if (errno == ECANCELED)906 if (errno == ECANCELED)
846 return MTP_RESPONSE_TRANSACTION_CANCELLED;907 result = MTP_RESPONSE_TRANSACTION_CANCELLED;
847 else908 else
848 return MTP_RESPONSE_GENERAL_ERROR;909 result = MTP_RESPONSE_GENERAL_ERROR;
849 }910 }
850 return MTP_RESPONSE_OK;911 close(mfr.fd);
912 return result;
851}913}
852914
853MtpResponseCode MtpServer::doSendObjectInfo() {915MtpResponseCode MtpServer::doSendObjectInfo() {
854 MtpString path;916 MtpString path;
917 uint16_t temp16;
918 uint32_t temp32;
919
920 if (mRequest.getParameterCount() < 2)
921 return MTP_RESPONSE_INVALID_PARAMETER;
855 MtpStorageID storageID = mRequest.getParameter(1);922 MtpStorageID storageID = mRequest.getParameter(1);
856 MtpStorage* storage = getStorage(storageID);923 MtpStorage* storage = getStorage(storageID);
857 MtpObjectHandle parent = mRequest.getParameter(2);924 MtpObjectHandle parent = mRequest.getParameter(2);
@@ -873,25 +940,29 @@
873 }940 }
874941
875 // read only the fields we need942 // read only the fields we need
876 mData.getUInt32(); // storage ID943 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // storage ID
877 MtpObjectFormat format = mData.getUInt16();944 if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
878 mData.getUInt16(); // protection status945 MtpObjectFormat format = temp16;
879 mSendObjectFileSize = mData.getUInt32();946 if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // protection status
880 mData.getUInt16(); // thumb format947 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
881 mData.getUInt32(); // thumb compressed size948 mSendObjectFileSize = temp32;
882 mData.getUInt32(); // thumb pix width949 if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb format
883 mData.getUInt32(); // thumb pix height950 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb compressed size
884 mData.getUInt32(); // image pix width951 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix width
885 mData.getUInt32(); // image pix height952 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // thumb pix height
886 mData.getUInt32(); // image bit depth953 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix width
887 mData.getUInt32(); // parent954 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image pix height
888 uint16_t associationType = mData.getUInt16();955 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image bit depth
889 uint32_t associationDesc = mData.getUInt32(); // association desc956 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // parent
890 mData.getUInt32(); // sequence number957 if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
958 uint16_t associationType = temp16;
959 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
960 uint32_t associationDesc = temp32; // association desc
961 if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // sequence number
891 MtpStringBuffer name, created, modified;962 MtpStringBuffer name, created, modified;
892 mData.getString(name); // file name963 if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER; // file name
893 mData.getString(created); // date created964 if (!mData.getString(created)) return MTP_RESPONSE_INVALID_PARAMETER; // date created
894 mData.getString(modified); // date modified965 if (!mData.getString(modified)) return MTP_RESPONSE_INVALID_PARAMETER; // date modified
895 // keywords follow966 // keywords follow
896967
897 VLOG(2) << "name: " << (const char *) name968 VLOG(2) << "name: " << (const char *) name
@@ -954,6 +1025,7 @@
954 MtpResponseCode result = MTP_RESPONSE_OK;1025 MtpResponseCode result = MTP_RESPONSE_OK;
955 mode_t mask;1026 mode_t mask;
956 int ret, initialData;1027 int ret, initialData;
1028 bool isCanceled = false;
9571029
958 if (mSendObjectHandle == kInvalidObjectHandle) {1030 if (mSendObjectHandle == kInvalidObjectHandle) {
959 LOG(ERROR) << "Expected SendObjectInfo before SendObject";1031 LOG(ERROR) << "Expected SendObjectInfo before SendObject";
@@ -970,7 +1042,9 @@
970 initialData = ret - MTP_CONTAINER_HEADER_SIZE;1042 initialData = ret - MTP_CONTAINER_HEADER_SIZE;
9711043
972 mtp_file_range mfr;1044 mtp_file_range mfr;
973 mfr.fd = open(mSendObjectFilePath.c_str(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);1045 mfr.fd = open(mSendObjectFilePath.c_str(),
1046 O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
1047 S_IRUSR | S_IWUSR);
974 if (mfr.fd < 0) {1048 if (mfr.fd < 0) {
975 result = MTP_RESPONSE_GENERAL_ERROR;1049 result = MTP_RESPONSE_GENERAL_ERROR;
976 goto done;1050 goto done;
@@ -981,28 +1055,38 @@
981 fchmod(mfr.fd, mFilePermission);1055 fchmod(mfr.fd, mFilePermission);
982 umask(mask);1056 umask(mask);
9831057
984 if (initialData > 0)1058 if (initialData > 0) {
985 ret = write(mfr.fd, mData.getData(), initialData);1059 ret = write(mfr.fd, mData.getData(), initialData);
9861060 }
987 if (mSendObjectFileSize - initialData > 0) {1061
988 mfr.offset = initialData;1062 if (ret < 0) {
989 if (mSendObjectFileSize == 0xFFFFFFFF) {1063 LOG(ERROR) << "failed to write initial data";
990 // tell driver to read until it receives a short packet1064 result = MTP_RESPONSE_GENERAL_ERROR;
991 mfr.length = 0xFFFFFFFF;1065 } else {
992 } else {1066 if (mSendObjectFileSize - initialData > 0) {
993 mfr.length = mSendObjectFileSize - initialData;1067 mfr.offset = initialData;
1068 if (mSendObjectFileSize == 0xFFFFFFFF) {
1069 // tell driver to read until it receives a short packet
1070 mfr.length = 0xFFFFFFFF;
1071 } else {
1072 mfr.length = mSendObjectFileSize - initialData;
1073 }
1074
1075 VLOG(2) << "receiving " << mSendObjectFilePath.c_str();
1076 // transfer the file
1077 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
1078 if ((ret < 0) && (errno == ECANCELED)) {
1079 isCanceled = true;
1080 }
1081
1082 VLOG(2) << "MTP_RECEIVE_FILE returned " << ret;
994 }1083 }
995
996 VLOG(2) << "receiving " << mSendObjectFilePath.c_str();
997 // transfer the file
998 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
999 VLOG(2) << "MTP_RECEIVE_FILE returned " << ret;
1000 }1084 }
1001 close(mfr.fd);1085 close(mfr.fd);
10021086
1003 if (ret < 0) {1087 if (ret < 0) {
1004 unlink(mSendObjectFilePath.c_str());1088 unlink(mSendObjectFilePath.c_str());
1005 if (errno == ECANCELED)1089 if (isCanceled)
1006 result = MTP_RESPONSE_TRANSACTION_CANCELLED;1090 result = MTP_RESPONSE_TRANSACTION_CANCELLED;
1007 else1091 else
1008 result = MTP_RESPONSE_GENERAL_ERROR;1092 result = MTP_RESPONSE_GENERAL_ERROR;
@@ -1021,7 +1105,7 @@
10211105
1022static void deleteRecursive(const char* path) {1106static void deleteRecursive(const char* path) {
1023 char pathbuf[PATH_MAX];1107 char pathbuf[PATH_MAX];
1024 int pathLength = strlen(path);1108 size_t pathLength = strlen(path);
1025 if (pathLength >= sizeof(pathbuf) - 1) {1109 if (pathLength >= sizeof(pathbuf) - 1) {
1026 LOG(ERROR) << "path too long: " << path;1110 LOG(ERROR) << "path too long: " << path;
1027 }1111 }
@@ -1082,8 +1166,10 @@
1082MtpResponseCode MtpServer::doDeleteObject() {1166MtpResponseCode MtpServer::doDeleteObject() {
1083 if (!hasStorage())1167 if (!hasStorage())
1084 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;1168 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
1169 if (mRequest.getParameterCount() < 1)
1170 return MTP_RESPONSE_INVALID_PARAMETER;
1085 MtpObjectHandle handle = mRequest.getParameter(1);1171 MtpObjectHandle handle = mRequest.getParameter(1);
1086 MtpObjectFormat format = mRequest.getParameter(2);1172 MtpObjectFormat format;
1087 // FIXME - support deleting all objects if handle is 0xFFFFFFFF1173 // FIXME - support deleting all objects if handle is 0xFFFFFFFF
1088 // FIXME - implement deleting objects by format1174 // FIXME - implement deleting objects by format
10891175
@@ -1127,6 +1213,8 @@
1127}1213}
11281214
1129MtpResponseCode MtpServer::doGetObjectPropDesc() {1215MtpResponseCode MtpServer::doGetObjectPropDesc() {
1216 if (mRequest.getParameterCount() < 2)
1217 return MTP_RESPONSE_INVALID_PARAMETER;
1130 MtpObjectProperty propCode = mRequest.getParameter(1);1218 MtpObjectProperty propCode = mRequest.getParameter(1);
1131 MtpObjectFormat format = mRequest.getParameter(2);1219 MtpObjectFormat format = mRequest.getParameter(2);
1132 VLOG(2) << "GetObjectPropDesc " << MtpDebug::getObjectPropCodeName(propCode)1220 VLOG(2) << "GetObjectPropDesc " << MtpDebug::getObjectPropCodeName(propCode)
@@ -1140,6 +1228,8 @@
1140}1228}
11411229
1142MtpResponseCode MtpServer::doGetDevicePropDesc() {1230MtpResponseCode MtpServer::doGetDevicePropDesc() {
1231 if (mRequest.getParameterCount() < 1)
1232 return MTP_RESPONSE_INVALID_PARAMETER;
1143 MtpDeviceProperty propCode = mRequest.getParameter(1);1233 MtpDeviceProperty propCode = mRequest.getParameter(1);
1144 VLOG(1) << "GetDevicePropDesc " << MtpDebug::getDevicePropCodeName(propCode);1234 VLOG(1) << "GetDevicePropDesc " << MtpDebug::getDevicePropCodeName(propCode);
1145 MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);1235 MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
@@ -1153,6 +1243,8 @@
1153MtpResponseCode MtpServer::doSendPartialObject() {1243MtpResponseCode MtpServer::doSendPartialObject() {
1154 if (!hasStorage())1244 if (!hasStorage())
1155 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;1245 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
1246 if (mRequest.getParameterCount() < 4)
1247 return MTP_RESPONSE_INVALID_PARAMETER;
1156 MtpObjectHandle handle = mRequest.getParameter(1);1248 MtpObjectHandle handle = mRequest.getParameter(1);
1157 uint64_t offset = mRequest.getParameter(2);1249 uint64_t offset = mRequest.getParameter(2);
1158 uint64_t offset2 = mRequest.getParameter(3);1250 uint64_t offset2 = mRequest.getParameter(3);
@@ -1188,19 +1280,27 @@
1188 length -= initialData;1280 length -= initialData;
1189 }1281 }
11901282
1191 if (length > 0) {1283 bool isCanceled = false;
1192 mtp_file_range mfr;1284 if (ret < 0) {
1193 mfr.fd = edit->mFD;1285 PLOG(ERROR) << "failed to write initial data";
1194 mfr.offset = offset;1286 } else {
1195 mfr.length = length;1287 if (length > 0) {
1288 mtp_file_range mfr;
1289 mfr.fd = edit->mFD;
1290 mfr.offset = offset;
1291 mfr.length = length;
11961292
1197 // transfer the file1293 // transfer the file
1198 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);1294 ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
1199 VLOG(2) << "MTP_RECEIVE_FILE returned " << ret;1295 if ((ret < 0) && (errno == ECANCELED)) {
1296 isCanceled = true;
1297 }
1298 VLOG(2) << "MTP_RECEIVE_FILE returned " << ret << " errno " << errno;
1299 }
1200 }1300 }
1201 if (ret < 0) {1301 if (ret < 0) {
1202 mResponse.setParameter(1, 0);1302 mResponse.setParameter(1, 0);
1203 if (errno == ECANCELED)1303 if (isCanceled)
1204 return MTP_RESPONSE_TRANSACTION_CANCELLED;1304 return MTP_RESPONSE_TRANSACTION_CANCELLED;
1205 else1305 else
1206 return MTP_RESPONSE_GENERAL_ERROR;1306 return MTP_RESPONSE_GENERAL_ERROR;
@@ -1217,6 +1317,8 @@
1217}1317}
12181318
1219MtpResponseCode MtpServer::doTruncateObject() {1319MtpResponseCode MtpServer::doTruncateObject() {
1320 if (mRequest.getParameterCount() < 3)
1321 return MTP_RESPONSE_INVALID_PARAMETER;
1220 MtpObjectHandle handle = mRequest.getParameter(1);1322 MtpObjectHandle handle = mRequest.getParameter(1);
1221 ObjectEdit* edit = getEditObject(handle);1323 ObjectEdit* edit = getEditObject(handle);
1222 if (!edit) {1324 if (!edit) {
@@ -1236,6 +1338,8 @@
1236}1338}
12371339
1238MtpResponseCode MtpServer::doBeginEditObject() {1340MtpResponseCode MtpServer::doBeginEditObject() {
1341 if (mRequest.getParameterCount() < 1)
1342 return MTP_RESPONSE_INVALID_PARAMETER;
1239 MtpObjectHandle handle = mRequest.getParameter(1);1343 MtpObjectHandle handle = mRequest.getParameter(1);
1240 if (getEditObject(handle)) {1344 if (getEditObject(handle)) {
1241 LOG(ERROR) << "object already open for edit in doBeginEditObject";1345 LOG(ERROR) << "object already open for edit in doBeginEditObject";
@@ -1249,7 +1353,7 @@
1249 if (result != MTP_RESPONSE_OK)1353 if (result != MTP_RESPONSE_OK)
1250 return result;1354 return result;
12511355
1252 int fd = open(path.c_str(), O_RDWR | O_EXCL);1356 int fd = open(path.c_str(), O_RDWR | O_EXCL | O_LARGEFILE);
1253 if (fd < 0) {1357 if (fd < 0) {
1254 PLOG(ERROR) << "open failed for " << path.c_str() << " in doBeginEditObject";1358 PLOG(ERROR) << "open failed for " << path.c_str() << " in doBeginEditObject";
1255 return MTP_RESPONSE_GENERAL_ERROR;1359 return MTP_RESPONSE_GENERAL_ERROR;
@@ -1260,6 +1364,8 @@
1260}1364}
12611365
1262MtpResponseCode MtpServer::doEndEditObject() {1366MtpResponseCode MtpServer::doEndEditObject() {
1367 if (mRequest.getParameterCount() < 1)
1368 return MTP_RESPONSE_INVALID_PARAMETER;
1263 MtpObjectHandle handle = mRequest.getParameter(1);1369 MtpObjectHandle handle = mRequest.getParameter(1);
1264 ObjectEdit* edit = getEditObject(handle);1370 ObjectEdit* edit = getEditObject(handle);
1265 if (!edit) {1371 if (!edit) {
12661372
=== modified file 'src/MtpStorageInfo.cpp'
--- src/MtpStorageInfo.cpp 2014-03-27 15:45:30 +0000
+++ src/MtpStorageInfo.cpp 2016-04-12 16:15:02 +0000
@@ -48,21 +48,23 @@
48 free(mVolumeIdentifier);48 free(mVolumeIdentifier);
49}49}
5050
51void MtpStorageInfo::read(MtpDataPacket& packet) {51bool MtpStorageInfo::read(MtpDataPacket& packet) {
52 MtpStringBuffer string;52 MtpStringBuffer string;
5353
54 // read the device info54 // read the device info
55 mStorageType = packet.getUInt16();55 if (!packet.getUInt16(mStorageType)) return false;
56 mFileSystemType = packet.getUInt16();56 if (!packet.getUInt16(mFileSystemType)) return false;
57 mAccessCapability = packet.getUInt16();57 if (!packet.getUInt16(mAccessCapability)) return false;
58 mMaxCapacity = packet.getUInt64();58 if (!packet.getUInt64(mMaxCapacity)) return false;
59 mFreeSpaceBytes = packet.getUInt64();59 if (!packet.getUInt64(mFreeSpaceBytes)) return false;
60 mFreeSpaceObjects = packet.getUInt32();60 if (!packet.getUInt32(mFreeSpaceObjects)) return false;
6161
62 packet.getString(string);62 if (!packet.getString(string)) return false;
63 mStorageDescription = strdup((const char *)string);63 mStorageDescription = strdup((const char *)string);
64 packet.getString(string);64 if (!packet.getString(string)) return false;
65 mVolumeIdentifier = strdup((const char *)string);65 mVolumeIdentifier = strdup((const char *)string);
66
67 return true;
66}68}
6769
68void MtpStorageInfo::print() {70void MtpStorageInfo::print() {
6971
=== modified file 'src/MtpStringBuffer.cpp'
--- src/MtpStringBuffer.cpp 2013-06-13 10:22:21 +0000
+++ src/MtpStringBuffer.cpp 2016-04-12 16:15:02 +0000
@@ -56,42 +56,47 @@
56}56}
5757
58void MtpStringBuffer::set(const char* src) {58void MtpStringBuffer::set(const char* src) {
59 int length = strlen(src);
60 if (length >= sizeof(mBuffer))
61 length = sizeof(mBuffer) - 1;
62 memcpy(mBuffer, src, length);
63
64 // count the characters59 // count the characters
65 int count = 0;60 int count = 0;
66 char ch;61 char ch;
67 while ((ch = *src++) != 0) {62 char* dest = (char*)mBuffer;
63
64 while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {
68 if ((ch & 0x80) == 0) {65 if ((ch & 0x80) == 0) {
69 // single byte character66 // single byte character
67 *dest++ = ch;
70 } else if ((ch & 0xE0) == 0xC0) {68 } else if ((ch & 0xE0) == 0xC0) {
71 // two byte character69 // two byte character
72 if (! *src++) {70 char ch1 = *src++;
71 if (! ch1) {
73 // last character was truncated, so ignore last byte72 // last character was truncated, so ignore last byte
74 length--;
75 break;73 break;
76 }74 }
75
76 *dest++ = ch;
77 *dest++ = ch1;
77 } else if ((ch & 0xF0) == 0xE0) {78 } else if ((ch & 0xF0) == 0xE0) {
78 // 3 byte char79 // 3 byte char
79 if (! *src++) {80 char ch1 = *src++;
80 // last character was truncated, so ignore last byte81 if (! ch1) {
81 length--;82 // last character was truncated, so ignore last byte
82 break;83 break;
83 }84 }
84 if (! *src++) {85 char ch2 = *src++;
85 // last character was truncated, so ignore last two bytes86 if (! ch2) {
86 length -= 2;87 // last character was truncated, so ignore last byte
87 break;88 break;
88 }89 }
90
91 *dest++ = ch;
92 *dest++ = ch1;
93 *dest++ = ch2;
89 }94 }
90 count++;95 count++;
91 }96 }
9297
93 mByteCount = length + 1;98 *dest++ = 0;
94 mBuffer[length] = 0;99 mByteCount = dest - (char*)mBuffer;
95 mCharCount = count;100 mCharCount = count;
96}101}
97102
@@ -100,7 +105,7 @@
100 uint16_t ch;105 uint16_t ch;
101 uint8_t* dest = mBuffer;106 uint8_t* dest = mBuffer;
102107
103 while ((ch = *src++) != 0 && count < 255) {108 while ((ch = *src++) != 0 && count < MTP_STRING_MAX_CHARACTER_NUMBER) {
104 if (ch >= 0x0800) {109 if (ch >= 0x0800) {
105 *dest++ = (uint8_t)(0xE0 | (ch >> 12));110 *dest++ = (uint8_t)(0xE0 | (ch >> 12));
106 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));111 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
@@ -118,11 +123,17 @@
118 mByteCount = dest - mBuffer;123 mByteCount = dest - mBuffer;
119}124}
120125
121void MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {126bool MtpStringBuffer::readFromPacket(MtpDataPacket* packet) {
122 int count = packet->getUInt8();127 uint8_t count;
128 if (!packet->getUInt8(count))
129 return false;
130
123 uint8_t* dest = mBuffer;131 uint8_t* dest = mBuffer;
124 for (int i = 0; i < count; i++) {132 for (int i = 0; i < count; i++) {
125 uint16_t ch = packet->getUInt16();133 uint16_t ch;
134
135 if (!packet->getUInt16(ch))
136 return false;
126 if (ch >= 0x0800) {137 if (ch >= 0x0800) {
127 *dest++ = (uint8_t)(0xE0 | (ch >> 12));138 *dest++ = (uint8_t)(0xE0 | (ch >> 12));
128 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));139 *dest++ = (uint8_t)(0x80 | ((ch >> 6) & 0x3F));
@@ -137,6 +148,7 @@
137 *dest++ = 0;148 *dest++ = 0;
138 mCharCount = count;149 mCharCount = count;
139 mByteCount = dest - mBuffer;150 mByteCount = dest - mBuffer;
151 return true;
140}152}
141153
142void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {154void MtpStringBuffer::writeToPacket(MtpDataPacket* packet) const {
143155
=== modified file 'src/MtpUtils.cpp'
--- src/MtpUtils.cpp 2013-09-10 15:54:14 +0000
+++ src/MtpUtils.cpp 2016-04-12 16:15:02 +0000
@@ -19,7 +19,6 @@
19#include <stdio.h>19#include <stdio.h>
20#include <time.h>20#include <time.h>
2121
22// #include <cutils/tztime.h>
23#include "MtpUtils.h"22#include "MtpUtils.h"
2423
25namespace android {24namespace android {
@@ -31,40 +30,40 @@
31DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date,30DD replaced by the day (01-31), T is a constant character 'T' delimiting time from date,
32hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the31hh is replaced by the hour (00-23), mm is replaced by the minute (00-59), and ss by the
33second (00-59). The ".s" is optional, and represents tenths of a second.32second (00-59). The ".s" is optional, and represents tenths of a second.
33This is followed by a UTC offset given as "[+-]zzzz" or the literal "Z", meaning UTC.
34*/34*/
3535
36bool parseDateTime(const char* dateTime, time_t& outSeconds) {36bool parseDateTime(const char* dateTime, time_t& outSeconds) {
37 int year, month, day, hour, minute, second;37 int year, month, day, hour, minute, second;
38 struct tm tm;
39
40 if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d",38 if (sscanf(dateTime, "%04d%02d%02dT%02d%02d%02d",
41 &year, &month, &day, &hour, &minute, &second) != 6)39 &year, &month, &day, &hour, &minute, &second) != 6)
42 return false;40 return false;
41
42 // skip optional tenth of second
43 const char* tail = dateTime + 15;43 const char* tail = dateTime + 15;
44 // skip optional tenth of second44 if (tail[0] == '.' && tail[1]) tail += 2;
45 if (tail[0] == '.' && tail[1])45
46 tail += 2;46 // FIXME: "Z" means UTC, but non-"Z" doesn't mean local time.
47 //FIXME - support +/-hhmm47 // It might be that you're in Asia/Seoul on vacation and your Android
48 // device has noticed this via the network, but your camera was set to
49 // America/Los_Angeles once when you bought it and doesn't know where
50 // it is right now, so the camera says "20160106T081700-0800" but we
51 // just ignore the "-0800" and assume local time which is actually "+0900".
52 // I think to support this (without switching to Java or using icu4c)
53 // you'd want to always use timegm(3) and then manually add/subtract
54 // the UTC offset parsed from the string (taking care of wrapping).
55 // mktime(3) ignores the tm_gmtoff field, so you can't let it do the work.
48 bool useUTC = (tail[0] == 'Z');56 bool useUTC = (tail[0] == 'Z');
4957
50 // hack to compute timezone58 struct tm tm = {};
51 time_t dummy;
52 tzset();
53 localtime_r(&dummy, &tm);
54
55 tm.tm_sec = second;59 tm.tm_sec = second;
56 tm.tm_min = minute;60 tm.tm_min = minute;
57 tm.tm_hour = hour;61 tm.tm_hour = hour;
58 tm.tm_mday = day;62 tm.tm_mday = day;
59 tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range63 tm.tm_mon = month - 1; // mktime uses months in 0 - 11 range
60 tm.tm_year = year - 1900;64 tm.tm_year = year - 1900;
61 tm.tm_wday = 0;
62 tm.tm_isdst = -1;65 tm.tm_isdst = -1;
63 outSeconds = mktime(&tm);66 outSeconds = useUTC ? timegm(&tm) : mktime(&tm);
64 /*if (useUTC)
65 outSeconds = mktime(&tm);
66 else
67 outSeconds = mktime_tz(&tm, tm.tm_zone);*/
6867
69 return true;68 return true;
70}69}
@@ -74,7 +73,7 @@
7473
75 localtime_r(&seconds, &tm);74 localtime_r(&seconds, &tm);
76 snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",75 snprintf(buffer, bufferLength, "%04d%02d%02dT%02d%02d%02d",
77 tm.tm_year + 1900, 76 tm.tm_year + 1900,
78 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range77 tm.tm_mon + 1, // localtime_r uses months in 0 - 11 range
79 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);78 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
80}79}
8180
=== modified file 'tests/TestMtpUtils.cpp'
--- tests/TestMtpUtils.cpp 2013-09-13 14:21:51 +0000
+++ tests/TestMtpUtils.cpp 2016-04-12 16:15:02 +0000
@@ -40,7 +40,7 @@
40{40{
41 time_t seconds = 1378726903;41 time_t seconds = 1378726903;
42 char buffer[25];42 char buffer[25];
43 char *expected = "20130909T114143";43 const char *expected = "20130909T114143";
4444
45 setenv("TZ", "UTC", 1);45 setenv("TZ", "UTC", 1);
4646

Subscribers

People subscribed via source and target branches

to all changes: