Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
663f3bb
feat(transport): add HTTP retry logic with exponential backoff
jpnurmi Feb 12, 2026
52a273e
fix(retry): filter startup scan by timestamp, create cache dir
jpnurmi Feb 12, 2026
e230f8b
fix(retry): use wall clock time instead of monotonic time
jpnurmi Feb 12, 2026
3810f2b
ref(retry): define backoff base in seconds
jpnurmi Feb 12, 2026
a910f32
ref(retry): replace scan+free_paths with foreach callback API
jpnurmi Feb 12, 2026
8b8921b
feat(transport): set 15s request timeout for curl and winhttp
jpnurmi Feb 12, 2026
46d2a9e
fix(retry): avoid duplicate delayed retry tasks on startup
jpnurmi Feb 12, 2026
4f3d625
ref(retry): take options in sentry__retry_new, own path construction
jpnurmi Feb 12, 2026
199bd30
ref(retry): set startup_time at creation, remove setter
jpnurmi Feb 12, 2026
94a7ca7
fix(retry): return total file count so polling continues during backoff
jpnurmi Feb 12, 2026
011fbb5
fix(retry): use callback return value to track remaining retry files
jpnurmi Feb 12, 2026
f673193
ref(retry): rename constants to SENTRY_RETRY_INTERVAL and SENTRY_RETR…
jpnurmi Feb 12, 2026
caef6c1
ref(retry): encapsulate retry scheduling into the retry module
jpnurmi Feb 12, 2026
9c7c99d
ref(transport): remove unnecessary includes, restore blank line
jpnurmi Feb 12, 2026
3813feb
ref(retry): move precondition checks to callers
jpnurmi Feb 12, 2026
ea5233f
ref(transport): extract http_send_envelope helper
jpnurmi Feb 12, 2026
f17f8f9
test(retry): remove redundant retry_no_duplicate_rescan test
jpnurmi Feb 12, 2026
e7886a4
ref(curl): use CURLOPT_TIMEOUT_MS for consistency with winhttp and cr…
jpnurmi Feb 12, 2026
ce4ac80
ref(retry): unify startup and poll into a single task
jpnurmi Feb 12, 2026
34d5131
ref(retry): extract sentry__retry_make_path helper
jpnurmi Feb 12, 2026
8015d2c
fix(retry): prevent envelope duplication between retry and cache
jpnurmi Feb 12, 2026
8fcdb4f
ref(database): derive can_cache flag to skip cache dir creation early
jpnurmi Feb 12, 2026
551ad74
ref(retry): change send callback to envelope-based API
jpnurmi Feb 12, 2026
d2f1a07
test(retry): verify cache_keep preserves envelopes on successful send
jpnurmi Feb 12, 2026
3750856
fix(retry): use PRIu64 format specifier for uint64_t
jpnurmi Feb 12, 2026
0cbf407
fix(retry): guard against unsigned underflow in backoff check
jpnurmi Feb 12, 2026
3b2a5d6
fix(retry): prevent startup poll from re-processing same-session enve…
jpnurmi Feb 13, 2026
6608084
fix(retry): flush pending retries on shutdown
jpnurmi Feb 14, 2026
961ec95
ref(retry): use millisecond timestamps for retry filenames
jpnurmi Feb 14, 2026
558c32e
fix(retry): flush pending retries synchronously before shutdown
jpnurmi Feb 14, 2026
be1d7cf
fix(retry): stop retrying on network failure
jpnurmi Feb 14, 2026
fccc565
fix(retry): dump unsent envelopes to retry dir on shutdown timeout
jpnurmi Feb 14, 2026
d831987
test(retry): update expectations for stop-on-failure behavior
jpnurmi Feb 14, 2026
69f4f68
style(retry): fix line length in unit tests
jpnurmi Feb 14, 2026
5562feb
fix(retry): prevent duplicate envelope writes from detached worker
jpnurmi Feb 14, 2026
0664fb3
docs: add changelog entry for HTTP retry feature
jpnurmi Feb 14, 2026
c241adf
test(retry): use sentry__retry_send instead of duplicated eligibility…
jpnurmi Feb 14, 2026
a053ccb
fix(retry): raise backoff cap from 2h to 8h to match crashpad
jpnurmi Feb 14, 2026
71ee17a
refactor(retry): introduce retry_item_t to avoid re-parsing filenames
jpnurmi Feb 15, 2026
dfe7c1f
feat(retry): add debug and warning output for HTTP retries
jpnurmi Feb 15, 2026
5d80da6
refactor(cache): add cache_path to sentry_run_t and centralize cache …
jpnurmi Feb 15, 2026
06cca66
fix(transport): use connect-only timeouts for curl and winhttp
jpnurmi Feb 15, 2026
fd6c577
fix(retry): decrement total count when removing corrupt envelope files
jpnurmi Feb 15, 2026
173de80
fix(retry): only warn about exhausted retries on network failure
jpnurmi Feb 15, 2026
0482bf4
docs(retry): add doc comments to sentry_retry.h declarations
jpnurmi Feb 15, 2026
39f36ec
feat(transport): add sentry_transport_retry()
jpnurmi Feb 15, 2026
7b30688
refactor(retry): store retry envelopes in cache/ directory
jpnurmi Feb 15, 2026
e6c8db4
fix(retry): own cache_path to prevent use-after-free on detached thread
jpnurmi Feb 16, 2026
c520575
fix(retry): don't consume shutdown timeout with bgworker flush
jpnurmi Feb 16, 2026
79d1732
fix(retry): flush in-flight retries before shutdown
jpnurmi Feb 16, 2026
344dcc8
refactor(retry): replace http_retries count with boolean http_retry
jpnurmi Feb 16, 2026
5cdcc47
fix(transport): use explicit WinHTTP send/receive timeouts
jpnurmi Feb 16, 2026
9136500
fix(retry): deduplicate poll tasks on concurrent envelope failures
jpnurmi Feb 16, 2026
9b14dc2
fix(retry): set sealed flag before dumping queued envelopes
jpnurmi Feb 16, 2026
e75f595
fix(retry): prevent retry flush from consuming shutdown timeout
jpnurmi Feb 16, 2026
136fabf
fix(retry): zero-initialize retry struct after malloc
jpnurmi Feb 16, 2026
1a0d99b
fix(retry): skip flush task after seal to prevent duplicate sends
jpnurmi Feb 16, 2026
ed28b85
refactor(database): remove unused sentry__run_write_cache
jpnurmi Feb 16, 2026
62999c3
fix(retry): make trigger one-shot to prevent rapid retry exhaustion
jpnurmi Feb 17, 2026
70b1040
fix(core): check http_retry option instead of transport capability
jpnurmi Feb 17, 2026
794df4b
fix(retry): prevent UB from negative count in backoff shift
jpnurmi Feb 17, 2026
83475e4
fix(options): normalize http_retry with !! to match other boolean set…
jpnurmi Feb 17, 2026
8aae746
revert(database): restore original variable names and whitespace in w…
jpnurmi Feb 23, 2026
791d598
docs: clarify sentry_transport_retry behavior and limitations
jpnurmi Feb 24, 2026
a2efe25
docs(retry): document retry behavior for network failures vs HTTP res…
jpnurmi Feb 24, 2026
4b1e7d7
fix(retry): only clear startup_time when envelope is written
jpnurmi Feb 24, 2026
6064f1d
fix(retry): check for NULL from sentry__path_clone
jpnurmi Feb 24, 2026
45ee886
fix(retry): apply backoff when system clock moves backward
jpnurmi Feb 24, 2026
ec59d5e
fix(retry): increase SENTRY_RETRY_ATTEMPTS to 6 to match Crashpad
jpnurmi Feb 24, 2026
00bef01
fix(retry): avoid retry flush consuming entire shutdown timeout
jpnurmi Feb 24, 2026
d96beb1
fix(retry): warn on failed retry envelope rename
jpnurmi Feb 24, 2026
985b3da
fix(retry): check for NULL from sentry__path_clone in retry send
jpnurmi Feb 24, 2026
87532a3
fix(retry): fix data race on startup_time between threads
jpnurmi Feb 24, 2026
754a65d
fix(retry): clear retry_func when retry fails to initialize
jpnurmi Feb 24, 2026
0e64115
fix(retry): persist non-event envelopes to the retry cache
jpnurmi Feb 25, 2026
9ab3e11
fix(retry): close race between poll task and enqueue on scheduled flag
jpnurmi Feb 25, 2026
5a10044
refactor(database): add retry_count to write_envelope, add sentry__ru…
jpnurmi Feb 25, 2026
f35817d
refactor(database): make sentry_run_t refcounted
jpnurmi Feb 25, 2026
123a7be
refactor(cache): strip retry prefix in move_cache and simplify handle…
jpnurmi Feb 25, 2026
acfd148
fix(cache): use cache_name instead of src_name for UUID in move_cache
jpnurmi Feb 25, 2026
019e0e9
fix(retry): prevent duplicate cache writes during shutdown race
jpnurmi Feb 26, 2026
0e83c47
fix(cache): replace length heuristic with proper filename parsing in …
jpnurmi Feb 26, 2026
5f8e452
docs: fix retry count 5 → 6 in sentry_transport_retry docs
jpnurmi Feb 26, 2026
69ffc09
fix(retry): prevent poll task from re-arming after shutdown
jpnurmi Feb 26, 2026
e50dcf5
fix(winhttp): cancel in-flight request before shutdown to unblock worker
jpnurmi Feb 26, 2026
db19679
fix(winhttp): fix double-close race on client->request between cancel…
jpnurmi Feb 26, 2026
898308d
fix(winhttp): use on_timeout callback to unblock worker instead of ca…
jpnurmi Feb 26, 2026
7db3274
fix(winhttp): remove unnecessary local request snapshot in winhttp_se…
jpnurmi Feb 26, 2026
5b32779
fix(sync): don't force running=0 before on_timeout callback
jpnurmi Feb 26, 2026
9c8d803
fix(test): disable transport retry in unit tests to fix valgrind flak…
jpnurmi Feb 26, 2026
a91842a
fix(retry): clear sealed_envelope after match to prevent address-reus…
jpnurmi Feb 26, 2026
c17329a
ref: consolidate filename formatting into make_cache_path
jpnurmi Mar 4, 2026
3461f52
Adapt to sentry__session_new() change
jpnurmi Mar 9, 2026
36568c1
ref: cache envelopes only on failed HTTP send
jpnurmi Mar 10, 2026
1d85dd8
Clarify bgworker shutdown timeout comment
jpnurmi Mar 10, 2026
168a807
Cache envelopes only on failed HTTP send
jpnurmi Mar 11, 2026
c0f920d
Remove unused sentry__transport_can_retry
jpnurmi Mar 11, 2026
bb06d6f
fix: incref options in cleanup task to prevent use-after-free
jpnurmi Mar 11, 2026
8840444
Update sentry docs URL for network failure handling
jpnurmi Mar 17, 2026
93d884a
Replace pointer comparison with envelope tag in retry seal check
jpnurmi Mar 17, 2026
93db900
Add TODO for retry jitter and shorter poll interval
jpnurmi Mar 17, 2026
8f104d2
Initialize tag for raw envelopes loaded from disk
cursoragent Mar 17, 2026
878ace5
Implement on_timeout for curl transport
jpnurmi Mar 18, 2026
b16281e
fix(curl): trim HTTP response header values
jpnurmi Feb 20, 2026
f18a4a3
feat(path): add sentry__path_copy with unit test
jpnurmi Feb 21, 2026
e0894ae
feat(path): add sentry__path_get_dir_size helper
jpnurmi Mar 4, 2026
eca309e
feat(transport): add streaming file upload and TUS request preparation
jpnurmi Mar 8, 2026
485eeb8
feat(tus): large attachment upload via TUS protocol
jpnurmi Mar 8, 2026
3928f05
refactor: centralize large attachment check in sentry__is_large_attac…
jpnurmi Mar 14, 2026
a9e5b92
feat(tus): split into separate creation and upload requests
jpnurmi Mar 14, 2026
c5ea059
Revert "feat(tus): split into separate creation and upload requests"
jpnurmi Mar 16, 2026
0b609aa
rename refs.json to __sentry-attachments.json to avoid conflicts
jpnurmi Mar 18, 2026
8bae6b3
refactor(tus): cache external attachments by type, choose upload meth…
jpnurmi Mar 18, 2026
0f27df0
Reapply "feat(tus): split into separate creation and upload requests"
jpnurmi Mar 19, 2026
1a676d8
fix(tus): resolve relative Location URL, add auth to PATCH, handle em…
jpnurmi Mar 19, 2026
14b3248
feat(envelope): support attachment-refs in raw envelopes
jpnurmi Mar 19, 2026
8e3b656
refactor(tus): append attachment-refs to event envelope
jpnurmi Mar 19, 2026
a07948d
feat(curl): log upload progress and reduce debug noise
jpnurmi Mar 19, 2026
7560af2
fix(tus): add +json suffix to attachment-ref content type
jpnurmi Mar 20, 2026
312493e
fix(tests): adapt crashpad/breakpad tests for external minidump caching
jpnurmi Mar 20, 2026
0766467
fix(envelope): include content_type in raw attachment-ref payload
jpnurmi Mar 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## Unreleased:
## Unreleased

