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