| 333 | } |
| 334 | |
| 335 | void write_pc_item(struct parallel_checkout_item *pc_item, |
| 336 | struct checkout *state) |
| 337 | { |
| 338 | unsigned int mode = (pc_item->ce->ce_mode & 0100) ? 0777 : 0666; |
| 339 | int fd = -1, fstat_done = 0; |
| 340 | struct strbuf path = STRBUF_INIT; |
| 341 | const char *dir_sep; |
| 342 | |
| 343 | strbuf_add(&path, state->base_dir, state->base_dir_len); |
| 344 | strbuf_add(&path, pc_item->ce->name, pc_item->ce->ce_namelen); |
| 345 | |
| 346 | dir_sep = find_last_dir_sep(path.buf); |
| 347 | |
| 348 | /* |
| 349 | * The leading dirs should have been already created by now. But, in |
| 350 | * case of path collisions, one of the dirs could have been replaced by |
| 351 | * a symlink (checked out after we enqueued this entry for parallel |
| 352 | * checkout). Thus, we must check the leading dirs again. |
| 353 | */ |
| 354 | if (dir_sep && !has_dirs_only_path(path.buf, dir_sep - path.buf, |
| 355 | state->base_dir_len)) { |
| 356 | pc_item->status = PC_ITEM_COLLIDED; |
| 357 | trace2_data_string("pcheckout", NULL, "collision/dirname", path.buf); |
| 358 | goto out; |
| 359 | } |
| 360 | |
| 361 | fd = open(path.buf, O_WRONLY | O_CREAT | O_EXCL, mode); |
| 362 | |
| 363 | if (fd < 0) { |
| 364 | if (errno == EEXIST || errno == EISDIR) { |
| 365 | /* |
| 366 | * Errors which probably represent a path collision. |
| 367 | * Suppress the error message and mark the item to be |
| 368 | * retried later, sequentially. ENOTDIR and ENOENT are |
| 369 | * also interesting, but the above has_dirs_only_path() |
| 370 | * call should have already caught these cases. |
| 371 | */ |
| 372 | pc_item->status = PC_ITEM_COLLIDED; |
| 373 | trace2_data_string("pcheckout", NULL, |
| 374 | "collision/basename", path.buf); |
| 375 | } else { |
| 376 | error_errno("failed to open file '%s'", path.buf); |
| 377 | pc_item->status = PC_ITEM_FAILED; |
| 378 | } |
| 379 | goto out; |
| 380 | } |
| 381 | |
| 382 | if (write_pc_item_to_fd(pc_item, fd, path.buf)) { |
| 383 | /* Error was already reported. */ |
| 384 | pc_item->status = PC_ITEM_FAILED; |
| 385 | close_and_clear(&fd); |
| 386 | unlink(path.buf); |
| 387 | goto out; |
| 388 | } |
| 389 | |
| 390 | fstat_done = fstat_checkout_output(fd, state, &pc_item->st); |
| 391 | |
| 392 | if (close_and_clear(&fd)) { |
no test coverage detected