ObjFW  Check-in [6146e60fc5]

Overview
Comment:Implement extended attributes on Haiku

Also disables hard links as those don't work on Haiku.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 6146e60fc517a80066a16f6e52dc1d0cf2ebbcdc0adfa45f37dd977bf1e5aa17
User & Date: js on 2024-04-03 01:10:16
Other Links: manifest | tags
Context
2024-04-03
02:16
Change license to LGPLv3 only check-in: 7413a728a7 user: js tags: trunk
01:10
Implement extended attributes on Haiku check-in: 6146e60fc5 user: js tags: trunk
2024-04-02
22:05
Fix another, new linker warning on macOS check-in: 6e6bb54df3 user: js tags: trunk
Changes

Modified src/OFFileIRIHandler.m from [b3f1e2319f] to [f57643608d].

31
32
33
34
35
36
37



38
39
40
41
42
43
44
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/time.h>
#if defined(OF_LINUX) || defined(OF_MACOS)
# include <sys/xattr.h>
#endif



#ifdef OF_WINDOWS
# include <utime.h>
#endif
#ifdef OF_DJGPP
# include <syslimits.h>
#endif








>
>
>







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#include <sys/time.h>
#if defined(OF_LINUX) || defined(OF_MACOS)
# include <sys/xattr.h>
#endif
#ifdef OF_HAIKU
# include <kernel/fs_attr.h>
#endif
#ifdef OF_WINDOWS
# include <utime.h>
#endif
#ifdef OF_DJGPP
# include <syslimits.h>
#endif

583
584
585
586
587
588
589

590

591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623


624


















625
626
627
628
629
630
631
#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
static void
setExtendedAttributes(OFMutableFileAttributes attributes, OFIRI *IRI)
{
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];

# if defined(OF_LINUX)

	ssize_t size = llistxattr(cPath, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = listxattr(cPath, NULL, 0, XATTR_NOFOLLOW);
# endif
	char *list = OFAllocMemory(1, size);
	OFMutableArray *names = nil;

	@try {
		char *name;

# if defined(OF_LINUX)
		if ((size = llistxattr(cPath, list, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = listxattr(cPath, list, size, XATTR_NOFOLLOW)) < 0)
# endif
			return;

		names = [OFMutableArray array];
		name = list;

		while (size > 0) {
			size_t length = strlen(name);

			[names addObject: [OFString stringWithCString: name
							     encoding: encoding
							       length: length]];

			name += length + 1;
			size -= length + 1;
		}
	} @finally {
		OFFreeMemory(list);
	}





















	[attributes setObject: names forKey: OFFileExtendedAttributesNames];
}
#endif

@implementation OFFileIRIHandler
+ (void)initialize
{







>
|
>

|

|

<




|

|

|


















>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600

601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
#ifdef OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
static void
setExtendedAttributes(OFMutableFileAttributes attributes, OFIRI *IRI)
{
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	OFMutableArray *names = nil;
# if defined(OF_LINUX) || defined(OF_MACOS)
#  if defined(OF_LINUX)
	ssize_t size = llistxattr(cPath, NULL, 0);
#  elif defined(OF_MACOS)
	ssize_t size = listxattr(cPath, NULL, 0, XATTR_NOFOLLOW);
#  endif
	char *list = OFAllocMemory(1, size);


	@try {
		char *name;

#  if defined(OF_LINUX)
		if ((size = llistxattr(cPath, list, size)) < 0)
#  elif defined(OF_MACOS)
		if ((size = listxattr(cPath, list, size, XATTR_NOFOLLOW)) < 0)
#  endif
			return;

		names = [OFMutableArray array];
		name = list;

		while (size > 0) {
			size_t length = strlen(name);

			[names addObject: [OFString stringWithCString: name
							     encoding: encoding
							       length: length]];

			name += length + 1;
			size -= length + 1;
		}
	} @finally {
		OFFreeMemory(list);
	}
# elif defined(OF_HAIKU)
	DIR *dir = fs_open_attr_dir(cPath);

	if (dir == NULL)
		return;

	@try {
		struct dirent *dirent;

		names = [OFMutableArray array];

		while ((dirent = fs_read_attr_dir(dir)) != NULL)
			[names addObject:
			    [OFString stringWithCString: dirent->d_name
					       encoding: encoding]];
	} @finally {
		fs_close_attr_dir(dir);
	}
# endif

	[names makeImmutable];
	[attributes setObject: names forKey: OFFileExtendedAttributesNames];
}
#endif

@implementation OFFileIRIHandler
+ (void)initialize
{
1591
1592
1593
1594
1595
1596
1597


1598

1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623



1624
1625
1626




































1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641



1642
1643
1644
1645

1646
1647
1648


1649









1650


1651

1652
1653
1654
1655
1656
1657
1658
1659
1660




















1661
1662
1663
1664
1665
1666
1667
1668
1669
1670


1671
1672

1673
1674
1675
1676
1677
1678













1679
1680
1681
1682
1683
1684
1685
1686
1687



















1688
1689
1690
1691
1692
			     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];


# if defined(OF_LINUX)

	ssize_t size = lgetxattr(cPath, cName, NULL, 0);
# elif defined(OF_MACOS)
	ssize_t size = getxattr(cPath, cName, NULL, 0, 0, XATTR_NOFOLLOW);
# endif
	void *value;
	OFData *data;

	if (size < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	value = OFAllocMemory(1, size);
	@try {
# if defined(OF_LINUX)
		if ((size = lgetxattr(cPath, cName, value, size)) < 0)
# elif defined(OF_MACOS)
		if ((size = getxattr(cPath, cName, value, size, 0,
		    XATTR_NOFOLLOW)) < 0)
# endif
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		data = [OFData dataWithItems: value count: size];



	} @finally {
		OFFreeMemory(value);
	}





































	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];




# if defined(OF_LINUX)
	if (lsetxattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], data.items,

	    data.count * data.itemSize, 0) != 0) {
# elif defined(OF_MACOS)
	if (setxattr([path cStringWithEncoding: encoding],


	    [name cStringWithEncoding: encoding], data.items,









	    data.count * data.itemSize, 0, XATTR_NOFOLLOW) != 0) {


# endif

		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}





















	objc_autoreleasePoolPop(pool);
}

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];



