all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH proxmox 0/2] fix rootfs extraction when paths already exist
@ 2025-12-01 17:13 Filip Schauer
  2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 1/2] oci: " Filip Schauer
  2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 2/2] oci: test replacing files in subsequent layers Filip Schauer
  0 siblings, 2 replies; 3+ messages in thread
From: Filip Schauer @ 2025-12-01 17:13 UTC (permalink / raw)
  To: pve-devel

Remove paths from previous layers that conflict with new layer entries
before unpacking. This aligns with the OCI spec. [0]

This fixes a rootfs extraction failure with docker.io/grafana/otel-lgtm,
which was reported in the Proxmox Forum [1].

[0] https://github.com/opencontainers/image-spec/blob/26647a49f642c7d22a1cd3aa0a48e4650a542269/layer.md#changeset-over-existing-files
[1] https://forum.proxmox.com/threads/otel-lgtm-oci-create-lxc-failed.176996/

Filip Schauer (2):
  oci: fix rootfs extraction when paths already exist
  oci: test replacing files in subsequent layers

 proxmox-oci/src/lib.rs                        |  20 ++++++
 proxmox-oci/tests/extract_replace.rs          |  57 ++++++++++++++++++
 .../oci_test_replace_dir_with_file.tar        | Bin 0 -> 8704 bytes
 .../oci_image_data/oci_test_replace_file.tar  | Bin 0 -> 8704 bytes
 .../oci_test_replace_file_with_dir.tar        | Bin 0 -> 8704 bytes
 5 files changed, 77 insertions(+)
 create mode 100644 proxmox-oci/tests/extract_replace.rs
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_dir_with_file.tar
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_file.tar
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_file_with_dir.tar

-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [pve-devel] [PATCH proxmox 1/2] oci: fix rootfs extraction when paths already exist
  2025-12-01 17:13 [pve-devel] [PATCH proxmox 0/2] fix rootfs extraction when paths already exist Filip Schauer
@ 2025-12-01 17:13 ` Filip Schauer
  2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 2/2] oci: test replacing files in subsequent layers Filip Schauer
  1 sibling, 0 replies; 3+ messages in thread
From: Filip Schauer @ 2025-12-01 17:13 UTC (permalink / raw)
  To: pve-devel

Remove paths from previous layers that conflict with new layer entries
before unpacking. This aligns with the OCI spec. [0]

This fixes a rootfs extraction failure with docker.io/grafana/otel-lgtm,
which was reported in the Proxmox Forum [1].

[0] https://github.com/opencontainers/image-spec/blob/26647a49f642c7d22a1cd3aa0a48e4650a542269/layer.md#changeset-over-existing-files
[1] https://forum.proxmox.com/threads/otel-lgtm-oci-create-lxc-failed.176996/

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
 proxmox-oci/src/lib.rs | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/proxmox-oci/src/lib.rs b/proxmox-oci/src/lib.rs
index cf0e4271..cce68207 100644
--- a/proxmox-oci/src/lib.rs
+++ b/proxmox-oci/src/lib.rs
@@ -302,6 +302,16 @@ fn extract_archive<R: Read, P: AsRef<Path>>(reader: &mut R, target_path: P) -> s
             }
         }
 
+        // If a file or directory already exists at this path, remove it first.
+        let file_path_abs = target_path.as_ref().join(file.path()?);
+        if file_path_abs.exists() {
+            if file_path_abs.is_dir() {
+                remove_dir_all(file_path_abs)?;
+            } else {
+                remove_file(file_path_abs)?;
+            }
+        }
+
         file.unpack_in(&target_path)?;
     }
 
@@ -309,6 +319,16 @@ fn extract_archive<R: Read, P: AsRef<Path>>(reader: &mut R, target_path: P) -> s
     // to avoid failure on restrictive parent directory permissions.
     directories.sort_by(|a, b| b.path_bytes().cmp(&a.path_bytes()));
     for mut dir in directories {
+        let dir_path_abs = target_path.as_ref().join(dir.path()?);
+
+        // Remove the trailing slash
+        let dir_path_abs = dir_path_abs.components().as_path();
+
+        // If a file already exists at this path, remove it first.
+        if dir_path_abs.exists() && !dir_path_abs.is_dir() {
+            remove_file(dir_path_abs)?;
+        }
+
         dir.unpack_in(&target_path)?;
     }
 
-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [pve-devel] [PATCH proxmox 2/2] oci: test replacing files in subsequent layers
  2025-12-01 17:13 [pve-devel] [PATCH proxmox 0/2] fix rootfs extraction when paths already exist Filip Schauer
  2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 1/2] oci: " Filip Schauer
@ 2025-12-01 17:13 ` Filip Schauer
  1 sibling, 0 replies; 3+ messages in thread
