static __regargs BOOL AllocHunks(FileT *fh, LONG hunkNum, HunkT **hunks) { LONG memFlags, n, size; HunkT *hunk, *prev = NULL; while (hunkNum--) { /* size specifiers including memory attribute flags */ FileRead(fh, ONSTACK(n)); memFlags = n >> 30; size = n & 0x3FFFFFFF; if (memFlags == 1) memFlags = MEMF_CHIP; else if (memFlags == 2) memFlags = MEMF_FAST; else memFlags = MEMF_PUBLIC; if (!(hunk = AllocMem(sizeof(HunkT) + n * sizeof(LONG), memFlags))) return FALSE; hunk->size = n * sizeof(LONG); hunk->next = NULL; if (prev) prev->next = MKBADDR(&hunk->next); prev = hunk; *hunks++ = hunk; } return TRUE; }
static BSTR mkbstr(APTR pool, CONST_STRPTR str) { UBYTE *buf; UBYTE len; len = strlen(str) & 0xff; buf = AllocPooled(pool, len + 1); CopyMem(str, &(buf[1]), len); buf[0] = len; return (BSTR) MKBADDR(buf); }
void mount(struct HDTBPartition *table, struct PartitionHandle *ph, STRPTR name, struct DosEnvec *de) { struct ExpansionBase *ExpansionBase; struct DeviceNode *dn; struct DosEnvec *nde; IPTR *params; ULONG i; D(bug("[HDToolBox] mount('%s')\n", name)); #error "TODO: pass DOS device name in params[0] and set handler name manually" #warning "TODO: get filesystem" if ((de->de_DosType & 0xFFFFFF00) == BBNAME_DOS) { ExpansionBase = (struct ExpansionBase *)OpenLibrary("expansion.library",41); if (ExpansionBase) { params = (IPTR *)AllocVec(sizeof(struct DosEnvec)+sizeof(IPTR)*4, MEMF_PUBLIC | MEMF_CLEAR); if (params) { nde = (struct DosEnvec *)¶ms[4]; CopyMem(de, nde, sizeof(struct DosEnvec)); params[0] = (IPTR)"afs.handler"; params[1] = (IPTR)table->hd->devname; params[2] = (IPTR)table->hd->unit; params[3] = 0; i = getOffset(ph->root); nde->de_LowCyl += i; nde->de_HighCyl += i; dn = MakeDosNode(params); if (dn) { dn->dn_Name = MKBADDR(AllocVec(AROS_BSTR_MEMSIZE4LEN(strlen(name)), MEMF_PUBLIC)); dn->dn_Ext.dn_AROS.dn_DevName = AROS_BSTR_ADDR(dn->dn_Name); i = 0; do { AROS_BSTR_putchar(dn->dn_Name, i, name[i]); } while (name[i++]); AROS_BSTR_setstrlen(dn->dn_Name, i-1); AddDosNode(nde->de_BootPri, ADNF_STARTPROC, dn); } else FreeVec(params); } CloseLibrary((struct Library *)ExpansionBase); } } else kprintf("ignored %s: unknown FS (0x%lx)\n", name, de->de_DosType); }
// Get the root of a pathname int get_path_root(char *path,char *root_name,struct DateStamp *date) { struct DevProc *proc; D_S(struct InfoData, info) struct DosList *dos; // Get device process if (!(proc=GetDeviceProc(path,0))) return 0; // Send info packet #ifdef __AROS__ if (((struct Library *)DOSBase)->lib_Version<50) { //Info(proc->dvp_Lock,info); BPTR lock; if (!(lock=Lock(path,SHARED_LOCK))) { FreeDeviceProc(proc); return 0; } Info(lock,info); UnLock(lock); } else #endif DoPkt(proc->dvp_Port,ACTION_DISK_INFO,MKBADDR(info),0,0,0,0); // Get DOS list pointer if (!(dos=(struct DosList *)BADDR(info->id_VolumeNode))) { FreeDeviceProc(proc); return 0; } // Get root device name if (root_name) { if (dos->dol_Name) BtoCStr(dos->dol_Name,root_name,32); else *root_name=0; } // Copy datestamp if buffer supplied if (date) *date=dos->dol_misc.dol_volume.dol_VolumeDate; // Free device process FreeDeviceProc(proc); // Return disk state return info->id_DiskState; }
SIPTR handleNIL(LONG action, SIPTR arg1, SIPTR arg2, SIPTR arg3) { switch(action) { case(ACTION_FINDUPDATE): case(ACTION_FINDINPUT): case(ACTION_FINDOUTPUT): { struct FileHandle * fh = BADDR(arg1); fh->fh_Type = BNULL; fh->fh_Interactive = DOSFALSE;/* NIL: is not considered interactive */ return (SIPTR)MKBADDR(fh); } case(ACTION_INFO): return (SIPTR)0; case(ACTION_FREE_LOCK): { FreeMem((APTR)arg1, sizeof(struct FileLock)); return (SIPTR)0; } case(ACTION_COPY_DIR_FH): { struct FileLock *fl = AllocMem(sizeof(struct FileLock), MEMF_PUBLIC | MEMF_CLEAR); fl->fl_Access = SHARED_LOCK; return (SIPTR)MKBADDR(fl); } case(ACTION_FH_FROM_LOCK): { struct FileHandle * fh = BADDR(arg2); fh->fh_Interactive = DOSFALSE; FreeMem((APTR)arg3, sizeof(struct FileLock)); return (SIPTR)DOSTRUE; } case(ACTION_WRITE): return (SIPTR)arg3; case(ACTION_PARENT_FH): return (SIPTR)BNULL; default: return TRUE; } }
/******************************************* Name : remDosVolume Descr.: removes a volume added by addDosVolume or if there are some locks active set dol_LockList Input : volume - volume to remove Output: - ********************************************/ void remDosVolume(struct AFSBase *afsbase, struct Volume *volume) { struct DosList *dl; dl = volume->volumenode; if (dl) { if (volume->locklist != NULL) { D(bug("[afs 0x%08lX] VolumeNode in use, keeping as offline\n", volume)); dl->dol_misc.dol_volume.dol_LockList = MKBADDR(volume->locklist); } else { D(bug("[afs 0x%08lX] Removing VolumeNode\n", volume)); remDosNode(afsbase, dl); } volume->volumenode = NULL; } }
BOOL MyRenameDosEntry(struct Handler *handler, struct DosList *entry, const TEXT *name) { LONG error = 0; UPINT length; TEXT *name_copy, *old_name; /* Allocate new string */ name_copy = NULL; if(name != NULL) { length = StrLen(name); #ifdef AROS_FAST_BPTR name_copy = AllocVec(length + 1, MEMF_PUBLIC); if(name_copy != NULL) { CopyMem(name, name_copy, length + 1); } #else name_copy = AllocVec(length + 2, MEMF_PUBLIC); if(name_copy != NULL) { name_copy[0] = (UBYTE)(length > 255 ? 255 : length); CopyMem(name, name_copy + 1, length + 1); } #endif else error = IoErr(); } /* Deallocate old string and set new one */ if(error == 0) { old_name = BADDR(entry->dol_Name); FreeVec(old_name); entry->dol_Name = MKBADDR(name_copy); } /* Store error code and return success flag */ SetIoErr(error); return error == 0; }
// Get disk info LONG GetDiskInfo(char *device,struct InfoData *info) { struct DevProc *proc; struct DosList *dos; LONG res=0; // Get device proc if (!(proc=GetDeviceProc(device,0))) return 0; // Send packet #ifdef __AROS__ if (((struct Library *)DOSBase)->lib_Version<50) { //res=Info(proc->dvp_Lock,info); BPTR lock; if ((lock=Lock(device,SHARED_LOCK))) { res=Info(lock,info); UnLock(lock); } } else #endif res=DoPkt(proc->dvp_Port,ACTION_DISK_INFO,MKBADDR(info),0,0,0,0); // Clear "in use" flag to indicate formatting by default info->id_InUse=0; // Get doslist pointer if ((dos=DeviceFromHandler(proc->dvp_Port,NULL))) { // Invalid device? if (!GetDeviceUnit(dos->dol_misc.dol_handler.dol_Startup,NULL,NULL)) { // Disk can't be formatted info->id_InUse=1; } } // Free device proc FreeDeviceProc(proc); return res; }
/******************************************* Name : initDeviceList Descr.: initializes a devicelist structure Input : devicelist - devicelist structure to initialize rootblock - cacheblock of the rootblock Output: DOSTRUE for success; DOSFALSE otherwise ********************************************/ LONG initDeviceList ( struct AFSBase *afsbase, struct Volume *volume, struct BlockCache *rootblock ) { STRPTR name; BSTR newname; UBYTE i; name=(char *)rootblock->buffer+(BLK_DISKNAME_START(volume)*4); volume->devicelist.dl_Next = 0; volume->devicelist.dl_Type = DLT_VOLUME; volume->devicelist.dl_Lock = 0; volume->devicelist.dl_VolumeDate.ds_Days = AROS_BE2LONG(rootblock->buffer[BLK_ROOT_DAYS(volume)]); volume->devicelist.dl_VolumeDate.ds_Minute = AROS_BE2LONG(rootblock->buffer[BLK_ROOT_MINS(volume)]); volume->devicelist.dl_VolumeDate.ds_Tick = AROS_BE2LONG(rootblock->buffer[BLK_ROOT_TICKS(volume)]); volume->devicelist.dl_LockList = 0; volume->devicelist.dl_DiskType = volume->dostype; if (volume->devicelist.dl_Name != BNULL) { newname = volume->devicelist.dl_Name; } else { newname = MKBADDR(AllocVec(32,MEMF_CLEAR | MEMF_PUBLIC)); if (newname == BNULL) return DOSFALSE; } for (i=0; i<name[0]; i++) AROS_BSTR_putchar(newname, i, name[i+1]); AROS_BSTR_setstrlen(newname, name[0]); volume->devicelist.dl_Name = newname; return DOSTRUE; }
__regargs BPTR LoadExecutable(FileT *fh) { HunkT **hunks; LONG n, hunkId, hunkNum; FileRead(fh, ONSTACK(hunkId)); hunkId &= 0x3FFFFFFF; if (hunkId == HUNK_HEADER) { /* Skip resident library names. */ do { FileRead(fh, ONSTACK(n)); if (n == 0) break; FileSeek(fh, n * sizeof(LONG), SEEK_CUR); } while(1); /* * number of hunks (including resident libraries and overlay hunks) * number of the first (root) hunk * number of the last (root) hunk */ { struct { LONG hunks, first, last; } s; FileRead(fh, ONSTACK(s)); hunkNum = s.last - s.first + 1; } hunks = __builtin_alloca(sizeof(HunkT *) * hunkNum); if (AllocHunks(fh, hunkNum, hunks)) { BPTR seglist = MKBADDR(&(hunks[0]->next)); if (LoadHunks(fh, hunks)) return seglist; FreeSegList(seglist); } } return NULL; }
BOOL MyRenameDosEntry(struct DosList *entry, const TEXT *name) { LONG error = 0; UPINT length; TEXT *name_copy, *old_name; /* Allocate new string */ name_copy = NULL; if(name != NULL) { length = StrLen(name); name_copy = AllocVec(length + 2, MEMF_PUBLIC); if(name_copy != NULL) { CopyMem(name, name_copy + 1, length + 1); *name_copy = length; } else error = IoErr(); } /* Deallocate old string and set new one */ if(error == 0) { old_name = BADDR(entry->dol_Name); FreeVec(old_name); entry->dol_Name = MKBADDR(name_copy); } /* Store error code and return success flag */ SetIoErr(error); return error == 0; }
static int GM_UNIQUENAME(Init)(LIBBASETYPEPTR conbase) { static const char *devnames[2] = { "CON", "RAW" }; struct DeviceNode *dn; int i; /* Really bad hack, but con_handler is in ROM, intuition.library is open, if intuition.library is open, then Input.Device must be open, too, ... and I don't like to OpenDevice just for Peek- Qualifier */ #warning InputDevice open hack. Hope this is not a problem since it is only used for PeekQualifier Forbid(); conbase->inputbase = (struct Device *)FindName(&SysBase->DeviceList, "input.device"); Permit(); /* Install CON: and RAW: handlers into device list * * KLUDGE: con-handler should create only one device node, depending on * the startup packet it gets. The mountlists for CON:/RAW: should be into dos.library bootstrap * routines. */ for(i = 0; i < 2; i++) { if((dn = AllocMem(sizeof (struct DeviceNode) + 4 + AROS_BSTR_MEMSIZE4LEN(3), MEMF_CLEAR|MEMF_PUBLIC))) { BSTR s = (BSTR)MKBADDR(((IPTR)dn + sizeof(struct DeviceNode) + 3) & ~3); WORD a; for(a = 0; a < 3; a++) { AROS_BSTR_putchar(s, a, devnames[i][a]); } AROS_BSTR_setstrlen(s, 3); dn->dn_Type = DLT_DEVICE; /* i equals 1 when dn_DevName is "RAW", and 0 otherwise. This tells con_task that it has to start in RAW mode */ dn->dn_Ext.dn_AROS.dn_Unit = (struct Unit *)i; dn->dn_Ext.dn_AROS.dn_Device = &conbase->device; dn->dn_Handler = NULL; dn->dn_Startup = NULL; dn->dn_Name = s; dn->dn_Ext.dn_AROS.dn_DevName = AROS_BSTR_ADDR(dn->dn_Name); if (AddDosEntry((struct DosList *)dn)) { if (i == 0) continue; return TRUE; } FreeMem(dn, sizeof (struct DeviceNode)); } } return FALSE; }
/**************************** Function: VPrintf Vector: 159 Offset: -954 Arguments: D1.L pointer to format string D2.L pointer to data array Returns: D0.L number of bytes written ****************************/ int lib_dos_f_VPrintf(emumsg_syscall_t *msg) { cpu_t *cpu; uint8_t *fptr, *bptr, *sptr; uint8_t ch, *buf; uint32_t fvptr, dvptr; int rc, status, f_long; uint16_t data16; uint32_t data32; DEBUG(4) dprintf("dos.library: lib_dos_f_VPrintf() called\n"); cpu = msg->proc->cpu; DEBUG(5) dprintf(" Format string (D1): 0x%x, Data stream (D2): 0x%x\n",cpu->d[1],cpu->d[2]); if(cpu->d[1] == 0) { DEBUG(1) dprintf("Warning: dos.library: lib_dos_f_VPrintf() called with NULL format string, skipping\n"); return HOOK_DONE; } /* TODO: Implement some kind of check for MMU entry ending within the string */ /* Allocate a native buffer for the converted native data stream */ buf = (uint8_t *)AllocVec(LIB_DOS_F_VPRINTF_BUFFER_SIZE,MEMF_PUBLIC|MEMF_CLEAR); if(buf == NULL) { dprintf("Error: dos.library: lib_dos_f_VPrintf: AllocVec failed for buffer\n"); return HOOK_END_PROC; } bptr = buf; /* Loop through the string to build a special mapping for the data stream */ fvptr = cpu->d[1]; dvptr = cpu->d[2]; status = 0; f_long = 0; rc = READMEM_8(fvptr++, &ch); if(rc) return rc; while(ch != '\0'){ if(status == 0) { /* Idle, look for a % */ if(ch == '%') { f_long = 0; status = 1; } } else { /* Got a % */ if(ch=='-' || (ch>='0' && ch<='9') || ch=='.') { /* Format parameters */ } else if(ch=='l') { /* Long indicator */ f_long = 1; } else if(ch=='d' || ch=='u' || ch=='x' || ch=='c') { /* Signed decimal, unsigned decimal, hexadecimal or character */ if(f_long) { /* 32bit data */ rc = READMEM_32(dvptr, &data32); if(rc) return rc; dvptr += 4; *((ULONG *)bptr)=(ULONG)data32; bptr += sizeof(LONG); } else { /* 16bit data */ rc = READMEM_16(dvptr, &data16); if(rc) return rc; dvptr += 2; *((UWORD *)bptr)=(UWORD)data32; bptr += sizeof(UWORD); } status = 0; } else if(ch=='s') { /* String */ /* 32bit pointer */ rc = READMEM_32(dvptr, &data32); if(rc) return rc; dvptr += 4; /* Get native pointer to string */ sptr = vptr(data32); /* TODO: Check mappings */ *((APTR *)bptr)=(APTR)sptr; bptr += sizeof(APTR); status = 0; } else if(ch=='b') { /* BString */ /* 32bit pointer */ rc = READMEM_32(dvptr, &data32); if(rc) return rc; dvptr += 4; /* BPTR -> APTR */ data32 <<= 2; /* Get native pointer to string */ sptr = vptr(data32); /* TODO: Check mappings */ *((BPTR *)bptr)=MKBADDR((APTR)sptr); bptr += sizeof(BPTR); status = 0; } else { /* Literal % or illegal char */ status = 0; } } rc = READMEM_8(fvptr++, &ch); if(rc) return rc; } fptr = vptr(cpu->d[1]); DEBUG(5) dprintf(" Format string (native): %p, Data stream (native): %p\n",fptr,buf); /* Prepare syscall */ msg->arg[0]._strptr = (STRPTR)fptr; msg->arg[1]._aptr = (APTR)buf; /* Remember buffer */ msg->internalPtr = buf; return HOOK_SYSCALL; }
INPUTS task - The new filesystem handler. RESULT The old filesystem handler. NOTES EXAMPLE BUGS SEE ALSO GetFileSysTask() INTERNALS *****************************************************************************/ { AROS_LIBFUNC_INIT struct Process *pr = (struct Process *)FindTask(NULL); BPTR old; old = pr->pr_FileSystemTask; pr->pr_FileSystemTask = MKBADDR(task); return BADDR(old); AROS_LIBFUNC_EXIT } /* SetFileSysTask */
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); }
void IOFS_SendPkt(struct DosPacket *dp, struct MsgPort *replyport, struct DosLibrary *DOSBase) { /* * Trying to emulate the packet system by rewriting the * packets to IO Requests. Sometimes there are too many * parameters in the packet but thats fine. If there are * not enough parameters or the wrong type etc. then * it is more difficult to translate the packet. * */ struct IOFileSys *iofs = AllocMem(sizeof(struct IOFileSys), MEMF_CLEAR); struct FileHandle *fh; BPTR oldCurDir; LONG result; if (iofs != NULL) { /* * Also attach the packet to the io request. * Will remain untouched by the driver. */ iofs->io_PacketEmulation = dp; /* * In case the packet is to be aborted * I know which IORequest to use. The user will * use the packet itself to abort the operation. */ dp->dp_Arg7 = (IPTR)iofs; iofs->IOFS.io_Message.mn_Node.ln_Type = NT_REPLYMSG; iofs->IOFS.io_Message.mn_ReplyPort = replyport; iofs->IOFS.io_Message.mn_Length = sizeof(struct IOFileSys); iofs->IOFS.io_Flags = 0; /* * Have to rewrite this packet... */ switch (dp->dp_Type) { case ACTION_NIL: case ACTION_READ_RETURN: case ACTION_WRITE_RETURN: case ACTION_TIMER: kprintf("This packet is a reserved one and should not be sent" " by you!\n"); // Alert(); return; // case ACTION_GET_BLOCK: case ACTION_DISK_CHANGE: case ACTION_DISK_TYPE: case ACTION_EVENT: case ACTION_SET_MAP: kprintf("This packet is obsolete. (ACTION type %d)\n", dp->dp_Type); return; case ACTION_FINDINPUT: // Open() MODE_OLDFILE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { kprintf("Error: Didn't find file\n"); return; } kprintf("Returned from DoNameAsynch()\n"); break; case ACTION_FINDOUTPUT: // Open() MODE_NEWFILE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_LOCK | FMF_CREATE | FMF_CLEAR | FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_FINDUPDATE: // Open() MODE_READWRITE [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Command = FSA_OPEN_FILE; iofs->io_Union.io_OPEN_FILE.io_FileMode = FMF_CREATE | FMF_WRITE | FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_READ: // Read() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_READ; iofs->io_Union.io_READ_WRITE.io_Buffer = (APTR)dp->dp_Arg2; iofs->io_Union.io_READ_WRITE.io_Length = (LONG)dp->dp_Arg3; break; case ACTION_WRITE: // Write() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_WRITE; iofs->io_Union.io_READ_WRITE.io_Buffer = (APTR)dp->dp_Arg2; iofs->io_Union.io_READ_WRITE.io_Length = (LONG)dp->dp_Arg3; break; case ACTION_SEEK: // Seek() [*] CH fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* If the file is in write mode flush it. This is done synchronously as otherwise the seek may be served before the flush. (TODO: What are a reasonable semantics here?) */ if (fh->fh_Flags & FHF_WRITE) { Flush(MKBADDR(fh)); } else { /* Read mode. Just reinit the buffers. We can't call Flush() in this case as that would end up in recursion. */ fh->fh_Pos = fh->fh_End = fh->fh_Buf; } iofs->IOFS.io_Command = FSA_SEEK; iofs->io_Union.io_SEEK.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_SEEK.io_SeekMode = dp->dp_Arg3; break; case ACTION_SET_FILE_SIZE: // SetFileSize() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_FILE_SIZE; iofs->io_Union.io_SET_FILE_SIZE.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_SET_FILE_SIZE.io_SeekMode = dp->dp_Arg3; break; case ACTION_EXAMINE_FH: // ExamineFH() case ACTION_EXAMINE_OBJECT: // Examine() [*] -- the same thing // in AROS { UBYTE *buffer = AllocVec(sizeof(struct ExAllData), MEMF_PUBLIC | MEMF_CLEAR); if (buffer == NULL) { dp->dp_Res1 = DOSFALSE; dp->dp_Res2 = ERROR_NO_FREE_STORE; return; } fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_EXAMINE; iofs->io_Union.io_EXAMINE.io_ead = (struct ExAllData *)buffer; iofs->io_Union.io_EXAMINE.io_Size = sizeof(struct ExAllData); iofs->io_Union.io_EXAMINE.io_Mode = ED_OWNER; /* A supplied FileInfoBlock (is a BPTR) is in dp_Arg2 */ break; } case ACTION_EXAMINE_NEXT: // ExNext() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_EXAMINE_NEXT; iofs->io_Union.io_EXAMINE_NEXT.io_fib = (BPTR)dp->dp_Arg2; break; case ACTION_CREATE_DIR: // CreateDir() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_CREATE_DIR; iofs->io_Union.io_CREATE_DIR.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg2); iofs->io_Union.io_CREATE_DIR.io_Protection = 0; break; case ACTION_DELETE_OBJECT: // DeleteFile() [*] // ARG1: LOCK Lock to which ARG2 is relative // ARG2: BSTR Name of object to delete (relative to ARG1) fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* IFS_DELETE_OBJECT just consists of a STRPTR so we have to use NameFromLock() here -- TODO */ // iofs->io_Union.io_DELETE_OBJECT.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg2); iofs->IOFS.io_Command = FSA_DELETE_OBJECT; break; case ACTION_RENAME_OBJECT: // Rename() /* TODO */ break; case ACTION_LOCK_RECORD: // LockRecord() fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->io_Union.io_RECORD.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_RECORD.io_Size = (LONG)dp->dp_Arg3; iofs->io_Union.io_RECORD.io_RecordMode = (LONG)dp->dp_Arg4; iofs->io_Union.io_RECORD.io_Timeout = (LONG)dp->dp_Arg5; break; case ACTION_FREE_RECORD: // UnlockRecord() fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->io_Union.io_RECORD.io_Offset = (QUAD)dp->dp_Arg2; iofs->io_Union.io_RECORD.io_Size = (LONG)dp->dp_Arg3; iofs->io_Union.io_RECORD.io_RecordMode = (LONG)dp->dp_Arg4; break; case ACTION_PARENT: // ParentDir() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; // Shared lock oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, "/", DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } return; case ACTION_SET_PROTECT: // SetProtection() [*] // STRPTR io_Filename; /* The file to change. */ // ULONG io_Protection; /* The new protection bits. */ fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_PROTECT; iofs->io_Union.io_SET_PROTECT.io_Protection = dp->dp_Arg4; iofs->io_Union.io_SET_PROTECT.io_Filename = BStrtoCStr(dp->dp_Arg3); break; case ACTION_SET_COMMENT: // SetComment() [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_COMMENT; iofs->io_Union.io_SET_COMMENT.io_Filename = BStrtoCStr((BSTR)dp->dp_Arg3); iofs->io_Union.io_SET_COMMENT.io_Comment = BStrtoCStr(dp->dp_Arg4); break; case ACTION_LOCATE_OBJECT: // Lock() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; switch (dp->dp_Arg3) { case EXCLUSIVE_LOCK: iofs->io_Union.io_OPEN.io_FileMode = FMF_LOCK | FMF_READ; break; case SHARED_LOCK: iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; break; default: iofs->io_Union.io_OPEN.io_FileMode = dp->dp_Arg3; break; } oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg2), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } dp->dp_Arg6 = (IPTR)AllocDosObject(DOS_FILEHANDLE, NULL); if (dp->dp_Arg6 == (IPTR)NULL) { return; } break; case ACTION_COPY_DIR: // DupLock() case ACTION_COPY_DIR_FH: // DupLockFromFH() -- the same thing // in AROS fh = (struct FileHandle *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_OPEN; /* Create a shared lock */ iofs->io_Union.io_OPEN.io_FileMode = FMF_READ; oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); result = DoNameAsynch(iofs, "", DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } dp->dp_Arg6 = (IPTR)AllocDosObject(DOS_FILEHANDLE, NULL); if (dp->dp_Arg6 == (IPTR)NULL) { return; } break; case ACTION_END: // Close() [*] case ACTION_FREE_LOCK: // UnLock() -- the same thing in AROS fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; /* If the filehandle has a pending write on it Flush() the buffer. This is made synchronously... */ if (fh->fh_Flags & FHF_WRITE) { Flush(MKBADDR(fh)); } iofs->IOFS.io_Command = FSA_CLOSE; break; case ACTION_SET_DATE: // SetFileDate() [*] fh = (struct FileHandle *)dp->dp_Arg2; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SET_DATE; memcpy(&iofs->io_Union.io_SET_DATE.io_Date, (APTR)dp->dp_Arg4, sizeof(struct DateStamp)); oldCurDir = CurrentDir((BPTR)dp->dp_Arg2); result = DoNameAsynch(iofs, BStrtoCStr((BSTR)dp->dp_Arg3), DOSBase); CurrentDir(oldCurDir); if (result != 0) { return; } break; case ACTION_SAME_LOCK: // SameLock() [*] fh = (struct FileHandle *)dp->dp_Arg1; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_SAME_LOCK; iofs->io_Union.io_SAME_LOCK.io_Lock[0] = BADDR((BPTR)dp->dp_Arg1); iofs->io_Union.io_SAME_LOCK.io_Lock[1] = BADDR((BPTR)dp->dp_Arg2); break; case ACTION_MAKE_LINK: // MakeLink() { STRPTR name = BStrtoCStr(dp->dp_Arg2); if (dp->dp_Arg4 == LINK_SOFT) { /* We want a soft-link. */ iofs->IOFS.io_Command = FSA_CREATE_SOFTLINK; iofs->io_Union.io_CREATE_SOFTLINK.io_Reference = (STRPTR)dp->dp_Arg3; } else { /* We want a hard-link. */ struct FileHandle *fh = (struct FileHandle *)BADDR((BPTR)dp->dp_Arg3); struct DevProc *dvp; /* We check, if name and dest are on the same device. */ if ((dvp = GetDeviceProc(name, NULL)) == NULL) { /* TODO: Simulate packet return */ return; } if (dvp->dvp_Port != (struct MsgPort *)fh->fh_Device) { FreeDeviceProc(dvp); SetIoErr(ERROR_RENAME_ACROSS_DEVICES); /* TODO: Simulate packet return */ return; } FreeDeviceProc(dvp); iofs->IOFS.io_Command = FSA_CREATE_HARDLINK; iofs->io_Union.io_CREATE_HARDLINK.io_OldFile = fh->fh_Unit; } oldCurDir = CurrentDir((BPTR)dp->dp_Arg1); DoNameAsynch(iofs, name, DOSBase); CurrentDir(oldCurDir); } break; case ACTION_READ_LINK: // ReadLink() /* TODO */ break; case ACTION_EXAMINE_ALL: // ExAll() /* TODO */ break; case ACTION_ADD_NOTIFY: // StartNotify() { struct NotifyRequest *notify = (struct NotifyRequest *)BADDR(dp->dp_Arg1); struct FileHandle *dir; iofs->IOFS.io_Command = FSA_ADD_NOTIFY; iofs->io_Union.io_NOTIFY.io_NotificationRequest = notify; notify->nr_MsgCount = 0; if (strchr(notify->nr_Name, ':') != NULL) { DoNameAsynch(iofs, notify->nr_Name, DOSBase); } else { dir = BADDR(CurrentDir(NULL)); CurrentDir(MKBADDR(dir)); /* Set back the current dir */ if (dir == NULL) { return; } iofs->IOFS.io_Device = dir->fh_Device; iofs->IOFS.io_Unit = dir->fh_Unit; /* Save device for EndNotify() purposes */ notify->nr_Handler = (struct MsgPort *) dir->fh_Device; if (iofs->IOFS.io_Device == NULL) { return; } } } break; case ACTION_REMOVE_NOTIFY: // EndNotify() { struct NotifyRequest *notify = (struct NotifyRequest *)BADDR(dp->dp_Arg1); iofs->IOFS.io_Command = FSA_REMOVE_NOTIFY; iofs->io_Union.io_NOTIFY.io_NotificationRequest = notify; if (strchr(notify->nr_Name, ':')) { DoNameAsynch(iofs, notify->nr_Name, DOSBase); } else { iofs->IOFS.io_Device = (struct Device *)notify->nr_Handler; if (iofs->IOFS.io_Device == NULL) { return; } } } break; /* The following five packets are only relative to the message port of the file system to send to. Therefore, we fill in only partial information in the IOFileSys and hope for the best... Specifically, the device cannot use iofs->io_Device. TODO */ case ACTION_RENAME_DISK: // Relabel() /* TODO */ break; case ACTION_FORMAT: // Format() /* TODO */ break; case ACTION_MORE_CACHE: // AddBuffers() /* TODO */ break; case ACTION_INHIBIT: // Inhibit() /* TODO */ break; case ACTION_IS_FILESYSTEM: // IsFileSystem() /* TODO */ break; case ACTION_DISK_INFO: // Info() /* TODO */ break; case ACTION_INFO: // No associated function /* TODO */ break; case ACTION_CURRENT_VOLUME: // No associated function /* TODO */ break; case ACTION_PARENT_FH: // ParentOfFH() /* TODO -- Should be the same as ACTION_PARENT? For some reason ParentDir() and ParentOfFH() is implemented differently in AROS. Have to investigate this further. */ break; case ACTION_FH_FROM_LOCK: // OpenFromLock() /* TODO: Have so simulate ReplyMsg() here */ return; case ACTION_SET_OWNER: // SetOwner() // Unfortunately, I have no info regardning this packet. // iofs->IOFS.io_Command = FSA_SET_OWNER; // iofs->io_Union.io_SET_OWNER.io_UID = owner_info >> 16; // iofs->io_Union.io_SET_OWNER.io_GID = owner_info & 0xffff; break; case ACTION_CHANGE_MODE: // ChangeMode() /* TODO */ break; /* I haven't looked into the following packets in detail */ case ACTION_DIE: // No associated function break; case ACTION_WRITE_PROTECT: // No associated function break; case ACTION_FLUSH: // No associated function break; case ACTION_SERIALIZE_DISK: // No associated function break; // --- Console only packets ------------------------------ /* I think these should not be implemented as packets except for ACTION_WAIT_CHAR which is not really a console only packet. Instead functions should be added to console.device */ case ACTION_SCREEN_MODE: // SetMode() /* TODO*/ break; case ACTION_CHANGE_SIGNAL: // No associated function { struct MsgPort *msgport; struct Task *task; fh = (struct FileHandle *)dp->dp_Arg1; msgport = (struct MsgPort *)dp->dp_Arg2; task = msgport ? msgport->mp_SigTask : NULL; iofs->IOFS.io_Device = fh->fh_Device; iofs->IOFS.io_Unit = fh->fh_Unit; iofs->IOFS.io_Command = FSA_CHANGE_SIGNAL; iofs->io_Union.io_CHANGE_SIGNAL.io_Task = task; } break; case ACTION_WAIT_CHAR: // WaitForChar() /* TODO */ break; default: D(kprintf("Unknown packet type %d found in SendPkt()\n", dp->dp_Type)); dp->dp_Res1 = DOSFALSE; dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN; PutMsg(replyport, dp->dp_Link); return; } D(kprintf("Calling SendIO() with command %u\n", iofs->IOFS.io_Command)); SendIO((struct IORequest *)iofs); } }
/* Mount a volume with the given name; route all handler ** messages to the given port. */ struct DeviceNode *Mount(char *name, struct MsgPort *port) { struct DeviceNode *volume; struct DosList *dlist; struct FileSysStartupMsg *fssm = AllocVec(sizeof(struct FileSysStartupMsg), MEMF_CLEAR); struct DosEnvec *dosenvec = AllocVec(sizeof(struct DosEnvec), MEMF_CLEAR); if(name == NULL || port == NULL) return NULL; /* make dosenvec */ /* test: bpt=8,hc=1250000 */ /* zip: bpt=8,hc=24575 */ dosenvec->de_TableSize = 17; dosenvec->de_SizeBlock = 128; dosenvec->de_Surfaces = 16; // 1; // !! dosenvec->de_SectorPerBlock = 1; dosenvec->de_BlocksPerTrack = 63; // 8; //555; // !! dosenvec->de_Reserved = 2; dosenvec->de_LowCyl = 2; // 0; // !! dosenvec->de_HighCyl = 14759; // 1250000; // !! dosenvec->de_NumBuffers = 350; dosenvec->de_BufMemType = 0; dosenvec->de_MaxTransfer = 0x1ffff; dosenvec->de_Mask = 0x7ffffffe; dosenvec->de_DosType = 0x6d757577; //ID_MUAF_DISK; // 0x6D754653; //ID_PFS_DISK or just fun: 0x6d757575; dosenvec->de_BootBlocks = 2; /* make fssm */ fssm->fssm_Unit = 1; // 5; // !! fssm->fssm_Device = MKBADDR(devicename); fssm->fssm_Environ = MKBADDR(dosenvec); fssm->fssm_Flags = 0; while(!(dlist = AttemptLockDosList(LDF_DEVICES|LDF_WRITE))) { /* Can't lock the DOS list. Wait a second and try again. */ Delay(50); } volume = (struct DeviceNode *)FindDosEntry(dlist, name, LDF_DEVICES); if(volume) RemDosEntry((struct DosList *)volume); UnLockDosList(LDF_DEVICES|LDF_WRITE); if(!volume && !(volume = (struct DeviceNode *)MakeDosEntry(name, DLT_DEVICE))) return NULL; volume->dn_Startup = MKBADDR(fssm); volume->dn_Lock = NULL; volume->dn_GlobalVec = -1; /* Now we can own the volume by giving it our msgport */ volume->dn_Task = port; while(!(dlist = AttemptLockDosList(LDF_DEVICES|LDF_WRITE))) { /* Oops, can't lock DOS list. Wait 1 second and retry. */ Delay(50); } AddDosEntry((struct DosList *)volume); UnLockDosList(LDF_DEVICES|LDF_WRITE); return volume; }
// Open a disk for IO DiskHandle *LIBFUNC L_OpenDisk( REG(a0, char *disk), REG(a1, struct MsgPort *port)) { DiskHandle *handle; struct DosList *dl; unsigned long blocks; char *ptr; // Allocate handle if (!(handle=AllocVec(sizeof(DiskHandle),MEMF_CLEAR))) return 0; // Copy name, strip colon stccpy(handle->dh_name,disk,31); if ((ptr=strchr(handle->dh_name,':'))) *ptr=0; // Lock DOS list dl=LockDosList(LDF_DEVICES|LDF_READ); // Find entry if (!(dl=FindDosEntry(dl,handle->dh_name,LDF_DEVICES))) { // Not found UnLockDosList(LDF_DEVICES|LDF_READ); FreeVec(handle); return 0; } // Add colon back on strcat(handle->dh_name,":"); // Get pointer to startup message and geometry handle->dh_startup=(struct FileSysStartupMsg *)BADDR(dl->dol_misc.dol_handler.dol_Startup); handle->dh_geo=(struct DosEnvec *)BADDR(handle->dh_startup->fssm_Environ); // Shortcuts to root block and blocksize blocks=handle->dh_geo->de_BlocksPerTrack* handle->dh_geo->de_Surfaces* (handle->dh_geo->de_HighCyl-handle->dh_geo->de_LowCyl+1); handle->dh_root=(blocks-1+handle->dh_geo->de_Reserved)>>1; handle->dh_blocksize=handle->dh_geo->de_SizeBlock<<2; // Get real device name L_BtoCStr((BPTR)handle->dh_startup->fssm_Device,handle->dh_device,32); // Get information #ifdef __AROS__ if (((struct Library *)DOSBase)->lib_Version<50) { //handle->dh_result=Info(dl->dol_Lock,&handle->dh_info); BPTR lock; handle->dh_result=0; if ((lock=Lock(handle->dh_name,SHARED_LOCK))) { handle->dh_result=Info(lock,&handle->dh_info); UnLock(lock); } } else #endif handle->dh_result=DoPkt(dl->dol_Task,ACTION_DISK_INFO,MKBADDR(&handle->dh_info),0,0,0,0); // Unlock dos list UnLockDosList(LDF_DEVICES|LDF_READ); // Create message port if needed if (!port) { if (!(handle->dh_port=CreateMsgPort())) { FreeVec(handle); return 0; } port=handle->dh_port; } // Create IO request if (!(handle->dh_io=(struct IOExtTD *)CreateIORequest(port,sizeof(struct IOExtTD)))) { if (handle->dh_port) DeleteMsgPort(handle->dh_port); FreeVec(handle); return 0; } // Open device if (OpenDevice( handle->dh_device, handle->dh_startup->fssm_Unit, (struct IORequest *)handle->dh_io, handle->dh_startup->fssm_Flags)) { // Failed to open L_CloseDisk(handle); return 0; } return handle; }