apa_cache_t *apaInsertPartition(s32 device, const apa_params_t *params, u32 sector, int *err) { // Adds a new partition using an empty block. apa_cache_t *clink_empty; apa_cache_t *clink_this; apa_cache_t *clink_next; if ((clink_this = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err)) == 0) return 0; while (clink_this->header->length != params->size) { if ((clink_next = apaCacheGetHeader(device, clink_this->header->next, APA_IO_MODE_READ, err)) == NULL) { // Get next partition apaCacheFree(clink_this); return 0; } clink_this->header->length >>= 1; clink_empty = apaRemovePartition(device, (clink_this->header->start + clink_this->header->length), clink_this->header->next, clink_this->header->start, clink_this->header->length); clink_this->header->next = clink_empty->header->start; clink_this->flags |= APA_CACHE_FLAG_DIRTY; clink_next->header->prev = clink_empty->header->start; clink_next->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink_empty); apaCacheFree(clink_next); } apaCacheFree(clink_this); clink_this = apaFillHeader(device, params, clink_this->header->start, clink_this->header->next, clink_this->header->prev, params->size, err); apaCacheFlushAllDirty(device); return clink_this; }
static int ioctl2DeleteLastSub(hdd_file_slot_t *fileSlot) { int rv; u32 device=fileSlot->f->unit; apa_cache_t *mainPart; apa_cache_t *subPart; if(!(fileSlot->f->mode & O_WRONLY)) return -EACCES; if(fileSlot->nsub==0) return -ENOENT; if(!(mainPart=apaCacheGetHeader(device, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv))) return rv; if((subPart=apaCacheGetHeader(device, mainPart->header->subs[mainPart->header->nsub-1].start, APA_IO_MODE_READ, &rv))) { fileSlot->nsub--; mainPart->header->nsub--; mainPart->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); rv=apaDelete(subPart); } apaCacheFree(mainPart); return rv; }
static int ioctl2AddSub(hdd_file_slot_t *fileSlot, char *argp) { int rv; u32 device=fileSlot->f->unit; apa_params_t params; u32 emptyBlocks[32]; apa_cache_t *clink; u32 sector=0; u32 length; if(!(fileSlot->f->mode & O_WRONLY)) return -EACCES; if(!(fileSlot->nsub < APA_MAXSUB)) return -EFBIG; memset(¶ms, 0, sizeof(apa_params_t)); if((rv=fioPartitionSizeLookUp(argp)) < 0) return rv; params.size=rv; params.flags=APA_FLAG_SUB; params.type=fileSlot->type; params.main=fileSlot->parts[0].start; params.number=fileSlot->nsub+1; if((rv=hddCheckPartitionMax(device, params.size)) < 0) return rv; // walk all looking for any empty blocks memset(&emptyBlocks, 0, sizeof(emptyBlocks)); clink=apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv); while(clink){ sector=clink->sector; apaAddEmptyBlock(clink->header, emptyBlocks); clink=apaGetNextHeader(clink, &rv); } if(rv!=0) return rv; if(!(clink=hddAddPartitionHere(device, ¶ms, emptyBlocks, sector, &rv))) return rv; sector=clink->header->start; length=clink->header->length; apaCacheFree(clink); if(!(clink=apaCacheGetHeader(device, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv))) return rv; clink->header->subs[clink->header->nsub].start=sector; clink->header->subs[clink->header->nsub].length=length; clink->header->nsub++; fileSlot->nsub++; fileSlot->parts[fileSlot->nsub].start=sector; fileSlot->parts[fileSlot->nsub].length=length; clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink); return rv; }
int apaDelete(apa_cache_t *clink) { int rv = 0; apa_cache_t *clink_mbr; u32 device = clink->device; u32 start = clink->header->start; int i; if (!start) { apaCacheFree(clink); return -EACCES; } if (clink->header->next == 0) { if ((clink_mbr = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv)) == NULL) { apaCacheFree(clink); return rv; } do { apaCacheFree(clink); if ((clink = apaCacheGetHeader(clink->device, clink->header->prev, APA_IO_MODE_READ, &rv)) == NULL) return 0; clink->header->next = 0; clink->flags |= APA_CACHE_FLAG_DIRTY; clink_mbr->header->prev = clink->header->start; clink_mbr->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); } while (clink->header->type == 0); apaCacheFree(clink_mbr); } else { u32 length = clink->header->length; for (i = 0; i < 2; i++) { if ((clink = apaDeleteFixPrev(clink, &rv)) == NULL) return 0; if ((clink = apaDeleteFixNext(clink, &rv)) == NULL) return 0; } if (clink->header->start == start && clink->header->length == length) { apaMakeEmpty(clink); apaCacheFlushAllDirty(clink->device); } } apaCacheFree(clink); return rv; }
// Unofficial helper for renaming APA partitions. static int apaRename(s32 device, const apa_params_t *oldParams, const apa_params_t *newParams) { apa_cache_t *clink; int i, rv; // look to see if can make(newname) or not... if((clink = apaFindPartition(device, newParams->id, &rv)) != NULL) { apaCacheFree(clink); SignalSema(fioSema); return -EEXIST; // File exists } // look to see if open(oldname) for(i=0;i<apaMaxOpen;i++) { if(hddFileSlots[i].f!=NULL) { if(memcmp(hddFileSlots[i].id, oldParams->id, APA_IDMAX)==0) { SignalSema(fioSema); return -EBUSY; } } } // Do not allow system partitions (__*) to be renamed. if(oldParams->id[0]=='_' && oldParams->id[1]=='_') return -EACCES; // find :) if((clink = apaFindPartition(device, oldParams->id, &rv)) == NULL) { SignalSema(fioSema); return rv; } // Check for access rights. if(apaPassCmp(clink->header->fpwd, oldParams->fpwd) != 0) { apaCacheFree(clink); return -EACCES; } // do the renaming :) note: subs have no names!! memcpy(clink->header->id, newParams->id, APA_IDMAX); // Update passwords memcpy(clink->header->rpwd, newParams->rpwd, APA_PASSMAX); memcpy(clink->header->fpwd, newParams->fpwd, APA_PASSMAX); clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink); return 0; }
static int devctlSetOsdMBR(s32 device, hddSetOsdMBR_t *mbrInfo) { int rv; apa_cache_t *clink; if(!(clink=apaCacheGetHeader(device, APA_SECTOR_MBR, APA_IO_MODE_READ, &rv))) return rv; APA_PRINTF( APA_DRV_NAME": mbr start: %ld\n" APA_DRV_NAME": mbr size : %ld\n", mbrInfo->start, mbrInfo->size); clink->header->mbr.osdStart=mbrInfo->start; clink->header->mbr.osdSize=mbrInfo->size; clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink); return rv; }
apa_cache_t *apaDeleteFixNext(apa_cache_t *clink, int *err) { apa_header_t *header = clink->header; u32 length = header->length; u32 saved_length = header->length; u32 lnext = header->next; apa_cache_t *clink1; apa_cache_t *clink2; u32 device = clink->device; u32 tmp; while (lnext != 0) { if (!(clink1 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) { apaCacheFree(clink); return 0; } header = clink1->header; tmp = header->length + length; if (header->type != 0) { apaCacheFree(clink1); break; } if ((clink->header->start % tmp) != 0 || ((tmp - 1) & tmp)) { apaCacheFree(clink1); break; } length = tmp; apaCacheFree(clink1); lnext = header->next; } if (length != saved_length) { if (!(clink2 = apaCacheGetHeader(device, lnext, APA_IO_MODE_READ, err))) { apaCacheFree(clink); return NULL; } clink->header->length = length; clink->header->next = lnext; apaMakeEmpty(clink); clink2->header->prev = clink->header->start; clink2->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink2); } return clink; }
apa_cache_t *apaDeleteFixPrev(apa_cache_t *clink, int *err) { apa_cache_t *clink2 = clink; apa_header_t *header = clink2->header; u32 device = clink->device; u32 length = clink->header->length; u32 saved_next = clink->header->next; u32 saved_length = clink->header->length; u32 tmp; while (header->start) { if (!(clink2 = apaCacheGetHeader(device, header->prev, APA_IO_MODE_READ, err))) { apaCacheFree(clink); return NULL; } header = clink2->header; tmp = header->length + length; if (header->type != 0) { apaCacheFree(clink2); break; } if ((header->start % tmp) || (tmp & (tmp - 1))) { apaCacheFree(clink2); break; } length = tmp; apaCacheFree(clink); clink = clink2; } if (length != saved_length) { if (!(clink2 = apaCacheGetHeader(device, saved_next, APA_IO_MODE_READ, err))) { apaCacheFree(clink); return NULL; } clink->header->length = length; clink->header->next = clink->header->start + length; clink2->header->prev = clink->header->start; clink2->flags |= APA_CACHE_FLAG_DIRTY; clink->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink2); } return clink; }
static int apaRemove(s32 device, const char *id, const char *fpwd) { u32 nsub; apa_cache_t *clink; apa_cache_t *clink2; int rv, i; for(i=0;i<apaMaxOpen;i++) // look to see if open { if(hddFileSlots[i].f!=0) { if(memcmp(hddFileSlots[i].id, id, APA_IDMAX)==0) return -EBUSY; } } if(id[0]=='_' && id[1]=='_') return -EACCES; if((clink=apaFindPartition(device, id, &rv))==NULL) return rv; if(apaPassCmp(clink->header->fpwd, fpwd)) { apaCacheFree(clink); return -EACCES; } // remove all subs frist... nsub=clink->header->nsub; clink->header->nsub=0; clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); for(i=nsub-1;i!=-1;i--) { if((clink2=apaCacheGetHeader(device, clink->header->subs[i].start, APA_IO_MODE_READ, &rv))){ if((rv=apaDelete(clink2))){ apaCacheFree(clink); return rv; } } } if(rv==0) return apaDelete(clink); apaCacheFree(clink); return rv; }
apa_cache_t *apaGetNextHeader(apa_cache_t *clink, int *err) { u32 start = clink->header->start; apaCacheFree(clink); if (!clink->header->next) return NULL; if (!(clink = apaCacheGetHeader(clink->device, clink->header->next, APA_IO_MODE_READ, err))) return NULL; if (start != clink->header->prev) { APA_PRINTF(APA_DRV_NAME ": Warning: Invalid partition information. start != prev\n"); clink->header->prev = start; clink->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(clink->device); } return clink; }
static int devctlSwapTemp(s32 device, char *argp) { int rv; apa_params_t params; char szBuf[APA_IDMAX]; apa_cache_t *partTemp; apa_cache_t *partNew; if((rv=fioGetInput(argp, ¶ms)) < 0) return rv; if(params.id[0] == '_' && params.id[1] == '_')// test for '__' system partition return -EINVAL; memset(szBuf, 0, APA_IDMAX); strcpy(szBuf, "_tmp"); if(!(partTemp=apaFindPartition(device, szBuf, &rv))) return rv; if((partNew=apaFindPartition(device, params.id, &rv))) { if((rv=apaPassCmp(partNew->header->fpwd, params.fpwd))==0) { memcpy(partTemp->header->id, partNew->header->id, APA_IDMAX); memcpy(partTemp->header->rpwd, partNew->header->rpwd, APA_PASSMAX); memcpy(partTemp->header->fpwd, partNew->header->fpwd, APA_PASSMAX); //memset(partNew->header->id, 0, 8);// BUG! can make it so can not open!! memset(partNew->header->id, 0, APA_IDMAX); strcpy(partNew->header->id, "_tmp"); memset(partNew->header->rpwd, 0, APA_PASSMAX); memset(partNew->header->fpwd, 0, APA_PASSMAX); partTemp->flags|=APA_CACHE_FLAG_DIRTY; partNew->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); } apaCacheFree(partNew); } apaCacheFree(partTemp); return rv; }
apa_cache_t *hddAddPartitionHere(s32 device, const apa_params_t *params, u32 *emptyBlocks, u32 sector, int *err) { apa_cache_t *clink_this; apa_cache_t *clink_next; apa_cache_t *clink_new; apa_header_t *header; u32 i; u32 tmp, some_size, part_end; u32 tempSize; // walk empty blocks in case can use one :) for (i = 0; i < 32; i++) { if ((u32)(1 << i) >= params->size && emptyBlocks[i] != 0) return apaInsertPartition(device, params, emptyBlocks[i], err); } clink_this = apaCacheGetHeader(device, sector, APA_IO_MODE_READ, err); header = clink_this->header; part_end = header->start + header->length; some_size = (part_end % params->size); tmp = some_size ? params->size - some_size : 0; if (hddDevices[device].totalLBA < (part_end + params->size + tmp) //Non-SONY: when dealing with large disks, this check may overflow (therefore, check for overflows!). || (part_end < sector)) { *err = -ENOSPC; apaCacheFree(clink_this); return NULL; } if ((clink_next = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, err)) == NULL) { apaCacheFree(clink_this); return NULL; } tempSize = params->size; while (part_end % params->size) { tempSize = params->size >> 1; while (0x3FFFF < tempSize) { if (!(part_end % tempSize)) { clink_new = apaRemovePartition(device, part_end, 0, clink_this->header->start, tempSize); clink_this->header->next = part_end; clink_this->flags |= APA_CACHE_FLAG_DIRTY; clink_next->header->prev = clink_new->header->start; part_end += tempSize; clink_next->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); apaCacheFree(clink_this); clink_this = clink_new; break; } tempSize >>= 1; } } if ((clink_new = apaFillHeader(device, params, part_end, 0, clink_this->header->start, params->size, err)) != NULL) { clink_this->header->next = part_end; clink_this->flags |= APA_CACHE_FLAG_DIRTY; clink_next->header->prev = clink_new->header->start; clink_next->flags |= APA_CACHE_FLAG_DIRTY; apaCacheFlushAllDirty(device); } apaCacheFree(clink_this); apaCacheFree(clink_next); return clink_new; }