1 /*
2 * MtpLocalFileCopy.cpp
3 *
4 * Author: Jason Ferrara
5 *
6 * This software is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 3 as published by the Free Software Foundation.
9 *
10 * This software is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02111-1301, USA.
19 * licensing@fsf.org
20 */
21 #include "MtpLocalFileCopy.h"
22 #include "mtpFilesystemErrors.h"
23 #include <sys/stat.h>
24 #include <iostream>
25 #include <unistd.h>
26
MtpLocalFileCopy(MtpDevice & device,uint32_t id)27 MtpLocalFileCopy::MtpLocalFileCopy(MtpDevice& device, uint32_t id) :
28 m_device(device), m_remoteId(id), m_needWriteBack(false)
29 {
30 m_localFile = tmpfile();
31 if (m_localFile == 0)
32 throw CantCreateTempFile(errno);
33 m_device.GetFile(m_remoteId, fileno(m_localFile));
34
35 }
36
~MtpLocalFileCopy()37 MtpLocalFileCopy::~MtpLocalFileCopy()
38 {
39 close();
40 }
41
42
close()43 uint32_t MtpLocalFileCopy::close()
44 {
45 if (m_localFile)
46 {
47 if (m_needWriteBack)
48 {
49 m_needWriteBack = false;
50 try
51 {
52 fflush(m_localFile);
53 if (fseek(m_localFile, 0, SEEK_SET))
54 throw WriteError(errno);
55 struct stat tempInfo;
56 if (fstat(fileno(m_localFile), &tempInfo))
57 throw ReadError(errno);
58 MtpFileInfo remoteInfo = m_device.GetFileInfo(m_remoteId);
59 NewLIBMTPFile newFile(remoteInfo.name, remoteInfo.parentId, remoteInfo.storageId, tempInfo.st_size);
60 m_device.DeleteObject(m_remoteId);
61 std::cout << "************ sending file" << std::endl;
62 m_device.SendFile(newFile, fileno(m_localFile));
63 m_remoteId = ((LIBMTP_file_t*)newFile)->item_id;
64 }
65 catch(...)
66 {
67 fclose(m_localFile);
68 m_localFile=0;
69 throw;
70 }
71 }
72
73 fclose(m_localFile);
74 m_localFile = 0;
75 }
76 return m_remoteId;
77 }
78
getSize()79 off_t MtpLocalFileCopy::getSize()
80 {
81 fflush(m_localFile);
82 struct stat tempInfo;
83 if (fstat(fileno(m_localFile), &tempInfo))
84 throw ReadError(errno);
85 return tempInfo.st_size;
86 }
87
seek(long offset)88 void MtpLocalFileCopy::seek(long offset)
89 {
90 if (fseek(m_localFile, offset, SEEK_SET))
91 throw MtpFilesystemErrorWithErrorCode(errno, "seek failed");
92 }
93
write(const void * ptr,size_t size)94 size_t MtpLocalFileCopy::write(const void* ptr, size_t size)
95 {
96 size_t wroteBytes = fwrite(ptr, 1, size, m_localFile);
97 m_needWriteBack = true;
98 if (wroteBytes!= size)
99 if (ferror(m_localFile))
100 throw WriteError(errno);
101 return wroteBytes;
102 }
103
read(void * ptr,size_t size)104 size_t MtpLocalFileCopy::read(void* ptr, size_t size)
105 {
106
107 size_t readBytes = fread(ptr, 1, size, m_localFile);
108 if (readBytes!= size)
109 if (ferror(m_localFile))
110 throw ReadError(errno);
111 return readBytes;
112 }
113
truncate(off_t length)114 void MtpLocalFileCopy::truncate(off_t length)
115 {
116 if (ftruncate(fileno(m_localFile), length))
117 throw WriteError(errno);
118 m_needWriteBack = true;
119 }
120
CopyTo(MtpDevice & device,NewLIBMTPFile & destination)121 void MtpLocalFileCopy::CopyTo(MtpDevice& device, NewLIBMTPFile& destination)
122 {
123 fflush(m_localFile);
124 if (fseek(m_localFile, 0, SEEK_SET))
125 throw WriteError(errno);
126 struct stat tempInfo;
127 if (fstat(fileno(m_localFile), &tempInfo))
128 throw ReadError(errno);
129
130 device.SendFile(destination, fileno(m_localFile));
131 }
132