int do_restore_client_burp1(struct asfd *asfd, struct conf *conf, enum action act, int vss_restore) { int ars=0; int ret=-1; char msg[512]=""; struct sbuf *sb=NULL; // Windows needs to have the VSS data written first, and the actual data // written immediately afterwards. The server is transferring them in two // chunks. So, leave bfd open after a Windows metadata transfer. BFILE bfd; #ifdef HAVE_WIN32 binit(&bfd, 0, conf); #endif logp("doing %s\n", act_str(act)); snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act), conf->backup?conf->backup:"", conf->regex?conf->regex:""); if(asfd->write_str(asfd, CMD_GEN, msg) || asfd->read_expect(asfd, CMD_GEN, "ok")) return -1; logp("doing %s confirmed\n", act_str(act)); if(conf->send_client_cntr) { // FIX THIS // if(cntr_recv(conf)) goto end; } #if defined(HAVE_WIN32) if(act==ACTION_RESTORE) win32_enable_backup_privileges(); #endif if(!(sb=sbuf_alloc(conf))) goto end; while(1) { char *fullpath=NULL; sbuf_free_content(sb); if((ars=sbufl_fill(sb, asfd, NULL, NULL, conf->cntr))) { if(ars<0) goto end; else { // ars==1 means it ended ok. //logp("got %s end\n", act_str(act)); if(asfd->write_str(asfd, CMD_GEN, "restoreend ok")) goto end; } break; } switch(sb->path.cmd) { case CMD_DIRECTORY: case CMD_FILE: case CMD_ENC_FILE: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: case CMD_EFS_FILE: if(conf->strip) { int s; s=strip_path_components(asfd, sb, &(sb->path.buf), conf); if(s<0) goto end; // error else if(s==0) { // Too many components stripped // - carry on. continue; } // It is OK, sb->path is now stripped. } if(!(fullpath=prepend_s(conf->restoreprefix, sb->path.buf))) { log_and_send_oom(asfd, __func__); goto end; } if(act==ACTION_RESTORE) { strip_invalid_characters(&fullpath); if(!overwrite_ok(sb, conf, &bfd, fullpath)) { char msg[512]=""; // Something exists at that path. snprintf(msg, sizeof(msg), "Path exists: %s", fullpath); if(restore_interrupt(asfd, sb, msg, conf)) goto end; else { if(fullpath) free(fullpath); continue; } } } break; default: break; } switch(sb->path.cmd) { case CMD_WARNING: cntr_add(conf->cntr, sb->path.cmd, 1); printf("\n"); logp("%s", sb->path); break; case CMD_DIRECTORY: if(restore_dir(asfd, sb, fullpath, act, conf)) goto end; break; case CMD_FILE: case CMD_VSS_T: // Have it a separate statement to the // encrypted version so that encrypted and not // encrypted files can be restored at the // same time. if(restore_file_or_get_meta(asfd, &bfd, sb, fullpath, act, NULL, NULL, NULL, vss_restore, conf)) { logp("restore_file error\n"); goto end; } break; case CMD_ENC_FILE: case CMD_ENC_VSS_T: if(restore_file_or_get_meta(asfd, &bfd, sb, fullpath, act, conf->encryption_password, NULL, NULL, vss_restore, conf)) { logp("restore_file error\n"); goto end; } break; case CMD_SOFT_LINK: case CMD_HARD_LINK: if(restore_link(asfd, sb, fullpath, conf->restoreprefix, act, conf)) goto end; break; case CMD_SPECIAL: if(restore_special(asfd, sb, fullpath, act, conf)) goto end; break; case CMD_METADATA: case CMD_VSS: if(restore_metadata(asfd, &bfd, sb, fullpath, act, NULL, vss_restore, conf)) goto end; break; case CMD_ENC_METADATA: case CMD_ENC_VSS: if(restore_metadata(asfd, &bfd, sb, fullpath, act, conf->encryption_password, vss_restore, conf)) goto end; break; case CMD_EFS_FILE: if(restore_file_or_get_meta(asfd, &bfd, sb, fullpath, act, NULL, NULL, NULL, vss_restore, conf)) { logp("restore_file error\n"); goto end; } break; default: logp("unknown cmd: %c\n", sb->path.cmd); goto end; break; } if(fullpath) free(fullpath); } ret=0; end: sbuf_free(sb); #ifdef HAVE_WIN32 // It is possible for a bfd to still be open. bclose(&bfd, asfd); #endif cntr_print_end(conf->cntr); cntr_print(conf->cntr, act); if(!ret) logp("%s finished\n", act_str(act)); else logp("ret: %d\n", ret); return ret; }
AROS_UFH3(void, packet_reply, AROS_UFHA(struct ph_mount *, mount, A1), AROS_UFHA(APTR, dummy, A5), AROS_UFHA(struct ExecBase *, SysBase, A6)) { AROS_USERFUNC_INIT struct DosPacket *dp; struct ph_packet *pkt; struct IOFileSys *iofs; struct ph_handle *handle; /* retrieve the message and fish the packet out */ dp = (struct DosPacket *) GetMsg(&(mount->reply_port))->mn_Node.ln_Name; pkt = (struct ph_packet *) dp->dp_Link; D(bug("[packet] got reply packet %d (%s)\n", dp->dp_Type, act_str(dp->dp_Type))); /* get the iofs back */ iofs = (struct IOFileSys *) dp->dp_Arg7; /* dos error code comes back in Res2 */ if (dp->dp_Res1 == DOSFALSE) { iofs->io_DosError = dp->dp_Res2; /* do any cleanup from the request (eg freeing memory) */ switch (dp->dp_Type) { case ACTION_FINDINPUT: case ACTION_FINDOUTPUT: case ACTION_FINDUPDATE: FreeMem((APTR) BADDR(dp->dp_Arg1), sizeof(struct ph_handle)); break; case ACTION_SAME_LOCK: /* DOSFALSE & no error means the locks are different */ if (iofs->io_DosError == 0) iofs->io_Union.io_SAME_LOCK.io_Same = LOCK_DIFFERENT; break; case ACTION_PARENT: /* no error means they tried to go up past the root. The * packet system allows this, IOFS does not */ if (iofs->io_DosError == 0) iofs->io_DosError = ERROR_OBJECT_NOT_FOUND; break; /* a zero result is not an error for the following three packet * types. We shouldn't really be here */ case ACTION_SEEK: iofs->io_Union.io_SEEK.io_Offset = dp->dp_Res1; iofs->io_DosError = 0; break; case ACTION_READ: iofs->io_Union.io_READ.io_Length = dp->dp_Res1; iofs->io_DosError = 0; break; case ACTION_SET_FILE_SIZE: iofs->io_DosError = 0; break; } /* kill the packet */ DeletePool(pkt->pool); D(bug("[packet] returning error %ld\n", iofs->io_DosError)); /* and tell them */ ReplyMsg((APTR) iofs); return; } /* no error */ iofs->io_DosError = 0; /* populate the iofs with the results. note that for packets that only * return success/failure we have nothing to do, so they're not listed * here */ switch (dp->dp_Type) { case ACTION_COPY_DIR: case ACTION_COPY_DIR_FH: case ACTION_LOCATE_OBJECT: case ACTION_PARENT: case ACTION_PARENT_FH: handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR); if (handle == NULL) { iofs->io_DosError = ERROR_NO_FREE_STORE; break; } /* we'll need the lock they gave us for future operations */ handle->actual = (void *) dp->dp_Res1; handle->is_lock = TRUE; handle->mount = mount; iofs->IOFS.io_Unit = (struct Unit *) handle; break; case ACTION_FINDINPUT: case ACTION_FINDOUTPUT: case ACTION_FINDUPDATE: { /* handlers return "internal data" (typically a lock, though we * can't assume that) in fh_Arg1. we need to keep it for later * filehandle operations. * the calls that need this data (e.g. ACTION_READ/WRITE/SEEK) * take it directly in dp_Arg1 */ handle = (struct ph_handle *) BADDR(dp->dp_Arg1); handle->actual = (void *) handle->fh.fh_Arg1; handle->is_lock = FALSE; handle->mount = mount; iofs->IOFS.io_Unit = (struct Unit *) handle; break; } case ACTION_FREE_LOCK: case ACTION_END: /* free up our data */ handle = (struct ph_handle *) iofs->IOFS.io_Unit; FreeMem((APTR) handle, sizeof(struct ph_handle)); iofs->IOFS.io_Unit = NULL; break; case ACTION_READ: if (dp->dp_Res1 == -1) iofs->io_DosError = dp->dp_Res2; iofs->io_Union.io_READ.io_Length = dp->dp_Res1; break; case ACTION_WRITE: iofs->io_Union.io_WRITE.io_Length = dp->dp_Res1; break; case ACTION_SEEK: if (dp->dp_Res1 == -1) iofs->io_DosError = dp->dp_Res2; else iofs->io_Union.io_SEEK.io_Offset = dp->dp_Res1; break; case ACTION_SET_FILE_SIZE: if (dp->dp_Res1 == -1) iofs->io_DosError = dp->dp_Res2; break; case ACTION_SAME_LOCK: iofs->io_Union.io_SAME_LOCK.io_Same = LOCK_SAME; break; case ACTION_EXAMINE_OBJECT: case ACTION_EXAMINE_FH: { struct FileInfoBlock *fib = (struct FileInfoBlock *) BADDR(dp->dp_Arg2); struct ExAllData *ead = iofs->io_Union.io_EXAMINE.io_ead; ULONG size = iofs->io_Union.io_EXAMINE.io_Size; ULONG mode = iofs->io_Union.io_EXAMINE.io_Mode; ULONG comment_len = 0, filename_len = 0; iofs->io_DirPos = fib->fib_DiskKey; /* make sure we have enough room for everything that came back */ if (size < sizeof(struct ExAllData) + (mode >= ED_COMMENT ? (comment_len = fib->fib_Comment[0]) : 0) + (mode >= ED_NAME ? (filename_len = fib->fib_FileName[0]) : 0)) { iofs->io_DosError = ERROR_BUFFER_OVERFLOW; FreeMem(fib, sizeof(struct FileInfoBlock)); break; } /* copy stuff from the fib to the ead */ switch (mode) { case ED_OWNER: ead->ed_OwnerUID = fib->fib_OwnerUID; ead->ed_OwnerGID = fib->fib_OwnerGID; case ED_COMMENT: /* store the comment in the spare space after the ead and * the filename */ ead->ed_Comment = (UBYTE *) ead + sizeof(struct ExAllData) + filename_len + 1; strcpy(ead->ed_Comment, mkcstr(pkt->pool, fib->fib_Comment)); case ED_DATE: ead->ed_Days = fib->fib_Date.ds_Days; ead->ed_Mins = fib->fib_Date.ds_Minute; ead->ed_Ticks = fib->fib_Date.ds_Tick; case ED_PROTECTION: ead->ed_Prot = fib->fib_Protection; case ED_SIZE: ead->ed_Size = fib->fib_Size; case ED_TYPE: ead->ed_Type = fib->fib_EntryType; case ED_NAME: /* store the name in the spare space after the ead */ ead->ed_Name = (UBYTE *) ead + sizeof(struct ExAllData); strcpy(ead->ed_Name, mkcstr(pkt->pool, fib->fib_FileName)); case 0: ead->ed_Next = NULL; break; default: iofs->io_DosError = ERROR_BAD_NUMBER; break; } FreeMem(fib, sizeof(struct FileInfoBlock)); break; } case ACTION_EXAMINE_NEXT: { struct FileInfoBlock *fib = iofs->io_Union.io_EXAMINE_NEXT.io_fib; strcpy(fib->fib_FileName, mkcstr(pkt->pool, fib->fib_FileName)); strcpy(fib->fib_Comment, mkcstr(pkt->pool, fib->fib_Comment)); break; } case ACTION_IS_FILESYSTEM: iofs->io_Union.io_IS_FILESYSTEM.io_IsFilesystem = TRUE; break; case ACTION_CREATE_DIR: handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR); if (handle == NULL) { iofs->io_DosError = ERROR_NO_FREE_STORE; break; } /* we'll need the lock they gave us for future operations */ handle->actual = (void *) dp->dp_Res1; handle->is_lock = TRUE; handle->mount = mount; iofs->IOFS.io_Unit = (struct Unit *) handle; break; case ACTION_READ_LINK: iofs->io_Union.io_READ_SOFTLINK.io_Size = dp->dp_Res1; iofs->io_DosError = dp->dp_Res1 < 0 ? dp->dp_Res2 : 0; break; case ACTION_MORE_CACHE: iofs->io_Union.io_MORE_CACHE.io_NumBuffers = dp->dp_Res1; } /* done with the packet */ DeletePool(pkt->pool); /* send it back */ ReplyMsg((APTR) iofs); AROS_USERFUNC_EXIT }
int do_restore_client(struct asfd *asfd, struct conf **confs, enum action act, int vss_restore) { int ret=-1; char msg[512]=""; struct sbuf *sb=NULL; struct blk *blk=NULL; BFILE *bfd=NULL; char *fullpath=NULL; char *style=NULL; char *datpath=NULL; struct cntr *cntr=get_cntr(confs); enum protocol protocol=get_protocol(confs); int strip=get_int(confs[OPT_STRIP]); int overwrite=get_int(confs[OPT_OVERWRITE]); const char *backup=get_string(confs[OPT_BACKUP]); const char *regex=get_string(confs[OPT_REGEX]); const char *restore_prefix=get_string(confs[OPT_RESTOREPREFIX]); const char *encryption_password=get_string(confs[OPT_ENCRYPTION_PASSWORD]); if(!(bfd=bfile_alloc())) goto end; bfile_init(bfd, 0, cntr); snprintf(msg, sizeof(msg), "%s %s:%s", act_str(act), backup?backup:"", regex?regex:""); logp("doing %s\n", msg); if(asfd->write_str(asfd, CMD_GEN, msg) || asfd_read_expect(asfd, CMD_GEN, "ok")) goto error; logp("doing %s confirmed\n", act_str(act)); #if defined(HAVE_WIN32) if(act==ACTION_RESTORE) win32_enable_backup_privileges(); #endif if(!(style=get_restore_style(asfd, confs))) goto error; if(!strcmp(style, RESTORE_SPOOL)) { if(restore_spool(asfd, confs, &datpath)) goto error; } else logp("Streaming restore direct\n"); logf("\n"); if(get_int(confs[OPT_SEND_CLIENT_CNTR]) && cntr_recv(asfd, confs)) goto error; if(!(sb=sbuf_alloc(protocol)) || (protocol==PROTO_2 && !(blk=blk_alloc()))) { log_and_send_oom(asfd, __func__); goto error; } while(1) { sbuf_free_content(sb); if(protocol==PROTO_1) sb->flags |= SBUF_CLIENT_RESTORE_HACK; switch(sbuf_fill_from_net(sb, asfd, blk, datpath, cntr)) { case 0: break; case 1: if(asfd->write_str(asfd, CMD_GEN, "restoreend ok")) goto error; goto end; // It was OK. default: case -1: goto error; } if(protocol==PROTO_2) { if(blk->data) { int wret=0; if(act==ACTION_VERIFY) cntr_add(cntr, CMD_DATA, 1); else wret=write_data(asfd, bfd, blk); if(!datpath) blk_free_content(blk); blk->data=NULL; if(wret) goto error; continue; } else if(sb->endfile.buf) { continue; } } switch(sb->path.cmd) { case CMD_DIRECTORY: case CMD_FILE: case CMD_ENC_FILE: case CMD_SOFT_LINK: case CMD_HARD_LINK: case CMD_SPECIAL: case CMD_METADATA: case CMD_ENC_METADATA: case CMD_VSS: case CMD_ENC_VSS: case CMD_VSS_T: case CMD_ENC_VSS_T: case CMD_EFS_FILE: if(strip) { int s; s=strip_path_components(asfd, sb, strip, cntr, protocol); if(s<0) goto error; if(s==0) { // Too many components stripped // - carry on. continue; } // It is OK, sb.path is now stripped. } free_w(&fullpath); if(!(fullpath=prepend_s(restore_prefix, sb->path.buf))) { log_and_send_oom(asfd, __func__); goto error; } if(act==ACTION_RESTORE) { strip_invalid_characters(&fullpath); if(!overwrite_ok(sb, overwrite, #ifdef HAVE_WIN32 bfd, #endif fullpath)) { char msg[512]=""; // Something exists at that path. snprintf(msg, sizeof(msg), "Path exists: %s\n", fullpath); if(restore_interrupt(asfd, sb, msg, cntr, protocol)) goto error; continue; } } break; case CMD_MESSAGE: case CMD_WARNING: log_recvd(&sb->path, cntr, 1); logf("\n"); continue; default: break; } switch(sb->path.cmd) { // These are the same in both protocol1 and protocol2. case CMD_DIRECTORY: if(restore_dir(asfd, sb, fullpath, act, cntr, protocol)) goto error; continue; case CMD_SOFT_LINK: case CMD_HARD_LINK: if(restore_link(asfd, sb, fullpath, act, cntr, protocol, restore_prefix)) goto error; continue; case CMD_SPECIAL: if(restore_special(asfd, sb, fullpath, act, cntr, protocol)) goto error; continue; default: break; } if(protocol==PROTO_2) { if(restore_switch_protocol2(asfd, sb, fullpath, act, bfd, vss_restore, cntr)) goto error; } else { if(restore_switch_protocol1(asfd, sb, fullpath, act, bfd, vss_restore, cntr, encryption_password)) goto error; } } end: ret=0; error: // It is possible for a fd to still be open. bfd->close(bfd, asfd); bfile_free(&bfd); cntr_print_end(cntr); cntr_print(cntr, act); if(!ret) logp("%s finished\n", act_str(act)); else logp("ret: %d\n", ret); sbuf_free(&sb); free_w(&style); if(datpath) { recursive_delete(datpath); free_w(&datpath); } free_w(&fullpath); blk_free(&blk); return ret; }
void packet_handle_request(struct IOFileSys *iofs, struct PacketBase *PacketBase) { struct ph_handle *handle; struct ph_packet *pkt; struct DosPacket *dp; D(bug("[packet] got io request %d (%s)\n", iofs->IOFS.io_Command, fsa_str(iofs->IOFS.io_Command))); /* get our data back */ handle = (struct ph_handle *) iofs->IOFS.io_Unit; /* make a fresh new packet */ pkt = packet_alloc(); dp = &(pkt->dp); /* hook the iofs up to the packet so we can find it on return * dp_Arg7 should be unused; DoPkt() doesn't touch it */ dp->dp_Arg7 = (IPTR) iofs; /* our reply port will cause packet_reply() to be called when they reply */ dp->dp_Port = &(handle->mount->reply_port); /* convert the command */ switch (iofs->IOFS.io_Command) { case FSA_OPEN: D(bug("[packet] OPEN: lock 0x%08x (%s) name '%s' type %s\n", handle->actual, handle_desc(handle), iofs->io_Union.io_OPEN.io_Filename, (iofs->io_Union.io_OPEN.io_FileMode & FMF_LOCK) ? "EXCLUSIVE" : "SHARED")); if (!handle->is_lock) { /* If passed a filehandle, we can only deal with locking the * filehandle itself or its parent (unless we were to resort * to sending multiple packets) */ if (iofs->io_Union.io_OPEN.io_Filename[0] == '\0') { dp->dp_Type = ACTION_COPY_DIR_FH; dp->dp_Arg1 = (IPTR) handle->actual; } else if (iofs->io_Union.io_OPEN.io_Filename[0] == '/' && iofs->io_Union.io_OPEN.io_Filename[1] == '\0') { dp->dp_Type = ACTION_PARENT_FH; dp->dp_Arg1 = (IPTR) handle->actual; } else { iofs->io_DosError = ERROR_NOT_IMPLEMENTED; goto reply; } } else { dp->dp_Type = ACTION_LOCATE_OBJECT; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_OPEN.io_Filename); dp->dp_Arg3 = (iofs->io_Union.io_OPEN.io_FileMode & FMF_LOCK) ? EXCLUSIVE_LOCK : SHARED_LOCK; } break; case FSA_OPEN_FILE: { ULONG mode = iofs->io_Union.io_OPEN_FILE.io_FileMode; struct ph_handle *new_handle; D(bug("[packet] OPEN_FILE: lock 0x%08x (%s) name '%s' mode 0x%x prot 0x%x\n", handle->actual, handle_desc(handle), iofs->io_Union.io_OPEN_FILE.io_Filename, mode, iofs->io_Union.io_OPEN_FILE.io_Protection)); /* convert modes to the proper packet type (as best we can) */ if ((mode & FMF_CLEAR) != 0) dp->dp_Type = ACTION_FINDOUTPUT; else if ((mode & FMF_CREATE) != 0) dp->dp_Type = ACTION_FINDUPDATE; else dp->dp_Type = ACTION_FINDINPUT; if ((mode & FMF_APPEND) != 0) { iofs->io_DosError = ERROR_BAD_NUMBER; goto reply; } /* make a new handle */ new_handle = (struct ph_handle *) AllocMem(sizeof(struct ph_handle), MEMF_PUBLIC | MEMF_CLEAR); if (new_handle == NULL) { iofs->io_DosError = ERROR_NO_FREE_STORE; goto reply; } /* dos.lib buffer stuff, must be initialised this way */ new_handle->fh.fh_Pos = new_handle->fh.fh_End = (UBYTE *) -1; dp->dp_Arg1 = (IPTR) MKBADDR(&new_handle->fh); dp->dp_Arg2 = (IPTR) (handle->is_lock ? handle->actual : NULL); dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_OPEN.io_Filename); break; } case FSA_CLOSE: D(bug("[packet] CLOSE: lock 0x%08x (%s)\n", handle->actual, handle_desc(handle))); /* if this is the root handle, then we previously intercepted a * call and returned it (e.g. FSA_OPEN/ACTION_PARENT), so we don't * want the handler to do anything */ if (handle == &(handle->mount->root_handle)) { iofs->IOFS.io_Unit = NULL; goto reply; } dp->dp_Type = (handle->is_lock) ? ACTION_FREE_LOCK : ACTION_END; dp->dp_Arg1 = (IPTR) handle->actual; break; case FSA_READ: D(bug("[packet] READ: handle 0x%08x buf 0x%08x len %ld\n", handle->actual, iofs->io_Union.io_READ.io_Buffer, iofs->io_Union.io_READ.io_Length)); dp->dp_Type = ACTION_READ; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_READ.io_Buffer; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_READ.io_Length; /* DOSFALSE == 0, so we can't distinguish between a zero-length * read and an actual error. So, we reset the length here. If the * returned packet is DOSFALSE, but no error, this will make sure * DOS gets the right length back */ iofs->io_Union.io_READ.io_Length = 0; break; case FSA_WRITE: D(bug("[packet] WRITE: handle 0x%08x buf 0x%08x len %ld\n", handle->actual, iofs->io_Union.io_WRITE.io_Buffer, iofs->io_Union.io_WRITE.io_Length)); dp->dp_Type = ACTION_WRITE; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_WRITE.io_Buffer; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_WRITE.io_Length; iofs->io_Union.io_WRITE.io_Length = 0; break; case FSA_SEEK: #if defined(DEBUG) && DEBUG != 0 { ULONG mode = iofs->io_Union.io_SEEK.io_SeekMode; bug("[packet] SEEK: handle 0x%08x offset %ld mode %ld (%s)\n", handle->actual, (LONG) iofs->io_Union.io_SEEK.io_Offset, mode, mode == OFFSET_BEGINNING ? "OFFSET_BEGINNING" : mode == OFFSET_CURRENT ? "OFFSET_CURRENT" : mode == OFFSET_END ? "OFFSET_END" : "[unknown]"); } #endif dp->dp_Type = ACTION_SEEK; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_SEEK.io_Offset; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_SEEK.io_SeekMode; break; case FSA_SET_FILE_SIZE: #if defined(DEBUG) && DEBUG != 0 { ULONG mode = iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode; bug("[packet] SET_FILE_SIZE: handle 0x%08x offset %ld mode %ld (%s)\n", handle->actual, (LONG) iofs->io_Union.io_SET_FILE_SIZE.io_Offset, mode, mode == OFFSET_BEGINNING ? "OFFSET_BEGINNING" : mode == OFFSET_CURRENT ? "OFFSET_CURRENT" : mode == OFFSET_END ? "OFFSET_END" : "[unknown]"); } #endif dp->dp_Type = ACTION_SET_FILE_SIZE; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_SET_FILE_SIZE.io_Offset; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode; break; case FSA_FILE_MODE: { D(bug("[packet] FILE_MODE: object 0x%08x (%s) mode 0x%x\b\n", handle->actual, handle_desc(handle), iofs->io_Union.io_FILE_MODE.io_FileMode)); dp->dp_Type = ACTION_CHANGE_MODE; /* We can only change access mode */ if ((iofs->io_Union.io_FILE_MODE.io_Mask & FMF_LOCK) == 0) { iofs->io_DosError = 0; goto reply; } if (handle->is_lock) { dp->dp_Arg1 = CHANGE_LOCK; dp->dp_Arg2 = (IPTR) handle->actual; } else { dp->dp_Arg1 = CHANGE_FH; handle->fh.fh_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) MKBADDR(&handle->fh); } dp->dp_Arg3 = (iofs->io_Union.io_FILE_MODE.io_FileMode & FMF_LOCK) ? EXCLUSIVE_LOCK : SHARED_LOCK; break; } case FSA_IS_INTERACTIVE: /* XXX is there some other way to query this? how does (eg) aos * console handler do it? */ iofs->io_Union.io_IS_INTERACTIVE.io_IsInteractive = FALSE; iofs->io_DosError = 0; goto reply; case FSA_SAME_LOCK: { struct ph_handle *h1, *h2; h1 = (struct ph_handle *) iofs->io_Union.io_SAME_LOCK.io_Lock[0]; h2 = (struct ph_handle *) iofs->io_Union.io_SAME_LOCK.io_Lock[1]; D(bug("[packet] SAME_LOCK: lock1 0x%08x (%s) lock2 0x%08x (%s)\n", h1->actual, handle_desc(h1), h2->actual, handle_desc(h2))); dp->dp_Type = ACTION_SAME_LOCK; dp->dp_Arg1 = (IPTR) h1->actual; dp->dp_Arg2 = (IPTR) h2->actual; break; } case FSA_EXAMINE: { struct FileInfoBlock *fib; D(bug("[packet] EXAMINE: lock 0x%08x (%s)\n", handle->actual, handle_desc(handle))); fib = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR); dp->dp_Type = (handle->is_lock) ? ACTION_EXAMINE_OBJECT : ACTION_EXAMINE_FH; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) MKBADDR(fib); break; } case FSA_EXAMINE_NEXT: D(bug("[packet] EXAMINE_NEXT: lock 0x%08x (%s) fib 0x%08x\n", handle->actual, handle_desc(handle), iofs->io_Union.io_EXAMINE_NEXT.io_fib)); dp->dp_Type = ACTION_EXAMINE_NEXT; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) MKBADDR(iofs->io_Union.io_EXAMINE_NEXT.io_fib); break; case FSA_CREATE_DIR: D(bug("[packet] CREATE_DIR: lock 0x%08x (%s) name '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_CREATE_DIR.io_Filename)); dp->dp_Type = ACTION_CREATE_DIR; dp->dp_Arg1 = (IPTR) (handle->is_lock ? handle->actual : NULL); dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_DIR.io_Filename); break; case FSA_IS_FILESYSTEM: dp->dp_Type = ACTION_IS_FILESYSTEM; break; case FSA_DISK_INFO: dp->dp_Type = ACTION_DISK_INFO; dp->dp_Arg1 = (IPTR) MKBADDR(iofs->io_Union.io_INFO.io_Info); break; case FSA_CREATE_HARDLINK: { struct ph_handle *target = (struct ph_handle *) iofs->io_Union.io_CREATE_HARDLINK.io_OldFile; D(bug("[packet] CREATE_HARDLINK: lock 0x%08x (%s) name '%s' " "target 0x%08x (%s)\n", handle->actual, handle_desc(handle), iofs->io_Union.io_CREATE_HARDLINK.io_Filename, target->actual, handle_desc(target))); dp->dp_Type = ACTION_MAKE_LINK; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_HARDLINK.io_Filename); dp->dp_Arg3 = (IPTR) target->actual; dp->dp_Arg4 = LINK_HARD; break; } case FSA_CREATE_SOFTLINK: D(bug("[packet] CREATE_SOFTLINK: lock 0x%08x (%s) name '%s' target '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_CREATE_SOFTLINK.io_Filename, iofs->io_Union.io_CREATE_SOFTLINK.io_Reference)); dp->dp_Type = ACTION_MAKE_LINK; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_CREATE_SOFTLINK.io_Filename); dp->dp_Arg3 = (IPTR) iofs->io_Union.io_CREATE_SOFTLINK.io_Reference; dp->dp_Arg4 = LINK_SOFT; break; case FSA_RENAME: D(bug("[packet] RENAME: lock 0x%08x (%s) name '%s' target '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_RENAME.io_Filename, iofs->io_Union.io_RENAME.io_NewName)); /* XXX the two paths from FSA_RENAME are copied directly from the * arguments to rename with no changes, so they may contain volume * specifiers, path seperators, etc. both can be calculated * relative to the handle. here we just pass them through to the * handler as-is, but I'm not sure if that's right. fat.handler at * least will do the right thing. this probably needs to be * revisited if another packet-based handler is ported */ dp->dp_Type = ACTION_RENAME_OBJECT; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RENAME.io_Filename); dp->dp_Arg3 = (IPTR) handle->actual; dp->dp_Arg4 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RENAME.io_NewName); break; case FSA_READ_SOFTLINK: D(bug("[packet] READ_SOFTLINK: lock 0x%08x (%s) name '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_READ_SOFTLINK.io_Filename)); dp->dp_Type = ACTION_READ_LINK; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_READ_SOFTLINK.io_Filename; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_READ_SOFTLINK.io_Buffer; dp->dp_Arg4 = (IPTR) iofs->io_Union.io_READ_SOFTLINK.io_Size; break; case FSA_DELETE_OBJECT: D(bug("[packet] DELETE: lock 0x%08x (%s) name '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_DELETE_OBJECT.io_Filename)); dp->dp_Type = ACTION_DELETE_OBJECT; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_DELETE_OBJECT.io_Filename); break; case FSA_SET_COMMENT: D(bug("[packet] SET_COMMENT: lock 0x%08x (%s) name '%s' comment '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_SET_COMMENT.io_Filename, iofs->io_Union.io_SET_COMMENT.io_Comment)); dp->dp_Type = ACTION_SET_COMMENT; dp->dp_Arg1 = 0; dp->dp_Arg2 = (IPTR) handle->actual; dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_COMMENT.io_Filename); dp->dp_Arg4 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_COMMENT.io_Comment); break; case FSA_SET_PROTECT: D(bug("[packet] SET_PROTECT: lock 0x%08x (%s) name '%s' attrs 0x%x\n", handle->actual, handle_desc(handle), iofs->io_Union.io_SET_PROTECT.io_Filename, iofs->io_Union.io_SET_PROTECT.io_Protection)); dp->dp_Type = ACTION_SET_PROTECT; dp->dp_Arg1 = 0; dp->dp_Arg2 = (IPTR) handle->actual; dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_PROTECT.io_Filename); dp->dp_Arg4 = (IPTR) iofs->io_Union.io_SET_PROTECT.io_Protection; break; case FSA_SET_OWNER: /* XXX untested */ D(bug("[packet] SET_OWNER: lock 0x%08x (%s) name '%s' uid 0x%x gid 0x%x\n", handle->actual, handle_desc(handle), iofs->io_Union.io_SET_OWNER.io_Filename, iofs->io_Union.io_SET_OWNER.io_UID, iofs->io_Union.io_SET_OWNER.io_GID)); dp->dp_Type = ACTION_SET_OWNER; dp->dp_Arg1 = 0; dp->dp_Arg2 = (IPTR) handle->actual; dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_OWNER.io_Filename); dp->dp_Arg4 = (IPTR) iofs->io_Union.io_SET_OWNER.io_GID << 16 | iofs->io_Union.io_SET_OWNER.io_UID; break; case FSA_SET_DATE: /* XXX untested */ #if defined(DEBUG) && DEBUG != 0 { struct DateTime dt; char datestr[LEN_DATSTRING]; dt.dat_Stamp = iofs->io_Union.io_SET_DATE.io_Date; dt.dat_Format = FORMAT_DOS; dt.dat_Flags = 0; dt.dat_StrDay = NULL; dt.dat_StrDate = datestr; dt.dat_StrTime = NULL; DateToStr(&dt); bug("[packet] SET_DATE: lock 0x%08x (%s) name '%s' date '%s'\n", handle->actual, handle_desc(handle), iofs->io_Union.io_SET_DATE.io_Filename, datestr); } #endif dp->dp_Type = ACTION_SET_DATE; dp->dp_Arg1 = 0; dp->dp_Arg2 = (IPTR) handle->actual; dp->dp_Arg3 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_SET_DATE.io_Filename); dp->dp_Arg4 = (IPTR) &iofs->io_Union.io_SET_DATE.io_Date; break; case FSA_MORE_CACHE: /* XXX untested */ D(bug("[packet] MORE_CACHE: buffers '0x%x'\n", iofs->io_Union.io_MORE_CACHE.io_NumBuffers)); dp->dp_Type = ACTION_MORE_CACHE; dp->dp_Arg1 = (IPTR) iofs->io_Union.io_MORE_CACHE.io_NumBuffers; break; case FSA_FORMAT: /* XXX untested */ D(bug("[packet] FSA_FORMAT: name '%s' type 0x%x\n", iofs->io_Union.io_FORMAT.io_VolumeName, iofs->io_Union.io_FORMAT.io_DosType)); dp->dp_Type = ACTION_FORMAT; dp->dp_Arg1 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_FORMAT.io_VolumeName); dp->dp_Arg2 = (IPTR) iofs->io_Union.io_FORMAT.io_DosType; break; case FSA_INHIBIT: D(bug("[packet] FSA_INHIBIT: %sinhibit\n", iofs->io_Union.io_INHIBIT.io_Inhibit == 0 ? "un" : "")); dp->dp_Type = ACTION_INHIBIT; dp->dp_Arg1 = iofs->io_Union.io_INHIBIT.io_Inhibit ? DOSTRUE : DOSFALSE; break; case FSA_RELABEL: D(bug("[packet] FSA_RELABEL: name '%s'\n", iofs->io_Union.io_RELABEL.io_NewName)); dp->dp_Type = ACTION_RENAME_DISK; dp->dp_Arg1 = (IPTR) mkbstr(pkt->pool, iofs->io_Union.io_RELABEL.io_NewName); break; case FSA_LOCK_RECORD: /* XXX untested */ #if defined(DEBUG) && DEBUG != 0 { ULONG mode = iofs->io_Union.io_RECORD.io_RecordMode; bug("[packet] FSA_LOCK_RECORD: handle 0x%08x offset %ld size %ld mode %d (%s) timeout %d\n", handle->actual, (LONG) iofs->io_Union.io_RECORD.io_Offset, iofs->io_Union.io_RECORD.io_Size, mode, mode == REC_EXCLUSIVE ? "REC_EXCLUSIVE" : mode == REC_EXCLUSIVE_IMMED ? "REC_EXCLUSIVE_IMMED" : mode == REC_SHARED ? "REC_SHARED" : mode == REC_SHARED_IMMED ? "REC_SHARED_IMMED" : "[unknown]", iofs->io_Union.io_RECORD.io_Timeout); } #endif dp->dp_Type = ACTION_LOCK_RECORD; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_RECORD.io_Offset; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_RECORD.io_Size; dp->dp_Arg4 = (IPTR) iofs->io_Union.io_RECORD.io_RecordMode; dp->dp_Arg5 = (IPTR) iofs->io_Union.io_RECORD.io_Timeout; break; case FSA_UNLOCK_RECORD: /* XXX untested */ D(bug("[packet] FSA_UNLOCK_RECORD: handle 0x%08x offset %ld size %ld\n", handle->actual, (LONG) iofs->io_Union.io_RECORD.io_Offset, iofs->io_Union.io_RECORD.io_Size)); dp->dp_Type = ACTION_FREE_RECORD; dp->dp_Arg1 = (IPTR) handle->actual; dp->dp_Arg2 = (IPTR) iofs->io_Union.io_RECORD.io_Offset; dp->dp_Arg3 = (IPTR) iofs->io_Union.io_RECORD.io_Size; break; case FSA_ADD_NOTIFY: D(bug("[packet] FSA_ADD_NOTIFY: nr 0x%08x name '%s'\n", iofs->io_Union.io_NOTIFY.io_NotificationRequest, iofs->io_Union.io_NOTIFY.io_NotificationRequest->nr_FullName)); dp->dp_Type = ACTION_ADD_NOTIFY; dp->dp_Arg1 = (SIPTR) iofs->io_Union.io_NOTIFY.io_NotificationRequest; break; case FSA_REMOVE_NOTIFY: D(bug("[packet] FSA_REMOVE_NOTIFY: nr 0x%08x name '%s'\n", iofs->io_Union.io_NOTIFY.io_NotificationRequest, iofs->io_Union.io_NOTIFY.io_NotificationRequest->nr_FullName)); dp->dp_Type = ACTION_REMOVE_NOTIFY; dp->dp_Arg1 = (SIPTR) iofs->io_Union.io_NOTIFY.io_NotificationRequest; break; /* XXX implement */ case FSA_EXAMINE_ALL: case FSA_EXAMINE_ALL_END: case FSA_MOUNT_MODE: case FSA_CHANGE_SIGNAL: case FSA_PARENT_DIR: case FSA_PARENT_DIR_POST: case FSA_CONSOLE_MODE: D(bug("[packet] command not implemented\n")); iofs->io_DosError = ERROR_NOT_IMPLEMENTED; goto reply; default: D(bug("[packet] unknown command\n")); iofs->io_DosError = ERROR_ACTION_NOT_KNOWN; goto reply; } D(bug("[packet] converted to %s packet\n", act_str(dp->dp_Type))); /* WaitIO() will look into this */ iofs->IOFS.io_Message.mn_Node.ln_Type = NT_MESSAGE; /* since these all go to the packet handler process, they can't be done now */ iofs->IOFS.io_Flags &= ~IOF_QUICK; /* send the packet */ PutMsg(&(handle->mount->process->pr_MsgPort), dp->dp_Link); return; /* jump here to reply to the packet now, handling IOF_QUICK appropriately */ reply: D(bug("[packet] replying directly with error %d\n", iofs->io_DosError)); /* kill the packet */ DeletePool(pkt->pool); /* if they can handle quick replies, just bail out */ if (iofs->IOFS.io_Flags & IOF_QUICK) return; /* otherwise tell them properly */ ReplyMsg((APTR) iofs); }