static void _handle_multipart_request( uint32_t transaction_id, uint16_t type, uint16_t flags, const buffer *body, void *user_data ) { struct protocol *protocol = user_data; assert( protocol ); if ( save_outstanding_request( &protocol->ctrl, transaction_id, type, flags ) == -1 ) { send_error_message( transaction_id, OFPET_BAD_REQUEST, OFPBRC_MULTIPART_BUFFER_OVERFLOW ); return; } const uint32_t capabilities = protocol->ctrl.capabilities; switch( type ) { case OFPMP_DESC: { // the request body is empty handle_desc( transaction_id, protocol->args->progname ); } break; case OFPMP_FLOW: { const struct ofp_flow_stats_request *req = ( const struct ofp_flow_stats_request * ) body->data; handle_flow_stats( req, transaction_id, capabilities ); } break; case OFPMP_AGGREGATE: { const struct ofp_aggregate_stats_request *req = ( const struct ofp_aggregate_stats_request * ) body->data; handle_aggregate_stats( req, transaction_id, capabilities ); } break; case OFPMP_TABLE: { // no request body is included with this type. handle_table_stats( transaction_id, capabilities ); } break; case OFPMP_PORT_STATS: { const struct ofp_port_stats_request *req = ( const struct ofp_port_stats_request * ) body->data; handle_port_stats( req, transaction_id, capabilities ); } break; case OFPMP_PORT_DESC: { // no request body is included with this type. handle_port_desc( transaction_id ); } break; case OFPMP_QUEUE: { const struct ofp_queue_stats_request *req = ( const struct ofp_queue_stats_request * ) body->data; handle_queue_stats( req, transaction_id, capabilities ); } break; case OFPMP_GROUP: { const struct ofp_group_stats_request *req = ( const struct ofp_group_stats_request * ) body->data; handle_group_stats( req, transaction_id, capabilities ); } break; case OFPMP_GROUP_DESC: { // the request body is empty. handle_group_desc( transaction_id, capabilities ); } break; case OFPMP_GROUP_FEATURES: { handle_group_features( transaction_id, capabilities ); } break; case OFPMP_METER: { const struct ofp_meter_multipart_request *req = ( const struct ofp_meter_multipart_request * ) body->data; handle_meter_stats( req, transaction_id ); } break; case OFPMP_METER_CONFIG: { const struct ofp_meter_multipart_request *req = ( const struct ofp_meter_multipart_request * ) body->data; handle_meter_config( req, transaction_id ); } break; case OFPMP_METER_FEATURES: { handle_meter_features( transaction_id ); } break; case OFPMP_TABLE_FEATURES: { /* * TODO Currently the setting of table features not supported by datapath */ handle_table_features( transaction_id ); } break; case OFPMP_EXPERIMENTER: { const struct ofp_experimenter_multipart_header *em_hdr = ( const struct ofp_experimenter_multipart_header * ) body->data; handle_experimenter_stats( em_hdr, transaction_id ); } break; default: send_error_message( transaction_id, OFPET_BAD_REQUEST, OFPBRC_BAD_MULTIPART ); break; } }
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); }