aboutsummaryrefslogtreecommitdiffstats
path: root/src/fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/StandardDirectory.cxx5
-rw-r--r--src/fs/TextFile.cxx81
-rw-r--r--src/fs/io/BufferedOutputStream.cxx (renamed from src/fs/output/BufferedOutputStream.cxx)0
-rw-r--r--src/fs/io/BufferedOutputStream.hxx (renamed from src/fs/output/BufferedOutputStream.hxx)0
-rw-r--r--src/fs/io/BufferedReader.cxx82
-rw-r--r--src/fs/io/BufferedReader.hxx75
-rw-r--r--src/fs/io/FileOutputStream.cxx (renamed from src/fs/output/FileOutputStream.cxx)0
-rw-r--r--src/fs/io/FileOutputStream.hxx (renamed from src/fs/output/FileOutputStream.hxx)0
-rw-r--r--src/fs/io/FileReader.cxx98
-rw-r--r--src/fs/io/FileReader.hxx67
-rw-r--r--src/fs/io/GzipOutputStream.cxx (renamed from src/fs/output/GzipOutputStream.cxx)0
-rw-r--r--src/fs/io/GzipOutputStream.hxx (renamed from src/fs/output/GzipOutputStream.hxx)0
-rw-r--r--src/fs/io/OutputStream.hxx (renamed from src/fs/output/OutputStream.hxx)0
-rw-r--r--src/fs/io/Reader.hxx51
-rw-r--r--src/fs/io/StdioOutputStream.hxx (renamed from src/fs/output/StdioOutputStream.hxx)0
-rw-r--r--src/fs/io/TextFile.cxx48
-rw-r--r--src/fs/io/TextFile.hxx (renamed from src/fs/TextFile.hxx)18
17 files changed, 431 insertions, 94 deletions
diff --git a/src/fs/StandardDirectory.cxx b/src/fs/StandardDirectory.cxx
index ea91399d1..7a836f906 100644
--- a/src/fs/StandardDirectory.cxx
+++ b/src/fs/StandardDirectory.cxx
@@ -40,8 +40,9 @@
#endif
#ifdef USE_XDG
+#include "util/Error.hxx"
#include "util/StringUtil.hxx"
-#include "TextFile.hxx"
+#include "io/TextFile.hxx"
#include <string.h>
#include <utility>
#endif
@@ -204,7 +205,7 @@ static AllocatedPath GetUserDir(const char *name)
if (config_dir.IsNull())
return result;
auto dirs_file = AllocatedPath::Build(config_dir, "user-dirs.dirs");
- TextFile input(dirs_file);
+ TextFile input(dirs_file, IgnoreError());
if (input.HasFailed())
return result;
char *line;
diff --git a/src/fs/TextFile.cxx b/src/fs/TextFile.cxx
deleted file mode 100644
index b1a92b9cc..000000000
--- a/src/fs/TextFile.cxx
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2003-2014 The Music Player Daemon Project
- * http://www.musicpd.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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 General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "config.h"
-#include "TextFile.hxx"
-#include "util/Alloc.hxx"
-#include "fs/Path.hxx"
-#include "fs/FileSystem.hxx"
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-TextFile::TextFile(Path path_fs)
- :file(FOpen(path_fs, FOpenMode::ReadText)),
- buffer((char *)xalloc(step)), capacity(step), length(0) {}
-
-TextFile::~TextFile()
-{
- free(buffer);
-
- if (file != nullptr)
- fclose(file);
-}
-
-char *
-TextFile::ReadLine()
-{
- assert(file != nullptr);
-
- while (true) {
- if (length >= capacity) {
- if (capacity >= max_length)
- /* too large already - bail out */
- return nullptr;
-
- capacity <<= 1;
- char *new_buffer = (char *)realloc(buffer, capacity);
- if (new_buffer == nullptr)
- /* out of memory - bail out */
- return nullptr;
- }
-
- char *p = fgets(buffer + length, capacity - length, file);
- if (p == nullptr) {
- if (length == 0 || ferror(file))
- return nullptr;
- break;
- }
-
- length += strlen(buffer + length);
- if (buffer[length - 1] == '\n')
- break;
- }
-
- /* remove the newline characters */
- if (buffer[length - 1] == '\n')
- --length;
- if (buffer[length - 1] == '\r')
- --length;
-
- buffer[length] = 0;
- length = 0;
- return buffer;
-}
diff --git a/src/fs/output/BufferedOutputStream.cxx b/src/fs/io/BufferedOutputStream.cxx
index 088a3e279..088a3e279 100644
--- a/src/fs/output/BufferedOutputStream.cxx
+++ b/src/fs/io/BufferedOutputStream.cxx
diff --git a/src/fs/output/BufferedOutputStream.hxx b/src/fs/io/BufferedOutputStream.hxx
index f2de758a2..f2de758a2 100644
--- a/src/fs/output/BufferedOutputStream.hxx
+++ b/src/fs/io/BufferedOutputStream.hxx
diff --git a/src/fs/io/BufferedReader.cxx b/src/fs/io/BufferedReader.cxx
new file mode 100644
index 000000000..ba2f17dcf
--- /dev/null
+++ b/src/fs/io/BufferedReader.cxx
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "BufferedReader.hxx"
+#include "Reader.hxx"
+#include "util/TextFile.hxx"
+
+bool
+BufferedReader::Fill(bool need_more)
+{
+ if (gcc_unlikely(last_error.IsDefined()))
+ return false;
+
+ if (eof)
+ return !need_more;
+
+ auto w = buffer.Write();
+ if (w.IsEmpty()) {
+ if (buffer.GetCapacity() >= MAX_SIZE)
+ return !need_more;
+
+ buffer.Grow(buffer.GetCapacity() * 2);
+ w = buffer.Write();
+ assert(!w.IsEmpty());
+ }
+
+ size_t nbytes = reader.Read(w.data, w.size, last_error);
+ if (nbytes == 0) {
+ if (gcc_unlikely(last_error.IsDefined()))
+ return false;
+
+ eof = true;
+ return !need_more;
+ }
+
+ buffer.Append(nbytes);
+ return true;
+}
+
+char *
+BufferedReader::ReadLine()
+{
+ do {
+ char *line = ReadBufferedLine(buffer);
+ if (line != nullptr)
+ return line;
+ } while (Fill(true));
+
+ if (last_error.IsDefined() || !eof || buffer.IsEmpty())
+ return nullptr;
+
+ auto w = buffer.Write();
+ if (w.IsEmpty()) {
+ buffer.Grow(buffer.GetCapacity() + 1);
+ w = buffer.Write();
+ assert(!w.IsEmpty());
+ }
+
+ /* terminate the last line */
+ w[0] = 0;
+
+ char *line = buffer.Read().data;
+ buffer.Clear();
+ return line;
+}
diff --git a/src/fs/io/BufferedReader.hxx b/src/fs/io/BufferedReader.hxx
new file mode 100644
index 000000000..61cc8df83
--- /dev/null
+++ b/src/fs/io/BufferedReader.hxx
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_BUFFERED_READER_HXX
+#define MPD_BUFFERED_READER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+#include "util/DynamicFifoBuffer.hxx"
+#include "util/Error.hxx"
+
+#include <stddef.h>
+
+class Reader;
+class Error;
+
+class BufferedReader {
+ static constexpr size_t MAX_SIZE = 512 * 1024;
+
+ Reader &reader;
+
+ DynamicFifoBuffer<char> buffer;
+
+ Error last_error;
+
+ bool eof;
+
+public:
+ BufferedReader(Reader &_reader)
+ :reader(_reader), buffer(4096), eof(false) {}
+
+ gcc_pure
+ bool Check() const {
+ return !last_error.IsDefined();
+ }
+
+ bool Check(Error &error) const {
+ if (last_error.IsDefined()) {
+ error.Set(last_error);
+ return false;
+ } else
+ return true;
+ }
+
+ bool Fill(bool need_more);
+
+ gcc_pure
+ WritableBuffer<void> Read() const {
+ return buffer.Read().ToVoid();
+ }
+
+ void Consume(size_t n) {
+ buffer.Consume(n);
+ }
+
+ char *ReadLine();
+};
+
+#endif
diff --git a/src/fs/output/FileOutputStream.cxx b/src/fs/io/FileOutputStream.cxx
index dc4456d1f..dc4456d1f 100644
--- a/src/fs/output/FileOutputStream.cxx
+++ b/src/fs/io/FileOutputStream.cxx
diff --git a/src/fs/output/FileOutputStream.hxx b/src/fs/io/FileOutputStream.hxx
index 68174ec83..68174ec83 100644
--- a/src/fs/output/FileOutputStream.hxx
+++ b/src/fs/io/FileOutputStream.hxx
diff --git a/src/fs/io/FileReader.cxx b/src/fs/io/FileReader.cxx
new file mode 100644
index 000000000..d63cd8ab0
--- /dev/null
+++ b/src/fs/io/FileReader.cxx
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "FileReader.hxx"
+#include "system/fd_util.h"
+#include "util/Error.hxx"
+
+#ifdef WIN32
+
+FileReader::FileReader(Path _path, Error &error)
+ :path(_path),
+ handle(CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ,
+ nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
+ nullptr))
+{
+ if (handle == INVALID_HANDLE_VALUE)
+ error.FormatLastError("Failed to open %s", path.c_str());
+}
+
+size_t
+FileReader::Read(void *data, size_t size, Error &error)
+{
+ assert(IsDefined());
+
+ DWORD nbytes;
+ if (!ReadFile(handle, data, size, &nbytes, nullptr)) {
+ error.FormatLastError("Failed to read from %s", path.c_str());
+ nbytes = 0;
+ }
+
+ return nbytes;
+}
+
+void
+FileReader::Close()
+{
+ assert(IsDefined());
+
+ CloseHandle(handle);
+}
+
+#else
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+FileReader::FileReader(Path _path, Error &error)
+ :path(_path),
+ fd(open_cloexec(path.c_str(),
+ O_RDONLY,
+ 0))
+{
+ if (fd < 0)
+ error.FormatErrno("Failed to open %s", path.c_str());
+}
+
+size_t
+FileReader::Read(void *data, size_t size, Error &error)
+{
+ assert(IsDefined());
+
+ ssize_t nbytes = read(fd, data, size);
+ if (nbytes < 0) {
+ error.FormatErrno("Failed to read from %s", path.c_str());
+ nbytes = 0;
+ }
+
+ return nbytes;
+}
+
+void
+FileReader::Close()
+{
+ assert(IsDefined());
+
+ close(fd);
+ fd = -1;
+}
+
+#endif
diff --git a/src/fs/io/FileReader.hxx b/src/fs/io/FileReader.hxx
new file mode 100644
index 000000000..34b43943c
--- /dev/null
+++ b/src/fs/io/FileReader.hxx
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_FILE_READER_HXX
+#define MPD_FILE_READER_HXX
+
+#include "check.h"
+#include "Reader.hxx"
+#include "fs/AllocatedPath.hxx"
+
+#include <assert.h>
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+class Path;
+
+class FileReader final : public Reader {
+ AllocatedPath path;
+
+#ifdef WIN32
+ HANDLE handle;
+#else
+ int fd;
+#endif
+
+public:
+ FileReader(Path _path, Error &error);
+
+ ~FileReader() {
+ if (IsDefined())
+ Close();
+ }
+
+
+ bool IsDefined() const {
+#ifdef WIN32
+ return handle != INVALID_HANDLE_VALUE;
+#else
+ return fd >= 0;
+#endif
+ }
+
+ void Close();
+
+ /* virtual methods from class Reader */
+ size_t Read(void *data, size_t size, Error &error) override;
+};
+
+#endif
diff --git a/src/fs/output/GzipOutputStream.cxx b/src/fs/io/GzipOutputStream.cxx
index d05645d9e..d05645d9e 100644
--- a/src/fs/output/GzipOutputStream.cxx
+++ b/src/fs/io/GzipOutputStream.cxx
diff --git a/src/fs/output/GzipOutputStream.hxx b/src/fs/io/GzipOutputStream.hxx
index 4f6d8b357..4f6d8b357 100644
--- a/src/fs/output/GzipOutputStream.hxx
+++ b/src/fs/io/GzipOutputStream.hxx
diff --git a/src/fs/output/OutputStream.hxx b/src/fs/io/OutputStream.hxx
index 71311c71f..71311c71f 100644
--- a/src/fs/output/OutputStream.hxx
+++ b/src/fs/io/OutputStream.hxx
diff --git a/src/fs/io/Reader.hxx b/src/fs/io/Reader.hxx
new file mode 100644
index 000000000..adf7a0667
--- /dev/null
+++ b/src/fs/io/Reader.hxx
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef MPD_READER_HXX
+#define MPD_READER_HXX
+
+#include "check.h"
+#include "Compiler.h"
+
+#include <stddef.h>
+
+class Error;
+
+/**
+ * An interface that can read bytes from a stream until the stream
+ * ends.
+ *
+ * This interface is simpler and less cumbersome to use than
+ * #InputStream.
+ */
+class Reader {
+public:
+ Reader() = default;
+ Reader(const Reader &) = delete;
+
+ /**
+ * Read data from the stream.
+ *
+ * @return the number of bytes read into the given buffer or 0
+ * on error/end-of-stream
+ */
+ virtual size_t Read(void *data, size_t size, Error &error) = 0;
+};
+
+#endif
diff --git a/src/fs/output/StdioOutputStream.hxx b/src/fs/io/StdioOutputStream.hxx
index e00db922f..e00db922f 100644
--- a/src/fs/output/StdioOutputStream.hxx
+++ b/src/fs/io/StdioOutputStream.hxx
diff --git a/src/fs/io/TextFile.cxx b/src/fs/io/TextFile.cxx
new file mode 100644
index 000000000..396d0f9cd
--- /dev/null
+++ b/src/fs/io/TextFile.cxx
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
+ * http://www.musicpd.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include "TextFile.hxx"
+#include "FileReader.hxx"
+#include "BufferedReader.hxx"
+#include "fs/Path.hxx"
+
+#include <assert.h>
+
+TextFile::TextFile(Path path_fs, Error &error)
+ :file_reader(new FileReader(path_fs, error)),
+ buffered_reader(file_reader->IsDefined()
+ ? new BufferedReader(*file_reader)
+ : nullptr)
+{
+}
+
+TextFile::~TextFile()
+{
+ delete buffered_reader;
+ delete file_reader;
+}
+
+char *
+TextFile::ReadLine()
+{
+ assert(buffered_reader != nullptr);
+
+ return buffered_reader->ReadLine();
+}
diff --git a/src/fs/TextFile.hxx b/src/fs/io/TextFile.hxx
index e3a712a88..33a1b8060 100644
--- a/src/fs/TextFile.hxx
+++ b/src/fs/io/TextFile.hxx
@@ -22,29 +22,26 @@
#include "Compiler.h"
-#include <stdio.h>
#include <stddef.h>
class Path;
+class Error;
+class FileReader;
+class BufferedReader;
class TextFile {
- static constexpr size_t max_length = 512 * 1024;
- static constexpr size_t step = 1024;
-
- FILE *const file;
-
- char *buffer;
- size_t capacity, length;
+ FileReader *const file_reader;
+ BufferedReader *const buffered_reader;
public:
- TextFile(Path path_fs);
+ TextFile(Path path_fs, Error &error);
TextFile(const TextFile &other) = delete;
~TextFile();
bool HasFailed() const {
- return gcc_unlikely(file == nullptr);
+ return gcc_unlikely(buffered_reader == nullptr);
}
/**
@@ -53,7 +50,6 @@ public:
* prevent denial of service.
*
* @param file the source file, opened in text mode
- * @param buffer an allocator for the buffer
* @return a pointer to the line, or nullptr on end-of-file or error
*/
char *ReadLine();