8
8
"io"
9
9
"io/fs"
10
10
"log"
11
+ "os"
11
12
"path"
12
13
"strings"
13
14
@@ -215,10 +216,16 @@ func (z Zip) Extract(ctx context.Context, sourceArchive io.Reader, handleFile Fi
215
216
}
216
217
217
218
info := f .FileInfo ()
219
+ linkTarget , err := z .getLinkTarget (f )
220
+ if err != nil {
221
+ return fmt .Errorf ("getting link target for file %d: %s: %w" , i , f .Name , err )
222
+ }
223
+
218
224
file := FileInfo {
219
225
FileInfo : info ,
220
226
Header : f .FileHeader ,
221
227
NameInArchive : f .Name ,
228
+ LinkTarget : linkTarget ,
222
229
Open : func () (fs.File , error ) {
223
230
openedFile , err := f .Open ()
224
231
if err != nil {
@@ -228,7 +235,7 @@ func (z Zip) Extract(ctx context.Context, sourceArchive io.Reader, handleFile Fi
228
235
},
229
236
}
230
237
231
- err : = handleFile (ctx , file )
238
+ err = handleFile (ctx , file )
232
239
if errors .Is (err , fs .SkipAll ) {
233
240
break
234
241
} else if errors .Is (err , fs .SkipDir ) && file .IsDir () {
@@ -264,6 +271,33 @@ func (z Zip) decodeText(hdr *zip.FileHeader) {
264
271
}
265
272
}
266
273
274
+ func (z Zip ) getLinkTarget (f * zip.File ) (string , error ) {
275
+ info := f .FileInfo ()
276
+ // Exit early if not a symlink
277
+ if info .Mode ()& os .ModeSymlink == 0 {
278
+ return "" , nil
279
+ }
280
+
281
+ // Open the file and read the link target
282
+ file , err := f .Open ()
283
+ if err != nil {
284
+ return "" , err
285
+ }
286
+ defer file .Close ()
287
+
288
+ const maxLinkTargetSize = 32768
289
+ linkTargetBytes , err := io .ReadAll (io .LimitReader (file , maxLinkTargetSize ))
290
+ if err != nil {
291
+ return "" , err
292
+ }
293
+
294
+ if len (linkTargetBytes ) == maxLinkTargetSize {
295
+ return "" , fmt .Errorf ("link target is too large: %d bytes" , len (linkTargetBytes ))
296
+ }
297
+
298
+ return string (linkTargetBytes ), nil
299
+ }
300
+
267
301
// Insert appends the listed files into the provided Zip archive stream.
268
302
// If the filename already exists in the archive, it will be replaced.
269
303
func (z Zip ) Insert (ctx context.Context , into io.ReadWriteSeeker , files []FileInfo ) error {
0 commit comments