1
0
mirror of https://github.com/pocketbase/pocketbase.git synced 2025-03-30 17:28:18 +02:00

[#3089] use a temp dir inside pb_data to prevent backups cross-device link error

This commit is contained in:
Gani Georgiev 2023-08-08 14:15:29 +03:00
parent bd18688f35
commit 7a3223e415
3 changed files with 27 additions and 17 deletions

View File

@ -1,11 +1,13 @@
## v0.17.3-WIP ## v0.17.3
- Fixed Docker `cross-device link` error when creating `pb_data` backups on a local mounted volume ([#3089](https://github.com/pocketbase/pocketbase/issues/3089)).
- Fixed the error messages for relation to views ([#3090](https://github.com/pocketbase/pocketbase/issues/3090)).
- Always reserve space for the scrollbar to reduce the layout shifts in the Admin UI records listing due to the deprecated `overflow: overlay`. - Always reserve space for the scrollbar to reduce the layout shifts in the Admin UI records listing due to the deprecated `overflow: overlay`.
- Enabled lazy loading for the Admin UI thumb images. - Enabled lazy loading for the Admin UI thumb images.
- Fixed the error messages for relation to views ([#3090](https://github.com/pocketbase/pocketbase/issues/3090)).
## v0.17.2 ## v0.17.2

View File

@ -57,16 +57,21 @@ func (app *BaseApp) CreateBackup(ctx context.Context, name string) error {
app.Cache().Set(CacheKeyActiveBackup, name) app.Cache().Set(CacheKeyActiveBackup, name)
defer app.Cache().Remove(CacheKeyActiveBackup) defer app.Cache().Remove(CacheKeyActiveBackup)
// make sure that the special temp directory exists
// note: it needs to be inside the current pb_data to avoid "cross-device link" errors
localTempDir := filepath.Join(app.DataDir(), LocalTempDirName)
if err := os.MkdirAll(localTempDir, os.ModePerm); err != nil {
return fmt.Errorf("failed to create a temp dir: %w", err)
}
// Archive pb_data in a temp directory, exluding the "backups" dir itself (if exist). // Archive pb_data in a temp directory, exluding the "backups" dir itself (if exist).
// //
// Run in transaction to temporary block other writes (transactions uses the NonconcurrentDB connection). // Run in transaction to temporary block other writes (transactions uses the NonconcurrentDB connection).
// --- // ---
tempPath := filepath.Join(os.TempDir(), "pb_backup_"+security.PseudorandomString(4)) tempPath := filepath.Join(localTempDir, "pb_backup_"+security.PseudorandomString(4))
createErr := app.Dao().RunInTransaction(func(txDao *daos.Dao) error { createErr := app.Dao().RunInTransaction(func(txDao *daos.Dao) error {
if err := archive.Create(app.DataDir(), tempPath, LocalBackupsDirName); err != nil { // @todo consider experimenting with temp switching the readonly pragma after the db interface change
return err return archive.Create(app.DataDir(), tempPath, LocalBackupsDirName)
}
return nil
}) })
if createErr != nil { if createErr != nil {
return createErr return createErr
@ -152,7 +157,15 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
} }
defer br.Close() defer br.Close()
tempZip, err := os.CreateTemp(os.TempDir(), "pb_restore") // make sure that the special temp directory exists
// note: it needs to be inside the current pb_data to avoid "cross-device link" errors
localTempDir := filepath.Join(app.DataDir(), LocalTempDirName)
if err := os.MkdirAll(localTempDir, os.ModePerm); err != nil {
return fmt.Errorf("failed to create a temp dir: %w", err)
}
// create a temp zip file from the blob.Reader and try to extract it
tempZip, err := os.CreateTemp(localTempDir, "pb_restore_zip")
if err != nil { if err != nil {
return err return err
} }
@ -162,13 +175,7 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
return err return err
} }
// make sure that the special temp directory extractedDataDir := filepath.Join(localTempDir, "pb_restore_"+security.PseudorandomString(4))
if err := os.MkdirAll(filepath.Join(app.DataDir(), LocalTempDirName), os.ModePerm); err != nil {
return fmt.Errorf("failed to create a temp dir: %w", err)
}
// note: it needs to be inside the current pb_data to avoid "cross-device link" errors
extractedDataDir := filepath.Join(app.DataDir(), LocalTempDirName, "pb_restore_"+security.PseudorandomString(4))
defer os.RemoveAll(extractedDataDir) defer os.RemoveAll(extractedDataDir)
if err := archive.Extract(tempZip.Name(), extractedDataDir); err != nil { if err := archive.Extract(tempZip.Name(), extractedDataDir); err != nil {
return err return err
@ -192,7 +199,7 @@ func (app *BaseApp) RestoreBackup(ctx context.Context, name string) error {
// move the current pb_data content to a special temp location // move the current pb_data content to a special temp location
// that will hold the old data between dirs replace // that will hold the old data between dirs replace
// (the temp dir will be automatically removed on the next app start) // (the temp dir will be automatically removed on the next app start)
oldTempDataDir := filepath.Join(app.DataDir(), LocalTempDirName, "old_pb_data_"+security.PseudorandomString(4)) oldTempDataDir := filepath.Join(localTempDir, "old_pb_data_"+security.PseudorandomString(4))
if err := osutils.MoveDirContent(app.DataDir(), oldTempDataDir, exclude...); err != nil { if err := osutils.MoveDirContent(app.DataDir(), oldTempDataDir, exclude...); err != nil {
return fmt.Errorf("failed to move the current pb_data content to a temp location: %w", err) return fmt.Errorf("failed to move the current pb_data content to a temp location: %w", err)
} }

View File

@ -127,6 +127,7 @@ func verifyBackupContent(app core.App, path string) error {
"logs.db-shm", "logs.db-shm",
"logs.db-wal", "logs.db-wal",
".gitignore", ".gitignore",
".pb_temp_to_delete",
} }
entries, err := os.ReadDir(dir) entries, err := os.ReadDir(dir)