1414 * limitations under the License.
1515 */
1616
17+ #define _GNU_SOURCE
1718#include "cli.h"
1819#include <dirent.h>
1920#include <errno.h>
@@ -232,6 +233,42 @@ static int add_file_to_container(bfc_t* writer, const char* file_path, const cha
232233 return 0 ;
233234}
234235
236+ static int add_symlink_to_container (bfc_t * writer , const char * link_path ,
237+ const char * container_path ) {
238+ print_verbose ("Adding symlink: %s -> %s" , link_path , container_path );
239+
240+ // Read the symlink target
241+ char target [1024 ];
242+ ssize_t target_len = readlink (link_path , target , sizeof (target ) - 1 );
243+ if (target_len == -1 ) {
244+ print_error ("Cannot readlink '%s': %s" , link_path , strerror (errno ));
245+ return -1 ;
246+ }
247+ target [target_len ] = '\0' ;
248+
249+ // Get symlink stats
250+ struct stat st ;
251+ if (lstat (link_path , & st ) != 0 ) {
252+ print_error ("Cannot lstat symlink '%s': %s" , link_path , strerror (errno ));
253+ return -1 ;
254+ }
255+
256+ // Add symlink to container
257+ uint64_t mtime_ns = (uint64_t ) st .st_mtime * 1000000000ULL ;
258+ int result = bfc_add_symlink (writer , container_path , target , st .st_mode & 0777 , mtime_ns );
259+
260+ if (result != BFC_OK ) {
261+ print_error ("Failed to add symlink '%s': %s" , container_path , bfc_error_string (result ));
262+ return -1 ;
263+ }
264+
265+ if (!g_options .quiet ) {
266+ printf ("Added: %s -> %s\n" , container_path , target );
267+ }
268+
269+ return 0 ;
270+ }
271+
235272static int add_directory_to_container (bfc_t * writer , const char * dir_path ,
236273 const char * container_path );
237274
@@ -249,15 +286,17 @@ static int process_directory_entry(bfc_t* writer, const char* base_path, const c
249286 }
250287
251288 struct stat st ;
252- if (stat (full_path , & st ) != 0 ) {
253- print_error ("Cannot stat '%s': %s" , full_path , strerror (errno ));
289+ if (lstat (full_path , & st ) != 0 ) {
290+ print_error ("Cannot lstat '%s': %s" , full_path , strerror (errno ));
254291 return -1 ;
255292 }
256293
257294 if (S_ISREG (st .st_mode )) {
258295 return add_file_to_container (writer , full_path , container_path );
259296 } else if (S_ISDIR (st .st_mode )) {
260297 return add_directory_to_container (writer , full_path , container_path );
298+ } else if (S_ISLNK (st .st_mode )) {
299+ return add_symlink_to_container (writer , full_path , container_path );
261300 } else {
262301 print_verbose ("Skipping special file: %s" , full_path );
263302 return 0 ;
@@ -417,7 +456,7 @@ int cmd_create(int argc, char* argv[]) {
417456 const char * input_path = opts .input_paths [i ];
418457
419458 struct stat st ;
420- if (stat (input_path , & st ) != 0 ) {
459+ if (lstat (input_path , & st ) != 0 ) {
421460 print_error ("Cannot access '%s': %s" , input_path , strerror (errno ));
422461 bfc_close (writer );
423462 return 1 ;
@@ -448,8 +487,13 @@ int cmd_create(int argc, char* argv[]) {
448487 bfc_close (writer );
449488 return 1 ;
450489 }
490+ } else if (S_ISLNK (st .st_mode )) {
491+ if (add_symlink_to_container (writer , input_path , basename ) != 0 ) {
492+ bfc_close (writer );
493+ return 1 ;
494+ }
451495 } else {
452- print_error ("'%s' is not a regular file or directory " , input_path );
496+ print_error ("'%s' is not a regular file, directory, or symlink " , input_path );
453497 bfc_close (writer );
454498 return 1 ;
455499 }
0 commit comments