static int FuseHFS_removexattr(const char *path, const char *name) { dprintf("removexattr %s %s\n", path, name); 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) { free(hfspath); // not really removing it return 0; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR))) { // resource fork hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, 0, SEEK_SET); hfs_truncate(fp, 0); hfs_close(fp); free(hfspath); return 0; } free(hfspath); return -ENOATTR; }
static int FuseHFS_truncate (const char *path, off_t length) { dprintf("truncate %s %lu\n", path, length); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; hfsfile *file = hfs_open(NULL, hfspath); free(hfspath); if (file == NULL) return -errno; if (hfs_truncate(file, length) == -1) { hfs_close(file); perror("truncate"); return -errno; } hfs_close(file); return 0; }
/* * NAME: hfs->umount() * DESCRIPTION: close an HFS volume */ int hfs_umount(hfsvol *vol) { int result = 0; if (getvol(&vol) == -1) goto fail; if (--vol->refs) { result = v_flush(vol); goto done; } /* close all open files and directories */ while (vol->files) { if (hfs_close(vol->files) == -1) result = -1; } while (vol->dirs) { if (hfs_closedir(vol->dirs) == -1) result = -1; } /* close medium */ if (v_close(vol) == -1) result = -1; /* remove from linked list of volumes */ if (vol->prev) vol->prev->next = vol->next; if (vol->next) vol->next->prev = vol->prev; if (vol == hfs_mounts) hfs_mounts = vol->next; if (vol == curvol) curvol = 0; FREE(vol); done: return result; fail: return -1; }
static int FuseHFS_release(const char *path, struct fuse_file_info *fi) { dprintf("close %s\n", path); // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; hfsfile *file = (hfsfile*)fi->fh; hfs_setfork(file, 0); hfs_close(file); free(hfspath); return 0; }
/* * NAME: closefiles() * DESCRIPTION: close source and destination files */ static void closefiles(hfsfile *ifile, int ofile, int *result) { if (close(ofile) == -1 && *result == 0) { ERROR(errno, "error closing destination file"); *result = -1; } if (hfs_close(ifile) == -1 && *result == 0) { ERROR(errno, hfs_error); *result = -1; } }
/* * NAME: opensrc() * DESCRIPTION: open the source file; set hint for destination filename */ static hfsfile *opensrc(hfsvol *vol, const char *srcname, const char **dsthint, const char *ext) { hfsfile *file; hfsdirent ent; static char name[HFS_MAX_FLEN + 4 + 1]; char *ptr; file = hfs_open(vol, srcname); if (file == 0) { ERROR(errno, hfs_error); return 0; } if (hfs_fstat(file, &ent) == -1) { ERROR(errno, hfs_error); hfs_close(file); return 0; } strcpy(name, ent.name); for (ptr = name; *ptr; ++ptr) { switch (*ptr) { case '/': *ptr = '-'; break; case ' ': *ptr = '_'; break; } } if (ext) strcat(name, ext); *dsthint = name; return file; }
/* * NAME: hfs->umount() * DESCRIPTION: close an HFS volume */ int hfs_umount(hfsvol *vol) { int result = 0; if (v_getvol(&vol) < 0) return -1; if (--vol->refs) return v_flush(vol, 0); /* close all open files and directories */ while (vol->files) hfs_close(vol->files); while (vol->dirs) hfs_closedir(vol->dirs); if (v_flush(vol, 1) < 0) result = -1; if ( #if 0 close(vol->fd) < 0 && #endif result == 0) { ERROR(errno, "error closing device"); result = -1; } if (vol->prev) vol->prev->next = vol->next; if (vol->next) vol->next->prev = vol->prev; if (vol == hfs_mounts) hfs_mounts = vol->next; if (vol == hfs_curvol) hfs_curvol = 0; v_destruct(vol); return result; }
/* * NAME: openfiles() * DESCRIPTION: open source and destination files */ static int openfiles(hfsvol *vol, const char *srcname, const char *dstname, const char *ext, hfsfile **ifile, int *ofile) { const char *dsthint; *ifile = opensrc(vol, srcname, &dsthint, ext); if (*ifile == 0) return -1; *ofile = opendst(dstname, dsthint); if (*ofile == -1) { hfs_close(*ifile); return -1; } return 0; }
/* * NAME: hfs->callback_close() * DESCRIPTION: close an HFS volume */ int hfs_callback_close(hfsvol *vol) { int result = 0; if (getvol(&vol) == -1) goto fail; if (--vol->refs) { result = v_flush(vol); goto done; } /* close all open files and directories */ while (vol->files) { if (hfs_close(vol->files) == -1) result = -1; } while (vol->dirs) { if (hfs_closedir(vol->dirs) == -1) result = -1; } /* close medium */ if (v_close(vol) == -1) result = -1; FREE(vol); done: return result; fail: return -1; }
static int FuseHFS_mknod(const char *path, mode_t mode, dev_t rdev) { dprintf("mknod %s\n", path); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // open file hfsfile *file; if ((file = hfs_create(NULL, hfspath, "TEXT", "FUSE"))) { // file hfs_close(file); hfs_flush(NULL); free(hfspath); return 0; } dprintf("mknod: EPERM\n"); free(hfspath); return -EPERM; }
static int FuseHFS_create(const char *path, mode_t mode, struct fuse_file_info *fi) { dprintf("create %s\n", path); if (_readonly) return -EPERM; // convert to hfs path char *hfspath = mkhfspath(path); if (hfspath == NULL) return -ENOENT; // open file hfsfile *file; if ((file = hfs_create(NULL, hfspath, "TEXT", "FUSE"))) { // close and reopen, because it won't exist until it's closed hfs_close(file); file = hfs_open(NULL, hfspath); fi->fh = (uint64_t)file; free(hfspath); return 0; } free(hfspath); perror("hfs_create"); return -errno; }
int hfsplus_close (PedFileSystem *fs) { HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) fs->type_specific; if (priv_data->bad_blocks_loaded) hfsplus_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); free(priv_data->alloc_map); free(priv_data->dirty_alloc_map); hfsplus_file_close (priv_data->allocation_file); hfsplus_file_close (priv_data->attributes_file); hfsplus_file_close (priv_data->catalog_file); hfsplus_file_close (priv_data->extents_file); if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); if (priv_data->wrapper) hfs_close(priv_data->wrapper); ped_geometry_destroy (fs->geom); free(priv_data->vh); free(priv_data); free(fs); return 1; }
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; }
static int FuseHFS_getxattr(const char *path, const char *name, char *value, size_t size, uint32_t position) { //dprintf("getxattr %s %s %p %lu %u\n", path, name, value, size, position); // 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 (value == NULL) { free(hfspath); return 32; } if (size < 32) { free(hfspath); return -ERANGE; } // return finder info if (ent.flags & HFS_ISDIR) { // directory info OSWriteBigInt16(value, 0, ent.u.dir.rect.top); OSWriteBigInt16(value, 2, ent.u.dir.rect.left); OSWriteBigInt16(value, 4, ent.u.dir.rect.bottom); OSWriteBigInt16(value, 6, ent.u.dir.rect.right); OSWriteBigInt16(value, 8, ent.fdflags); OSWriteBigInt16(value, 10, ent.fdlocation.v); OSWriteBigInt16(value, 12, ent.fdlocation.h); OSWriteBigInt16(value, 14, ent.u.dir.view); // DXInfo OSWriteBigInt16(value, 16, ((DXInfo*)(ent.u.dir.xinfo))->frScroll.v); OSWriteBigInt16(value, 18, ((DXInfo*)(ent.u.dir.xinfo))->frScroll.h); OSWriteBigInt32(value, 20, ((DXInfo*)(ent.u.dir.xinfo))->frOpenChain); OSWriteBigInt16(value, 24, ((DXInfo*)(ent.u.dir.xinfo))->frUnused); OSWriteBigInt16(value, 26, ((DXInfo*)(ent.u.dir.xinfo))->frComment); OSWriteBigInt32(value, 28, ((DXInfo*)(ent.u.dir.xinfo))->frPutAway); } else { // file info memcpy(value, ent.u.file.type, 4); memcpy(value+4, ent.u.file.creator, 4); OSWriteBigInt16(value, 8, ent.fdflags); OSWriteBigInt16(value, 10, ent.fdlocation.v); OSWriteBigInt16(value, 12, ent.fdlocation.h); OSWriteBigInt16(value, 14, ent.u.file.window); // FXInfo OSWriteBigInt16(value, 16, ((FXInfo*)(ent.u.file.xinfo))->fdIconID); OSWriteBigInt16(value, 18, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[0]); OSWriteBigInt16(value, 20, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[1]); OSWriteBigInt16(value, 22, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[2]); OSWriteBigInt16(value, 24, ((FXInfo*)(ent.u.file.xinfo))->fdUnused[3]); OSWriteBigInt16(value, 26, ((FXInfo*)(ent.u.file.xinfo))->fdComment); OSWriteBigInt32(value, 28, ((FXInfo*)(ent.u.file.xinfo))->fdPutAway); } free(hfspath); return 32; } else if (strcmp(name, XATTR_RESOURCEFORK_NAME) == 0 && (!(ent.flags & HFS_ISDIR)) && ent.u.file.rsize) { // resource fork if (value == NULL) { free(hfspath); return ent.u.file.rsize-position; } int bw = ent.u.file.rsize-position; if (bw > size) bw = size; // copy resource fork hfsfile *fp = hfs_open(NULL, hfspath); hfs_setfork(fp, 1); hfs_seek(fp, position, SEEK_SET); hfs_read(fp, value, bw); hfs_close(fp); // the end free(hfspath); return bw; } free(hfspath); dprintf("getxattr: ENOATTR\n"); 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; }
/* copy_to_mac_vol: copy all files in a directory to corresponding ** Mac folder. ** ** Files are copied recursively to corresponding folders on the Mac ** volume. The caller routine needs to do a hfs_chdir before calling this ** routine. */ int FDECL2(copy_to_mac_vol, hfsvol *, vol, struct directory *, node) { struct directory_entry * s_entry; /* ISO directory entry */ struct directory_entry * s_entry1; /* tmp ISO directory entry */ struct directory *dpnt; /* ISO directory */ hfsfile *hfp; /* HFS file */ hfsdirent *ent; /* HFS file entities */ long id; /* current HFS folder */ long dext, rext; /* real data/rsrc start blk */ int ret; /* result code */ int new_name; /* HFS file has modified name */ int tens; int digits; int i; /* store the current HFS directory ID */ if ((id = hfs_getcwd(vol)) == 0) return(-1); if (verbose > 1) fprintf(stderr,"HFS scanning %s\n", node->whole_name); /* loop through the ISO directory entries and process files */ for(s_entry = node->contents; s_entry; s_entry = s_entry->next) { /* ignore directory and associated (rsrc) files */ if(s_entry->isorec.flags[0]) continue; /* ignore any non-Mac type file */ if(!s_entry->hfs_ent) continue; #ifdef DEBUG fprintf(stderr," Name = %s", s_entry->whole_name); fprintf(stderr," Startb = %d\n", s_entry->starting_block); #endif /* DEBUG */ ent = s_entry->hfs_ent; /* create file */ i = HFS_MAX_FLEN - strlen(ent->name); new_name = 0; tens = TEN; digits = 1; while (1) { /* try to open file - if it exists, then append '_' to the name and try again */ errno = 0; if ((hfs_create(vol, ent->name, ent->type, ent->creator)) < 0) { if (errno != EEXIST ) { /* not an "exist" error, or we can't append as the filename is already HFS_MAX_FLEN chars */ snprintf(hce->error, ERROR_SIZE, "can't HFS create file %s", s_entry->whole_name); return(-1); } else if (i == 0) { /* File name at max HFS length - make unique name */ if (!new_name) new_name++; sprintf(ent->name + HFS_MAX_FLEN - digits - 1, "%s%d", LCHAR, new_name); new_name++; if (new_name == tens) { tens *= TEN; digits++; } } else { /* append '_' to get new name */ strcat(ent->name, LCHAR); i--; new_name = 1; } } else break; } /* warn that we have a new name */ if (new_name && verbose > 0) { fprintf(stderr, "Using HFS name: %s for %s\n", ent->name, s_entry->whole_name); } /* open file */ if ((hfp = hfs_open(vol, ent->name)) == 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS open %s", s_entry->whole_name); return(-1); } /* if it has a data fork, then "write" it out */ if (ent->dsize) write_fork(hfp, ent->dsize); /* if it has a resource fork, set the fork and "write" it out */ if (ent->rsize) { if ((hfs_setfork(hfp, 1)) < 0) return(-1); write_fork(hfp, ent->rsize); } /* update any HFS file attributes */ if ((hfs_fsetattr(hfp, ent)) < 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS set attributes %s", s_entry->whole_name); return(-1); } /* get the ISO starting block of data fork (may be zero) and convert to the equivalent HFS block */ if (ent->dsize) dext = s_entry->starting_block * BLK_CONV; else dext = 0; /* if the file has a resource fork (associated file), get it's ISO starting block and convert as above */ if (s_entry->assoc && ent->rsize) rext = s_entry->assoc->starting_block * BLK_CONV; else rext = 0; /* close the file and update the starting blocks */ if (hfs_close(hfp, dext, rext) < 0) { snprintf(hce->error, ERROR_SIZE, "can't HFS close file %s", s_entry->whole_name); return(-1); } } /* process sub-directories - have a slight problem here, if the directory had been relocated, then we need to find the real directory - we do this by first finding the real directory_entry, and then finding it's directory info */ /* following code taken from joliet.c */ for(s_entry=node->contents;s_entry;s_entry=s_entry->next) { if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) { /* if the directory has been reloacted, then search the relocated directory for the real entry */ for(s_entry1=reloc_dir->contents;s_entry1;s_entry1=s_entry1->next) { if(s_entry1->parent_rec == s_entry) break; } /* have a problem - can't find the real directory */ if(s_entry1 == NULL) { snprintf(hce->error, ERROR_SIZE, "can't locate relocated directory %s", s_entry->whole_name); return(-1); } } else s_entry1 = s_entry; /* now have the correct entry - now find the actual directory */ if ((s_entry1->isorec.flags[0] & 2) && strcmp(s_entry1->name,".") && strcmp(s_entry1->name,"..")) { if((s_entry->de_flags & RELOCATED_DIRECTORY) != 0) dpnt = reloc_dir->subdir; else dpnt = node->subdir; while(1) { if (dpnt->self == s_entry1) break; dpnt = dpnt->next; if(!dpnt) { snprintf(hce->error, ERROR_SIZE, "can't find directory location %s", s_entry1->whole_name); return (-1); } } /* now have the correct directory - so do the HFS stuff */ ent = dpnt->hfs_ent; /* if we don't have hfs entries, then this is a "deep" directory - this will be processed later */ if (!ent) continue; /* make sub-folder */ i = HFS_MAX_FLEN - strlen(ent->name); new_name = 0; tens = TEN; digits = 1; while (1) { /* try to create new directory - if it exists, then append '_' to the name and try again */ errno = 0; if (hfs_mkdir(vol, ent->name) < 0) { if (errno != EEXIST) { /* not an "exist" error, or we can't append as the filename is already HFS_MAX_FLEN chars */ snprintf(hce->error, ERROR_SIZE, "can't HFS create folder %s", s_entry->whole_name); return(-1); } else if (i == 0) { /* File name at max HFS length - make unique name */ if (!new_name) new_name++; sprintf(ent->name + HFS_MAX_FLEN - digits - 1, "%s%d", LCHAR, new_name); new_name++; if (new_name == tens) { tens *= TEN; digits++; } } else { /* append '_' to get new name */ strcat(ent->name, LCHAR); i--; new_name = 1; } } else break; } /* warn that we have a new name */ if (new_name && verbose > 0) { fprintf(stderr, "Using HFS name: %s for %s\n", ent->name, s_entry->whole_name); } /* see if we need to "bless" this folder */ if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless) == 0) { hfs_stat(vol, ent->name, ent); hfs_vsetbless(vol, ent->cnid); if (verbose > 0) { fprintf(stderr, "Blessing %s (%s)\n", ent->name, s_entry->whole_name); } /* stop any further checks */ hfs_bless = NULL; } /* change to sub-folder */ if (hfs_chdir(vol, ent->name) < 0) return(-1); /* recursively copy files ... */ ret = copy_to_mac_vol(vol, dpnt); if (ret < 0) return(ret); /* change back to this folder */ if (hfs_setcwd(vol, id) < 0) return(-1); } } return(0); }
PedFileSystem* hfsplus_open (PedGeometry* geom) { uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; PedFileSystem* fs; HfsPVolumeHeader* vh; HfsPPrivateFSData* priv_data; PedGeometry* wrapper_geom; unsigned int map_sectors; if (!hfsc_can_use_geom (geom)) return NULL; fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); if (!fs) goto hpo; vh = (HfsPVolumeHeader*) ped_malloc (sizeof (HfsPVolumeHeader)); if (!vh) goto hpo_fs; priv_data = (HfsPPrivateFSData*)ped_malloc (sizeof (HfsPPrivateFSData)); if (!priv_data) goto hpo_vh; fs->geom = ped_geometry_duplicate (geom); if (!fs->geom) goto hpo_pd; fs->type_specific = (void*) priv_data; if ((wrapper_geom = hfs_and_wrapper_probe (geom))) { HfsPrivateFSData* hfs_priv_data; PedSector abs_sect, length; unsigned int bs; ped_geometry_destroy (wrapper_geom); priv_data->wrapper = hfs_open(geom); if (!priv_data->wrapper) goto hpo_gm; hfs_priv_data = (HfsPrivateFSData*) priv_data->wrapper->type_specific; bs = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; abs_sect = (PedSector) geom->start + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->start_block) + (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.start_block ) * bs; length = (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb->old_new .embedded.location.block_count) * bs; priv_data->plus_geom = ped_geometry_new (geom->dev, abs_sect, length); if (!priv_data->plus_geom) goto hpo_wr; priv_data->free_geom = 1; } else { priv_data->wrapper = NULL; priv_data->plus_geom = fs->geom; priv_data->free_geom = 0; } if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) goto hpo_pg; memcpy (vh, buf, sizeof (HfsPVolumeHeader)); priv_data->vh = vh; if (vh->signature != PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->signature != PED_CPU_TO_BE16(HFSX_SIGNATURE)) { ped_exception_throw ( PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, _("No valid HFS[+X] signature has been found while " "opening.")); goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSP_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSP_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFS+ isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } if (vh->signature == PED_CPU_TO_BE16(HFSX_SIGNATURE) && vh->version != PED_CPU_TO_BE16(HFSX_VERSION)) { if (ped_exception_throw ( PED_EXCEPTION_NO_FEATURE, PED_EXCEPTION_IGNORE_CANCEL, _("Version %d of HFSX isn't supported."), PED_BE16_TO_CPU(vh->version)) != PED_EXCEPTION_IGNORE) goto hpo_pg; } priv_data->jib_start_block = 0; priv_data->jl_start_block = 0; if (vh->attributes & PED_CPU_TO_BE32(1<<HFSP_JOURNALED)) { if (!hfsj_replay_journal(fs)) goto hpo_pg; } priv_data->bad_blocks_loaded = 0; priv_data->bad_blocks_xtent_nb = 0; priv_data->bad_blocks_xtent_list = NULL; priv_data->extents_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), vh->extents_file.extents, PED_BE64_TO_CPU ( vh->extents_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->extents_file) goto hpo_pg; priv_data->catalog_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), vh->catalog_file.extents, PED_BE64_TO_CPU ( vh->catalog_file.logical_size ) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->catalog_file) goto hpo_ce; priv_data->attributes_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ATTRIB_ID), vh->attributes_file.extents, PED_BE64_TO_CPU ( vh->attributes_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->attributes_file) goto hpo_cc; map_sectors = ( PED_BE32_TO_CPU (vh->total_blocks) + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); priv_data->dirty_alloc_map = (uint8_t*) ped_malloc ((map_sectors + 7) / 8); if (!priv_data->dirty_alloc_map) goto hpo_cl; memset(priv_data->dirty_alloc_map, 0, (map_sectors + 7) / 8); priv_data->alloc_map = (uint8_t*) ped_malloc (map_sectors * PED_SECTOR_SIZE_DEFAULT); if (!priv_data->alloc_map) goto hpo_dm; priv_data->allocation_file = hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ALLOC_ID), vh->allocation_file.extents, PED_BE64_TO_CPU ( vh->allocation_file.logical_size) / PED_SECTOR_SIZE_DEFAULT); if (!priv_data->allocation_file) goto hpo_am; if (!hfsplus_file_read (priv_data->allocation_file, priv_data->alloc_map, 0, map_sectors)) { hfsplus_close(fs); return NULL; } fs->type = &hfsplus_type; fs->checked = ((PED_BE32_TO_CPU (vh->attributes) >> HFS_UNMOUNTED) & 1) && !((PED_BE32_TO_CPU (vh->attributes) >> HFSP_INCONSISTENT) & 1); return fs; /*--- clean error handling ---*/ hpo_am: free(priv_data->alloc_map); hpo_dm: free(priv_data->dirty_alloc_map); hpo_cl: hfsplus_file_close (priv_data->attributes_file); hpo_cc: hfsplus_file_close (priv_data->catalog_file); hpo_ce: hfsplus_file_close (priv_data->extents_file); hpo_pg: if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); hpo_wr: if (priv_data->wrapper) hfs_close(priv_data->wrapper); hpo_gm: ped_geometry_destroy (fs->geom); hpo_pd: free(priv_data); hpo_vh: free(vh); hpo_fs: free(fs); hpo: return NULL; }