size_t comment_len (const char *path) { char infopath[MAXPATHLEN]; int f, i, r, len = 0; struct stat sb; union { struct hfs_cap_info cap; struct hfs_dbl_hdr dbl; } hdr; if (!finderinfo_path(infopath, path, &sb)) { f = open(infopath, O_RDONLY); if (f >= 0) { switch (cfg.fork) { case HFS_FORK_CAP: if (read(f, &hdr.cap, SIZEOF_HFS_CAP_INFO) == SIZEOF_HFS_CAP_INFO) len = hdr.cap.fi_comln > 200 ? 200 : hdr.cap.fi_comln; break; case HFS_FORK_NETATALK: case HFS_FORK_DOUBLE: r = read(f, &hdr.dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) break; if (ntohs(hdr.dbl.entries) > HFS_HDR_MAX) hdr.dbl.entries = htons(HFS_HDR_MAX); r = read(f, &hdr.dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)) break; for (i = 0; i < ntohs(hdr.dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (ntohl(descr->id) == HFS_HDR_COMNT) len = ntohl(descr->length) > 200 ? 200 : ntohl(descr->length); } break; } close(f); } } if (!stat(path, &sb) && !S_ISDIR(sb.st_mode)) { if (!len && cfg.comment) { len = strlen(cfg.comment); if (len > 200) len = 200; } } else { if (!len && cfg.dir_comment) { len = strlen(cfg.dir_comment); if (len > 200) len = 200; } } return len; }
size_t resource_len (const char *path) { size_t len = 0; if (cfg.fork == HFS_FORK_CAP) { char rsrcpath[MAXPATHLEN]; struct stat sb; if (!resource_path(rsrcpath, path, &sb)) len = sb.st_size; } else { /* AppleDouble */ char infopath[MAXPATHLEN]; struct hfs_dbl_hdr dbl; struct stat sb; ssize_t r; u_int16_t i; int f; if (!finderinfo_path(infopath, path, &sb)) { f = open(infopath, O_RDONLY); if (f < 0) return 0; r = read(f, &dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) goto funkdat; if (ntohs(dbl.entries) > HFS_HDR_MAX) dbl.entries = htons(HFS_HDR_MAX); r = read(f, &dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)) goto funkdat; for (i = 0; i < ntohs(dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (ntohl(descr->id) == HFS_HDR_RSRC) { len = ntohl(descr->length); break; } } funkdat: close(f); } } return len; }
int resource_open (const char *path, int mode, int perm) { if (cfg.fork == HFS_FORK_CAP) { char rsrcpath[MAXPATHLEN]; if (resource_path(rsrcpath, path, 0)) return -1; return open(rsrcpath, mode, perm); } else { /* AppleDouble */ char infopath[MAXPATHLEN]; struct hfs_dbl_hdr dbl; struct stat sb; ssize_t r; u_int16_t i; int f; if (!finderinfo_path(infopath, path, &sb)) { f = open(infopath, mode); if (f < 0) return 0; r = read(f, &dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) goto funkdat; if (ntohs(dbl.entries) > HFS_HDR_MAX) dbl.entries = htons(HFS_HDR_MAX); r = read(f, &dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)) goto funkdat; for (i = 0; i < ntohs(dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (ntohl(descr->id) == HFS_HDR_RSRC) { if (lseek(f, ntohl(descr->offset), SEEK_SET) != (off_t)ntohl(descr->offset)) goto funkdat; return f; } } funkdat: close(f); return -1; } } return -1; }
void rcv_file_delete (struct htlc_conn *htlc) { u_int16_t fnlen = 0; char dir[MAXPATHLEN], filename[NAME_MAX], oldbuf[MAXPATHLEN]; char rsrcpath_old[MAXPATHLEN]; struct stat sb, rsb; int err; dir[0] = 0; dh_start(htlc) switch (dh_type) { case HTLC_DATA_FILE_NAME: fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(filename, dh_data, fnlen); break; case HTLC_DATA_DIR: if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) { snd_strerror(htlc, err); return; } break; } dh_end() if (!fnlen && !dir[0]) { hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?"); return; } if (dir[0]) { if (fnlen) snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename); else strcpy(oldbuf, dir); } else { snprintf(oldbuf, sizeof(oldbuf), "%s/%s", ROOTDIR, filename); } if (check_dropbox(htlc, oldbuf)) { snd_strerror(htlc, EPERM); return; } if (log_delete) hxd_log("%s:%s:%u - delete %s", htlc->name, htlc->login, htlc->uid, oldbuf); if (SYS_lstat(oldbuf, &sb)) { snd_strerror(htlc, errno); return; } #if defined(CONFIG_HFS) if (!hxd_cfg.operation.hfs) goto skiphfs; if (hxd_cfg.files.fork == HFS_FORK_CAP) { if (!S_ISDIR(sb.st_mode) && !resource_path(rsrcpath_old, oldbuf, &rsb) && !S_ISDIR(rsb.st_mode)) { if (unlink(rsrcpath_old)) { snd_strerror(htlc, errno); return; } } } if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) { if (unlink(rsrcpath_old)) { snd_strerror(htlc, errno); return; } } skiphfs: #endif /* CONFIG_HFS */ if (S_ISDIR(sb.st_mode) && !S_ISLNK(sb.st_mode)) err = recursive_rmdir(oldbuf); else err = unlink(oldbuf); if (err) snd_strerror(htlc, errno); else hlwrite(htlc, HTLS_HDR_TASK, 0, 0); }
void rcv_file_symlink (struct htlc_conn *htlc) { u_int16_t fnlen = 0, newfnlen = 0; char dir[MAXPATHLEN], newdir[MAXPATHLEN], filename[NAME_MAX], newfilename[NAME_MAX], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN]; char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN]; struct stat rsb; int err; dir[0] = newdir[0] = 0; dh_start(htlc) switch (dh_type) { case HTLC_DATA_FILE_NAME: fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(filename, dh_data, fnlen); break; case HTLC_DATA_FILE_RENAME: newfnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(newfilename, dh_data, newfnlen); break; case HTLC_DATA_DIR: if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) { snd_strerror(htlc, err); return; } break; case HTLC_DATA_DIR_RENAME: if ((err = hldir_to_path(dh, ROOTDIR, newdir, newdir))) { snd_strerror(htlc, err); return; } break; } dh_end() if ((!dir[0] && !fnlen) || !newdir[0]) { hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?"); return; } if (!dir[0]) strcpy(dir, ROOTDIR); if (fnlen) { snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename); snprintf(newbuf, sizeof(newbuf), "%s/%s", newdir, newfnlen ? newfilename : filename); } else { strcpy(oldbuf, dir); strcpy(newbuf, newdir); } if (check_dropbox(htlc, oldbuf)) { snd_strerror(htlc, EPERM); return; } if (log_symlink) hxd_log("%s:%s:%u - symlink %s to %s", htlc->name, htlc->login, htlc->uid, newbuf, oldbuf); if (sys_symlink(oldbuf, newbuf)) snd_strerror(htlc, errno); else hlwrite(htlc, HTLS_HDR_TASK, 0, 0); #if defined(CONFIG_HFS) if (!hxd_cfg.operation.hfs) return; if (hxd_cfg.files.fork == HFS_FORK_CAP) { if (!resource_path(rsrcpath_old, oldbuf, &rsb)) { if ((err = resource_path(rsrcpath_new, newbuf, 0))) { /* (void)unlink(newbuf); */ snd_strerror(htlc, err); return; } else { if (sys_symlink(rsrcpath_old, rsrcpath_new)) { /* (void)unlink(newbuf); */ snd_strerror(htlc, errno); return; } } } } if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) { if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) { /* (void)unlink(newbuf); */ snd_strerror(htlc, err); return; } else { if (sys_symlink(rsrcpath_old, rsrcpath_new)) { /* (void)unlink(newbuf); */ snd_strerror(htlc, errno); return; } } } #endif /* CONFIG_HFS */ }
void rcv_file_move (struct htlc_conn *htlc) { u_int16_t fnlen = 0; char dir[MAXPATHLEN], newdir[MAXPATHLEN], filename[NAME_MAX], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN]; char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN]; struct stat sb, rsb; int err; dev_t diff_device; dir[0] = newdir[0] = 0; dh_start(htlc) switch (dh_type) { case HTLC_DATA_FILE_NAME: fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(filename, dh_data, fnlen); break; case HTLC_DATA_DIR: if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) { snd_strerror(htlc, err); return; } break; case HTLC_DATA_DIR_RENAME: if ((err = hldir_to_path(dh, ROOTDIR, newdir, newdir))) { snd_strerror(htlc, err); return; } break; } dh_end() if ((!dir[0] && !fnlen) || !newdir[0]) { hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?"); return; } if (!dir[0]) strcpy(dir, ROOTDIR); if (fnlen) { snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir, filename); snprintf(newbuf, sizeof(newbuf), "%s/%s", newdir, filename); } else { strcpy(oldbuf, dir); strcpy(newbuf, newdir); } if (check_dropbox(htlc, oldbuf) || check_dropbox(htlc, newbuf)) { snd_strerror(htlc, EPERM); return; } if (stat(oldbuf, &sb)) { snd_strerror(htlc, errno); return; } if (S_ISDIR(sb.st_mode)) { if (!htlc->access.move_folders) { snd_strerror(htlc, EPERM); return; } } else { if (!htlc->access.move_files) { snd_strerror(htlc, EPERM); return; } } if (log_move) hxd_log("%s:%s:%u - move %s to %s", htlc->name, htlc->login, htlc->uid, oldbuf, newbuf); diff_device = sb.st_dev; if (stat(newdir, &sb)) { snd_strerror(htlc, errno); return; } #if 0 /* gcc on hpux does not like this */ diff_device &= ~sb.st_dev; #else diff_device = diff_device != sb.st_dev; #endif if (diff_device ? copy_and_unlink(oldbuf, newbuf) : rename(oldbuf, newbuf)) { snd_strerror(htlc, errno); return; } #if defined(CONFIG_HFS) if (!hxd_cfg.operation.hfs) goto ret; if (hxd_cfg.files.fork == HFS_FORK_CAP) { if (!resource_path(rsrcpath_old, oldbuf, &rsb)) { if ((err = resource_path(rsrcpath_new, newbuf, 0))) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, err); return; } else { if (diff_device ? copy_and_unlink(rsrcpath_old, rsrcpath_new) : rename(rsrcpath_old, rsrcpath_new)) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, errno); return; } } } } if (!finderinfo_path(rsrcpath_old, oldbuf, &rsb)) { if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, err); return; } else { if (diff_device ? copy_and_unlink(rsrcpath_old, rsrcpath_new) : rename(rsrcpath_old, rsrcpath_new)) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, errno); return; } } } ret: #endif /* CONFIG_HFS */ hlwrite(htlc, HTLS_HDR_TASK, 0, 0); }
void rcv_file_setinfo (struct htlc_conn *htlc) { u_int16_t fnlen = 0, newfnlen = 0, comlen = 0; char dir[MAXPATHLEN], oldbuf[MAXPATHLEN], newbuf[MAXPATHLEN], filename[NAME_MAX], newfilename[NAME_MAX]; char rsrcpath_old[MAXPATHLEN], rsrcpath_new[MAXPATHLEN]; u_int8_t comment[200]; struct stat sb; int err; dir[0] = 0; dh_start(htlc) switch (dh_type) { case HTLC_DATA_FILE_NAME: fnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(filename, dh_data, fnlen); break; case HTLC_DATA_FILE_RENAME: newfnlen = dh_len >= NAME_MAX ? NAME_MAX - 1 : dh_len; read_filename(newfilename, dh_data, newfnlen); break; case HTLC_DATA_DIR: if ((err = hldir_to_path(dh, ROOTDIR, dir, dir))) { snd_strerror(htlc, err); return; } break; case HTLC_DATA_FILE_COMMENT: comlen = dh_len > 255 ? 255 : dh_len; memcpy(comment, dh_data, comlen); break; } dh_end() if (!fnlen || (!newfnlen && !comlen)) { hlwrite(htlc, HTLS_HDR_TASK, 1, 1, HTLS_DATA_TASKERROR, 6, "huh?!?"); return; } snprintf(oldbuf, sizeof(oldbuf), "%s/%s", dir[0] ? dir : ROOTDIR, filename); if (stat(oldbuf, &sb)) { snd_strerror(htlc, errno); return; } if (check_dropbox(htlc, oldbuf)) { snd_strerror(htlc, EPERM); return; } #if defined(CONFIG_HFS) if (hxd_cfg.operation.hfs && comlen) { if (S_ISDIR(sb.st_mode)) { if (!htlc->access.comment_folders) { snd_strerror(htlc, EPERM); return; } } else { if (!htlc->access.comment_files) { snd_strerror(htlc, EPERM); return; } } if (log_comment) hxd_log("%s:%s:%u - comment %s to %.*s", htlc->name, htlc->login, htlc->uid, oldbuf, comlen, comment); comment_write(oldbuf, comment, comlen); } #endif if (!newfnlen) goto ret; if (dir[0]) snprintf(newbuf, sizeof(newbuf), "%s/%s", dir, newfilename); else snprintf(newbuf, sizeof(newbuf), "%s/%s", ROOTDIR, newfilename); if (S_ISDIR(sb.st_mode)) { if (!htlc->access.rename_folders) { snd_strerror(htlc, EPERM); return; } } else { if (!htlc->access.rename_files) { snd_strerror(htlc, EPERM); return; } } if (log_rename) hxd_log("%s:%s:%u - rename %s to %s", htlc->name, htlc->login, htlc->uid, oldbuf, newbuf); if (rename(oldbuf, newbuf)) { snd_strerror(htlc, errno); return; } #if defined(CONFIG_HFS) if (!hxd_cfg.operation.hfs) goto ret; if (hxd_cfg.files.fork == HFS_FORK_CAP) { if (!resource_path(rsrcpath_old, oldbuf, &sb)) { if ((err = resource_path(rsrcpath_new, newbuf, 0))) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, err); return; } else { if (rename(rsrcpath_old, rsrcpath_new)) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, errno); return; } } } } if (!finderinfo_path(rsrcpath_old, oldbuf, &sb)) { if ((err = finderinfo_path(rsrcpath_new, newbuf, 0))) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, err); return; } else { if (rename(rsrcpath_old, rsrcpath_new)) { /* (void)rename(newbuf, oldbuf); */ snd_strerror(htlc, errno); return; } } } #endif /* CONFIG_HFS */ ret: hlwrite(htlc, HTLS_HDR_TASK, 0, 0); }
void comment_write (const char *path, char *comment, int comlen) { char infopath[MAXPATHLEN]; int f; #if 0 int i, r; #endif union { struct hfs_cap_info cap; struct hfs_dbl_hdr dbl; } hdr; if (!finderinfo_path(infopath, path, 0)) { f = open(infopath, O_RDWR|O_CREAT, cfg.file_perm); if (f >= 0) { if (comlen > 200) comlen = 200; switch (cfg.fork) { case HFS_FORK_CAP: if (read(f, &hdr.cap, SIZEOF_HFS_CAP_INFO) != SIZEOF_HFS_CAP_INFO) { memset(&hdr.cap, 0, sizeof(struct hfs_cap_info)); hdr.cap.fi_magic1 = HFS_CAP_MAGIC1; hdr.cap.fi_version = HFS_CAP_VERSION; hdr.cap.fi_magic = HFS_CAP_MAGIC; hdr.cap.fi_datemagic = HFS_CAP_DMAGIC; suffix_type_creator(hdr.cap.fi_fndr, path); } hdr.cap.fi_comln = comlen; memcpy(hdr.cap.fi_comnt, comment, comlen); lseek(f, 0, SEEK_SET); write(f, &hdr.cap, SIZEOF_HFS_CAP_INFO); break; #if 0 case HFS_FORK_NETATALK: case HFS_FORK_DOUBLE: r = read(f, &hdr.dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) break; if (ntohs(hdr.dbl.entries) > HFS_HDR_MAX) hdr.dbl.entries = htons(HFS_HDR_MAX); r = read(f, &hdr.dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)) break; for (i = 0; i < ntohs(hdr.dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (ntohl(descr->id) == HFS_HDR_COMNT) { descr->length = htonl(comlen); if (lseek(f, ntohl(descr->offset), SEEK_SET) != (off_t)ntohl(descr->offset)) continue; write(f, comment, comlen); if (lseek(f, SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * i, SEEK_SET) != (off_t)(SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * i)) continue; write(f, descr, SIZEOF_HFS_HDR_DESCR); } } break; #endif } fsync(f); close(f); } } }
void hfsinfo_write (const char *path, struct hfsinfo *fi) { char infopath[MAXPATHLEN]; #ifdef HAVE_CORESERVICES char type[5], creator[5], rpath[MAXPATHLEN]; #endif int f, i, r; union { struct hfs_cap_info cap; struct hfs_dbl_hdr dbl; } hdr; #ifdef HAVE_CORESERVICES if (!resolve_alias_path(path, rpath) || mac_errno) goto fark; memcpy(type, fi->type, 4); type[4] = 0; memcpy(creator, fi->creator, 4); creator[4] = 0; mac_set_type(rpath, type, creator); fark: #endif if (!finderinfo_path(infopath, path, 0)) { f = open(infopath, O_RDWR|O_CREAT, cfg.file_perm); if (f >= 0) { switch (cfg.fork) { case HFS_FORK_CAP: memset(&hdr.cap, 0, sizeof(struct hfs_cap_info)); hdr.cap.fi_magic1 = HFS_CAP_MAGIC1; hdr.cap.fi_version = HFS_CAP_VERSION; hdr.cap.fi_magic = HFS_CAP_MAGIC; hdr.cap.fi_datemagic = HFS_CAP_DMAGIC; hdr.cap.fi_datevalid = HFS_CAP_MDATE|HFS_CAP_CDATE; memcpy(hdr.cap.fi_fndr, fi->type, 8); memcpy(hdr.cap.fi_ctime, &fi->create_time, 8); hdr.cap.fi_comln = fi->comlen > 200 ? 200 : fi->comlen; memcpy(hdr.cap.fi_comnt, fi->comment, hdr.cap.fi_comln); write(f, &hdr.cap, SIZEOF_HFS_CAP_INFO); break; case HFS_FORK_NETATALK: case HFS_FORK_DOUBLE: r = read(f, &hdr.dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) { struct hfs_hdr_descr *descr; #define NENTRIES 4 hdr.dbl.entries = htons(NENTRIES); descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * 0]); descr->id = htonl(HFS_HDR_COMNT); descr->offset = htonl(SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * NENTRIES); descr->length = htonl(fi->comlen); descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * 1]); descr->id = htonl(HFS_HDR_DATES); descr->offset = htonl(SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * NENTRIES + fi->comlen); descr->length = htonl(8); descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * 2]); descr->id = htonl(HFS_HDR_FINFO); descr->offset = htonl(SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * NENTRIES + fi->comlen + 8); descr->length = htonl(8); descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * 3]); descr->id = htonl(HFS_HDR_RSRC); descr->offset = htonl(SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * NENTRIES + fi->comlen + 8 + 8); descr->length = htonl(0); } else { if (ntohs(hdr.dbl.entries) > HFS_HDR_MAX) hdr.dbl.entries = htons(HFS_HDR_MAX); r = read(f, &hdr.dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)) break; } for (i = 0; i < ntohs(hdr.dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (lseek(f, ntohl(descr->offset), SEEK_SET) != (off_t)ntohl(descr->offset)) continue; switch (ntohl(descr->id)) { case HFS_HDR_COMNT: if (r == SIZEOF_HFS_DBL_HDR) break; descr->length = htonl(fi->comlen); write(f, fi->comment, fi->comlen); break; case HFS_HDR_OLDI: case HFS_HDR_DATES: if (descr->length < 8) descr->length = 8; write(f, &fi->create_time, 8); break; case HFS_HDR_FINFO: if (descr->length < 8) descr->length = 8; write(f, fi->type, 8); break; case HFS_HDR_RSRC: descr->length = htonl(fi->rsrclen); break; } } hdr.dbl.magic = htonl(HFS_DBL_MAGIC); if (cfg.fork == HFS_FORK_NETATALK) hdr.dbl.version = htonl(HFS_HDR_VERSION_1); else hdr.dbl.version = htonl(HFS_HDR_VERSION_2); lseek(f, 0, SEEK_SET); write(f, &hdr.dbl, SIZEOF_HFS_DBL_HDR + SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)); break; } fsync(f); close(f); } } }
void hfsinfo_read (const char *path, struct hfsinfo *fi) { char infopath[MAXPATHLEN]; #ifdef HAVE_CORESERVICES char type[5], creator[5]; char rpath[MAXPATHLEN]; #endif int f, i, r; struct stat sb; union { struct hfs_cap_info cap; struct hfs_dbl_hdr dbl; } hdr; memset(fi, 0, sizeof(struct hfsinfo)); if (!finderinfo_path(infopath, path, &sb)) { f = open(infopath, O_RDONLY); if (f >= 0) { switch (cfg.fork) { case HFS_FORK_CAP: r = read(f, &hdr.cap, SIZEOF_HFS_CAP_INFO); if (r != SIZEOF_HFS_CAP_INFO) break; memcpy(fi->type, hdr.cap.fi_fndr, 8); if (hdr.cap.fi_datevalid & HFS_CAP_CDATE) memcpy(&fi->create_time, hdr.cap.fi_ctime, 4); else fi->create_time = 0; if (hdr.cap.fi_datevalid & HFS_CAP_MDATE) memcpy(&fi->modify_time, hdr.cap.fi_mtime, 4); else fi->modify_time = 0; fi->comlen = hdr.cap.fi_comln > 200 ? 200 : hdr.cap.fi_comln; memcpy(fi->comment, hdr.cap.fi_comnt, fi->comlen); break; case HFS_FORK_NETATALK: case HFS_FORK_DOUBLE: r = read(f, &hdr.dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) break; if (ntohs(hdr.dbl.entries) > HFS_HDR_MAX) hdr.dbl.entries = htons(HFS_HDR_MAX); r = read(f, &hdr.dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(hdr.dbl.entries)) break; for (i = 0; i < ntohs(hdr.dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&hdr.dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (lseek(f, ntohl(descr->offset), SEEK_SET) != (off_t)ntohl(descr->offset)) continue; switch (ntohl(descr->id)) { case HFS_HDR_COMNT: fi->comlen = ntohl(descr->length) > 200 ? 200 : ntohl(descr->length); r = read(f, fi->comment, fi->comlen); if (r != (int)fi->comlen) fi->comlen = 0; break; case HFS_HDR_OLDI: case HFS_HDR_DATES: r = read(f, &fi->create_time, 8); if (r != 8) fi->create_time = fi->modify_time = 0; break; case HFS_HDR_FINFO: r = read(f, fi->type, 8); if (r != 8) memset(fi->type, 0, 8); break; case HFS_HDR_RSRC: fi->rsrclen = ntohl(descr->length); break; } } break; } close(f); } } if (!(*(u_int32_t *)(&fi->type[0])) || !(*(u_int32_t *)(&fi->type[4]))) suffix_type_creator(fi->type, path); #ifdef HAVE_CORESERVICES if (!resolve_alias_path(path, rpath) || mac_errno) goto fark; if (mac_get_type(path, type, creator) || mac_errno) goto fark; if (strcmp(type, "????") || strcmp(creator, "????")) { memcpy(fi->type, type, 4); memcpy(fi->creator, creator, 4); } fark: #endif if (!fi->create_time || !fi->modify_time) { if (!stat(path, &sb)) { u_int32_t htime = hfs_u_to_htime(sb.st_mtime); if (!fi->create_time) fi->create_time = htime; if (!fi->modify_time) fi->modify_time = htime; } } if (!stat(path, &sb) && !S_ISDIR(sb.st_mode)) { if (!fi->comlen && cfg.comment) { fi->comlen = strlen(cfg.comment); if (fi->comlen > 200) fi->comlen = 200; memcpy(fi->comment, cfg.comment, fi->comlen); } } else { if (!fi->comlen && cfg.dir_comment) { fi->comlen = strlen(cfg.dir_comment); if (fi->comlen > 200) fi->comlen = 200; memcpy(fi->comment, cfg.dir_comment, fi->comlen); } } }
void type_creator (u_int8_t *buf, const char *path) { char infopath[MAXPATHLEN]; struct stat sb; u_int8_t is_link = 0; #ifdef HAVE_CORESERVICES if (!resolve_alias_path(path, infopath) || mac_errno) return; if (is_alias(infopath, &is_link) || mac_errno) return; if (is_link) strcpy(buf, "alis"); else { char type[5], creator[5]; if (!mac_get_type(infopath, type, creator) && !mac_errno) { memcpy(buf, type, 4); memcpy(buf + 4, creator, 4); } } if (memcmp(buf, "????????", 8)) return; #endif if (!finderinfo_path(infopath, path, &sb)) { int r, f; f = open(infopath, O_RDONLY); if (f < 0) goto use_suffix; switch (cfg.fork) { default: case HFS_FORK_CAP: r = read(f, buf, 8); if (r != 8 || !(*(u_int32_t *)(&buf[0])) || !(*(u_int32_t *)(&buf[4]))) r = 0; break; case HFS_FORK_NETATALK: case HFS_FORK_DOUBLE: { struct hfs_dbl_hdr dbl; int i; r = read(f, &dbl, SIZEOF_HFS_DBL_HDR); if (r != SIZEOF_HFS_DBL_HDR) { r = -1; break; } if (ntohs(dbl.entries) > HFS_HDR_MAX) dbl.entries = htons(HFS_HDR_MAX); r = read(f, &dbl.descrs, SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)); if (r != SIZEOF_HFS_HDR_DESCR * ntohs(dbl.entries)) { r = -1; break; } for (i = 0; i < ntohs(dbl.entries); i++) { struct hfs_hdr_descr *descr = (struct hfs_hdr_descr *)(&dbl.descrs[SIZEOF_HFS_HDR_DESCR * i]); if (ntohl(descr->id) == HFS_HDR_FINFO) { if (lseek(f, ntohl(descr->offset), SEEK_SET) != (off_t)ntohl(descr->offset)) continue; r = 8; r = read(f, buf, 8); break; } } } break; } close(f); if (r == 8) return; } use_suffix: suffix_type_creator(buf, path); }