From: Filip Schauer @ 2025-12-01 17:13 UTC (permalink / raw)
  To: pve-devel

Add tests that verify later layer entries properly replace paths from
earlier layers.

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
 proxmox-oci/tests/extract_replace.rs          |  57 ++++++++++++++++++
 .../oci_test_replace_dir_with_file.tar        | Bin 0 -> 8704 bytes
 .../oci_image_data/oci_test_replace_file.tar  | Bin 0 -> 8704 bytes
 .../oci_test_replace_file_with_dir.tar        | Bin 0 -> 8704 bytes
 4 files changed, 57 insertions(+)
 create mode 100644 proxmox-oci/tests/extract_replace.rs
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_dir_with_file.tar
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_file.tar
 create mode 100644 proxmox-oci/tests/oci_image_data/oci_test_replace_file_with_dir.tar

diff --git a/proxmox-oci/tests/extract_replace.rs b/proxmox-oci/tests/extract_replace.rs
new file mode 100644
index 00000000..eb41f9e3
--- /dev/null
+++ b/proxmox-oci/tests/extract_replace.rs
@@ -0,0 +1,57 @@
+use std::fs::{read_to_string, remove_dir_all};
+
+use proxmox_oci::{parse_and_extract_image, Arch};
+use proxmox_sys::fs::make_tmp_dir;
+
+#[test]
+fn test_replace_file() {
+    let extract_dir = make_tmp_dir("/tmp/", None).unwrap();
+
+    parse_and_extract_image(
+        &"tests/oci_image_data/oci_test_replace_file.tar".into(),
+        &extract_dir,
+        Some(&Arch::Amd64),
+    )
+    .unwrap();
+
+    let replaced_path = extract_dir.join("etc/a");
+    assert!(replaced_path.is_file());
+    assert_eq!(read_to_string(replaced_path).unwrap(), "2");
+
+    // Cleanup
+    remove_dir_all(extract_dir).unwrap();
+}
+
+#[test]
+fn test_replace_file_with_dir() {
+    let extract_dir = make_tmp_dir("/tmp/", None).unwrap();
+
+    parse_and_extract_image(
+        &"tests/oci_image_data/oci_test_replace_file_with_dir.tar".into(),
+        &extract_dir,
+        Some(&Arch::Amd64),
+    )
+    .unwrap();
+
+    assert!(extract_dir.join("etc/a").is_dir());
+
+    // Cleanup
+    remove_dir_all(extract_dir).unwrap();
+}
+
+#[test]
+fn test_replace_dir_with_file() {
+    let extract_dir = make_tmp_dir("/tmp/", None).unwrap();
+
+    parse_and_extract_image(
+        &"tests/oci_image_data/oci_test_replace_dir_with_file.tar".into(),
+        &extract_dir,
+        Some(&Arch::Amd64),
+    )
+    .unwrap();
+
+    assert!(extract_dir.join("etc/a").is_file());
+
+    // Cleanup
+    remove_dir_all(extract_dir).unwrap();
+}
diff --git a/proxmox-oci/tests/oci_image_data/oci_test_replace_dir_with_file.tar b/proxmox-oci/tests/oci_image_data/oci_test_replace_dir_with_file.tar
new file mode 100644
index 0000000000000000000000000000000000000000..c4e488602eef13d5cee53710b97ffce5bf0586c7
GIT binary patch
literal 8704
zcmeHM&1+m$6n|QyVekvPu!!jJ7DcEtz26_fjUW-xO=)nU1i7D?C&^5hnS`b_P+h2K
z79#!uqM&R23oN*(I}xdi2trrlN_Q@b^}ILJn3;5Dsxt|dytjDo&3X5pd+xdC_q*qw
zv8yfHIh!2nh2WB$C;1bu;pcu??;Rt7MN;L5YE@tPMyG4q)oRjiwYuZRoAiBL-@Evm
zE!Mx&FocW43WI!6|K0jyLCW<%lBgM2|ELX7hz4(QjE-WC48cM>$A!}|Xb^I%i13jp
zB_y^0Qy-O%&`Mx53a|P43&w_Vf9p3QjO@Kb(*zO11WKytC_He?@&ELP^YgW@Yguwa
zN#bK<Q8CY`MZ{r+NidQyucF0_aYBrXNJfKLkd~|H;2AYj0^3OHz@y2_wU@4~e2P(W
zZ|D4Z^w533veUcYe{=Qc%g<l=<l4h0-u~hG$KR%NbMJn3<Hloe{WkyIBj-M<?A(0e
zi7yj!{g)rt*<UYSdFIsI=a;`o61DqNn#><X2ps1z2Jp`bV@xTFF!v!wZ#>7$M_68O
zDHlKj+zO?L3I^`ZAdLbt)*1yQpuHa9$cgxuco_eJl=vUv&Dn}`{I|c#@eiwv5Y`+i
z%_#QDD9?>l!f5zHsl>#{U;*xeMZ*mZR(c++h7Cb!>djR6-@WI9C3^DYbAPnnf9mGx
z#l;6J_p{B%Pwo8vr+l*Uz|K48P-PLA;n5_iTz#*dRA%dhW2|ie|Hf0~gEY~>)-JFE
zOe4#Q*DPx3uy<B_>?IR~TWJ`8U-BTN6tG=OhV2MH=J+3z|6xK8;GeM)|0BFPTk)kz
zwVHNZBdnQML%Wl;n(0E7Jey0`g3rv-)_MR*YS!0RGiSQc;Ou78*IO>DXKQ99)YnWi
zi=or4Z{jm=cA$UJ*|nN6TY;YW0C%pe*KI%*boSW_43L}AJE$xK#T4e0GptP@LSyQQ
zPyqr7Qqstb&chRXL9qymAdZ+ckh{o8onu0Y!p3~!*~NTzlyb0gyD)s!Y=Iv@_<CV@
z&-^=|K+zrS&)M+I%EfHGKh*7JG3|EykLvzBu*&DrpGmdv`opn(+M~ij+Xd;_4)^8C
zcFFLw#rY_01N=WNtVRqnf&UT5ayb7(f|uvN5$>F+xZr=&c8#nXTz8}0Bl|TkSb@;g
zwS(yfpK~ukgx4^sA-sg~0@4eJ*QpSM!f~Cw)@$C#I^9-#E2q!pf=*jGm8Pp%bK^p<
zMP5gXxv;-6bc+op?bB}Fr=ZFh-^e^P>#;D1`pgft2uGZx!Uiv`ih(o1p#~8VCC&?O
zh-X1K2{w^HwDlnn4|NP<yblb=eY{iDycP_TmPo^6aF~KVL;}{76X}sNoLUM=F{6|+
zDX7QJ2;&eWM3yNpky1V_EMA8D_WzN!vZfCg>iNDs)36#)R-FG1)_wOdPx(;(hoSNW
z^}n+IGvLNU`BC71ME=)L?EZT)blcRh5AdOkZrY>AK3w;5IwAVGP?=AR3mnMfYrws&
zjj?}zjMFgr+a&xWD)zVl+9n9_k6DTT$)26Q#ig`3#l2F5z}^Wk#dTCi>Gt&cOAVz5
ON)MDCC_Qj@df;!g^|Z$T

literal 0
HcmV?d00001

diff --git a/proxmox-oci/tests/oci_image_data/oci_test_replace_file.tar b/proxmox-oci/tests/oci_image_data/oci_test_replace_file.tar
new file mode 100644
index 0000000000000000000000000000000000000000..77922f7dbb6588a25e2b2514ec017d7327469d06
GIT binary patch
literal 8704
zcmeHMOK%)S5FQ8tYsE|CKolWZ%^^Yx-gNc5EiOpN5`s$<iv!3){j>+!yVma7iW4jW
z2cAA4#1BCH1O5S#I0R0JLoVUO32}lG93qA8*|p;}nYHomq9A4to>fg(b#+yL)%}&t
zTF3M*W;1<Id<0`zddKJR`=D&_8xRMcHQ7wP8XDj1^>w$|%(|UUf82aWeIKWLAAd7t
z{(Gw$Gd`<rkdpe(@(&!>`TtjT%}D++fRIKz!KHHsdl8hy-Un`p2S5T_K+?wn$V<b8
z4+a}a7-B}NAf>7B_=x-iCa_l%2KdJW0n3`G!roNH|8x9bYc!jA&#wA){kre=icULU
zXyO-=bltl`FKuu5D9QE4##&)@KMuIK)po6pEn3C8Uh%DU-7bRf^;=tT;q6}3FO_Yl
z9g3BxnI<^Cv4Pr%si^FVl{i6iV^F9Ts00c@JE;w2PAE%t+=?1g3Pcmeq`<@qh?|me
z#Dca86HbNJAp|2els=|~7gy8j2w~C7ozn3&y&dBag>ROQ58OZg0!sDhe=D9U7gnwo
z8^fvYwF-lDVAvAN4Kf0G4cZ3~iaTPRB$U~JAut8fsfa$$t@27SWQj6Da(&nIa2<eg
z>2$f0<}mcL@f~qVg(nz0<B;Jt_z<*mL^^O_ENH}})8K^%=@o&1m9boa5fpjHX|?Zh
z1<Q?{##BLG8>@=INd2EQsTGr?qRuJZtMP~52n61f4eLJ^>HM$je?>s2D1PqKxw*#I
z^F?+Fr;?SuI{(Vel`jEh5B4r!Mvp!83q619hi`8D^zKX7zqtAMsrP>T`SWk{)2Bc9
z>h|rY-uZRzyC*Jv*4VxC^0`|Ne6mE&oO$v0&PUJQIls90XyakJ_4L`@-~JTmRv+1Y
z{}O5}UVr}VlUert$9Mk7YIsjEhm)8Z!T+QOQiUTYz(1?;UlGhHixd94CH~7R%PjE!
z%qadFH$Lpv_@8nbPi$@k|C3&;E4)bfAIJY0h{NYUB{l!6h~{*~CI8c1yIS<U?QeDm
zWN&@%hMwE5*M092_reIXdBF1smH-xzT0pEtILDC$Q2IuBq0d)~Ucb}bPV{NHq*I+l
zrSi3+y?JFYBK6Ti5)O%Bza*IXkai`Vk}8GpR^j5X0Sk+wA@kEz7%Vgk-U5-qBkVyD
zhJ`~`GhzrrKnWpKaN@vft}Swk8Y-PYQn~}YqwIMt#6AaA0eQk46*3~gd4`--#866{
z3YY?=+<_9*IN`JfZWMNcXm7nCEH6D?j(>Oli>#$+JAb8>c>8qs)j@0J`TzI6?>^=U
zJJkOHV5q+T9}MBlewX;K=>H5GJ11|3+_N<_1o)wj&ZMo!1GpaabU05vorKD|pD<?k
z#6I49ti7GhvH$!SW8fH{j>118e7_dNu^Ec^2U_$0V}y3%A=mP<i~Cx+1@=3@IkZp<
X<vSCbuMN}@s3TBEppL+O8iBt6LZ+LJ

