diff options
| -rw-r--r-- | doc/gensquashfs.1 | 3 | ||||
| -rw-r--r-- | include/tar.h | 1 | ||||
| -rw-r--r-- | lib/fstree/fstree_from_file.c | 14 | ||||
| -rw-r--r-- | lib/tar/read_header.c | 3 | ||||
| -rw-r--r-- | mkfs/options.c | 3 | ||||
| -rw-r--r-- | tar/tar2sqfs.c | 15 | 
6 files changed, 34 insertions, 5 deletions
diff --git a/doc/gensquashfs.1 b/doc/gensquashfs.1 index 04dd968..0de39bf 100644 --- a/doc/gensquashfs.1 +++ b/doc/gensquashfs.1 @@ -105,6 +105,7 @@ file <path> <mode> <uid> <gid> [<location>]  dir <path> <mode> <uid> <gid>  nod <path> <mode> <uid> <gid> <dev_type> <maj> <min>  slink <path> <mode> <uid> <gid> <target> +link <path> <dummy> <dummy> <dummy> <target>  pipe <path> <mode> <uid> <gid>  sock <path> <mode> <uid> <gid>  .fi @@ -131,7 +132,7 @@ Optional location of the input file. Can be specified relative to either the  description file or the pack directory. If omitted, the image path is used  as a relative path.  T} -<target>;Symlink target. +<target>;Symlink or hardlink target.  <mode>;Mode/permissions of the entry.  <uid>;Numeric user id.  <gid>;Numeric group id. diff --git a/include/tar.h b/include/tar.h index 22563c4..617148f 100644 --- a/include/tar.h +++ b/include/tar.h @@ -84,6 +84,7 @@ typedef struct {  	sqfs_u64 actual_size;  	sqfs_u64 record_size;  	bool unknown_record; +	bool is_hard_link;  	tar_xattr_t *xattr;  	/* broken out since struct stat could contain diff --git a/lib/fstree/fstree_from_file.c b/lib/fstree/fstree_from_file.c index 9cdf9a1..bf11755 100644 --- a/lib/fstree/fstree_from_file.c +++ b/lib/fstree/fstree_from_file.c @@ -62,6 +62,19 @@ static int add_file(fstree_t *fs, const char *filename, size_t line_num,  	return add_generic(fs, filename, line_num, path, basic, extra);  } +static int add_hard_link(fstree_t *fs, const char *filename, size_t line_num, +			 const char *path, struct stat *basic, const char *extra) +{ +	(void)basic; + +	if (fstree_add_hard_link(fs, path, extra) == NULL) { +		fprintf(stderr, "%s: " PRI_SZ ": %s\n", +			filename, line_num, strerror(errno)); +		return -1; +	} +	return 0; +} +  static const struct {  	const char *keyword;  	unsigned int mode; @@ -71,6 +84,7 @@ static const struct {  } file_list_hooks[] = {  	{ "dir", S_IFDIR, false, add_generic },  	{ "slink", S_IFLNK, true, add_generic }, +	{ "link", 0, true, add_hard_link },  	{ "nod", 0, true, add_device },  	{ "pipe", S_IFIFO, false, add_generic },  	{ "sock", S_IFSOCK, false, add_generic }, diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c index 7d209ae..f82f9a5 100644 --- a/lib/tar/read_header.c +++ b/lib/tar/read_header.c @@ -345,8 +345,7 @@ static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax,  		out->sb.st_mode |= S_IFREG;  		break;  	case TAR_TYPE_LINK: -		/* XXX: hard links are not support yet */ -		out->sb.st_mode = S_IFLNK | 0777; +		out->is_hard_link = true;  		break;  	case TAR_TYPE_SLINK:  		out->sb.st_mode = S_IFLNK | 0777; diff --git a/mkfs/options.c b/mkfs/options.c index 39ecdc7..fd6ca46 100644 --- a/mkfs/options.c +++ b/mkfs/options.c @@ -112,6 +112,7 @@ const char *help_details =  "dir <path> <mode> <uid> <gid>\n"  "nod <path> <mode> <uid> <gid> <dev_type> <maj> <min>\n"  "slink <path> <mode> <uid> <gid> <target>\n" +"link <path> <dummy> <dummy> <dummy> <target>\n"  "pipe <path> <mode> <uid> <gid>\n"  "sock <path> <mode> <uid> <gid>\n"  "\n" @@ -120,7 +121,7 @@ const char *help_details =  "<location>   If given, location of the input file. Either absolute or relative\n"  "             to the description file. If omitted, the image path is used,\n"  "             relative to the description file.\n" -"<target>     Symlink target.\n" +"<target>     Symlink or hardlink target.\n"  "<mode>       Mode/permissions of the entry.\n"  "<uid>        Numeric user id.\n"  "<gid>        Numeric group id.\n" diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c index 63933eb..f522239 100644 --- a/tar/tar2sqfs.c +++ b/tar/tar2sqfs.c @@ -355,6 +355,19 @@ static int create_node_and_repack_data(tar_header_decoded_t *hdr)  {  	tree_node_t *node; +	if (hdr->is_hard_link) { +		node = fstree_add_hard_link(&sqfs.fs, hdr->name, +					    hdr->link_target); +		if (node == NULL) +			goto fail_errno; + +		if (!cfg.quiet) { +			printf("Hard link %s -> %s\n", hdr->name, +			       hdr->link_target); +		} +		return 0; +	} +  	if (!keep_time) {  		hdr->sb.st_mtime = sqfs.fs.defaults.st_mtime;  	} @@ -385,7 +398,7 @@ fail_errno:  static int set_root_attribs(const tar_header_decoded_t *hdr)  { -	if (!S_ISDIR(hdr->sb.st_mode)) { +	if (hdr->is_hard_link || !S_ISDIR(hdr->sb.st_mode)) {  		fprintf(stderr, "'%s' is not a directory!\n", hdr->name);  		return -1;  	}  | 
