AD_DEV, AD_INO, AD_SYN, AD_ID
};
+static char empty_resourcefork[] = {
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E,
+ 0x54, 0x68, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73,
+ 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x66, 0x6F,
+ 0x72, 0x6B, 0x20, 0x69, 0x6E, 0x74, 0x65, 0x6E,
+ 0x74, 0x69, 0x6F, 0x6E, 0x61, 0x6C, 0x6C, 0x79,
+ 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x62, 0x6C,
+ 0x61, 0x6E, 0x6B, 0x20, 0x20, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1C, 0x00, 0x1E, 0xFF, 0xFF
+};
+
struct fio {
/* tcon config handle */
struct fruit_config_data *config;
return true;
}
+static bool ad_convert_blank_rfork(struct adouble *ad,
+ bool *blank)
+{
+ struct fruit_config_data *config = NULL;
+ uint8_t *map = MAP_FAILED;
+ size_t maplen;
+ int cmp;
+ ssize_t len;
+ int rc;
+ bool ok;
+
+ *blank = false;
+
+ SMB_VFS_HANDLE_GET_DATA(ad->ad_handle, config,
+ struct fruit_config_data, return false);
+
+ if (!config->wipe_intentionally_left_blank_rfork) {
+ return true;
+ }
+
+ if (ad_getentrylen(ad, ADEID_RFORK) != sizeof(empty_resourcefork)) {
+ return true;
+ }
+
+ maplen = ad_getentryoff(ad, ADEID_RFORK) +
+ ad_getentrylen(ad, ADEID_RFORK);
+
+ /* FIXME: direct use of mmap(), vfs_aio_fork does it too */
+ map = mmap(NULL, maplen, PROT_READ|PROT_WRITE, MAP_SHARED,
+ ad->ad_fd, 0);
+ if (map == MAP_FAILED) {
+ DBG_ERR("mmap AppleDouble: %s\n", strerror(errno));
+ return false;
+ }
+
+ cmp = memcmp(map + ADEDOFF_RFORK_DOT_UND,
+ empty_resourcefork,
+ sizeof(empty_resourcefork));
+ rc = munmap(map, maplen);
+ if (rc != 0) {
+ DBG_ERR("munmap failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ if (cmp != 0) {
+ return true;
+ }
+
+ ad_setentrylen(ad, ADEID_RFORK, 0);
+
+ ok = ad_pack(ad);
+ if (!ok) {
+ return false;
+ }
+
+ len = sys_pwrite(ad->ad_fd, ad->ad_data, AD_DATASZ_DOT_UND, 0);
+ if (len != AD_DATASZ_DOT_UND) {
+ return false;
+ }
+
+ *blank = true;
+ return true;
+}
+
/**
* Convert from Apple's ._ file to Netatalk
*
{
bool ok;
bool converted_xattr = false;
+ bool blank;
ok = ad_convert_xattr(ad, smb_fname, &converted_xattr);
if (!ok) {
return -1;
}
- if (converted_xattr) {
+ ok = ad_convert_blank_rfork(ad, &blank);
+ if (!ok) {
+ return -1;
+ }
+
+ if (converted_xattr || blank) {
ok = ad_convert_truncate(ad, smb_fname);
if (!ok) {
return -1;