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; }
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; }
// 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 apaOpen(s32 device, hdd_file_slot_t *fileSlot, apa_params_t *params, int mode) { int rv=0; u32 emptyBlocks[32]; apa_cache_t *clink; apa_cache_t *clink2; u32 sector=0; // walk all looking for any empty blocks & look for partition clink=apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv); memset(&emptyBlocks, 0, sizeof(emptyBlocks)); while(clink) { sector=clink->sector; if(!(clink->header->flags & APA_FLAG_SUB)) { if(memcmp(clink->header->id, params->id, APA_IDMAX) == 0) break; // found :) } apaAddEmptyBlock(clink->header, emptyBlocks); clink=apaGetNextHeader(clink, &rv); } if(rv!=0) return rv; rv=-ENOENT; if(clink==NULL && (mode & O_CREAT)) { if((rv=hddCheckPartitionMax(device, params->size))>=0) { if((clink=hddAddPartitionHere(device, params, emptyBlocks, sector, &rv))!=NULL) { sector=clink->header->start; clink2=apaCacheAlloc(); memset(clink2->header, 0, sizeof(apa_header_t)); ata_device_sector_io(device, clink2->header, sector+8 , 2, ATA_DIR_WRITE); ata_device_sector_io(device, clink2->header, sector+0x2000, 2, ATA_DIR_WRITE); apaCacheFree(clink2); } } } if(clink==NULL) return rv; fileSlot->parts[0].start=clink->header->start; fileSlot->parts[0].length=clink->header->length; memcpy(&fileSlot->parts[1], &clink->header->subs, APA_MAXSUB*sizeof(apa_sub_t)); fileSlot->type=clink->header->type; fileSlot->nsub=clink->header->nsub; memcpy(&fileSlot->id, &clink->header->id, APA_IDMAX); apaCacheFree(clink); if(apaPassCmp(clink->header->fpwd, params->fpwd)!=0) { rv = (!(mode & O_WRONLY)) ? apaPassCmp(clink->header->rpwd, params->rpwd) : -EACCES; } else rv = 0; return rv; }
int hddDread(iop_file_t *f, iox_dirent_t *dirent) { int rv; hdd_file_slot_t *fileSlot=f->privdata; apa_cache_t *clink; if(!(f->mode & O_DIROPEN)) return -ENOTDIR; if(fileSlot->parts[0].start==-1) return 0;// end :) WaitSema(fioSema); if((clink=apaCacheGetHeader(f->unit, fileSlot->parts[0].start, APA_IO_MODE_READ, &rv)) && clink->header->length) { if(clink->header->flags & APA_FLAG_SUB) { // if sub get id from main header... apa_cache_t *cmain=apaCacheGetHeader(f->unit, clink->header->main, APA_IO_MODE_READ, &rv); if(cmain!=NULL){ /* This was the SONY original, which didn't do bounds-checking: rv=strlen(cmain->header->id); strcpy(dirent->name, cmain->header->id); */ strncpy(dirent->name, cmain->header->id, APA_IDMAX); dirent->name[APA_IDMAX] = '\0'; rv=strlen(dirent->name); apaCacheFree(cmain); } } else { /* This was the SONY original, which didn't do bounds-checking: rv=strlen(clink->header->id); strcpy(dirent->name, clink->header->id); */ strncpy(dirent->name, clink->header->id, APA_IDMAX); dirent->name[APA_IDMAX] = '\0'; rv=strlen(dirent->name); } fioGetStatFiller(clink, &dirent->stat); if(clink->header->next==0) fileSlot->parts[0].start=-1; // mark end else fileSlot->parts[0].start=clink->header->next;// set next apaCacheFree(clink); } SignalSema(fioSema); return rv; }
void apaSetPartErrorSector(s32 device, u32 lba) { // used to set the lba of a partition that has a error... apa_cache_t *clink; clink = apaCacheAlloc(); apaSaveError(device, clink->header, APA_SECTOR_PART_ERROR, lba); apaCacheFree(clink); }
int apaGetPartErrorName(s32 device, char *name) { u32 lba; int rv = 0; apa_cache_t *clink; if ((rv = apaGetPartErrorSector(device, APA_SECTOR_PART_ERROR, &lba)) <= 0) return rv; if (!(clink = apaCacheGetHeader(device, 0, APA_IO_MODE_READ, &rv))) return rv; while (clink) { if (clink->header->type != APA_TYPE_FREE && !(clink->header->flags & APA_CACHE_FLAG_DIRTY) && clink->header->start == lba) { if (name) { strncpy(name, clink->header->id, APA_IDMAX - 1); name[APA_IDMAX - 1] = '\0'; } apaCacheFree(clink); return 1; } clink = apaGetNextHeader(clink, &rv); } // clear error if no errors and partitions was not found... if (rv == 0) apaSetPartErrorSector(device, 0); return rv; }
int apaJournalRestore(s32 device) { // copys apa headers from apal to apa system int i; u32 sector; apa_cache_t *clink; APA_PRINTF(APA_DRV_NAME": checking log...\n"); if(ata_device_sector_io(device, &journalBuf, APA_SECTOR_APAL, sizeof(apa_journal_t)/512, ATA_DIR_READ)){ apaJournalReset(device); return -EIO; } if(journalBuf.magic==APAL_MAGIC) { if(journalBuf.num==0) return 0; clink=apaCacheAlloc(); for(i=0, sector=APA_SECTOR_APAL_HEADERS;i<journalBuf.num;i++, sector+=2) { if(ata_device_sector_io(device, clink->header, sector, 2, ATA_DIR_READ)) break; if(ata_device_sector_io(device, clink->header, journalBuf.sectors[i], 2, ATA_DIR_WRITE)) break; } apaCacheFree(clink); return apaJournalReset(device);// only do if journal.. } memset(&journalBuf, 0, sizeof(apa_journal_t));// safe e journalBuf.magic=APAL_MAGIC; return 0;//-EINVAL; }
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; }
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; }
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; }
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; }
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; }
int hddGetStat(iop_file_t *f, const char *name, iox_stat_t *stat) { apa_cache_t *clink; apa_params_t params; int rv; if((rv=fioGetInput(name, ¶ms))<0) return rv; WaitSema(fioSema); if((clink=apaFindPartition(f->unit, params.id, &rv))){ if((rv=apaPassCmp(clink->header->fpwd, params.fpwd))==0 || (rv=apaPassCmp(clink->header->rpwd, params.rpwd))==0) fioGetStatFiller(clink, stat); apaCacheFree(clink); } SignalSema(fioSema); return rv; }
int apaGetPartErrorSector(s32 device, u32 lba, u32 *lba_out) { apa_cache_t *clink; int rv = 0; if (!(clink = apaCacheAlloc())) return -ENOMEM; if (ata_device_sector_io(device, clink->header, lba, 1, ATA_DIR_READ)) return -EIO; if (lba_out) *lba_out = *clink->error_lba; if (*clink->error_lba) rv = 1; // error is set ;) 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; }
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; }
int apaGetFormat(s32 device, int *format) { apa_cache_t *clink; int rv = 0; u32 *pDW, i; clink = apaCacheAlloc(); *format = 0; if ((rv = apaReadHeader(device, clink->header, 0)) == 0) { *format = clink->header->mbr.version; if (ata_device_sector_io(device, clink->header, APA_SECTOR_SECTOR_ERROR, 2, ATA_DIR_READ)) rv = -EIO; // return -EIO; if (rv == 0) { pDW = (u32 *)clink->header; for (i = 0; i < 256; i++) { if ((i & 0x7F) && pDW[i] != 0) rv = 1; } } } apaCacheFree(clink); return rv == 0; }
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; }
int hddFormat(iop_file_t *f, const char *dev, const char *blockdev, void *arg, int arglen) { int rv=0; apa_cache_t *clink; u32 i; #ifdef APA_FORMAT_MAKE_PARTITIONS apa_params_t params; u32 emptyBlocks[32]; #endif if(f->unit >= 2) return -ENXIO; // clear all errors on hdd clink=apaCacheAlloc(); memset(clink->header, 0, sizeof(apa_header_t)); if(ata_device_sector_io(f->unit, clink->header, APA_SECTOR_SECTOR_ERROR, 1, ATA_DIR_WRITE)){ apaCacheFree(clink); return -EIO; } if(ata_device_sector_io(f->unit, clink->header, APA_SECTOR_PART_ERROR, 1, ATA_DIR_WRITE)){ apaCacheFree(clink); return -EIO; } // clear apa headers for(i=1024*8;i<hddDevices[f->unit].totalLBA;i+=(1024*256)) { ata_device_sector_io(f->unit, clink->header, i, sizeof(apa_header_t)/512, ATA_DIR_WRITE); } apaCacheFree(clink); if((rv=apaJournalReset(f->unit))!=0) return rv; // set up mbr :) if((clink=apaCacheGetHeader(f->unit, 0, APA_IO_MODE_WRITE, &rv))){ apa_header_t *header=clink->header; memset(header, 0, sizeof(apa_header_t)); header->magic=APA_MAGIC; header->length=(1024*256); // 128MB header->type=APA_TYPE_MBR; strcpy(header->id,"__mbr"); #ifdef APA_FORMAT_LOCK_MBR apaEncryptPassword(header->id, header->fpwd, "sce_mbr"); apaEncryptPassword(header->id, header->rpwd, "sce_mbr"); #endif memcpy(header->mbr.magic, apaMBRMagic, sizeof(header->mbr.magic)); header->mbr.version=APA_MBR_VERSION; header->mbr.nsector=0; apaGetTime(&header->created); apaGetTime(&header->mbr.created); header->checksum=apaCheckSum(header); clink->flags|=APA_CACHE_FLAG_DIRTY; apaCacheFlushDirty(clink); ata_device_flush_cache(f->unit); apaCacheFree(clink); hddDevices[f->unit].status=0; hddDevices[f->unit].format=APA_MBR_VERSION; } #ifdef APA_FORMAT_MAKE_PARTITIONS memset(&emptyBlocks, 0, sizeof(emptyBlocks)); memset(¶ms, 0, sizeof(apa_params_t)); params.size=(1024*256); params.type=APA_TYPE_PFS; // add __net, __system.... for(i=0;formatPartList[i];i++) { memset(params.id, 0, APA_IDMAX); strcpy(params.id, formatPartList[i]); if(!(clink=hddAddPartitionHere(f->unit, ¶ms, emptyBlocks, i ? clink->sector : 0, &rv))) return rv; apaCacheFree(clink); params.size<<=1; if(hddDevices[f->unit].partitionMaxSize < params.size) params.size=hddDevices[f->unit].partitionMaxSize; } #endif 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; }