static int FuseHFS_setcrtime (const char *path, const struct timespec *tv) { dprintf("setcrtime %s\n", path); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; int err; // get file info hfsdirent ent; if (hfs_stat(NULL, hfspath, &ent) == 0) { ent.crdate = tv->tv_sec; err = hfs_setattr(NULL, hfspath, &ent); free(hfspath); if (!err) return 0; perror("hfs_setattr"); return -errno; } free(hfspath); perror("hfs_stat"); return -errno; }
static int FuseHFS_setxattr(const char *path, const char *name, const char *value, size_t size, int flags, uint32_t position) { dprintf("setxattr %s %s %p %lu %02x %u\n", path, name, value, size, flags, position); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // find file hfsdirent ent; if (hfs_stat(NULL, hfspath, &ent) == -1) { free(hfspath); return -ENOENT; } if (strcmp(name, XATTR_FINDERINFO_NAME) == 0) { if (size != 32) { dprintf("setxattr: finder info is not 32 bytes\n"); free(hfspath); return -ERANGE; } // write finder info to dirent if (ent.flags & HFS_ISDIR) { // directory ent.u.dir.rect.top = OSReadBigInt16(value, 0); ent.u.dir.rect.left = OSReadBigInt16(value, 2); ent.u.dir.rect.bottom = OSReadBigInt16(value, 4); ent.u.dir.rect.right = OSReadBigInt16(value, 6); ent.fdflags = OSReadBigInt16(value, 8); ent.fdlocation.v = OSReadBigInt16(value, 10); ent.fdlocation.h = OSReadBigInt16(value, 12); ent.u.dir.view = OSReadBigInt16(value, 14); // DXInfo ((DXInfo*)(ent.u.dir.xinfo))->frScroll.v = OSReadBigInt16(value, 16); ((DXInfo*)(ent.u.dir.xinfo))->frScroll.h = OSReadBigInt16(value, 18); ((DXInfo*)(ent.u.dir.xinfo))->frOpenChain = OSReadBigInt32(value, 20); ((DXInfo*)(ent.u.dir.xinfo))->frUnused = OSReadBigInt16(value, 24); ((DXInfo*)(ent.u.dir.xinfo))->frComment = OSReadBigInt16(value, 26); ((DXInfo*)(ent.u.dir.xinfo))->frPutAway = OSReadBigInt32(value, 28); } else { // regular file memcpy(ent.u.file.type, value, 4); memcpy(ent.u.file.creator, value+4, 4); ent.u.file.type[4] = ent.u.file.type[4] = '\0'; ent.fdflags = OSReadBigInt16(value, 8); ent.fdlocation.v = OSReadBigInt16(value, 10); ent.fdlocation.h = OSReadBigInt16(value, 12); ent.u.file.window = OSReadBigInt16(value, 14); // FXInfo ((FXInfo*)(ent.u.file.xinfo))->fdIconID = OSReadBigInt16(value, 16); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[0] = OSReadBigInt16(value, 18); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[1] = OSReadBigInt16(value, 20); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[2] = OSReadBigInt16(value, 22); ((FXInfo*)(ent.u.file.xinfo))->fdUnused[3] = OSReadBigInt16(value, 24); ((FXInfo*)(ent.u.file.xinfo))->fdComment = OSReadBigInt16(value, 26); ((FXInfo*)(ent.u.file.xinfo))->fdPutAway = OSReadBigInt32(value, 28); // bless parent folder if it's a system file if ((strcmp(ent.u.file.type, "zsys") == 0) && (strcmp(ent.u.file.creator, "MACS") == 0) && (strcmp(ent.name, "System") == 0)) { // bless dprintf("setxattr: blessing folder %lu\n", ent.parid); hfsvolent volent; hfs_vstat(NULL, &volent); volent.blessed = ent.parid; hfs_vsetattr(NULL, &volent); } } // update file hfs_setattr(NULL, hfspath, &ent); free(hfspath); return 0; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR))) { // resource fork // TODO: how are resource forks truncated? hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, position, SEEK_SET); hfs_write(fp, value, size); hfs_close(fp); // the end free(hfspath); return 0; } else { free(hfspath); return 0; } free(hfspath); return -ENOATTR; }
int make_desktop(hfsvol *vol, int end) /* hfsvol *vol; Mac volume */ { hfsfile *hfp; /* Mac file */ hfsdirent ent; /* Mac finderinfo */ unsigned short clps; /* clump size */ unsigned short blks; /* blocks in a clump */ unsigned char *blk; /* user data */ int i; /* set up default directory entries - not all these fields are needed, but we'll set them up anyway ... */ ent.rsize = 0; /* resource size == 0 */ strcpy(ent.creator, DBFC); /* creator */ strcpy(ent.type, DBT); /* type */ ent.crdate = ent.mddate = time(0); /* date is now */ ent.fdflags = HFS_FNDR_ISINVISIBLE; /* invisible files */ /* clear the DB file */ blk = hce->hfs_ce + hce->hfs_ce_size*HFS_BLOCKSZ; blks = hce->hfs_dt_size; clps = blks*HFS_BLOCKSZ; memset(blk, 0, clps); /* create "Desktop DB" (if it doesn't exist) */ if(hfs_create(vol, DB, ent.type, ent.creator) == 0) { /* DB file size from hce_mem info */ /* set up "Desktop DB" data - following found by od'ing the "Desktop DB" file */ d_putw(blk+8, 0x100); d_putw(blk+10, 0x3); d_putw(blk+32, 0x200); d_putw(blk+34, 0x25); d_putl(blk+36, blks); d_putl(blk+40, blks - 1); d_putw(blk+48, clps); d_putw(blk+50, 0xff); d_putw(blk+120, 0x20a); d_putw(blk+122, 0x100); d_putw(blk+248, 0x8000); d_putl(blk+504, 0x1f800f8); d_putl(blk+508, 0x78000e); /* entries for "Desktop DB" */ ent.dsize = clps; /* size = clump size */ /* open file */ if((hfp = hfs_open(vol, DB)) == 0) err(1, hfs_error); /* "write" file */ write_fork(hfp, clps); /* set DB file attributes */ if (hfs_fsetattr(hfp, &ent) < 0) err(1, hfs_error); /* find the real start of the file */ end += hce->hfs_ce_size; /* close DB file */ if (hfs_close(hfp, end, 0) < 0) err(1, hfs_error); } else { /* if it already exists, then make sure it has the correct type/creator and flags */ if(hfs_setattr(vol, DB, &ent) < 0) err(1, hfs_error); } /* setup "Desktop DF" file as an empty file */ strcpy(ent.type, DFT); /* type */ ent.dsize = 0; /* empty */ /* create DF file (if it doesn't exist) - no need to open it */ hfs_create(vol, DF, ent.type, ent.creator); /* set DB file attributes */ if (hfs_setattr(vol, DF, &ent) < 0) err(1, hfs_error); return 0; }