# if defined(OF_LINUX)

	if (lremovexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding]) != 0) {
# elif defined(OF_MACOS)
	if (removexattr([path cStringWithEncoding: encoding],
	    [name cStringWithEncoding: encoding], XATTR_NOFOLLOW) != 0) {
# endif













		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}




















	objc_autoreleasePoolPop(pool);
}
#endif
@end







>
>
|
>

|

|
<
<








|

|


|




|
>
>
>



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>















>
>
>

|
<
<
>
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
|
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
>

|
>
|
<
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629


1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710


1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776

1777

1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
			     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];
	void *value = NULL;
	OFData *data;
# if defined(OF_LINUX) || defined(OF_MACOS)
#  if defined(OF_LINUX)
	ssize_t size = lgetxattr(cPath, cName, NULL, 0);
#  elif defined(OF_MACOS)
	ssize_t size = getxattr(cPath, cName, NULL, 0, 0, XATTR_NOFOLLOW);
#  endif



	if (size < 0)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	value = OFAllocMemory(1, size);
	@try {
#  if defined(OF_LINUX)
		if ((size = lgetxattr(cPath, cName, value, size)) < 0)
#  elif defined(OF_MACOS)
		if ((size = getxattr(cPath, cName, value, size, 0,
		    XATTR_NOFOLLOW)) < 0)
#  endif
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		data = [OFData dataWithItemsNoCopy: value
					     count: size
				      freeWhenDone: true];
		value = NULL;
	} @finally {
		OFFreeMemory(value);
	}
# elif defined(OF_HAIKU)
	int fd = open(cPath, O_RDONLY);
	struct attr_info info;

	if (fd == -1)
		@throw [OFGetItemAttributesFailedException
		    exceptionWithIRI: IRI
			       errNo: errno];

	@try {
		if (fs_stat_attr(fd, cName, &info) != 0)
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		if (info.size < 0 || info.size > SSIZE_MAX)
			@throw [OFOutOfRangeException exception];

		value = OFAllocMemory(1, (size_t)info.size);

		errno = 0;
		if (fs_read_attr(fd, cName, B_ANY_TYPE, 0, value,
		    (size_t)info.size) != (ssize_t)info.size)
			@throw [OFGetItemAttributesFailedException
			    exceptionWithIRI: IRI
				       errNo: errno];

		data = [OFData dataWithItemsNoCopy: value
					     count: (size_t)info.size
				      freeWhenDone: true];
		value = NULL;
	} @finally {
		OFFreeMemory(value);
		close(fd);
	}