**Features**:

- Add HTTP retry with exponential backoff. ([#1520](https://github.com/getsentry/sentry-native/pull/1520))

**Fixes**:

Expand Down
8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,14 @@ endif()
include(CheckTypeSize)
check_type_size("long" CMAKE_SIZEOF_LONG)

if(LINUX)
include(CheckSymbolExists)
check_symbol_exists(copy_file_range "unistd.h" HAVE_COPY_FILE_RANGE)
if(HAVE_COPY_FILE_RANGE)
target_compile_definitions(sentry PRIVATE SENTRY_HAVE_COPY_FILE_RANGE)
endif()
endif()

# https://gitlab.kitware.com/cmake/cmake/issues/18393
if(SENTRY_BUILD_SHARED_LIBS)
if(APPLE)
Expand Down
26 changes: 26 additions & 0 deletions examples/example.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,25 @@ main(int argc, char **argv)
sentry_options_add_attachment(options, "./CMakeCache.txt");
}

if (has_arg(argc, argv, "large-attachment")) {
const char *large_file = ".sentry-large-attachment";
FILE *f = fopen(large_file, "wb");
if (f) {
// 100 MB = TUS upload threshold
char zeros[4096];
memset(zeros, 0, sizeof(zeros));
size_t remaining = 100 * 1024 * 1024;
while (remaining > 0) {
size_t chunk
= remaining < sizeof(zeros) ? remaining : sizeof(zeros);
fwrite(zeros, 1, chunk, f);
remaining -= chunk;
}
fclose(f);
sentry_options_add_attachment(options, large_file);
}
}

if (has_arg(argc, argv, "stdout")) {
sentry_options_set_transport(
options, sentry_transport_new(print_envelope));
Expand Down Expand Up @@ -659,6 +678,9 @@ main(int argc, char **argv)
sentry_options_set_cache_max_age(options, 5 * 24 * 60 * 60); // 5 days
sentry_options_set_cache_max_items(options, 5);
}
if (has_arg(argc, argv, "no-http-retry")) {
sentry_options_set_http_retry(options, false);
}

if (has_arg(argc, argv, "enable-metrics")) {
sentry_options_set_enable_metrics(options, true);
Expand Down Expand Up @@ -940,6 +962,10 @@ main(int argc, char **argv)
sentry_reinstall_backend();
}

if (has_arg(argc, argv, "flush")) {
sentry_flush(10000);
}

if (has_arg(argc, argv, "sleep")) {
sleep_s(10);
}
Expand Down
41 changes: 36 additions & 5 deletions include/sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -946,6 +946,24 @@ SENTRY_API void sentry_transport_set_shutdown_func(
sentry_transport_t *transport,
int (*shutdown_func)(uint64_t timeout, void *state));

/**
* Retries sending all pending envelopes in the transport's retry queue,
* e.g. when coming back online. Only applicable for HTTP transports.
*
* Note: The SDK automatically retries failed envelopes on next application
* startup. This function allows manual triggering of pending retries at
* runtime. Each envelope is retried up to 6 times. If all attempts are
* exhausted during intermittent connectivity, events will be discarded
* (or moved to cache if enabled via sentry_options_set_cache_keep).
*
* Warning: This function has no rate limiting - it will immediately
* attempt to send all pending envelopes. Calling this repeatedly during
* extended network outages may exhaust retry attempts that might have
* succeeded with the SDK's built-in exponential backoff.
*/
SENTRY_EXPERIMENTAL_API void sentry_transport_retry(
sentry_transport_t *transport);

/**
* Generic way to free transport.
*/
Expand Down Expand Up @@ -1476,12 +1494,13 @@ SENTRY_API int sentry_options_get_symbolize_stacktraces(
const sentry_options_t *opts);

/**
* Enables or disables storing envelopes in a persistent cache.
* Enables or disables storing failed envelopes in a persistent cache.
*
* When enabled, envelopes that fail to send are written to a `cache/`
* subdirectory within the database directory. The cache is cleared on startup
* based on the cache_max_items, cache_max_size, and cache_max_age options.
*
* When enabled, envelopes are written to a `cache/` subdirectory within the
* database directory and retained regardless of send success or failure.
* The cache is cleared on startup based on the cache_max_items, cache_max_size,
* and cache_max_age options.
* Only applicable for HTTP transports.
*
* Disabled by default.
*/
Expand Down Expand Up @@ -2258,6 +2277,18 @@ SENTRY_EXPERIMENTAL_API void sentry_options_set_enable_logs(
SENTRY_EXPERIMENTAL_API int sentry_options_get_enable_logs(
const sentry_options_t *opts);

/**
* Enables or disables HTTP retry with exponential backoff for network failures.
*
* Only applicable for HTTP transports.
*
* Enabled by default.
*/
SENTRY_EXPERIMENTAL_API void sentry_options_set_http_retry(
sentry_options_t *opts, int enabled);
SENTRY_EXPERIMENTAL_API int sentry_options_get_http_retry(
const sentry_options_t *opts);

/**
* Enables or disables custom attributes parsing for structured logging.
*
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ sentry_target_sources_cwd(sentry
sentry_process.h
sentry_ratelimiter.c
sentry_ratelimiter.h
sentry_retry.c
sentry_retry.h
sentry_ringbuffer.c
sentry_ringbuffer.h
sentry_sampling_context.h
Expand Down
10 changes: 10 additions & 0 deletions src/backends/sentry_backend_breakpad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ breakpad_backend_callback(const google_breakpad::MinidumpDescriptor &descriptor,

sentry__envelope_item_set_header(item, "filename",
sentry_value_new_string(sentry__path_filename(dump_path)));
} else {
sentry_uuid_t event_id
= sentry__envelope_get_event_id(envelope);
sentry_attachment_t tmp;
memset(&tmp, 0, sizeof(tmp));
tmp.path = dump_path;
tmp.type = MINIDUMP;
tmp.next = nullptr;
sentry__cache_external_attachments(
options->run->cache_path, &event_id, &tmp, nullptr);
}

if (options->attach_screenshot) {
Expand Down
13 changes: 7 additions & 6 deletions src/backends/sentry_backend_crashpad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,11 @@ report_to_envelope(const crashpad::CrashReportDatabase::Report &report,

if (sentry__envelope_add_event(envelope, event)) {
sentry__envelope_add_attachments(envelope, attachments);
sentry_uuid_t event_id = sentry__envelope_get_event_id(envelope);
if (options->run) {
sentry__cache_external_attachments(options->run->cache_path,
&event_id, attachments, options->run->run_path);
}
} else {
sentry_value_decref(event);
sentry_envelope_free(envelope);
Expand Down Expand Up @@ -565,11 +570,9 @@ process_completed_reports(

SENTRY_DEBUGF("caching %zu completed reports", reports.size());

sentry_path_t *cache_dir
= sentry__path_join_str(options->database_path, "cache");
if (!cache_dir || sentry__path_create_dir_all(cache_dir) != 0) {
sentry_path_t *cache_dir = options->run->cache_path;
if (sentry__path_create_dir_all(cache_dir) != 0) {
SENTRY_WARN("failed to create cache dir");
sentry__path_free(cache_dir);
return;
}

Expand All @@ -593,8 +596,6 @@ process_completed_reports(
sentry__path_free(out_path);
sentry_envelope_free(envelope);
}

sentry__path_free(cache_dir);
}

static int
Expand Down
3 changes: 2 additions & 1 deletion src/backends/sentry_backend_inproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1156,8 +1156,9 @@ process_ucontext_deferred(const sentry_ucontext_t *uctx,
}
TEST_CRASH_POINT("before_capture");
if (should_handle) {
sentry_uuid_t event_id;
sentry_envelope_t *envelope = sentry__prepare_event(options, event,
NULL, !options->on_crash_func && !skip_hooks, NULL);
&event_id, !options->on_crash_func && !skip_hooks, NULL);
// TODO(tracing): Revisit when investigating transaction flushing
// during hard crashes.

Expand Down
13 changes: 13 additions & 0 deletions src/path/sentry_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,19 @@ sentry__path_remove_all(const sentry_path_t *path)
return sentry__path_remove(path);
}

size_t
sentry__path_get_dir_size(const sentry_path_t *path)
{
size_t total = 0;
sentry_pathiter_t *iter = sentry__path_iter_directory(path);
const sentry_path_t *entry;
while (iter && (entry = sentry__pathiter_next(iter)) != NULL) {
total += sentry__path_get_size(entry);
}
sentry__pathiter_free(iter);
return total;
}

sentry_filelock_t *
sentry__filelock_new(sentry_path_t *path)
{
Expand Down
66 changes: 66 additions & 0 deletions src/path/sentry_path_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <unistd.h>

#ifdef SENTRY_PLATFORM_DARWIN
# include <copyfile.h>
# include <mach-o/dyld.h>
#endif

Expand Down Expand Up @@ -333,6 +334,71 @@ sentry__path_rename(const sentry_path_t *src, const sentry_path_t *dst)
return status == 0 ? 0 : 1;
}

int
sentry__path_copy(const sentry_path_t *src, const sentry_path_t *dst)
{
#ifdef SENTRY_PLATFORM_DARWIN
return copyfile(src->path, dst->path, NULL, COPYFILE_DATA) == 0 ? 0 : 1;
#else
int src_fd = open(src->path, O_RDONLY);
if (src_fd < 0) {
return 1;
}
int dst_fd = open(dst->path, O_WRONLY | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
if (dst_fd < 0) {
close(src_fd);
return 1;
}

int rv = 0;

# ifdef SENTRY_HAVE_COPY_FILE_RANGE
while (true) {
ssize_t n
= copy_file_range(src_fd, NULL, dst_fd, NULL, SIZE_MAX / 2, 0);
if (n > 0) {
continue;
} else if (n == 0) {
goto done;
} else if (errno == EAGAIN || errno == EINTR) {
continue;
} else if (errno == ENOSYS || errno == EXDEV || errno == EOPNOTSUPP
|| errno == EINVAL) {
break;
} else {
rv = 1;
goto done;
}
}
# endif

{
char buf[16384];
while (true) {
ssize_t n = read(src_fd, buf, sizeof(buf));
if (n < 0 && (errno == EAGAIN || errno == EINTR)) {
continue;
} else if (n <= 0) {
rv = n < 0;
break;
}
if (write_loop(dst_fd, buf, (size_t)n) != 0) {
rv = 1;
break;
}
}
}

# ifdef SENTRY_HAVE_COPY_FILE_RANGE
done:
# endif
close(src_fd);
close(dst_fd);
return rv;
#endif
}

int
sentry__path_create_dir_all(const sentry_path_t *path)
{
Expand Down
9 changes: 9 additions & 0 deletions src/path/sentry_path_windows.c
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,15 @@ sentry__path_rename(const sentry_path_t *src, const sentry_path_t *dst)
return MoveFileExW(src_w, dst_w, MOVEFILE_REPLACE_EXISTING) ? 0 : 1;
}

int
sentry__path_copy(const sentry_path_t *src, const sentry_path_t *dst)
{
if (!src->path_w || !dst->path_w) {
return 1;
}
return CopyFileW(src->path_w, dst->path_w, FALSE) ? 0 : 1;
}

int
sentry__path_create_dir_all(const sentry_path_t *path)
{
Expand Down
29 changes: 29 additions & 0 deletions src/sentry_attachment.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,32 @@ sentry__attachments_extend(
attachments_ptr, attachment_clone(it), it->type, it->content_type);
}
}

size_t
sentry__attachment_get_size(const sentry_attachment_t *attachment)
{
return attachment->buf ? attachment->buf_len
: sentry__path_get_size(attachment->path);
}

const char *
sentry__attachment_get_filename(const sentry_attachment_t *attachment)
{
return sentry__path_filename(
attachment->filename ? attachment->filename : attachment->path);
}

const char *
sentry__attachment_type_to_string(sentry_attachment_type_t attachment_type)
{
switch (attachment_type) {
case ATTACHMENT:
return "event.attachment";
case MINIDUMP:
return "event.minidump";
case VIEW_HIERARCHY:
return "event.view_hierarchy";
default:
return "event.attachment";
}
}
Loading
Loading