1 /*
2 Copyright (C) 2005-2006 Remon Sijrier
3 
4 This file is part of Traverso
5 
6 Traverso is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA.
19 
20 $Id: FileHelpers.cpp,v 1.10 2007/11/05 15:49:30 r_sijrier Exp $
21 */
22 
23 #include "FileHelpers.h"
24 
25 #include <sys/stat.h>
26 #include "Config.h"
27 #include <QDir>
28 #include <Utils.h>
29 #include <QObject>
30 #include <QFile>
31 #include <unistd.h>
32 
33 #include "Debugger.h"
34 
35 // delete file/dir pName after prepending $HOME/traversoprojects/ to it
36 //
37 // if it is a directory, calls itself recursively  on any file/dir in the directory
38 // before removing the directory
remove_recursively(const QString & pName)39 int FileHelper::remove_recursively(const QString& pName)
40 {
41 	QString name = config().get_property("Project", "directory", "/directory/unknown").toString();
42 	name += "/" + pName;
43 
44 	QFileInfo fileInfo(name);
45 
46 	if (!fileInfo.exists()) {
47 		PERROR("File does not exist! %s", QS_C(name));
48 		return -1;
49 	}
50 
51 	if (!fileInfo.isWritable()) {
52 		PERROR("failed to remove %s: you don't have write access to it\n", name.toLatin1().data());
53 		return -1;
54 	}
55 
56 	if(fileInfo.isFile()) {
57 		QFile file(name);
58 		if (!file.remove()) {
59 			PERROR("failed to remove file %s\n", name.toLatin1().data());
60 			return -1;
61 		}
62 		return 1;
63 	} else if(fileInfo.isDir()) {
64 		QDir dir(name);
65 		QFileInfoList list = dir.entryInfoList();
66 		QFileInfo fi;
67 
68 		for (int i = 0; i < list.size(); ++i) {
69 			fi = list.at(i);
70 			if ((fi.fileName() != ".") && (fi.fileName() != "..")) {
71 				QString nextFileName = pName + "/" + fi.fileName();
72 				if (remove_recursively(nextFileName) < 0) {
73 					PERROR("failed to remove directory %s\n", nextFileName.toLatin1().data());
74 					return -1;
75 				}
76 			}
77 		}
78 
79 		if (!dir.rmdir(name)) {
80 			PERROR("failed to remove directory %s\n", name.toLatin1().data());
81 			return -1;
82 		}
83 
84 		return 1;
85 	}
86 
87 	return 1;
88 }
89 
90 
copy_recursively(const QString & pNameFrom,const QString & pNameTo)91 int FileHelper::copy_recursively(const QString& pNameFrom, const QString& pNameTo)
92 {
93 #if defined (Q_WS_X11) || defined (Q_WS_MAC)
94 	QString nameFrom = config().get_property("Project", "directory", "/directory/unknown").toString();
95 	QString nameTo(nameFrom);
96 
97 	nameFrom += pNameFrom;
98 	nameTo += pNameTo;
99 
100 	QFileInfo fileFromInfo(nameFrom);
101 	QFileInfo fileToInfo(nameTo);
102 
103 	if (!fileFromInfo.exists()) {
104 		PERROR("File or directory %s doesn't exist\n", pNameFrom.toLatin1().data());
105 		return -1;
106 	}
107 	if (fileToInfo.exists()) {
108 		PERROR("File or directory %s already exists", pNameTo.toLatin1().data());
109 		return -1;
110 	}
111 
112 	if(fileFromInfo.isFile()) {
113 		QFile fileFrom(nameFrom);
114 		if (!fileFrom.open(QIODevice::ReadOnly)) {
115 			PERROR("failed to open file %s for reading\n", nameFrom.toLatin1().data());
116 			return -1;
117 		}
118 
119 		QFile fileTo(nameTo);
120 		if (!fileTo.open(QIODevice::WriteOnly)) {
121 			fileFrom.close();
122 			PERROR("failed to open file for writting%s\n", nameFrom.toLatin1().data());
123 			return -1;
124 		}
125 
126 		// the real copy part should perhaps be implemented using QDataStream
127 		// but .handle() will still be needed to get the optimal block-size
128 		//
129 		//! \todo does not keep file mode yet
130 		int bufferSize = 4096;
131 		int fileDescFrom = fileFrom.handle();
132 		int fileDescTo = fileTo.handle();
133 
134 #if defined(DHAVE_SYS_STAT_H)
135 		struct stat fileStat;
136 		if (fstat(fileDescFrom, &fileStat) == 0) {
137 			bufferSize = (int)fileStat.st_blksize;
138 		}
139 #endif
140 
141 		void *buffer = malloc(sizeof(char) * bufferSize);
142 		// QMemArray<char> buffer(bufferSize);
143 
144 		for (;;) {
145 			int nRead = read(fileDescFrom, buffer, bufferSize);
146 			if (nRead < 0) {
147 				fileFrom.close();
148 				fileTo.close();
149 				PERROR("Error while reading file %s\n", nameFrom.toLatin1().data());
150 				return -1;
151 			}
152 			if (nRead == 0)
153 				break;
154 			if (write(fileDescTo, buffer, nRead) < 0) {
155 				fileFrom.close();
156 				fileTo.close();
157 				PERROR("Error while writing file %s\n", nameTo.toLatin1().data());
158 				return -1;
159 			}
160 		}
161 		free(buffer);
162 
163 		fileFrom.close();
164 		fileTo.close();
165 
166 		return 0;
167 	} else if(fileFromInfo.isDir()) {
168 		QDir dirFrom(nameFrom);
169 		QDir dirTo(nameTo);
170 		if (!dirTo.mkdir(nameTo)) {
171 			PERROR("failed to create directory %s\n", nameTo.toLatin1().data());
172 			return -1;
173 		}
174 
175 		QFileInfoList list = dirFrom.entryInfoList();
176 		QFileInfo fi;
177 		QString fileName;
178 		for (int i = 0; i < list.size(); ++i) {
179 			fileName = fi.fileName();
180 			if ((fileName != ".") && (fileName != "..")) {
181 				copy_recursively(pNameFrom + "/" + fileName, pNameTo + "/" + fileName);
182 			}
183 		}
184 		return 0;
185 	}
186 
187 #endif
188 
189 	return -1;
190 }
191 
fileerror_to_string(int error)192 QString FileHelper::fileerror_to_string(int error)
193 {
194 	switch(error) {
195 		case QFile::NoError: return QObject::tr("No error occurred"); break;
196 		case QFile::ReadError: return QObject::tr("An error occurred when reading from the file."); break;
197 		case QFile::WriteError: return QObject::tr("An error occurred when writing to the file."); break;
198 		case QFile::FatalError: return QObject::tr("A fatal error occurred."); break;
199 		case QFile::OpenError: return QObject::tr("The file could not be opened."); break;
200 		case QFile::ResourceError: return QObject::tr("Resourc error"); break;
201 		case QFile::AbortError: return QObject::tr("The operation was aborted."); break;
202 		case QFile::TimeOutError: return QObject::tr("A timeout occurred."); break;
203 		case QFile::UnspecifiedError: return QObject::tr("An unspecified error occurred."); break;
204 		case QFile::RemoveError: return QObject::tr("The file could not be removed."); break;
205 		case QFile::RenameError: return QObject::tr("The file could not be renamed."); break;
206 		case QFile::PositionError: return QObject::tr("The position in the file could not be changed."); break;
207 		case QFile::ResizeError: return QObject::tr("The file could not be resized."); break;
208 		case QFile::PermissionsError: return QObject::tr("The file could not be accessed."); break;
209 		case QFile::CopyError: return QObject::tr("The file could not be copied."); break;
210 		default: return QObject::tr("Unknown error");
211 	}
212 }
213