File: file.cpp

package info (click to toggle)
cupt 2.10.4%2Bnmu2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 3,144 kB
  • sloc: cpp: 23,642; perl: 1,599; sh: 40; makefile: 19
file content (111 lines) | stat: -rw-r--r-- 3,626 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/**************************************************************************
*   Copyright (C) 2008-2011 by Eugene V. Lyubimkin                        *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License                  *
*   (version 3 or above) as published by the Free Software Foundation.    *
*                                                                         *
*   This program is distributed in the hope that it will be useful,       *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
*   GNU General Public License for more details.                          *
*                                                                         *
*   You should have received a copy of the GNU GPL                        *
*   along with this program; if not, write to the                         *
*   Free Software Foundation, Inc.,                                       *
*   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA               *
**************************************************************************/
// this group is for stat()
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

using std::to_string;

#include <cupt/download/method.hpp>
#include <cupt/download/uri.hpp>
#include <cupt/file.hpp>

namespace cupt {

class FileMethod: public download::Method
{
	string copyFile(const string& sourcePath, File& sourceFile, const string& targetPath,
			const std::function< void (const vector< string >&) >& callback)
	{
		// preparing target
		string openError;
		File targetFile(targetPath, "a", openError);
		if (!openError.empty())
		{
			return format2("unable to open the file '%s' for appending: %s", targetPath, openError);
		}
		auto totalBytes = targetFile.tell();
		callback({ "downloading", to_string(totalBytes), to_string(0)});

		{ // determing the size
			struct stat st;
			if (::stat(sourcePath.c_str(), &st) == -1)
			{
				fatal2e(__("%s() failed: '%s'"), "stat", sourcePath);
			}
			callback({ "expected-size", to_string(st.st_size) });
		}

		{ // writing
			while (auto rawBuffer = sourceFile.getBlock(4096))
			{
				targetFile.put(rawBuffer.data, rawBuffer.size);
				totalBytes += rawBuffer.size;
				callback({ "downloading", to_string(totalBytes), to_string(rawBuffer.size)});
			}
		}

		return string();
	}
	string perform(const Config&, const download::Uri& uri,
			const string& targetPath, const std::function< void (const vector< string >&) >& callback)
	{
		auto sourcePath = uri.getOpaque();
		auto protocol = uri.getProtocol();

		// preparing source
		string openError;
		File sourceFile(sourcePath, "r", openError);
		if (!openError.empty())
		{
			return format2("unable to open the file '%s' for reading: %s", sourcePath, openError);
		}

		if (protocol == "copy")
		{
			return copyFile(sourcePath, sourceFile, targetPath, callback); // full copying
		}
		else if (protocol == "file")
		{
			// symlinking
			unlink(targetPath.c_str()); // yep, no error handling;
			if (symlink(sourcePath.c_str(), targetPath.c_str()) == -1)
			{
				return format2e("unable to create symbolic link '%s' -> '%s'", targetPath, sourcePath);
			}
			return string();
		}
		else
		{
			fatal2i("a wrong scheme '%s' for the 'file' download method", protocol);
			return string(); // unreachable
		}
	}
};

}

extern "C"
{
	cupt::download::Method* construct()
	{
		return new cupt::FileMethod();
	}
}