fix for corrupted graphics when manipulating config files
[open-ps2-loader.git] / modules / ps2fs / block.c
blobc57b62df8a7d32e45331d7378f7979d14a359b86
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: block.c 911 2005-03-14 21:02:17Z oopo $
11 # PFS block/zone related routines
14 #include "pfs.h"
16 // Sets 'blockpos' to point to the next block segment for the inode (and moves onto the
17 // next block descriptor inode if necessary)
18 int blockSeekNextSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos)
20 pfs_cache_t *nextSegment;
21 int result=0;
23 if (blockpos->byte_offset)
25 printf("ps2fs: Panic: This is a bug!\n");
26 return -1;
29 // If we're at the end of the block descriptor array for the current
30 // inode, then move onto the next inode
31 if (fixIndex(blockpos->block_segment+1)==0)
33 if ((nextSegment=blockGetNextSegment(cacheUsedAdd(blockpos->inode), &result)) == NULL)
34 return result;
35 cacheAdd(blockpos->inode);
36 blockpos->inode=nextSegment;
37 if (clink->u.inode->number_data-1 == ++blockpos->block_segment)
38 return -EINVAL;
41 blockpos->block_offset=0;
42 blockpos->block_segment++;
43 return result;
46 u32 blockSyncPos(pfs_blockpos_t *blockpos, u64 size)
48 u32 i;
50 i = size / blockpos->inode->pfsMount->zsize;
51 blockpos->byte_offset += size % blockpos->inode->pfsMount->zsize;
53 if (blockpos->byte_offset >= blockpos->inode->pfsMount->zsize)
55 blockpos->byte_offset -= blockpos->inode->pfsMount->zsize;
56 i++;
58 return i;
61 int blockInitPos(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u64 position)
63 blockpos->inode=cacheUsedAdd(clink);
64 blockpos->byte_offset=0;
66 if (clink->u.inode->size)
68 blockpos->block_segment=1;
69 blockpos->block_offset=0;
70 }else{
71 blockpos->block_segment=0;
72 blockpos->block_offset=1;
74 return inodeSync(blockpos, position, clink->u.inode->number_data);
77 // Attempt to expand the block segment 'blockpos' by 'count' blocks
78 int blockExpandSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 count)
80 int ret;
81 pfs_blockinfo *bi;
83 if(fixIndex(blockpos->block_segment)==0)
84 return 0;
86 bi = &blockpos->inode->u.inode->data[fixIndex(blockpos->block_segment)];
88 if ((ret = bitmapAllocateAdditionalZones(clink->pfsMount, bi, count)))
90 bi->count+=ret;
91 clink->u.inode->number_blocks+=ret;
92 blockpos->inode->flags |= CACHE_FLAG_DIRTY;
93 clink->flags |= CACHE_FLAG_DIRTY;
96 return ret;
99 // Attempts to allocate 'blocks' new blocks for an inode
100 int blockAllocNewSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 blocks)
102 pfs_blockinfo bi, *bi2;
103 int result=0;
104 pfs_mount_t *pfsMount=clink->pfsMount;
105 u32 i, old_blocks = blocks;
107 dprintf2("ps2fs CALL: allocNewBlockSegment(, , %ld)\n", blocks);
109 if (cacheIsFull())
110 return -ENOMEM;
112 // create "indirect segment descriptor" if necessary
113 if (fixIndex(clink->u.inode->number_data) == 0)
115 pfs_cache_t *clink2;
117 bi2 = &blockpos->inode->u.inode->data[fixIndex(blockpos->block_segment)];
118 bi.subpart=bi2->subpart;
119 bi.count=1;
120 bi.number=bi2->number+bi2->count;
121 result=searchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks);
122 if (result<0)
124 dprintf("ps2fs: Error: Couldnt allocate zone! (1)\n");
125 return result;
128 clink2=cacheGetData(pfsMount, bi.subpart, bi.number << pfsMount->inode_scale,
129 CACHE_FLAG_SEGI | CACHE_FLAG_NOLOAD, &result);
130 memset(clink2->u.inode, 0, sizeof(pfs_inode));
131 clink2->u.inode->magic=PFS_SEGI_MAGIC;
133 memcpy(&clink2->u.inode->inode_block, &clink->u.inode->inode_block, sizeof(pfs_blockinfo));
134 memcpy(&clink2->u.inode->last_segment, &blockpos->inode->u.inode->data[0], sizeof(pfs_blockinfo));
135 memcpy(&clink2->u.inode->data[0], &bi, sizeof(pfs_blockinfo));
137 clink2->flags |= CACHE_FLAG_DIRTY;
139 clink->u.inode->number_blocks+=bi.count;
140 clink->u.inode->number_data++;
142 memcpy(&clink->u.inode->last_segment, &bi, sizeof(pfs_blockinfo));
144 clink->u.inode->number_segdesg++;
146 clink->flags |= CACHE_FLAG_DIRTY;
147 blockpos->block_segment++;
148 blockpos->block_offset=0;
150 memcpy(&blockpos->inode->u.inode->next_segment, &bi, sizeof(pfs_blockinfo));
152 blockpos->inode->flags |= CACHE_FLAG_DIRTY;
153 cacheAdd(blockpos->inode);
154 blockpos->inode=clink2;
157 bi2 = &blockpos->inode->u.inode->data[fixIndex(blockpos->block_segment)];
158 bi.subpart = bi2->subpart;
159 bi.count = blocks;
160 bi.number = bi2->number + bi2->count;
162 result = searchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks);
163 if(result < 0)
165 dprintf("ps2fs: Error: Couldnt allocate zone! (2)\n");
166 return result;
169 clink->u.inode->number_blocks += bi.count;
170 clink->u.inode->number_data++;
171 clink->flags |= CACHE_FLAG_DIRTY;
172 blockpos->block_offset=0;
173 blockpos->block_segment++;
175 i = fixIndex(clink->u.inode->number_data-1);
176 memcpy(&blockpos->inode->u.inode->data[i], &bi, sizeof(pfs_blockinfo));
178 blockpos->inode->flags |= CACHE_FLAG_DIRTY;
179 blocks -= bi.count;
180 if (blocks)
181 blocks -= blockExpandSegment(clink, blockpos, blocks);
183 return old_blocks - blocks;
186 // Returns the block info for the block segment corresponding to the
187 // files current position.
188 pfs_blockinfo* blockGetCurrent(pfs_blockpos_t *blockpos)
190 return &blockpos->inode->u.inode->data[fixIndex(blockpos->block_segment)];
193 // Returns the next block descriptor inode
194 pfs_cache_t *blockGetNextSegment(pfs_cache_t *clink, int *result)
196 cacheAdd(clink);
198 if (clink->u.inode->next_segment.number)
199 return cacheGetData(clink->pfsMount,
200 clink->u.inode->next_segment.subpart,
201 clink->u.inode->next_segment.number << clink->pfsMount->inode_scale,
202 CACHE_FLAG_SEGI, result);
204 printf( "ps2fs: Error: There is no next segment descriptor\n");
205 *result=-EINVAL;
206 return NULL;
209 pfs_cache_t *blockGetLastSegmentDescriptorInode(pfs_cache_t *clink, int *result)
211 return cacheGetData(clink->pfsMount, clink->u.inode->last_segment.subpart,
212 clink->u.inode->last_segment.number<<clink->pfsMount->inode_scale,
213 (clink->u.inode->last_segment.subpart==
214 clink->u.inode->inode_block.subpart)&&
215 (clink->u.inode->last_segment.number==
216 clink->u.inode->inode_block.number) ? 16 : 32, result);