| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
Add Gentoo package badge (#3278) * Add Gentoo package badge * Fix spelling issue in cgi.d | 1 年前 | |
Fix spelling problems as identified by GitHub Action check-spelling (#2946) * Fix spelling problems as identified by GitHub Action check-spelling | 1 年前 | |
Clarify error message for `sync_list` rule (#3761) * Update error message for invalid sync_list rule to clarify that directories at the root level must be manually added each. * Fix messaging output to align to the actual breach --------- Co-authored-by: abraunegg <alex.braunegg@gmail.com> | 2 个月前 | |
Add notify_monitor_start option to silence monitor-start notification (#3779) Addresses discussion #3109 Running in `--monitor` mode sends a GUI notification on every startup confirming that filesystem monitoring has begun. There was previously no way to silence just this notification short of disabling all notifications via `disable_notifications`. * Add `notify_monitor_start` config option (default `true`, preserving existing behaviour) that gates only the monitor-start GUI notification * Document the option in `config`, `docs/application-config-options.md` and `docs/usage.md` To disable just this notification, add this to your cofig: ``` notify_monitor_start = "false" ``` Checked to compile with LDC v1.20.1 (Debian) and LDC 1.42.0 (Fedora). | 10 天前 | |
Fix Bug #3816: Fix OAuth token exposure in --debug-https logging (#3838) Prevent `--debug-https` from exposing OAuth access and refresh tokens in diagnostic output. The existing HTTPS debug path filtered the `Authorization` header from the application's request-header dump, but OAuth credentials could still be exposed through several other paths: * libcurl verbose output could print the `Authorization` header directly * OAuth token request bodies could expose `refresh_token` * OAuth token endpoint responses could expose both `access_token` and `refresh_token` * exception and response diagnostics could stringify these values unchanged Add a central sanitisation layer in `curlEngine.d` that redacts OAuth credentials only when producing diagnostic output. The sanitiser covers: * `Authorization` and `Proxy-Authorization` headers * HTTP/2-style libcurl `[authorization: ...]` trace output * form-encoded `access_token` and `refresh_token` values * JSON `access_token` and `refresh_token` fields Replace the default libcurl verbose handler with a sanitised debug callback so useful HTTPS connection, TLS, protocol and header diagnostics remain available without exposing credentials. Raw HTTP/TLS payload callbacks are not emitted by the libcurl debug callback. Application-level request and response diagnostics remain available through `CurlResponse`, with OAuth secrets redacted before logging. Add regression tests covering HTTP/1.1 headers, HTTP/2 diagnostic formatting, form-encoded refresh tokens and OAuth JSON responses. This change does not alter OAuth authentication, token renewal, token storage, Graph API behaviour or the explicit `--print-access-token` functionality. | 19 天前 | |
Reduce idle CPU usage in WebSocket monitor loop (#3762) Replace short-interval idle polling in the Socket.IO WebSocket receive loop with socket-readiness waiting. Previously, an idle WebSocket connection repeatedly called curl_easy_recv(), received CURLE_AGAIN, slept for 20ms, and retried. This caused approximately 50 idle wakeups per second while --monitor was otherwise idle. The receive loop now waits on the active libcurl socket before retrying, reducing idle CPU usage and context-switch churn while preserving WebSocket notification and ping/pong behaviour. Validation on Fedora laptop: - pidstat idle CPU reduced from ~0.82% to ~0.05% - perf task-clock reduced from ~1466 ms / 147 s to ~42 ms / 129 s - context switches reduced from ~50/sec to ~2/sec - strace confirms the 20ms recvfrom(EAGAIN) sleep loop is gone - local upload, WebSocket notification receipt, and /delta processing remain functional | 2 个月前 | |
Fix Bug #3710: Fix that 'azure_tenant_id' entries for intune based authentication were being ignored (#3711) * Use azure_tenant_id from config in responseUrl on intune authentication - forward responseUrl to token request - forward authorityUrl to token requst --------- Co-authored-by: abraunegg <alex.braunegg@gmail.com> | 4 个月前 | |
Fix Bug #3834: Remove fabricated timestamp generation (#3837) ## Summary This PR removes the use of fabricated timestamps for real OneDrive objects. Previously, in several code paths, if a valid `fileSystemInfo.lastModifiedDateTime` value was unavailable, the client could substitute the current local system time via `Clock.currTime()`. This ensured that timestamp-dependent code always had a value to work with, but it also meant that an unknown or invalid remote timestamp could be converted into a value that appeared authoritative. With timestamp authority now available within the application, this behaviour is no longer appropriate. This PR changes the affected code paths so that: * real OneDrive objects no longer receive a fabricated `Clock.currTime()` timestamp; * missing or invalid `fileSystemInfo.lastModifiedDateTime` values are treated as unavailable rather than replaced with the current time; * affected operations are deferred or failed through existing error-handling paths rather than allowing fabricated timestamp data to propagate into the local filesystem or database; * the existing `remoteItem.fileSystemInfo` / top-level `fileSystemInfo` fallback behaviour used for shared items and shortcuts is preserved; * Business Shared Folder search handling now retrieves the authoritative DriveItem metadata before constructing the internal item representation; * local move/rename operations use the actual local filesystem modification time rather than `Clock.currTime()`; * online move/rename operations use the existing known item timestamp rather than generating a new current-time value. ## `createFakeResponse()` `createFakeResponse()` is intentionally unchanged. This function is used for synthetic responses where no real Microsoft Graph transaction exists, including: * `--dry-run` operation simulation; * locally generated synthetic objects such as the Business "Files Shared With Me" hierarchy. In these cases the response itself is intentionally synthetic, so this behaviour is separate from the problem addressed by this PR. ## Scope This PR is deliberately limited to **fabricated timestamp removal**. It does **not** change: * timestamp authority or source-of-truth policy; * timestamp comparison logic; * local-vs-remote conflict resolution; * `--local-first` behaviour; * timestamp application direction; * whether timestamps should be updated during move/rename operations; * existing "newer timestamp" reconciliation decisions. Those areas will be audited separately once all timestamps entering normal reconciliation are either: 1. sourced from a legitimate timestamp authority; or 2. explicitly unavailable. ## Expected Outcome After this change, the client should no longer convert: ```text timestamp unknown ``` into: ```text timestamp = current local system time ``` for real OneDrive objects. This prevents fabricated timestamp values from being written to the local filesystem, stored in the sync database, or subsequently used as if they originated from Microsoft Graph or the local filesystem. | 19 天前 | |
Implement FR #3787: Use different browser with --reauth and friends (#3848) ## Overview This pull request implements the feature request raised in #3787 to allow a user to explicitly select which browser is used for interactive Microsoft authentication. The current GUI authentication path launches the Microsoft authorisation URL using `xdg-open`. This means the desktop environment's configured default browser is normally selected. In environments where a user intentionally uses a different browser for Microsoft 365 authentication, setting the standard `BROWSER` environment variable does not reliably override that desktop preference because `xdg-open` may successfully select the desktop-configured browser before consulting `BROWSER`. For example, a user may use Firefox as their normal desktop browser while using Microsoft Edge exclusively for Microsoft 365 authentication and SSO. This change allows that user to run: ```bash BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth ``` and have the Microsoft authentication URL opened directly using Microsoft Edge. ## Changes The browser launch logic in `src/localAuth.d` has been updated so that: 1. If the `BROWSER` environment variable is set, the client first attempts to launch the configured executable directly with the Microsoft authorisation URL. 2. If the configured browser cannot be launched, the failure is written to the debug log and the client falls back to the existing `xdg-open` behaviour. 3. If `BROWSER` is not set, behaviour remains unchanged and `xdg-open` is used as before. 4. If browser launch ultimately fails, the existing authentication fallback behaviour remains unchanged. Both an explicit executable path: ```bash BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth ``` and an executable available through `PATH`: ```bash BROWSER=microsoft-edge-stable onedrive --reauth ``` are supported. ## Design Considerations This change deliberately does not attempt to automatically detect Microsoft Edge or introduce a Microsoft Edge-specific configuration option. `BROWSER` is treated as a user-selected browser executable, making the implementation browser-neutral and allowing the same mechanism to be used with Firefox, Chromium, Chrome, Edge or another browser. The value is passed directly to `spawnProcess()` as an executable rather than being executed through a shell. This keeps the authentication path deterministic and avoids introducing shell command parsing into OAuth browser launching. The existing behaviour remains the fallback path, so an invalid or stale `BROWSER` value does not prevent authentication from proceeding through the normal desktop browser. ## Behaviour With no override configured: ```bash unset BROWSER onedrive --reauth ``` the existing desktop/default-browser behaviour is retained. With an explicit browser configured: ```bash BROWSER=/usr/bin/microsoft-edge-stable onedrive --reauth ``` the selected browser is used for Microsoft authentication. If the configured browser does not exist or cannot be started: ```bash BROWSER=/does/not/exist onedrive --reauth ``` the client falls back to `xdg-open`. ## Scope This is intentionally a laser-focused change. There are no changes to: * OAuth request or response handling * local loopback authentication * GUI session detection * authentication callback processing * device authentication * headless or SSH authentication behaviour * application configuration options * Microsoft Edge detection * the existing manual authentication fallback Only the browser-selection step of the existing GUI authentication workflow is changed. | 11 天前 | |
Fix Bug #3830: Improve long-running memory and resource cleanup (#3832) This PR addresses several long-running memory and resource-retention findings identified while investigating #3830. The changes are deliberately targeted and avoid altering sync behaviour. Key improvements include: * deterministically clean up WebSocket `CurlWebSocket` / libcurl handles during reconnect and failure paths rather than relying on GC finalisation * ensure locally-created `OneDriveApi` instances are released on handled failure and early-return paths in long-running download and upload operations * clear per-sync tracking arrays that do not need to persist between monitor cycles * prevent duplicate accumulation of `syncListSkippedParentIds` * release backing allocations for transient `SyncEngine`, CurlEngine pool, and logging buffers after use * retain the existing 24-hour `GC.collect()` / `GC.minimize()` behaviour rather than adding more aggressive GC calls * add post-cleanup memory telemetry so RSS and GC statistics can be compared immediately before and after the scheduled 24-hour cleanup These changes focus on correcting identifiable object/resource lifetime issues first, before considering any broader allocator or GC tuning. | 22 天前 | |
Add notify_monitor_start option to silence monitor-start notification (#3779) Addresses discussion #3109 Running in `--monitor` mode sends a GUI notification on every startup confirming that filesystem monitoring has begun. There was previously no way to silence just this notification short of disabling all notifications via `disable_notifications`. * Add `notify_monitor_start` config option (default `true`, preserving existing behaviour) that gates only the monitor-start GUI notification * Document the option in `config`, `docs/application-config-options.md` and `docs/usage.md` To disable just this notification, add this to your cofig: ``` notify_monitor_start = "false" ``` Checked to compile with LDC v1.20.1 (Debian) and LDC 1.42.0 (Fedora). | 10 天前 | |
Fix Bug #3840: Monitor mode can miss completed files created via temporary-file hard-link finalisation on Linux (#3841) On Linux, some applications can finalise a completed temporary file without generating the normal `IN_MOVED_FROM` / `IN_MOVED_TO` sequence expected for a rename. This was reproduced with WinSCP, where the kernel instead reports: ```text IN_CREATE <temporary file> IN_CLOSE_WRITE <temporary file> IN_CREATE <final file> IN_DELETE <temporary file> ``` The existing Linux monitor logic intentionally does not treat a regular-file `IN_CREATE` event as immediately actionable, as the file may still be actively written. As a result, the `IN_CLOSE_WRITE` event makes only the temporary pathname actionable, that pending change is subsequently cancelled when the temporary pathname is deleted, and no actionable event remains for the surviving final pathname. The final file is therefore not immediately uploaded and is only discovered by the next normal monitor synchronisation, potentially delaying the upload by up to the configured `monitor_interval`. This PR adds a deliberately narrow, Linux-only, capture-local state machine to recognise this specific completed-file hand-off sequence. When the complete sequence is observed on the same inotify watch: ```text CREATE source CLOSE_WRITE source CREATE destination DELETE source ``` the destination pathname inherits the already-observed write-completion state and is queued as an actionable local change. The implementation deliberately: * does **not** make generic Linux `IN_CREATE` events actionable; * does **not** special-case WinSCP or the `.filepart` filename suffix; * does **not** reinterpret genuine `IN_MOVED_FROM` / `IN_MOVED_TO` events; * abandons the hand-off candidate when the sequence becomes incomplete or ambiguous; * preserves expected-event suppression and existing move/delete coalescing; * keeps the state local to a single inotify capture/drain; * leaves FreeBSD and OpenBSD monitor behaviour unchanged; * does not modify the existing monitor drift/reconciliation handling; * does not modify `sync.d` or any remote synchronisation logic. Manual reproduction using the original WinSCP workflow confirms that the final file is now detected and uploaded immediately through the monitor event path, without requiring a manual `touch` or waiting for the next 300-second synchronisation cycle. Subsequent monitor cycles recognise the uploaded file as unchanged, with no duplicate upload or reconciliation loop. | 17 天前 | |
Fix Bug #3834: Remove fabricated timestamp generation (#3837) ## Summary This PR removes the use of fabricated timestamps for real OneDrive objects. Previously, in several code paths, if a valid `fileSystemInfo.lastModifiedDateTime` value was unavailable, the client could substitute the current local system time via `Clock.currTime()`. This ensured that timestamp-dependent code always had a value to work with, but it also meant that an unknown or invalid remote timestamp could be converted into a value that appeared authoritative. With timestamp authority now available within the application, this behaviour is no longer appropriate. This PR changes the affected code paths so that: * real OneDrive objects no longer receive a fabricated `Clock.currTime()` timestamp; * missing or invalid `fileSystemInfo.lastModifiedDateTime` values are treated as unavailable rather than replaced with the current time; * affected operations are deferred or failed through existing error-handling paths rather than allowing fabricated timestamp data to propagate into the local filesystem or database; * the existing `remoteItem.fileSystemInfo` / top-level `fileSystemInfo` fallback behaviour used for shared items and shortcuts is preserved; * Business Shared Folder search handling now retrieves the authoritative DriveItem metadata before constructing the internal item representation; * local move/rename operations use the actual local filesystem modification time rather than `Clock.currTime()`; * online move/rename operations use the existing known item timestamp rather than generating a new current-time value. ## `createFakeResponse()` `createFakeResponse()` is intentionally unchanged. This function is used for synthetic responses where no real Microsoft Graph transaction exists, including: * `--dry-run` operation simulation; * locally generated synthetic objects such as the Business "Files Shared With Me" hierarchy. In these cases the response itself is intentionally synthetic, so this behaviour is separate from the problem addressed by this PR. ## Scope This PR is deliberately limited to **fabricated timestamp removal**. It does **not** change: * timestamp authority or source-of-truth policy; * timestamp comparison logic; * local-vs-remote conflict resolution; * `--local-first` behaviour; * timestamp application direction; * whether timestamps should be updated during move/rename operations; * existing "newer timestamp" reconciliation decisions. Those areas will be audited separately once all timestamps entering normal reconciliation are either: 1. sourced from a legitimate timestamp authority; or 2. explicitly unavailable. ## Expected Outcome After this change, the client should no longer convert: ```text timestamp unknown ``` into: ```text timestamp = current local system time ``` for real OneDrive objects. This prevents fabricated timestamp values from being written to the local filesystem, stored in the sync database, or subsequently used as if they originated from Microsoft Graph or the local filesystem. | 19 天前 | |
OneDrive Client for Linux v2.5.0 (#2805) OneDrive Client for Linux v2.5.0 --------- Signed-off-by: Thomas Staudinger <Staudi.Kaos@gmail.com> Co-authored-by: JC-comp <147694781+JC-comp@users.noreply.github.com> Co-authored-by: Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com> Co-authored-by: Pierrick Caillon <megamisan@users.noreply.github.com> Co-authored-by: Pierrick Caillon <pierrick.caillon@megami.fr> Co-authored-by: Thomas Staudinger <Staudi.Kaos@gmail.com> Co-authored-by: Yuan Liu <Lyncredible@users.noreply.github.com> | 1 年前 | |
Fix Bug #3830: Improve long-running memory and resource cleanup (#3832) This PR addresses several long-running memory and resource-retention findings identified while investigating #3830. The changes are deliberately targeted and avoid altering sync behaviour. Key improvements include: * deterministically clean up WebSocket `CurlWebSocket` / libcurl handles during reconnect and failure paths rather than relying on GC finalisation * ensure locally-created `OneDriveApi` instances are released on handled failure and early-return paths in long-running download and upload operations * clear per-sync tracking arrays that do not need to persist between monitor cycles * prevent duplicate accumulation of `syncListSkippedParentIds` * release backing allocations for transient `SyncEngine`, CurlEngine pool, and logging buffers after use * retain the existing 24-hour `GC.collect()` / `GC.minimize()` behaviour rather than adding more aggressive GC calls * add post-cleanup memory telemetry so RSS and GC statistics can be compared immediately before and after the scheduled 24-hour cleanup These changes focus on correcting identifiable object/resource lifetime issues first, before considering any broader allocator or GC tuning. | 22 天前 | |
Fix Bug #3788: Batch delta JSON processing into database transactions (#3791) ### Summary When processing a `/delta` response, every item is written to the database as an individual autocommitted transaction. As `synchronous` is set to `FULL`, each of those transactions must be flushed to physical media before the next can proceed, resulting in one `fdatasync()` per item. This adds explicit transaction control and wraps the existing per-batch processing loop in `applyDifferences()` so that a batch of items is committed as a single unit of work: ```d itemDB.beginTransaction(); scope(failure) itemDB.rollbackTransaction(); processJSONItemsInBatch(batchOfJSONItems, batchesProcessed, batchCount); itemDB.commitTransaction(); ``` `batchSize` is 500, so this reduces the number of flushes during reconciliation by approximately three orders of magnitude. Note that `synchronous` is deliberately left as `FULL`, and transfer-completion writes are deliberately left committing individually - there the flush is amortised against actual network activity and its cost is negligible. ### Why this is safe - `processJSONItemsInBatch()` is processed sequentially, as the API returns items in the order in which they must be processed, so there are no concurrent writers within the transaction. - This phase performs no network activity. Downloads are handled separately in `processDownloadActivities()`, so the database write lock is held only for the duration of local database work. - The data written is reconstructible. `setDeltaLink()` is not called until any required transfers have completed, so an incomplete batch is simply re-obtained from the API on the next run. ### Implementation - `sqlite.d`: add `inTransaction()`, using `sqlite3_get_autocommit()`, so that a transaction is never nested and a commit is never attempted when none is open. - `itemdb.d`: add `beginTransaction()`, `commitTransaction()` and `rollbackTransaction()`, following the existing `performCheckpoint()` pattern. If a transaction cannot be started the database simply remains in autocommit mode, so the behaviour degrades to what it was previously. - `sync.d`: wrap the existing batch processing loop. No user visible logging output is changed. The new log entries are debug level only, matching the existing convention used by the surrounding database functions. * Fix Bug #3788: Batch delta JSON processing into database transactions When processing a `/delta` response, every item is written to the database as an individual autocommitted transaction. As `synchronous` is set to `FULL`, each of those transactions must be flushed to physical media before the next can proceed, resulting in one `fdatasync()` per item. This adds explicit transaction control and wraps the existing per-batch processing loop in `applyDifferences()` so that a batch of items is committed as a single unit of work: ```d itemDB.beginTransaction(); scope(failure) itemDB.rollbackTransaction(); processJSONItemsInBatch(batchOfJSONItems, batchesProcessed, batchCount); itemDB.commitTransaction(); ``` `batchSize` is 500, so this reduces the number of flushes during reconciliation by approximately three orders of magnitude. Note that `synchronous` is deliberately left as `FULL`, and transfer-completion writes are deliberately left committing individually - there the flush is amortised against actual network activity and its cost is negligible. - `processJSONItemsInBatch()` is processed sequentially, as the API returns items in the order in which they must be processed, so there are no concurrent writers within the transaction. - This phase performs no network activity. Downloads are handled separately in `processDownloadActivities()`, so the database write lock is held only for the duration of local database work. - The data written is reconstructible. `setDeltaLink()` is not called until any required transfers have completed, so an incomplete batch is simply re-obtained from the API on the next run. - `sqlite.d`: add `inTransaction()`, using `sqlite3_get_autocommit()`, so that a transaction is never nested and a commit is never attempted when none is open. - `itemdb.d`: add `beginTransaction()`, `commitTransaction()` and `rollbackTransaction()`, following the existing `performCheckpoint()` pattern. If a transaction cannot be started the database simply remains in autocommit mode, so the behaviour degrades to what it was previously. - `sync.d`: wrap the existing batch processing loop. No user visible logging output is changed. The new log entries are debug level only, matching the existing convention used by the surrounding database functions. --------- Co-authored-by: abraunegg <alex.braunegg@gmail.com> | 21 天前 | |
Fix Bug #3850: 'skip_dir' full path rule (leading '/') also excludes same-named directories at any depth (#3851) ## Summary Fixes #3850, where a `skip_dir` full-path rule using a leading `/` could incorrectly exclude same-named directories at deeper levels. For example: ```text skip_dir = "/bin" ``` is intended to exclude only: ```text [sync_dir]/bin ``` but could also exclude: ```text [sync_dir]/some/deeper/path/bin ``` when processing remote `/delta` data. ## Root Cause When processing a remote directory, the client can calculate two paths for `skip_dir` evaluation: * a simplified path, which may degrade to only the directory name when `parentReference.name` is not supplied by the Microsoft OneDrive API * a complete sync-root-relative path derived from database state or `parentReference.path` The existing logic evaluated the simplified path first and only evaluated the complete path when the simplified path did not match. For a rule such as: ```text skip_dir = "/bin" ``` a remotely discovered nested directory could therefore be reduced to: ```text bin ``` before matching. The existing path normalisation performed by `isDirNameExcluded()` then generates both relative and rooted matching candidates, allowing the degraded `bin` value to match `/bin` before the actual full path was considered. This also meant that `skip_dir_strict_match = "true"` could not prevent the incorrect exclusion. ## Resolution Where a complete sync-root-relative path is available, the client now treats that path as authoritative for `skip_dir` evaluation. The simplified path is used only when a complete path genuinely cannot be constructed. This change has been applied to both affected remote directory filtering paths in `src/sync.d`. The existing `skip_dir` matching implementation itself is unchanged. This preserves existing behaviour for: * non-strict directory-name matching * strict full-path matching * leading `/` sync-root anchoring * wildcard matching * case-insensitive matching * multiple configured `skip_dir` rules In particular, case-insensitive matching remains intentional and unchanged. ## E2E Test Coverage TC0012 has been significantly expanded to validate `skip_dir` semantics in both upload and download directions. Coverage now includes: * unanchored non-strict directory-name matching * strict explicit multi-segment path matching * leading `/` single-segment sync-root anchoring with strict matching disabled * leading `/` single-segment sync-root anchoring with strict matching enabled * rooted multi-segment paths containing spaces and trailing `/` * `*` and `?` wildcard matching * case-insensitive matching * multiple and pipe-separated `skip_dir` rules * rooted wildcard rules * local-to-remote and remote-to-local filtering behaviour The regression scenarios specifically confirm that a root-anchored directory is excluded while the same directory name at a deeper path remains synchronised. ### TC0061 adjustment The full E2E run also exposed that TC0061 had historically depended on the same simplified-path behaviour corrected by this PR. TC0061 configured: ```text skip_dir = "Pictures/Archive" skip_dir_strict_match = "true" ``` while the actual test path was: ```text [sync_dir]/ZZ_E2E_TC0061_<run>/Pictures/Archive ``` The previous simplified-path-first behaviour caused this testcase to pass because the complete sync-root-relative path was never evaluated. TC0061 has therefore been corrected so its strict `skip_dir` rule describes the actual full path relative to `sync_dir`. No production behaviour was relaxed to accommodate this testcase. ## Validation Validation completed successfully: * Original Issue #3850 behaviour reproduced before the fix * Expanded TC0012 regression coverage passes all scenarios * Corrected TC0061 passes using the complete strict path * Full 79-case E2E suite passes * Original issue reporter has independently validated the fix against the environment that reproduced the defect This preserves the documented distinction between directory-name matching and explicit full-path matching while ensuring remote directory filtering uses the most authoritative path information available. | 10 天前 | |
Fix Bug #3834: Validate timestamp authority and detect time differences between host platform and Microsoft OneDrive (#3836) ## Summary This PR implements the first stage of #3834 by introducing a system-time authority and safety gate before timestamp-sensitive OneDrive synchronisation is allowed to proceed. The client now validates the host system clock against time returned by the Microsoft service and maintains a process-wide time-authority state that can be used to determine whether synchronisation is safe. This PR intentionally **does not change how file or directory timestamps are applied during synchronisation**. The broader audit and correction of timestamp application logic described in #3834 will be handled in a separate follow-up PR. ## System Time Validation The client uses Microsoft service time as the external reference and accounts for HTTP round-trip time and measurement uncertainty when calculating effective clock skew. The current policy is: * **0–15 seconds:** system time considered acceptable * **>15 seconds to 120 seconds:** warning is generated, synchronisation continues * **>120 seconds:** potentially unsafe; a second independent Microsoft time observation is performed before the condition is treated as blocking A single anomalous observation therefore cannot immediately prevent synchronisation. When significant drift is confirmed, the client enters `TIME_DRIFT_BLOCKING` and timestamp-sensitive synchronisation is not permitted until system time has been corrected and successfully revalidated. System time is periodically revalidated while the application is running, and significant wall-clock discontinuities trigger revalidation of the previously established authority state. ## Behaviour ### `--sync` If unsafe system clock drift is confirmed before synchronisation begins: * synchronisation does not start * the user is advised to correct the local system clock or time synchronisation service * the application exits with failure If system time becomes unsafe during synchronisation, further timestamp-sensitive processing is stopped and the application exits with failure. ### `--monitor` If unsafe clock drift is present when monitor mode starts: * the monitor process remains running * synchronisation and event processing do not begin * system time is periodically revalidated * normal monitor startup automatically continues once system time is corrected If system time becomes unsafe while monitor mode is already running: * timestamp-sensitive synchronisation is suspended * the monitor process remains running * local filesystem observations may still be retained for later processing * WebSocket/Webhook-triggered reconciliation is prevented while the safety gate is closed * processing automatically resumes once system time has been corrected and revalidated Important blocking and recovery state changes are emitted through normal application logging and notification paths and therefore do not require `--verbose`. ## Configuration A `disable_time_check` configuration option / `--disable-time-check` command-line option is provided for users who explicitly need to bypass system-time validation. ## E2E Coverage A new **TC0077 — Timestamp authority safety gating validation** test case has been added with three scenarios: * **TA-0001:** `--monitor` starts with unsafe clock drift, remains suspended, and automatically starts synchronisation after time is corrected * **TA-0002:** an already-running `--monitor` instance develops unsafe clock drift, suspends synchronisation, retains pending local work, and resumes processing after time recovery * **TA-0003:** `--sync` starts with unsafe clock drift, performs no synchronisation and exits with failure * **TA-0004:** unsafe clock drift with `--disable-time-check` validates that the explicit time-validation override bypasses the clock safety gate, permits normal synchronisation to proceed despite otherwise blocking clock drift, and confirms through independent remote verification that local content is successfully propagated to OneDrive The E2E implementation uses process-local clock manipulation so the GitHub Actions runner, filesystem timestamps and Microsoft-side timestamps are not modified by the test. ## Scope This PR establishes **whether the local system clock can safely participate in timestamp-sensitive synchronisation decisions**. It does **not** yet alter: * remote-to-local timestamp application * local-to-remote timestamp propagation * file or directory timestamp semantics * move/rename timestamp handling * timestamp-only reconciliation * `lastModifiedDateTime` update behaviour * `--local-first` timestamp authority semantics Those areas will be reviewed separately once this timestamp-authority foundation has been merged. | 20 天前 | |
Fix Bug #3834: Remove fabricated timestamp generation (#3837) ## Summary This PR removes the use of fabricated timestamps for real OneDrive objects. Previously, in several code paths, if a valid `fileSystemInfo.lastModifiedDateTime` value was unavailable, the client could substitute the current local system time via `Clock.currTime()`. This ensured that timestamp-dependent code always had a value to work with, but it also meant that an unknown or invalid remote timestamp could be converted into a value that appeared authoritative. With timestamp authority now available within the application, this behaviour is no longer appropriate. This PR changes the affected code paths so that: * real OneDrive objects no longer receive a fabricated `Clock.currTime()` timestamp; * missing or invalid `fileSystemInfo.lastModifiedDateTime` values are treated as unavailable rather than replaced with the current time; * affected operations are deferred or failed through existing error-handling paths rather than allowing fabricated timestamp data to propagate into the local filesystem or database; * the existing `remoteItem.fileSystemInfo` / top-level `fileSystemInfo` fallback behaviour used for shared items and shortcuts is preserved; * Business Shared Folder search handling now retrieves the authoritative DriveItem metadata before constructing the internal item representation; * local move/rename operations use the actual local filesystem modification time rather than `Clock.currTime()`; * online move/rename operations use the existing known item timestamp rather than generating a new current-time value. ## `createFakeResponse()` `createFakeResponse()` is intentionally unchanged. This function is used for synthetic responses where no real Microsoft Graph transaction exists, including: * `--dry-run` operation simulation; * locally generated synthetic objects such as the Business "Files Shared With Me" hierarchy. In these cases the response itself is intentionally synthetic, so this behaviour is separate from the problem addressed by this PR. ## Scope This PR is deliberately limited to **fabricated timestamp removal**. It does **not** change: * timestamp authority or source-of-truth policy; * timestamp comparison logic; * local-vs-remote conflict resolution; * `--local-first` behaviour; * timestamp application direction; * whether timestamps should be updated during move/rename operations; * existing "newer timestamp" reconciliation decisions. Those areas will be audited separately once all timestamps entering normal reconciliation are either: 1. sourced from a legitimate timestamp authority; or 2. explicitly unavailable. ## Expected Outcome After this change, the client should no longer convert: ```text timestamp unknown ``` into: ```text timestamp = current local system time ``` for real OneDrive objects. This prevents fabricated timestamp values from being written to the local filesystem, stored in the sync database, or subsequently used as if they originated from Microsoft Graph or the local filesystem. | 19 天前 | |
Harden monitor lifecycle, event handling, and DB reconciliation (#3756) This PR hardens monitor-mode reliability under high local and remote data churn. The original focus was lifecycle and worker teardown safety, ensuring monitor, WebSocket, webhook, and related worker resources are shut down in a controlled order without destroying shared state while worker threads may still be active. During extended stress testing, this work was expanded to cover several subtle monitor-mode drift issues found under heavy create / modify / delete churn across multiple systems. The additional fixes tighten local filesystem event handling, avoid discarding legitimate monitor wake events, and correct database reconciliation behaviour when OneDrive reports same-name items with different remote identifiers. ## Changes * Improve monitor worker lifecycle handling and shutdown ordering. * Avoid closing monitor worker resources unless worker shutdown is confirmed. * Ensure WebSocket and webhook workers are stopped before dependent objects/configuration are destroyed. * Preserve queued local filesystem monitor wake events after inotify processing instead of treating them as stale and discarding them. * Improve high-churn monitor-mode reconciliation where local and remote events arrive close together. * Correct orphan database item replacement so same-name items are reconciled using the correct parent identifier. * Preserve existing safety checks that prevent deleting a local path when the current database record belongs to a different OneDrive item ID. * Add additional validation through high-churn multi-system testing involving repeated create, modify, delete, upload, and download activity. ## Why this matters Under normal usage these issues are difficult to trigger, but heavy concurrent churn exposed several race/order-sensitive cases where monitor-mode reconciliation could temporarily or persistently drift from the expected local/remote state. The fixes in this PR make monitor mode more resilient by ensuring worker teardown is safe, monitor wake events are not accidentally lost, and database item replacement behaves correctly when Microsoft OneDrive assigns a new identifier to a recreated same-name item. ## Validation Tested with sustained high-churn monitor-mode workloads across multiple systems, including repeated local creation, modification, deletion, remote download reconciliation, and same-name folder replacement scenarios. The testing specifically targets previously observed drift patterns involving retained extra directories, stale empty directory resurrection, and missed reconciliation during overlapping local filesystem and WebSocket/delta activity. | 2 个月前 | |
Fix Bug #3276: Fix implementation of 'write_xattr_data' to support FreeBSD (#3285) * Fix implementation of 'write_xattr_data' to support FreeBSD to resolve compilation failure * Update spelling add 'attrnamespace' and 'extattr' | 1 年前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 年前 | ||
| 1 年前 | ||
| 2 个月前 | ||
| 10 天前 | ||
| 19 天前 | ||
| 2 个月前 | ||
| 4 个月前 | ||
| 19 天前 | ||
| 11 天前 | ||
| 22 天前 | ||
| 10 天前 | ||
| 17 天前 | ||
| 19 天前 | ||
| 1 年前 | ||
| 22 天前 | ||
| 21 天前 | ||
| 10 天前 | ||
| 20 天前 | ||
| 19 天前 | ||
| 2 个月前 | ||
| 1 年前 |