|
60 | 60 | #include <evalfunction.h>
|
61 | 61 | #include <changes_chroot.h> /* PrepareChangesChroot(), RecordFileChangedInChroot() */
|
62 | 62 | #include <fsattrs.h>
|
| 63 | +#include <override_fsattrs.h> |
63 | 64 |
|
64 | 65 | static PromiseResult FindFilePromiserObjects(EvalContext *ctx, const Promise *pp);
|
65 | 66 | static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promise *pp);
|
66 | 67 | static PromiseResult WriteContentFromString(EvalContext *ctx, const char *path, const Attributes *attr,
|
67 |
| - const Promise *pp); |
| 68 | + const Promise *pp, bool override_immutable); |
68 | 69 |
|
69 | 70 | /*****************************************************************************/
|
70 | 71 |
|
@@ -401,6 +402,11 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
|
401 | 402 | }
|
402 | 403 | }
|
403 | 404 |
|
| 405 | + /* If we encounter any promises to mutate the file and the immutable |
| 406 | + * attribute in body fsattrs is "true", we will override the immutable bit |
| 407 | + * by temporarily clearing it when ever needed. */ |
| 408 | + const bool override_immutable = a.havefsattrs && a.fsattrs.haveimmutable && a.fsattrs.immutable && is_immutable; |
| 409 | + |
404 | 410 | if (lstat(changes_path, &oslb) == -1) /* Careful if the object is a link */
|
405 | 411 | {
|
406 | 412 | if ((a.create) || (a.touch))
|
@@ -610,7 +616,7 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
|
610 | 616 | Log(LOG_LEVEL_VERBOSE, "Replacing '%s' with content '%s'",
|
611 | 617 | path, a.content);
|
612 | 618 |
|
613 |
| - PromiseResult render_result = WriteContentFromString(ctx, path, &a, pp); |
| 619 | + PromiseResult render_result = WriteContentFromString(ctx, path, &a, pp, override_immutable); |
614 | 620 | result = PromiseResultUpdate(result, render_result);
|
615 | 621 |
|
616 | 622 | goto exit;
|
@@ -759,7 +765,7 @@ static PromiseResult VerifyFilePromise(EvalContext *ctx, char *path, const Promi
|
759 | 765 | /*****************************************************************************/
|
760 | 766 |
|
761 | 767 | static PromiseResult WriteContentFromString(EvalContext *ctx, const char *path, const Attributes *attr,
|
762 |
| - const Promise *pp) |
| 768 | + const Promise *pp, bool override_immutable) |
763 | 769 | {
|
764 | 770 | assert(path != NULL);
|
765 | 771 | assert(attr != NULL);
|
@@ -794,30 +800,45 @@ static PromiseResult WriteContentFromString(EvalContext *ctx, const char *path,
|
794 | 800 | return result;
|
795 | 801 | }
|
796 | 802 |
|
797 |
| - FILE *f = safe_fopen(changes_path, "w"); |
| 803 | + char override_path[PATH_MAX]; |
| 804 | + if (!OverrideImmutableBegin(changes_path, override_path, sizeof(override_path), override_immutable)) |
| 805 | + { |
| 806 | + RecordFailure(ctx, pp, attr, "Failed to override immutable bit on file '%s'", changes_path); |
| 807 | + return PromiseResultUpdate(result, PROMISE_RESULT_FAIL); |
| 808 | + } |
| 809 | + |
| 810 | + FILE *f = safe_fopen(override_path, "w"); |
798 | 811 | if (f == NULL)
|
799 | 812 | {
|
800 | 813 | RecordFailure(ctx, pp, attr, "Cannot open file '%s' for writing", path);
|
| 814 | + OverrideImmutableAbort(changes_path, override_path, override_immutable, true); |
801 | 815 | return PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
|
802 | 816 | }
|
803 | 817 |
|
| 818 | + bool override_abort = false; |
804 | 819 | Writer *w = FileWriter(f);
|
805 | 820 | if (WriterWriteLen(w, attr->content, bytes_to_write) == bytes_to_write )
|
806 | 821 | {
|
807 | 822 | RecordChange(ctx, pp, attr,
|
808 | 823 | "Updated file '%s' with content '%s'",
|
809 | 824 | path, attr->content);
|
810 |
| - |
811 | 825 | result = PromiseResultUpdate(result, PROMISE_RESULT_CHANGE);
|
812 | 826 | }
|
813 | 827 | else
|
814 | 828 | {
|
815 | 829 | RecordFailure(ctx, pp, attr,
|
816 | 830 | "Failed to update file '%s' with content '%s'",
|
817 | 831 | path, attr->content);
|
| 832 | + override_abort = true; |
818 | 833 | result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
|
819 | 834 | }
|
820 | 835 | WriterClose(w);
|
| 836 | + |
| 837 | + if (!OverrideImmutableCommit(changes_path, override_path, override_immutable, override_abort)) |
| 838 | + { |
| 839 | + RecordFailure(ctx, pp, attr, "Failed to override immutable bit on file '%s'", changes_path); |
| 840 | + result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); |
| 841 | + } |
821 | 842 | }
|
822 | 843 |
|
823 | 844 | return result;
|
|
0 commit comments