Add an additional free disk space check before saving the datastore (#1913)

Fixes https://github.com/shaarli/Shaarli/issues/1810
This commit is contained in:
ArthurHoaro 2022-11-25 17:23:43 +01:00 committed by GitHub
parent 4242f6955a
commit 84b37c7baa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 1 deletions

View file

@ -9,6 +9,8 @@
use malkusch\lock\mutex\NoMutex; use malkusch\lock\mutex\NoMutex;
use Shaarli\Bookmark\Exception\DatastoreNotInitializedException; use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
use Shaarli\Bookmark\Exception\EmptyDataStoreException; use Shaarli\Bookmark\Exception\EmptyDataStoreException;
use Shaarli\Bookmark\Exception\InvalidWritableDataException;
use Shaarli\Bookmark\Exception\NotEnoughSpaceException;
use Shaarli\Bookmark\Exception\NotWritableDataStoreException; use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
use Shaarli\Config\ConfigManager; use Shaarli\Config\ConfigManager;
@ -107,6 +109,7 @@ public function read()
* @param Bookmark[] $links * @param Bookmark[] $links
* *
* @throws NotWritableDataStoreException the datastore is not writable * @throws NotWritableDataStoreException the datastore is not writable
* @throws InvalidWritableDataException
*/ */
public function write($links) public function write($links)
{ {
@ -118,9 +121,19 @@ public function write($links)
throw new NotWritableDataStoreException(dirname($this->datastore)); 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) { $this->synchronized(function () use ($data) {
if (!$this->checkDiskSpace($data)) {
throw new NotEnoughSpaceException();
}
file_put_contents( file_put_contents(
$this->datastore, $this->datastore,
$data $data
@ -144,4 +157,17 @@ protected function synchronized(callable $function): void
$function(); $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);
}
} }

View file

@ -0,0 +1,14 @@
<?php
namespace Shaarli\Bookmark\Exception;
class InvalidWritableDataException extends \Exception
{
/**
* InvalidWritableDataException constructor.
*/
public function __construct()
{
$this->message = 'Couldn\'t generate bookmark data to store in the datastore. Skipping file writing.';
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Shaarli\Bookmark\Exception;
class NotEnoughSpaceException extends \Exception
{
/**
* NotEnoughSpaceException constructor.
*/
public function __construct()
{
$this->message = 'Not enough available disk space to save the datastore.';
}
}