diff --git a/internal/db/sqlite/db_open.go b/internal/db/sqlite/db_open.go index 88bbad0f4..dcce4319a 100644 --- a/internal/db/sqlite/db_open.go +++ b/internal/db/sqlite/db_open.go @@ -16,6 +16,7 @@ import ( "github.com/syncthing/syncthing/internal/db" "github.com/syncthing/syncthing/internal/slogutil" + "github.com/syncthing/syncthing/lib/build" ) const ( @@ -65,6 +66,8 @@ func Open(path string, opts ...Option) (*DB, error) { } _ = os.MkdirAll(path, 0o700) + initTmpDir(path) + mainPath := filepath.Join(path, "main.db") mainBase, err := openBase(mainPath, maxDBConns, pragmas, schemas, migrations) if err != nil { @@ -114,6 +117,8 @@ func OpenForMigration(path string) (*DB, error) { } _ = os.MkdirAll(path, 0o700) + initTmpDir(path) + mainPath := filepath.Join(path, "main.db") mainBase, err := openBase(mainPath, 1, pragmas, schemas, migrations) if err != nil { @@ -143,3 +148,24 @@ func (s *DB) Close() error { } return wrap(s.baseDB.Close()) } + +func initTmpDir(path string) { + if build.IsWindows || build.IsDarwin || os.Getenv("SQLITE_TMPDIR") != "" { + // Doesn't use SQLITE_TMPDIR, isn't likely to have a tiny + // ram-backed temp directory, or already set to something. + return + } + + // Attempt to override the SQLite temporary directory by setting the + // env var prior to the (first) database being opened and hence + // SQLite becoming initialized. We set the temp dir to the same + // place we store the database, in the hope that there will be + // enough space there for the operations it needs to perform, as + // opposed to /tmp and similar, on some systems. + dbTmpDir := filepath.Join(path, ".tmp") + if err := os.MkdirAll(dbTmpDir, 0o700); err == nil { + os.Setenv("SQLITE_TMPDIR", dbTmpDir) + } else { + slog.Warn("Failed to create temp directory for SQLite", slogutil.FilePath(dbTmpDir), slogutil.Error(err)) + } +}