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 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); }