literal 0
HcmV?d00001

diff --git a/proxmox-oci/tests/oci_image_data/oci_test_replace_file_with_dir.tar b/proxmox-oci/tests/oci_image_data/oci_test_replace_file_with_dir.tar
new file mode 100644
index 0000000000000000000000000000000000000000..24743290414dc36a3cf3695b298b567932c5d812
GIT binary patch
literal 8704
zcmeHM&1)n@6mMOlVekw0;3A?!9~NPq+4}wnUIdAVUX~3Wlpyt)v?McOW)e2L238L$
znuCacfGFr${{k00tTz!^4-teti6^~zSX^IsPhv8g&aBQvR_s1>XI@pkdhb>Je)a0b
zu5@kxY;vp*f=6<m<X?D3zx!q7-xvujk|sY^tA@(g`vcQ!Hj`erJ2+~-aqUNqy@T6q
zvHtyKL%2AuZICbO-&=nyNWK35%C0%E{)ijPh{g&V7r6@>bBCQV+)#!PM>-mAtuhu<
z>6LOUNZ}Rb$T};G3KbTQS$|9@-sOZ6|AYv_lP0RrH&yZf9RHUZ&1Twn%VE{L9D4n%
z+ezn|<mp_x8hmCJHrE13QnR+Uk~uSg4rezyzTI_MJ6knNp}lH4Sq%L_djp?&y$|Dy
z!LHkh*%FM*C%AoO<*);)V6e}YV1nF?lBnjQ<*;c87J(2$v5zq*M{U%Baiy7J40A<I
zP!<VA1$7)__$`UkByj2q8*|6Ai@A4{a<Fo%Fnq;qLL5N&YGHV3{_Q(Z3<vw$aH^bH
zx|ppEr#j3FP8eefY{cA$7`^cvGam)E-cl}v)7%QBhzbVY&LE8fGS(UumDXPWrF!TG
zR=FQTPnyHfACK)(8=?>m-r^V?#T*$}4(%KVvt!U8<W>>kBT-67Y~e)rV0MIF0waE_
z?ShoH!+Wu@)tD;CYh_gtIKcmt!m47DG5n7>mZSWSnXLK0BAind7yNH}ZaEtSH(2kL
zWWVYKD-fExUND2;bM7UG@D?U5gcmTLLwXMJHWh+U0zCFg*?l?d54ye0oIV!|I_>6E
znyzG>^$TT>JdcjKaCk5biUTGc(r!Mcpvo9u%RF=|Sr|k^<~K}QA`OqhVX9(4Bw$TB
zksdk2sig>EMk!@dP!G9_Fb;XmEK^=0rTjkLDRSO9U@S+Rq{0R-EokISaA2y4C~;nJ
zLp%$@NpO+`qOA{scwjqYyblb=w6J&)-dq1g);fUyNe`rootfibFt&^F(JvzMko*tT
z_^$}(RK-ueKRes|qLn2lAngF`XpSI(f|N=b<++hc7!56yN=%FlkYX{x;2L0Pu+sBj
zHJtKFQ*ZK&CwZ~;!nLK3F-q?4pFfWtxaVhfdgt4(uKsxW*()Did+@}Y-(COk>vU%3
z?N4spc;t;=X1{sp+y{;Ao6kMAbJu$d^yJBBe(S#b#Ld(5^Y=IIWgCy4+Wz%-`S|jE
z+i#sijrl82oq9M)8du-xC3SW%txa$M|C1(l6-JH4KO?)GkatZGaIL8EUlGmeigWz8
zzRdBjB!PPri;8(hEg}xe03^VjiFp+*W{ksK%S9xkL2&W6T*bTq0ED1`AR?Iv|DPx1
z`cL1lu|J*%l+S#6`LiTZJ3pk!>~y`YwT(s~>-cb?o!{F>Tc-EB!2hjv-#yGzK63tJ
zxK2X-ude@0Zw;z675RTf{byL%`RB!uLrX)$1b?KWGim8@UtV9<bc7hzLh5=#)!OHB
zsN=QZ?$upC@}D0^X&B!&4*!UXJuWEDf51OxHU7s(cJdyV(xQs{Qn3a0D!?gjqc%#n
VCf8qUs3TBEppHNtfjct-e*)yOwi^Hd

literal 0
HcmV?d00001

-- 
2.47.3



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-12-01 17:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-01 17:13 [pve-devel] [PATCH proxmox 0/2] fix rootfs extraction when paths already exist Filip Schauer
2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 1/2] oci: " Filip Schauer
2025-12-01 17:13 ` [pve-devel] [PATCH proxmox 2/2] oci: test replacing files in subsequent layers Filip Schauer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal