Browse code

Add source code of the XiPC emulator

Pawel Jablonski authored on 17/03/2023 16:46:08
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,194 @@
1
+/*
2
+ * Author: Pawel Jablonski
3
+ * E-mail: pj@xirx.net
4
+ * WWW: xirx.net
5
+ * GIT: git.xirx.net
6
+ *
7
+ * License: You can use this code however you like
8
+ * but leave information about the original author.
9
+ * Code is free for non-commercial and commercial use.
10
+ */
11
+
12
+#include "fs.h"
13
+
14
+/**
15
+ * Constructor for the file system class
16
+ *
17
+ * @param parent Parent object
18
+ */
19
+FS::FS(QObject *parent) : QObject(parent)
20
+{
21
+	this->path = "";
22
+
23
+	this->reset();
24
+}
25
+
26
+//! Reset the file system buffers and path
27
+void FS::reset()
28
+{
29
+	this->buffer.clear();
30
+}
31
+
32
+/**
33
+ * Set path to the emulated file system on the local disk
34
+ *
35
+ * @param path Path to emulated file system
36
+ */
37
+void FS::setPath(const QString &path)
38
+{
39
+	this->path = path;
40
+}
41
+
42
+/**
43
+ * Open and load to buffer a file from the emulated file system
44
+ *
45
+ * @param dirName Name of the directory. "app" or "file".
46
+ * @param fileName Name of the file to open
47
+ * @param size Struct where size of the file will be written
48
+ *
49
+ * @return Status of the open operation
50
+ */
51
+bool FS::open(const QString &dirName, const FS::Name &fileName, FS::Size &size)
52
+{
53
+	size.low = 0;
54
+	size.high = 0;
55
+
56
+	if(!dirName.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})$")))
57
+	{
58
+		return(false);
59
+	}
60
+
61
+	QString name(reinterpret_cast<const char *>(fileName.data.constData()));
62
+
63
+	if(!name.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})(([\\\\.])([0-9a-zA-Z_-]{1,3}))?$")))
64
+	{
65
+		return(false);
66
+	}
67
+
68
+	QString filePath = QString(this->path).append("/").append(dirName).append("/").append(name);
69
+	QFile file(filePath);
70
+
71
+	if(!file.open(QIODevice::ReadOnly))
72
+	{
73
+		return(false);
74
+	}
75
+
76
+	if(file.size() > FILE_MAX_SIZE)
77
+	{
78
+		file.close();
79
+
80
+		return(false);
81
+	}
82
+
83
+	this->buffer = file.readAll();
84
+
85
+	file.close();
86
+
87
+	size.low = static_cast<unsigned char>(this->buffer.size() % 256);
88
+	size.high = static_cast<unsigned char>((this->buffer.size() / 256) & 0xff);
89
+
90
+	return(true);
91
+}
92
+
93
+/**
94
+ * Create a list of files in the directory from the emulated file system
95
+ *
96
+ * @param dirName Name of the directory. "app" or "file".
97
+ * @param size Struct where size of the buffer with description of the files will be written
98
+ *
99
+ * @return Status of the list operation
100
+ */
101
+bool FS::list(const QString &dirName, FS::Size &size)
102
+{
103
+	size.low = 0;
104
+	size.high = 0;
105
+
106
+	if(!dirName.contains(QRegularExpression("^([0-9a-zA-Z_-]{1,8})$")))
107
+	{
108
+		return(false);
109
+	}
110
+
111
+	QString dirPath = QString(this->path).append("/").append(dirName);
112
+	QDir dir;
113
+
114
+	dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
115
+	dir.setSorting(QDir::Name);
116
+
117
+	if(!dir.cd(dirPath))
118
+	{
119
+		return(false);
120
+	}
121
+
122
+	QFileInfoList fileInfoList = dir.entryInfoList();
123
+
124
+	this->buffer.clear();
125
+
126
+	for(const QFileInfo &fileInfo : fileInfoList)
127
+	{
128
+		QString fileName = fileInfo.fileName();
129
+		qint64 fileSize = fileInfo.size();
130
+
131
+		if(fileSize > FILE_MAX_SIZE)
132
+		{
133
+			continue;
134
+		}
135
+
136
+		if(!fileName.contains(QRegularExpression(R"(^([0-9a-zA-Z_-]{1,8})(([\\.])([0-9a-zA-Z_-]{1,3}))?$)")))
137
+		{
138
+			continue;
139
+		}
140
+
141
+		int j = 0;
142
+
143
+		for(; ((j < NAME_MAX_LENGTH) && (j < fileName.length())); j++)
144
+		{
145
+			this->buffer.append(fileName.at(j).toLatin1());
146
+		}
147
+
148
+		for(; j < (DIR_ENTRY_SIZE - DIR_SIZE_FIELD_SIZE); j++)
149
+		{
150
+			this->buffer.append(static_cast<char>(0));
151
+		}
152
+
153
+		QVector<unsigned char> size(2);
154
+
155
+		size[0] = static_cast<unsigned char>(fileSize % 256);
156
+		size[1] = static_cast<unsigned char>((fileSize / 256) & 0xff);
157
+
158
+		this->buffer.append(static_cast<char>(size[0]));
159
+		this->buffer.append(static_cast<char>(size[1]));
160
+
161
+		if(this->buffer.size() >= (DIR_MAX_QUANTITY * DIR_ENTRY_SIZE))
162
+		{
163
+			break;
164
+		}
165
+	}
166
+
167
+	size.low = static_cast<unsigned char>(this->buffer.size() % 256);
168
+	size.high = static_cast<unsigned char>((this->buffer.size() / 256) & 0xff);
169
+
170
+	return(true);
171
+}
172
+
173
+/**
174
+ * Read data from buffer to block based on offset
175
+ *
176
+ * @param block Struct where the data from the buffer will be written
177
+ * @param number Number of the selected virtual block selected to read
178
+ */
179
+void FS::readBlock(FS::Block &block, int number)
180
+{
181
+	for(int i = 0; i < BLOCK_SIZE; i++)
182
+	{
183
+		int j = ((number * BLOCK_SIZE) + i);
184
+
185
+		if(j < this->buffer.size())
186
+		{
187
+			block.data[i] = static_cast<unsigned char>(this->buffer.at(j));
188
+		}
189
+		else
190
+		{
191
+			block.data[i] = 0;
192
+		}
193
+	}
194
+}