From 84b37c7baa632e2fd2a05cbe34c9b35817086254 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Fri, 25 Nov 2022 17:23:43 +0100 Subject: [PATCH] Add an additional free disk space check before saving the datastore (#1913) Fixes https://github.com/shaarli/Shaarli/issues/1810 --- application/bookmark/BookmarkIO.php | 28 ++++++++++++++++++- .../InvalidWritableDataException.php | 14 ++++++++++ .../exception/NotEnoughSpaceException.php | 14 ++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 application/bookmark/exception/InvalidWritableDataException.php create mode 100644 application/bookmark/exception/NotEnoughSpaceException.php diff --git a/application/bookmark/BookmarkIO.php b/application/bookmark/BookmarkIO.php index 8439d470..fa5cefb5 100644 --- a/application/bookmark/BookmarkIO.php +++ b/application/bookmark/BookmarkIO.php @@ -9,6 +9,8 @@ use malkusch\lock\mutex\Mutex; use malkusch\lock\mutex\NoMutex; use Shaarli\Bookmark\Exception\DatastoreNotInitializedException; use Shaarli\Bookmark\Exception\EmptyDataStoreException; +use Shaarli\Bookmark\Exception\InvalidWritableDataException; +use Shaarli\Bookmark\Exception\NotEnoughSpaceException; use Shaarli\Bookmark\Exception\NotWritableDataStoreException; use Shaarli\Config\ConfigManager; @@ -107,6 +109,7 @@ class BookmarkIO * @param Bookmark[] $links * * @throws NotWritableDataStoreException the datastore is not writable + * @throws InvalidWritableDataException */ public function write($links) { @@ -118,9 +121,19 @@ class BookmarkIO throw new NotWritableDataStoreException(dirname($this->datastore)); } - $data = self::$phpPrefix . base64_encode(gzdeflate(serialize($links))) . self::$phpSuffix; + $data = base64_encode(gzdeflate(serialize($links))); + + if (empty($data)) { + throw new InvalidWritableDataException(); + } + + $data = self::$phpPrefix . $data . self::$phpSuffix; $this->synchronized(function () use ($data) { + if (!$this->checkDiskSpace($data)) { + throw new NotEnoughSpaceException(); + } + file_put_contents( $this->datastore, $data @@ -144,4 +157,17 @@ class BookmarkIO $function(); } } + + /** + * Make sure that there is enough disk space available to save the current data store. + * We add an arbitrary margin of 500kB. + * + * @param string $data to be saved + * + * @return bool True if data can safely be saved + */ + public function checkDiskSpace(string $data): bool + { + return disk_free_space(dirname($this->datastore)) > (strlen($data) + 1024 * 500); + } } diff --git a/application/bookmark/exception/InvalidWritableDataException.php b/application/bookmark/exception/InvalidWritableDataException.php new file mode 100644 index 00000000..bf3ae167 --- /dev/null +++ b/application/bookmark/exception/InvalidWritableDataException.php @@ -0,0 +1,14 @@ +message = 'Couldn\'t generate bookmark data to store in the datastore. Skipping file writing.'; + } +} diff --git a/application/bookmark/exception/NotEnoughSpaceException.php b/application/bookmark/exception/NotEnoughSpaceException.php new file mode 100644 index 00000000..e55dd22e --- /dev/null +++ b/application/bookmark/exception/NotEnoughSpaceException.php @@ -0,0 +1,14 @@ +message = 'Not enough available disk space to save the datastore.'; + } +}