@@ -236,20 +236,28 @@ static int copy_file(const char *src, const char *dst, int mode)
236236 return ret ;
237237}
238238
239- static int stat_src (const char * path , int * type , int * mode )
239+ static int stat_src (const char * path , int * type , int * mode , int * size )
240240{
241241 struct stat stat ;
242242 struct lkl_stat lkl_stat ;
243243 int ret ;
244244
245245 if (cptofs ) {
246246 ret = lstat (path , & stat );
247- * type = stat .st_mode & S_IFMT ;
248- * mode = stat .st_mode & ~S_IFMT ;
247+ if (type )
248+ * type = stat .st_mode & S_IFMT ;
249+ if (mode )
250+ * mode = stat .st_mode & ~S_IFMT ;
251+ if (size )
252+ * size = stat .st_size ;
249253 } else {
250254 ret = lkl_sys_lstat (path , & lkl_stat );
251- * type = lkl_stat .st_mode & S_IFMT ;
252- * mode = lkl_stat .st_mode & ~S_IFMT ;
255+ if (type )
256+ * type = lkl_stat .st_mode & S_IFMT ;
257+ if (mode )
258+ * mode = lkl_stat .st_mode & ~S_IFMT ;
259+ if (size )
260+ * size = lkl_stat .st_size ;
253261 }
254262
255263 if (ret )
@@ -280,6 +288,79 @@ static int mkdir_dst(const char *path, int mode)
280288 return ret ;
281289}
282290
291+ static int readlink_src (const char * src , char * out , int outsize )
292+ {
293+ int ret ;
294+
295+ if (cptofs )
296+ ret = readlink (src , out , outsize );
297+ else
298+ ret = lkl_sys_readlink (src , out , outsize );
299+
300+ if (ret < 0 )
301+ fprintf (stderr , "unable to readlink '%s': %s\n" , src ,
302+ cptofs ? strerror (errno ) : lkl_strerror (ret ));
303+
304+ return ret ;
305+ }
306+
307+ static int symlink_dst (const char * path , const char * target )
308+ {
309+ int ret ;
310+
311+ if (cptofs )
312+ ret = lkl_sys_symlink (target , path );
313+ else
314+ ret = symlink (target , path );
315+
316+ if (ret )
317+ fprintf (stderr , "unable to symlink '%s' with target '%s': %s\n" ,
318+ path , target , cptofs ? lkl_strerror (ret ) :
319+ strerror (errno ));
320+
321+ return ret ;
322+ }
323+
324+ static int copy_symlink (const char * src , const char * dst )
325+ {
326+ int ret ;
327+ int size ;
328+ char * target = NULL ;
329+
330+ ret = stat_src (src , NULL , NULL , & size );
331+ if (ret ) {
332+ ret = -1 ;
333+ goto out ;
334+ }
335+
336+ target = malloc (size + 1 );
337+ if (!target ) {
338+ fprintf (stderr , "Unable to allocate memory (%d bytes)\n" ,
339+ size + 1 );
340+ ret = -1 ;
341+ goto out ;
342+ }
343+
344+ ret = readlink_src (src , target , size );
345+ if (ret != size ) {
346+ fprintf (stderr , "readlink(%s) bad size: got %d, expected %d\n" ,
347+ src , ret , size );
348+ ret = -1 ;
349+ goto out ;
350+ }
351+ target [size ] = 0 ; // readlink doesn't append the trailing null byte
352+
353+ ret = symlink_dst (dst , target );
354+ if (ret )
355+ ret = -1 ;
356+
357+ out :
358+ if (target )
359+ free (target );
360+
361+ return ret ;
362+ }
363+
283364static int do_entry (const char * _src , const char * _dst , const char * name )
284365{
285366 char src [PATH_MAX ], dst [PATH_MAX ];
@@ -289,7 +370,7 @@ static int do_entry(const char *_src, const char *_dst, const char *name)
289370 snprintf (src , sizeof (src ), "%s/%s" , _src , name );
290371 snprintf (dst , sizeof (dst ), "%s/%s" , _dst , name );
291372
292- ret = stat_src (src , & type , & mode );
373+ ret = stat_src (src , & type , & mode , NULL );
293374
294375 switch (type ) {
295376 case S_IFREG :
@@ -304,6 +385,8 @@ static int do_entry(const char *_src, const char *_dst, const char *name)
304385 ret = searchdir (src , dst , NULL );
305386 break ;
306387 case S_IFLNK :
388+ ret = copy_symlink (src , dst );
389+ break ;
307390 case S_IFSOCK :
308391 case S_IFBLK :
309392 case S_IFCHR :
0 commit comments