PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
blockWrite.c
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.
9#
10# PFS block/zone (write) related routines
11*/
12
13#include <errno.h>
14#include <stdio.h>
15#ifdef _IOP
16#include <sysclib.h>
17#else
18#include <string.h>
19#endif
20
21#include "libpfs.h"
22
23// Attempt to expand the block segment 'blockpos' by 'count' blocks
24int pfsBlockExpandSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 count)
25{
26 int ret;
28
29 if(pfsFixIndex(blockpos->block_segment)==0)
30 return 0;
31
32 bi = &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)];
33
34 if ((ret = pfsBitmapAllocateAdditionalZones(clink->pfsMount, bi, count)))
35 {
36 bi->count+=ret;
37 clink->u.inode->number_blocks+=ret;
38 blockpos->inode->flags |= PFS_CACHE_FLAG_DIRTY;
39 clink->flags |= PFS_CACHE_FLAG_DIRTY;
40 }
41
42 return ret;
43}
44
45// Attempts to allocate 'blocks' new blocks for an inode
46int pfsBlockAllocNewSegment(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 blocks)
47{
48 pfs_blockinfo_t bi, *bi2;
49 int result=0;
50 pfs_mount_t *pfsMount=clink->pfsMount;
51 u32 i, old_blocks = blocks;
52
53 if (pfsCacheIsFull())
54 return -ENOMEM;
55
56 // create "indirect segment descriptor" if necessary
57 if (pfsFixIndex(clink->u.inode->number_data) == 0)
58 {
59 pfs_cache_t *clink2;
60
61 bi2 = &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)];
62 bi.subpart=bi2->subpart;
63 bi.count=1;
64 bi.number=bi2->number+bi2->count;
65 result=pfsBitmapSearchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks);
66 if (result<0)
67 {
68 PFS_PRINTF(PFS_DRV_NAME": Error: Couldnt allocate zone! (1)\n");
69 return result;
70 }
71
72 clink2=pfsCacheGetData(pfsMount, bi.subpart, bi.number << pfsMount->inode_scale,
73 PFS_CACHE_FLAG_SEGI | PFS_CACHE_FLAG_NOLOAD, &result);
74 memset(clink2->u.inode, 0, sizeof(pfs_inode_t));
75 clink2->u.inode->magic=PFS_SEGI_MAGIC;
76
77 memcpy(&clink2->u.inode->inode_block, &clink->u.inode->inode_block, sizeof(pfs_blockinfo_t));
78 memcpy(&clink2->u.inode->last_segment, &blockpos->inode->u.inode->data[0], sizeof(pfs_blockinfo_t));
79 memcpy(&clink2->u.inode->data[0], &bi, sizeof(pfs_blockinfo_t));
80
81 clink2->flags |= PFS_CACHE_FLAG_DIRTY;
82
83 clink->u.inode->number_blocks+=bi.count;
84 clink->u.inode->number_data++;
85
86 memcpy(&clink->u.inode->last_segment, &bi, sizeof(pfs_blockinfo_t));
87
88 clink->u.inode->number_segdesg++;
89
90 clink->flags |= PFS_CACHE_FLAG_DIRTY;
91 blockpos->block_segment++;
92 blockpos->block_offset=0;
93
94 memcpy(&blockpos->inode->u.inode->next_segment, &bi, sizeof(pfs_blockinfo_t));
95
96 blockpos->inode->flags |= PFS_CACHE_FLAG_DIRTY;
97 pfsCacheFree(blockpos->inode);
98 blockpos->inode=clink2;
99 }
100
101 bi2 = &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)];
102 bi.subpart = bi2->subpart;
103 bi.count = blocks;
104 bi.number = bi2->number + bi2->count;
105
106 result = pfsBitmapSearchFreeZone(pfsMount, &bi, clink->u.inode->number_blocks);
107 if(result < 0)
108 {
109 PFS_PRINTF(PFS_DRV_NAME": Error: Couldnt allocate zone! (2)\n");
110 return result;
111 }
112
113 clink->u.inode->number_blocks += bi.count;
114 clink->u.inode->number_data++;
115 clink->flags |= PFS_CACHE_FLAG_DIRTY;
116 blockpos->block_offset=0;
117 blockpos->block_segment++;
118
119 i = pfsFixIndex(clink->u.inode->number_data-1);
120 memcpy(&blockpos->inode->u.inode->data[i], &bi, sizeof(pfs_blockinfo_t));
121
122 blockpos->inode->flags |= PFS_CACHE_FLAG_DIRTY;
123 blocks -= bi.count;
124 if (blocks)
125 blocks -= pfsBlockExpandSegment(clink, blockpos, blocks);
126
127 return old_blocks - blocks;
128}
129
130// Returns the block info for the block segment corresponding to the
131// files current position.
132pfs_blockinfo_t* pfsBlockGetCurrent(pfs_blockpos_t *blockpos)
133{
134 return &blockpos->inode->u.inode->data[pfsFixIndex(blockpos->block_segment)];
135}
136
137pfs_cache_t *pfsBlockGetLastSegmentDescriptorInode(pfs_cache_t *clink, int *result)
138{
139 return pfsCacheGetData(clink->pfsMount, clink->u.inode->last_segment.subpart,
140 clink->u.inode->last_segment.number<<clink->pfsMount->inode_scale,
141 (clink->u.inode->last_segment.subpart==
142 clink->u.inode->inode_block.subpart)&&
143 (clink->u.inode->last_segment.number==
144 clink->u.inode->inode_block.number) ? 16 : 32, result);
145}
#define ENOMEM
Definition errno.h:43
u32 count
start sector of fragmented bd/file