| 220 | } |
| 221 | |
| 222 | static char *activation_unique_path(const char *directory, const char *tag) { |
| 223 | uint64_t sequence = |
| 224 | atomic_fetch_add_explicit(&activation_unique_sequence, 1U, memory_order_relaxed) + 1U; |
| 225 | #ifdef _WIN32 |
| 226 | unsigned long process_id = (unsigned long)GetCurrentProcessId(); |
| 227 | #else |
| 228 | unsigned long process_id = (unsigned long)getpid(); |
| 229 | #endif |
| 230 | size_t directory_length = strlen(directory); |
| 231 | size_t needed = directory_length + strlen(tag) + 80U; |
| 232 | char *path = malloc(needed); |
| 233 | if (!path) { |
| 234 | return NULL; |
| 235 | } |
| 236 | /* Windows joins use the backslash: extended-length (\\\\?\\) directories |
| 237 | * reach this composer and that namespace performs no forward-slash |
| 238 | * translation. POSIX keeps the slash. */ |
| 239 | #ifdef _WIN32 |
| 240 | const char *separator = "\\"; |
| 241 | #else |
| 242 | const char *separator = "/"; |
| 243 | #endif |
| 244 | int written = |
| 245 | snprintf(path, needed, "%s%s.cbm-%s-%lu-%" PRIu64, directory, |
| 246 | directory[directory_length - 1U] == '/' || directory[directory_length - 1U] == '\\' |
| 247 | ? "" |
| 248 | : separator, |
| 249 | tag, process_id, sequence); |
| 250 | if (written <= 0 || (size_t)written >= needed) { |
| 251 | free(path); |
| 252 | return NULL; |
| 253 | } |
| 254 | return path; |
| 255 | } |
| 256 | |
| 257 | static bool activation_identity_equal(const activation_file_identity_t *left, |
| 258 | const activation_file_identity_t *right) { |
no outgoing calls
no test coverage detected