/******************************************* Name : attemptAddDosVolume Descr.: adds a new volume to dos Input : volume - volume to add Output: DOSTRUE for success; DOSFALSE otherwise ********************************************/ LONG attemptAddDosVolume(struct AFSBase *afsbase, struct Volume *volume) { struct DosList *doslist; struct DosList *dl=NULL; char string[32]; BSTR bname; UBYTE i; if (volume->volumenode) { D(bug("[afs 0x%08lX] VolumeNode is already present!\n", volume)); return DOSTRUE; } bname = volume->devicelist.dl_Name; for (i=0; i<AROS_BSTR_strlen(bname); i++) string[i] = AROS_BSTR_getchar(bname,i); string[AROS_BSTR_strlen(bname)] = 0; D(bug("[afs 0x%08lX] Processing inserted volume %s\n", volume, string)); /* is the volume already in the list? */ doslist = AttemptLockDosList(LDF_WRITE | LDF_VOLUMES); if (doslist != NULL) { dl = FindDosEntry(doslist,string,LDF_VOLUMES); UnLockDosList(LDF_WRITE | LDF_VOLUMES); } else return TRUE; /* if not create a new doslist */ if (dl == NULL) { D(bug("[afs 0x%08lX] Creating new VolumeNode\n", volume)); doslist = MakeDosEntry(string,DLT_VOLUME); if (doslist == NULL) return DOSFALSE; doslist->dol_Task = &((struct Process *)FindTask(NULL))->pr_MsgPort; doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Days = volume->devicelist.dl_VolumeDate.ds_Days; doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Minute = volume->devicelist.dl_VolumeDate.ds_Minute; doslist->dol_misc.dol_volume.dol_VolumeDate.ds_Tick = volume->devicelist.dl_VolumeDate.ds_Tick; AddDosEntry(doslist); /* if we re-use "volume" clear locklist */ volume->locklist = NULL; dl = doslist; } volume->volumenode = dl; SendEvent(afsbase, IECLASS_DISKINSERTED); return DOSTRUE; }
/* 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; }
struct DiskIO *DIO_Setup(CONST_STRPTR name, const struct TagItem *tags) { DEBUGF("DIO_Setup('%s', %#p)\n", name, tags); if (name == NULL || name[0] == '\0' || name[0] == ':') { DEBUGF("DIO_Setup: No valid name argument specified.\n"); return NULL; } struct DiskIO *dio; struct TagItem *tstate; const struct TagItem *tag; #ifndef DISABLE_DOSTYPE_CHECK ULONG check_dostype = 0; ULONG dostype_mask = ~0; #endif struct DosList *dol; struct DeviceNode *dn = NULL; struct FileSysStartupMsg *fssm = NULL; struct DosEnvec *de = NULL; struct MsgPort *mp = NULL; struct IOExtTD *iotd = NULL; char devname[256]; struct NSDeviceQueryResult nsdqr; int error = DIO_ERROR_UNSPECIFIED; int *error_storage; dio = AllocMem(sizeof(*dio), MEMF_PUBLIC|MEMF_CLEAR); if (dio == NULL) { error = DIO_ERROR_NOMEM; goto cleanup; } tstate = (struct TagItem *)tags; while ((tag = NextTagItem(&tstate)) != NULL) { switch (tag->ti_Tag) { #ifndef DISABLE_BLOCK_CACHE case DIOS_Cache: dio->no_cache = !tag->ti_Data; break; case DIOS_WriteCache: dio->no_write_cache = !tag->ti_Data; break; #endif case DIOS_Inhibit: dio->inhibit = !!tag->ti_Data; break; #ifndef DISABLE_DOSTYPE_CHECK case DIOS_DOSType: check_dostype = tag->ti_Data; break; case DIOS_DOSTypeMask: dostype_mask = tag->ti_Data; break; #endif case DIOS_ReadOnly: dio->read_only = !!tag->ti_Data; break; } } /* Remove possible colon from name and anything else that might follow it */ SplitName(name, ':', dio->devname, 0, sizeof(dio->devname)); /* Find device node */ dol = LockDosList(LDF_DEVICES|LDF_READ); if (dol != NULL) { dn = (struct DeviceNode *)FindDosEntry(dol, dio->devname, LDF_DEVICES|LDF_READ); UnLockDosList(LDF_DEVICES|LDF_READ); } if (dn == NULL) { error = DIO_ERROR_GETFSD; goto cleanup; } /* Add back trailing colon for Inhibit() */ strlcat((char *)dio->devname, ":", sizeof(dio->devname)); /* Check that device node has the necessary data */ if ((fssm = BADDR(dn->dn_Startup)) == NULL || (de = BADDR(fssm->fssm_Environ)) == NULL || de->de_TableSize < DE_UPPERCYL) { error = DIO_ERROR_GETFSD; goto cleanup; } if (dio->inhibit) { if (!Inhibit(dio->devname, TRUE)) { error = DIO_ERROR_INHIBIT; goto cleanup; } dio->uninhibit = TRUE; /* So Cleanup() knows that it should uninhibit */ } dio->diskmp = mp = CreateMsgPort(); dio->diskiotd = iotd = CreateIORequest(dio->diskmp, sizeof(*iotd)); if (iotd == NULL) { error = DIO_ERROR_NOMEM; goto cleanup; } FbxCopyStringBSTRToC(fssm->fssm_Device, (STRPTR)devname, sizeof(devname)); if (OpenDevice((CONST_STRPTR)devname, fssm->fssm_Unit, (struct IORequest *)iotd, fssm->fssm_Flags) != 0) { DEBUGF("DIO_Setup: Failed to open %s unit %u using flags 0x%x.\n", fssm->fssm_Device, (unsigned int)fssm->fssm_Unit, (unsigned int)fssm->fssm_Flags); error = DIO_ERROR_OPENDEVICE; goto cleanup; } dio->disk_device = iotd->iotd_Req.io_Device; if (de->de_LowCyl == 0) { dio->use_full_disk = TRUE; DEBUGF("de_LowCyl == 0 => using full disk\n"); } else { UQUAD sector_size = de->de_SizeBlock * sizeof(ULONG); UQUAD cylinder_size = (UQUAD)de->de_BlocksPerTrack * (UQUAD)de->de_Surfaces * sector_size; dio->use_full_disk = FALSE; SetSectorSize(dio, sector_size); dio->partition_start = (UQUAD)de->de_LowCyl * cylinder_size; dio->partition_size = (UQUAD)(de->de_HighCyl - de->de_LowCyl + 1) * cylinder_size; dio->total_sectors = dio->partition_size / dio->sector_size; DEBUGF("partiton start: %llu partition size: %llu cylinder size: %llu sector size: %lu total sectors: %llu\n", dio->partition_start, dio->partition_size, cylinder_size, dio->sector_size, dio->total_sectors); } DEBUGF("Trying NSD query command\n"); iotd->iotd_Req.io_Command = NSCMD_DEVICEQUERY; iotd->iotd_Req.io_Data = &nsdqr; iotd->iotd_Req.io_Length = sizeof(nsdqr); bzero(&nsdqr, sizeof(nsdqr)); /* Required for usbscsi.device */ if (DoIO((struct IORequest *)iotd) == 0) { if (nsdqr.DeviceType != NSDEVTYPE_TRACKDISK) { DEBUGF("Not a trackdisk device\n"); error = DIO_ERROR_NSDQUERY; goto cleanup; } if (nsdqr.SupportedCommands != NULL) { UWORD cmd; int i = 0; while ((cmd = nsdqr.SupportedCommands[i++]) != CMD_INVALID) { if (cmd == CMD_READ) dio->cmd_support |= CMDSF_TD32; else if (cmd == ETD_READ) dio->cmd_support |= CMDSF_ETD32; else if (cmd == TD_READ64) dio->cmd_support |= CMDSF_TD64; else if (cmd == NSCMD_TD_READ64) dio->cmd_support |= CMDSF_NSD_TD64; else if (cmd == NSCMD_ETD_READ64) dio->cmd_support |= CMDSF_NSD_ETD64; else if (cmd == CMD_UPDATE) dio->cmd_support |= CMDSF_CMD_UPDATE; else if (cmd == ETD_UPDATE) dio->cmd_support |= CMDSF_ETD_UPDATE; } } } else if (iotd->iotd_Req.io_Error == IOERR_NOCMD) { DEBUGF("Not an NSD device\n"); dio->cmd_support = CMDSF_TD32|CMDSF_CMD_UPDATE; DEBUGF("Checking for TD64 support\n"); iotd->iotd_Req.io_Command = TD_READ64; iotd->iotd_Req.io_Data = NULL; iotd->iotd_Req.io_Actual = 0; iotd->iotd_Req.io_Offset = 0; iotd->iotd_Req.io_Length = 0; if (DoIO((struct IORequest *)iotd) != IOERR_NOCMD) dio->cmd_support |= CMDSF_TD64; } else { DEBUGF("NSD query command failed (error: %d)\n", (int)iotd->iotd_Req.io_Error); error = DIO_ERROR_NSDQUERY; goto cleanup; } if ((dio->cmd_support & (CMDSF_TD32|CMDSF_ETD32|CMDSF_TD64|CMDSF_NSD_TD64|CMDSF_NSD_ETD64)) == 0) { DEBUGF("No I/O commands supported\n"); error = DIO_ERROR_NSDQUERY; goto cleanup; } if (dio->cmd_support & CMDSF_ETD_UPDATE) dio->update_cmd = ETD_UPDATE; else if (dio->cmd_support & CMDSF_CMD_UPDATE) dio->update_cmd = CMD_UPDATE; else dio->update_cmd = CMD_INVALID; dio->mempool = CreatePool(MEMF_PUBLIC, 4096, 1024); if (dio->mempool == NULL) { error = DIO_ERROR_NOMEM; goto cleanup; } DIO_Update(dio); DEBUGF("DIO_Setup: %#p\n", dio); return dio; cleanup: if (dio != NULL) DIO_Cleanup(dio); error_storage = (int *)GetTagData(DIOS_Error, (Tag)NULL, tags); if (error_storage != NULL) *error_storage = error; DEBUGF("DIO_Setup failed (error: %d)\n", error); return NULL; }
// 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; }
LONG DoNameAsynch(struct IOFileSys *iofs, STRPTR name, struct DosLibrary *DOSBase) { STRPTR volname, pathname, s1 = NULL; BPTR cur, lock = (BPTR)NULL; struct DosList *dl; struct Device *device; struct Unit *unit; struct FileHandle *fh; struct Process *me = (struct Process *)FindTask(NULL); if (!Strnicmp(name, "PROGDIR:", 8) && me->pr_HomeDir) { cur = me->pr_HomeDir; volname = NULL; pathname = name + 8; } else if (*name == ':') { cur = me->pr_CurrentDir; volname = NULL; pathname = name + 1; } else { /* Copy volume name */ cur = me->pr_CurrentDir; s1 = name; pathname = name; volname = NULL; while (*s1) { if (*s1++ == ':') { volname = (STRPTR)AllocMem(s1-name, MEMF_ANY); if (volname == NULL) { return ERROR_NO_FREE_STORE; } CopyMem(name, volname, s1 - name - 1); volname[s1 - name - 1] = '\0'; pathname = s1; break; } } } if (!volname && !cur && !DOSBase->dl_SYSLock) { return ERROR_OBJECT_NOT_FOUND; } dl = LockDosList(LDF_ALL | LDF_READ); if (volname != NULL) { /* Find logical device */ dl = FindDosEntry(dl, volname, LDF_ALL); if (dl == NULL) { UnLockDosList(LDF_ALL | LDF_READ); FreeMem(volname, s1 - name); return ERROR_DEVICE_NOT_MOUNTED; } else if (dl->dol_Type == DLT_LATE) { lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); UnLockDosList(LDF_ALL | LDF_READ); if (lock != NULL) { AssignLock(volname, lock); dl = LockDosList(LDF_ALL | LDF_READ); dl = FindDosEntry(dl, volname, LDF_ALL); if (dl == NULL) { UnLockDosList(LDF_ALL | LDF_READ); FreeMem(volname, s1 - name); return ERROR_DEVICE_NOT_MOUNTED; } device = dl->dol_Ext.dol_AROS.dol_Device; unit = dl->dol_Ext.dol_AROS.dol_Unit; } else { FreeMem(volname, s1 - name); return IoErr(); } } else if (dl->dol_Type == DLT_NONBINDING) { lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); fh = (struct FileHandle *)BADDR(lock); if (fh != NULL) { device = fh->fh_Device; unit = fh->fh_Unit; } else { UnLockDosList(LDF_ALL | LDF_READ); FreeMem(volname, s1 - name); return IoErr(); } } else { device = dl->dol_Ext.dol_AROS.dol_Device; unit = dl->dol_Ext.dol_AROS.dol_Unit; } } else if (cur) { fh = (struct FileHandle *)BADDR(cur); device = fh->fh_Device; unit = fh->fh_Unit; } else { #if 0 /* stegerg: ?? */ device = DOSBase->dl_NulHandler; unit = DOSBase->dl_NulLock; #else fh = (struct FileHandle *)BADDR(DOSBase->dl_SYSLock); device = fh->fh_Device; unit = fh->fh_Unit; #endif } iofs->IOFS.io_Device = device; iofs->IOFS.io_Unit = unit; iofs->io_Union.io_NamedFile.io_Filename = pathname; if (volname != NULL) { FreeMem(volname, s1 - name); } return 0; }
int access ( /* SYNOPSIS */ const char *path, int mode) /* FUNCTION Check access permissions of a file or pathname INPUTS path - the path of the file being checked mode - the bitwise inclusive OR of the access permissions to be checked: W_OK - for write permission R_OK - for readpermissions X_OK - for execute permission F_OK - Just to see whether the file exists RESULT If path cannot be found or if any of the desired access modes would not be granted, then a -1 value is returned; otherwise a 0 value is returned. NOTES EXAMPLE BUGS SEE ALSO open(), ftruncate() INTERNALS ******************************************************************************/ { BPTR lock = NULL; struct FileInfoBlock *fib = NULL; int result = -1; char vol[32]; struct DosList *dl = NULL; if (!path) /* safety check */ { errno = EFAULT; return -1; } if (!strlen(path)) /* empty path */ { errno = ENOENT; return -1; } /* Check if the volume exists. Calling Lock on non-existing volume will bring up System Requester */ if (SplitName(__path_u2a(path), ':', vol, 0, sizeof(vol)-1) != -1) { if(strcmp(vol, "PROGDIR") != 0) { dl = LockDosList(LDF_ALL | LDF_READ); dl = FindDosEntry(dl, vol, LDF_ALL); UnLockDosList(LDF_ALL | LDF_READ); /* Volume / Assign / Device not found */ if (dl == NULL) { errno = ENOENT; return -1; } } } /* Create a lock and examine a lock */ lock = Lock(__path_u2a(path), SHARED_LOCK); if (lock == NULL) { errno = IoErr2errno(IoErr()); return -1; } fib = AllocDosObject(DOS_FIB, NULL); if (!fib) { errno = IoErr2errno(IoErr()); UnLock(lock); return -1; } if (Examine(lock, fib)) { /* Notice : protection flags are 'low-active' (0 means access is granted) */ result = 0; if ((mode & R_OK) && (result == 0) && (fib->fib_Protection & (1 << FIBB_READ))) { errno = EACCES; result = -1; } if ((mode & W_OK) && (result == 0) && (fib->fib_Protection & (1 << FIBB_WRITE))) { errno = EACCES; result = -1; } if ((mode & X_OK) && (result == 0) && (fib->fib_Protection & (1 << FIBB_EXECUTE))) { errno = EACCES; result = -1; } } else { errno = EBADF; result = -1; } FreeDosObject(DOS_FIB, fib); fib = NULL; UnLock(lock); return result; }
/* Output: 0 - no mount (no partition change) 1 - mount that device 2 - reboot not really neccessary (FS not so important things changed like de_Mask) 3 - reboot neccessary (FS important things changed like de_LowCyl) */ WORD checkMount(struct HDTBPartition *table, STRPTR name, struct DosEnvec *de) { WORD retval = 1; struct DosList *dl; struct DeviceNode *entry; ULONG i; D(bug("[HDToolBox] checkMount('%s')\n", name)); dl = LockDosList(LDF_READ | LDF_DEVICES); if (dl) { entry = (struct DeviceNode *)FindDosEntry(dl, name, LDF_DEVICES); if (entry) { struct FileSysStartupMsg *fssm; struct DosEnvec *d_de; STRPTR devname; fssm = (struct FileSysStartupMsg *)BADDR(entry->dn_Startup); devname = AROS_BSTR_ADDR(fssm->fssm_Device); if ( (fssm->fssm_Unit != table->hd->unit) || (strcmp(devname, table->hd->devname)) ) { retval = 3; /* better do a reboot */ } else { d_de = (struct DosEnvec *)BADDR(fssm->fssm_Environ); i = getOffset(table->ph); if ( (d_de->de_SizeBlock != de->de_SizeBlock) || (d_de->de_Reserved != de->de_Reserved) || (d_de->de_PreAlloc != de->de_PreAlloc) || (d_de->de_LowCyl != (de->de_LowCyl+i)) || (d_de->de_HighCyl != (de->de_HighCyl+i)) || (d_de->de_DosType != de->de_DosType) || ( ( /* at least one has de_BootBocks */ (d_de->de_TableSize>=DE_BOOTBLOCKS) || (de->de_TableSize>=DE_BOOTBLOCKS) ) && ( /* if one has no de_BootBlock assume de_BootBlock change */ (d_de->de_TableSize<DE_BOOTBLOCKS) || (de->de_TableSize<DE_BOOTBLOCKS) ) ) || ( /* both have de_BootBlocks */ (d_de->de_TableSize>=DE_BOOTBLOCKS) && (de->de_TableSize>=DE_BOOTBLOCKS) && (d_de->de_BootBlocks != de->de_BootBlocks) ) ) { retval = 3; } else if ( (d_de->de_NumBuffers != de->de_NumBuffers) || (d_de->de_BufMemType != de->de_BufMemType) || (d_de->de_MaxTransfer != de->de_MaxTransfer) || (d_de->de_Mask != de->de_Mask) || (d_de->de_BootPri != de->de_BootPri) ) { retval = 2; } else retval = 0; } } UnLockDosList(LDF_READ | LDF_DEVICES); } return retval; }