# endif

	[data retain];

	objc_autoreleasePoolPop(pool);

	return [data autorelease];
}

- (void)setExtendedAttributeData: (OFData *)data
			 forName: (OFString *)name
		     ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];
	size_t size = data.count * data.itemSize;

# if defined(OF_LINUX) || defined(OFMACOS)


#  if defined(OF_LINUX)
	if (lsetxattr(cPath, cName, data.items, size, 0) != 0) {
#  elif defined(OF_MACOS)
	if (setxattr(cPath, cName, data.items, size, 0, XATTR_NOFOLLOW) != 0) {
#  endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}
# elif defined(OF_HAIKU)
	int fd;

	if (size > SSIZE_MAX)
		@throw [OFOutOfRangeException exception];

	if ((fd = open(cPath, O_WRONLY)) == -1) {
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	@try {
		if (fs_write_attr(fd, cName, B_RAW_TYPE, 0, data.items, size) !=
		    (ssize_t)size) {
			int errNo = errno;

			/*
			 * TODO: Add an attribute (prefix?) for extended
			 *	 attributes?
			 */
			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: [OFDictionary dictionary]
			     failedAttribute: @""
				       errNo: errNo];
		}
	} @finally {
		close(fd);
	}
# endif

	objc_autoreleasePoolPop(pool);
}

- (void)removeExtendedAttributeForName: (OFString *)name
			   ofItemAtIRI: (OFIRI *)IRI
{
	void *pool = objc_autoreleasePoolPush();
	OFString *path = IRI.fileSystemRepresentation;
	OFStringEncoding encoding = [OFLocale encoding];
	const char *cPath = [path cStringWithEncoding: encoding];
	const char *cName = [name cStringWithEncoding: encoding];

# if defined(OF_LINUX) || defined(OF_MACOS)
#  if defined(OF_LINUX)
	if (lremovexattr(cPath, cName) != 0) {

#  elif defined(OF_MACOS)

	if (removexattr(cPath, cName, XATTR_NOFOLLOW) != 0) {
#  endif
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}
# elif defined(OF_HAIKU)
	int fd;

	if ((fd = open(cPath, O_WRONLY)) == -1) {
		int errNo = errno;

		/* TODO: Add an attribute (prefix?) for extended attributes? */
		@throw [OFSetItemAttributesFailedException
		    exceptionWithIRI: IRI
			  attributes: [OFDictionary dictionary]
		     failedAttribute: @""
			       errNo: errNo];
	}

	@try {
		if (fs_remove_attr(fd, cName) != 0) {
			int errNo = errno;

			/*
			 * TODO: Add an attribute (prefix?) for extended
			 *	 attributes?
			 */
			@throw [OFSetItemAttributesFailedException
			    exceptionWithIRI: IRI
				  attributes: [OFDictionary dictionary]
			     failedAttribute: @""
				       errNo: errNo];
		}
	} @finally {
		close(fd);
	}
# endif

	objc_autoreleasePoolPop(pool);
}
#endif
@end

Modified src/OFFileManager.h from [e4f59a6817] to [cfcf38ef14].

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
#ifdef OF_HAVE_FILES
# if (defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
# endif
# if (defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_OWNER
# endif
# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) || \
    defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_LINKS
# endif
# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || \
    defined(OF_WINDOWS) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_SYMLINKS
# endif
# if defined(OF_LINUX) || defined(OF_MACOS) || defined(DOXYGEN)

#  define OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
# endif
#endif

@class OFArray OF_GENERIC(ObjectType);
@class OFConstantString;
@class OFDate;







|
|






|
>







23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifdef OF_HAVE_FILES
# if (defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
# endif
# if (defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS)) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_OWNER
# endif
# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS) && !defined(OF_HAIKU)) || \
    defined(OF_WINDOWS) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_LINKS
# endif
# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || \
    defined(OF_WINDOWS) || defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_SYMLINKS
# endif
# if defined(OF_LINUX) || defined(OF_MACOS) ||defined(OF_HAIKU) || \
    defined(DOXYGEN)
#  define OF_FILE_MANAGER_SUPPORTS_EXTENDED_ATTRIBUTES
# endif
#endif

@class OFArray OF_GENERIC(ObjectType);
@class OFConstantString;
@class OFDate;