UbixOS V2
2.0
ubixfs.cpp
Go to the documentation of this file.
1
/*#include <stddef.h>
2
#include <stdlib.h>
3
#include <unistd.h>
4
#include <string.h>
5
#include <assert.h>
6
#include <iostream>
7
8
#include "ubixfs.h"
9
#include "btree.h"
10
11
using namespace std;
12
13
UbixFS::UbixFS(void) {
14
device = NULL;
15
freeBlockList = NULL;
16
superBlock = NULL;
17
root = NULL;
18
} // UbixFS::UbixFS
19
20
21
UbixFS::UbixFS(device_t * dev) {
22
device = dev;
23
freeBlockList = NULL;
24
superBlock = NULL;
25
root = NULL;
26
} // UbixFS::UbixFS
27
28
void
29
UbixFS::printSuperBlock(void) {
30
printf("superBlock->name........... %s\n", superBlock->name);
31
printf("superBlock->magic1......... %X\n", superBlock->magic1);
32
printf("superBlock->fsByteOrder.... %d\n", superBlock->fsByteOrder);
33
printf("superBlock->blockSize...... %d\n", superBlock->blockSize);
34
printf("superBlock->blockShift..... %d\n", superBlock->blockShift);
35
printf("superBlock->numBlocks...... %lld\n", superBlock->numBlocks);
36
printf("superBlock->usedBlocks..... %lld\n", superBlock->usedBlocks);
37
printf("superBlock->batSectors..... %d\n", superBlock->batSectors);
38
printf("superBlock->inodeCount..... %d\n", superBlock->inodeCount);
39
printf("superBlock->magic2......... %X\n", superBlock->magic2);
40
printf("superBlock->blocksPerAG.... %d\n", superBlock->blocksPerAG);
41
printf("superBlock->AGShift........ %d\n", superBlock->AGShift);
42
printf("superBlock->numAGs......... %d\n", superBlock->numAGs);
43
printf("superBlock->lastUsedAG..... %d\n", superBlock->lastUsedAG);
44
printf("superBlock->flags.......... %X\n", superBlock->flags);
45
printf("superBlock->magic3......... %X\n", superBlock->magic3);
46
return;
47
} // UbixFS::printSuperBlock
48
49
int
50
UbixFS::vfs_init(void) {
51
assert(device);
52
size_t result;
53
cout << "vfs_init()" << endl;
54
assert(device);
55
56
if (device == NULL) return -1;
57
if (superBlock != NULL) delete superBlock;
58
superBlock = new diskSuperBlock;
59
assert(superBlock);
60
if (superBlock == NULL) return -1;
61
62
// read in the superBlock. It's always the last block on the partition
63
cout << "reading in superBlock" << endl;
64
device->read(device, superBlock, device->sectors-1, 1);
65
cout << "done" << endl;
66
67
assert(superBlock->magic1 == UBIXFS_MAGIC1);
68
assert(superBlock->magic2 == UBIXFS_MAGIC2);
69
assert(superBlock->magic3 == UBIXFS_MAGIC3);
70
assert(strcmp(superBlock->name, "UbixFS") == 0);
71
assert((1 << superBlock->blockShift) == superBlock->blockSize);
72
assert((unsigned)(1 << superBlock->AGShift) == superBlock->blocksPerAG);
73
assert(superBlock->flags == UBIXFS_CLEAN);
74
75
if (freeBlockList != NULL) delete [] freeBlockList;
76
freeBlockList = new signed char[superBlock->batSectors*512];
77
assert(freeBlockList);
78
memset(freeBlockList, 0, superBlock->batSectors*512);
79
80
device->read(device,
81
freeBlockList,
82
device->sectors - superBlock->batSectors-1,
83
superBlock->batSectors
84
); // device->read()
85
86
root = new fileDescriptor;
87
assert(root);
88
memset(root, 0, sizeof(fileDescriptor));
89
cout << "allocating root dir inode" << endl;
90
root->inode = new ubixfsInode;
91
memset(root->inode, 0, sizeof(ubixfsInode));
92
cout << "root dir inode starting sector: " <<
93
((superBlock->rootDir.AG << superBlock->AGShift)
94
+ superBlock->rootDir.start) * (superBlock->blockSize / 512)
95
<< endl;
96
97
cout << "reading in root dir inode" << endl;
98
99
device->read(device,
100
root->inode,
101
((superBlock->rootDir.AG << superBlock->AGShift)
102
+ superBlock->rootDir.start) * (superBlock->blockSize / 512),
103
sizeof(ubixfsInode) / 512
104
);
105
cout << "done" << endl;
106
ubixfsInode * rootInode = static_cast<ubixfsInode *>(root->inode);
107
assert(rootInode);
108
109
//the bTree constructor now loads in the header
110
111
rootInode->data.btPtr = new bTree(this, root);
112
rootInode->data.btPtr->Info();
113
printSuperBlock();
114
return 0;
115
} // UbixFS::init
116
117
int
118
UbixFS::vfs_format(device_t * dev) {
119
cout << "vfs_format()" << endl;
120
char sector[512];
121
uInt32 blocks, batSect, batSize;
122
if (dev == NULL) return -1;
123
124
// zero out the sector
125
memset(§or, 0x0, sizeof(sector));
126
127
// fill the drive in with zeroed out sectors
128
cout << "dev->sectors: " << dev->sectors << endl;
129
cout << "clearing device...";
130
131
for (unsigned int i = 0; i < dev->sectors; i++) {
132
dev->write(dev, §or, i, 1);
133
} // for i
134
135
cout << "done" << endl;
136
137
// allocate a new superBlock and clear it
138
139
diskSuperBlock *sb = new diskSuperBlock;
140
if (sb == NULL) return -1;
141
memset(sb, 0, sizeof(diskSuperBlock));
142
143
// dev->sectors is the number of 512 byte sectors
144
145
blocks = (dev->sectors-1) / 8; // 4k blocks
146
batSize = (dev->sectors-1) % 8; // remainder
147
148
// compute the BAT size
149
150
while ((batSize * 4096) < blocks) {
151
batSize += 8;
152
--blocks;
153
} // while
154
155
// batSize is in sectors
156
batSect = blocks * 8;
157
158
strcpy(sb->name, "UbixFS");
159
sb->magic1 = UBIXFS_MAGIC1;
160
sb->fsByteOrder = 0;
161
sb->blockSize = 4096;
162
sb->blockShift = 12;
163
sb->numBlocks = blocks;
164
sb->usedBlocks = 2; // root dir takes two blocks (inode + bTree header)
165
sb->inodeCount = 1;
166
sb->inodeSize = 4096;
167
sb->magic2 = UBIXFS_MAGIC2;
168
sb->blocksPerAG = 2048;
169
sb->AGShift = 11;
170
sb->numAGs = (sb->numBlocks+2047) / 2048;
171
sb->lastUsedAG = 0;
172
173
// the BAT exists outside our official block count, so no
174
// entries in the BAT need to be set for it
175
sb->batSectors = batSize;
176
177
sb->flags = 0x434C454E; // CLEN
178
sb->logBlocks.AG = 0;
179
sb->logBlocks.start = 0;
180
sb->logBlocks.len = 0;
181
sb->logStart = 0;
182
sb->logEnd = 0;
183
sb->magic3 = UBIXFS_MAGIC3;
184
sb->indicies.AG = 0;
185
sb->indicies.start = 0;
186
sb->indicies.len = 0;
187
188
sb->rootDir.AG = 0;
189
sb->rootDir.start = 0;
190
sb->rootDir.len = 1;
191
192
// write out the superBlock
193
194
dev->write(dev, sb, dev->sectors-1, 1);
195
196
// mark the first two 4k blocks used
197
memset(§or, 0, sizeof(sector));
198
sector[0] = (1 << 7) | (1 << 6);
199
200
// write out the first sector of the BAT
201
202
dev->write(dev, §or, batSect, 1);
203
// clear the rest
204
sector[0] = 0;
205
206
// write out the rest of the BAT
207
208
for (unsigned int i = 1; i < batSize; i++) {
209
dev->write(dev, §or, (batSect)+i, 1);
210
} // for i
211
212
// allocate part of the root dir
213
214
// sanity checks
215
assert(sb->blockSize);
216
assert((unsigned)sb->blockSize >= sizeof(bTreeHeader));
217
218
bTreeHeader * bth = new bTreeHeader;
219
assert(bth);
220
memset(bth, 0, sizeof(bTreeHeader));
221
222
bth->firstDeleted = -1;
223
bth->firstNodeOffset = -1;
224
bth->treeDepth = 1;
225
bth->treeWidth = 0;
226
bth->treeLeafCount = 0;
227
228
// create the root dir inode here
229
230
ubixfsInode * inode = new ubixfsInode;
231
assert(inode);
232
if (inode == NULL) return -1;
233
memset(inode, 0, sizeof(ubixfsInode));
234
235
inode->magic1 = UBIXFS_INODE_MAGIC;
236
237
// inodes point to themselves
238
inode->inodeNum.AG = 0;
239
inode->inodeNum.start = 0;
240
inode->inodeNum.len = 1;
241
242
// root dir has no parent directory
243
inode->parent.iAddr.AG = 0;
244
inode->parent.iAddr.start = 0;
245
inode->parent.iAddr.len = 0;
246
247
// this is part of the root dir structure (the bTreeHeader)
248
inode->blocks.direct[0].AG = 0;
249
inode->blocks.direct[0].start = 1;
250
inode->blocks.direct[0].len = 1;
251
252
inode->blocks.maxDirectRange = sizeof(bTreeHeader);
253
inode->blocks.size = sizeof(bTreeHeader);
254
255
strcpy(inode->name, "/");
256
inode->uid = getuid();
257
inode->gid = getgid();
258
// inode->mode
259
inode->flags = INODE_DIRECTORY;
260
// inode->createTime
261
// inode->lastModifiedTime
262
// inode->type
263
264
inode->attributes.AG = 0;
265
inode->attributes.start = 0;
266
inode->attributes.len = 0;
267
268
inode->inodeSize = sb->inodeSize;
269
270
*/
/*
271
* next and prev are used in memory to hold pointers to the next/prev
272
* inodes in this dir. On disk they may have another value, but for
273
* now they should be set to null.
274
*/
/*
275
276
inode->next.offset = 0;
277
inode->prev.offset = 0;
278
279
// write out the "root" dir inode
280
281
dev->write(dev,
282
inode,
283
((inode->inodeNum.AG << sb->AGShift) +
284
inode->inodeNum.start) * (sb->blockSize / 512),
285
sb->inodeSize / 512
286
); // dev->write
287
288
// write out the "root" dir
289
290
dev->write(dev,
291
bth,
292
((inode->blocks.direct[0].AG << sb->AGShift) +
293
inode->blocks.direct[0].start) * (sb->blockSize / 512),
294
sb->blockSize / 512
295
); // dev->write
296
297
delete inode;
298
delete bth;
299
delete sb;
300
cout << "format complete" << endl;
301
return 0;
302
} // UbixFS::vfs_format
303
304
void *
305
UbixFS::vfs_mknod(const char *path, mode_t mode) {
306
return mknod(path, 0, mode); // <- this probably isn't correct
307
} // UbixFS::vfs_mknod
308
309
int
310
UbixFS::vfs_open(const char * filename, fileDescriptor * fd, int flags, ...) {
311
if (filename == NULL || fd == NULL) return -1;
312
flags = flags;
313
fd->inode = NULL;
314
fd->offset = 0;
315
fd->size = 0;
316
// look up the file here
317
return 0;
318
} // UbixFS::vfs_open
319
320
size_t
321
UbixFS::vfs_read(fileDescriptor * fd, void * data, off_t offset, size_t size) {
322
323
unsigned int i;
324
off_t sum, startingBlock;
325
size_t runSize, sectorCount, totalSize, bSize; // blockSize
326
ubixfsInode * inode = NULL;
327
328
if (fd == NULL || data == NULL) return ~0;
329
330
if (size == 0) return 0; // don't fail if size is 0?
331
332
assert(device);
333
assert(superBlock);
334
335
inode = static_cast<ubixfsInode *>(fd->inode);
336
337
assert(inode);
338
339
bSize = superBlock->blockSize;
340
341
totalSize = sum = i = 0;
342
343
while (size > 0) {
344
345
*/
/*
346
* place check here to see which set of blocks we're looking through
347
*/
/*
348
349
// scan through direct blocks
350
do {
351
if (offset >= sum && offset < sum + inode->blocks.direct[i].len * bSize) break;
352
353
sum += inode->blocks.direct[i++].len * bSize;
354
355
} while (i < NUM_DIRECT_BLOCKS);
356
357
startingBlock = (inode->blocks.direct[i].AG << superBlock->AGShift) +
358
inode->blocks.direct[i].start + ((offset - sum) / bSize);
359
360
runSize = inode->blocks.direct[i].len * bSize;
361
362
// startingBlock is in 4k blocks
363
startingBlock *= (bSize / 512);
364
// startingBlock is now in sectors
365
366
if (runSize >= size) {
367
runSize = size;
368
size = 0;
369
} else {
370
size -= runSize;
371
} // else
372
373
sectorCount = runSize / 512;
374
375
cout << "device->read(device, data, " << startingBlock << ", ";
376
cout << sectorCount << ");" << endl;
377
378
device->read(device, data, startingBlock, sectorCount);
379
380
(uInt8 *)data += runSize;
381
totalSize += runSize;
382
} // while
383
return totalSize;
384
} // UbixFS::vfs_read
385
386
size_t
387
UbixFS::vfs_write(fileDescriptor * fd, void * data, off_t offset, size_t size) {
388
// char * sector[512]; // used to pad
389
unsigned int i, whichBlocks;
390
off_t sum, startingBlock, EORPos, maxRange;
391
size_t runSize, runRemainder, sectorCount, totalSize, bSize; // blockSize
392
ubixfsInode * inode = NULL;
393
blockRun br;
394
395
if (fd == NULL || data == NULL) return ~0;
396
397
if (size == 0) return 0; // don't fail if size is 0?
398
399
assert(device);
400
assert(superBlock);
401
402
inode = static_cast<ubixfsInode *>(fd->inode);
403
404
assert(inode);
405
406
bSize = superBlock->blockSize;
407
assert(bSize != 0);
408
409
totalSize = sum = i = whichBlocks = 0;
410
411
EORPos = offset + size; // compute End Of Run Position
412
maxRange = inode->blocks.maxDirectRange;
413
414
if (inode->blocks.maxIndirectRange > maxRange) {
415
maxRange = inode->blocks.maxIndirectRange;
416
whichBlocks = 1;
417
}
418
419
if (inode->blocks.maxDoubleIndirectRange > maxRange) {
420
maxRange = inode->blocks.maxDoubleIndirectRange;
421
whichBlocks = 2;
422
}
423
424
if (EORPos > maxRange) {
425
*/
/*
426
* The offset+size is greater than the size of the file, so we need to
427
* extend out the file. Scan through the direct blocks (FIX LATER)
428
* to find out where we need to extend
429
*/
/*
430
switch (whichBlocks) {
431
case 0:
432
while (i < NUM_DIRECT_BLOCKS && inode->blocks.direct[i].len != 0) ++i;
433
// i holds which direct block we're going to add to
434
break;
435
case 1:
436
case 2:
437
assert(false); // UNFINISHED
438
break;
439
default:
440
assert(false); // sanity check
441
} // switch
442
443
*/
/*
444
* NOTE: it's possible that if we scan through to find where the
445
* run goes, we might be able to extend the previous block extent.
446
* This will require that we set up br.start to be where we'd like to
447
* start looking through the free block list, and then modifying
448
* getFreeBlock() to honour that.
449
*/
/*
450
451
br.AG = inode->inodeNum.AG; // request a sane allocation group
452
br.start = 0; // getFreeBlock() will ignore this
453
454
*/
/*
455
* The length that we need is determined by how much extra slack we
456
* already have in the pre-allocated blocks.
457
* e.g. (assumes 4k blocks)
458
* bSize = 4096
459
* maxRange = 4096
460
* size = 3000
461
* offset = 3000
462
* size = 4000
463
* [--- data block ---][--- data block ---] <---- blocks on disk
464
* <-file data-> <---- actual file size
465
* <-----> <---- slack
466
* [ data block size ] <---- maxRange
467
* | <---- offset
468
* ***************** <---- new data
469
*
470
* In the above example, you'd need at least one more block to write
471
* out the data.
472
* ((offset + size) - maxRange + (bSize-1)) / bSize
473
* ((3000 + 4000) - 4096 + (4095)) / 4096 == 1 (rounded down)
474
* And then we expand it by a little extra so we don't have to keep
475
* looking for more blocks. Currently we use 32k of slack (or 8 blocks)
476
*/
/*
477
478
br.len = ((EORPos - maxRange + (bSize-1)) / bSize);
479
480
if (br.len < 8) br.len = 8; // we allocate 32k if the file needs to grow
481
482
br = getFreeBlock(br);
483
assert(br.len > 0);
484
switch (whichBlocks) {
485
case 0:
486
inode->blocks.direct[i] = br;
487
inode->blocks.maxDirectRange += br.len * bSize;
488
break;
489
case 1:
490
assert(false); // UNFINISHED
491
inode->blocks.maxIndirectRange += br.len * bSize;
492
break;
493
case 2:
494
assert(false); // UNFINISHED
495
inode->blocks.maxDoubleIndirectRange += br.len * bSize;
496
break;
497
default:
498
assert(false); // sanity check
499
} // switch
500
501
inode->blocks.size = EORPos;
502
} // if
503
504
505
runRemainder = size % 512;
506
size -= runRemainder;
507
508
totalSize = sum = i = 0;
509
510
while (size > 0) {
511
512
/ place check here to see which set of blocks we're looking through
513
514
515
// scan through direct blocks
516
do {
517
if (offset >= sum && offset < sum + inode->blocks.direct[i].len * bSize)
518
break;
519
520
sum += inode->blocks.direct[i++].len * bSize;
521
522
} while (i < NUM_DIRECT_BLOCKS);
523
524
startingBlock = (inode->blocks.direct[i].AG << superBlock->AGShift) +
525
inode->blocks.direct[i].start + ((offset - sum) / bSize);
526
527
runSize = inode->blocks.direct[i].len * bSize;
528
529
// startingBlock is in 4k blocks
530
startingBlock *= (bSize / 512);
531
// startingBlock is now in sectors
532
533
if (runSize >= size) {
534
runSize = size;
535
size = 0;
536
} else {
537
size -= runSize;
538
} // else
539
540
sectorCount = runSize / 512;
541
542
cout << "device->write(device, data, " << startingBlock << ", ";
543
cout << sectorCount << ");" << endl;
544
545
device->write(device, data, startingBlock, sectorCount);
546
547
(uInt8 *)data += runSize;
548
totalSize += runSize;
549
} // while
550
551
assert(runRemainder != 0); // UNFINISHED
552
return totalSize;
553
} // UbixFS::vfs_write
554
555
int
556
UbixFS::vfs_stop(void) {
557
if (vfs_sync() != 0) return -1;
558
559
// you must delete the root dir first, in case it needs to
560
// still write anything out
561
562
if (root != NULL) {
563
ubixfsInode * rootInode = static_cast<ubixfsInode *>(root->inode);
564
delete rootInode->data.btPtr;
565
delete rootInode;
566
root->inode = NULL;
567
568
} // if
569
570
delete root;
571
delete [] freeBlockList;
572
delete superBlock;
573
574
freeBlockList = NULL;
575
superBlock = NULL;
576
root = NULL;
577
578
*/
/*
579
* The device isn't null at this point, allowing for people to restart
580
* the mount point. Or, alternatively, to blow things up.
581
*/
/*
582
583
return 0;
584
} // UbixFS::vfs_stop
585
586
int
587
UbixFS::vfs_sync(void) {
588
if (device == NULL || superBlock == NULL || freeBlockList == NULL) return -1;
589
device->write(device,
590
freeBlockList,
591
device->sectors - superBlock->batSectors - 1,
592
superBlock->batSectors
593
);
594
device->write(device, superBlock, device->sectors-1, 1);
595
return 0;
596
} // UbixFS::vfs_sync
597
598
void
599
UbixFS::setFreeBlock(blockRun ibr) {
600
signed char * ptr;
601
602
if (superBlock == NULL || freeBlockList == NULL) return;
603
if (ibr.len == 0) return;
604
ptr = freeBlockList + ((ibr.AG << superBlock->AGShift) >> 3);
605
ptr += ibr.start >> 3;
606
607
if (ibr.start % 8 != 0) {
608
609
ibr.len -= ibr.start % 8;
610
} // if
611
612
} // UbixFS::setFreeBlock
613
614
blockRun
615
UbixFS::getFreeBlock(blockRun ibr) {
616
signed char * ptr;
617
signed char * holdPtr;
618
int32 count, holdCount;
619
620
blockRun obr = {0, 0, 0}; // output block run
621
622
// Check to make sure none of these are null
623
if (device == NULL || freeBlockList == NULL || superBlock == NULL) return obr;
624
625
if (ibr.len == 0) return obr;
626
627
if (ibr.len > superBlock->numBlocks) return obr;
628
629
if (ibr.len == 1) return getFreeBlock(ibr.AG);
630
*/
/*
631
* count is the block from the base of the list.
632
* Since we're given a specific AG to look through, we start the count at
633
* AG << AGShift, where AGShift is the shift value of the number of blocks
634
* in an AG
635
*/
/*
636
637
count = (ibr.AG << superBlock->AGShift);
638
639
*/
/*
640
* The freeBlockList is a bit map of the free/used blocks.
641
* Used = on bit
642
* Unused = off bit
643
* There are 8 bits per byte (hopefully) and so we have to divide the count
644
* by 8 to get our starting byte offset to look from
645
*/
/*
646
647
ptr = freeBlockList + (count >> 3);
648
649
rescan:
650
// look for the first free 8 blocks (this may create holes)
651
while (*ptr != 0) {
652
++ptr;
653
count += 8;
654
if (count+8 > superBlock->numBlocks) {
655
ptr = freeBlockList;
656
count = 0;
657
} // if
658
} // while *ptr != 0
659
660
holdPtr = ptr;
661
holdCount = count;
662
663
for (unsigned short i = 0; i < ((ibr.len+7) / 8); i++) {
664
++ptr;
665
count += 8;
666
if (count+8 > superBlock->numBlocks) {
667
ptr = freeBlockList;
668
count = 0;
669
goto rescan;
670
} // if
671
if (*ptr != 0) goto rescan;
672
} // for i
673
674
// we have found a range of blocks that work for us
675
676
obr.AG = holdCount / superBlock->blocksPerAG;
677
obr.start = holdCount % superBlock->blocksPerAG;
678
obr.len = ibr.len;
679
680
for (unsigned short i = 0; i < (ibr.len / 8); i++) {
681
*holdPtr = -1;
682
++holdPtr;
683
} // for
684
685
if (ibr.len % 8 != 0) *holdPtr = (-1 << (8-(ibr.len % 8)));
686
687
superBlock->usedBlocks += ibr.len; // increment the number of used blocks
688
return obr;
689
} // UbixFS::getFreeBlock
690
691
blockRun
692
UbixFS::getFreeBlock(uInt32 AG) {
693
// AG == AllocationGroup
694
blockRun br;
695
signed char * ptr;
696
int32 count;
697
int32 subCount = 128;
698
699
br.AG = 0;
700
br.start = 0;
701
br.len = 0;
702
// Check to make sure neither of these are null
703
if (device == NULL || freeBlockList == NULL || superBlock == NULL) return br;
704
705
// Are there any blocks available?
706
if (superBlock->numBlocks == superBlock->usedBlocks) return br;
707
708
*/
/*
709
* count is the block from the base of the list.
710
* Since we're given a specific AG to look through, we start the count at
711
* AG << AGShift, where AGShift is the shift value of the number of blocks
712
* in an AG
713
*/
/*
714
715
count = (AG << superBlock->AGShift);
716
717
*/
/*
718
* The freeBlockList is a bit map of the free/used blocks.
719
* Used = on bit
720
* Unused = off bit
721
* There are 8 bits per byte (hopefully) and so we have to divide the count
722
* by 8 to get our starting byte offset to look from
723
*/
/*
724
725
ptr = freeBlockList + (count >> 3);
726
727
// Scan through the freeBlockList
728
729
rescan:
730
while (*ptr == -1) {
731
++ptr;
732
count += 8;
733
if (count+8 > superBlock->numBlocks) break;
734
} // while *ptr == -1
735
736
subCount = 128;
737
738
do {
739
if ((*ptr & subCount) == 0) break;
740
subCount >>= 1;
741
++count;
742
if (count == superBlock->numBlocks) {
743
count = 0;
744
ptr = freeBlockList;
745
goto rescan;
746
} // if
747
} while(subCount > 1);
748
749
*ptr |= subCount; // mark this block as used
750
++superBlock->usedBlocks; // increment the number of used blocks
751
752
br.AG = count / superBlock->blocksPerAG;
753
br.start = count % superBlock->blocksPerAG;
754
br.len = 1;
755
return br; // return the allocated block number
756
} // Ubixfs::getFreeBlock
757
758
uInt32
759
UbixFS::getNextAG(void) {
760
761
if (superBlock->lastUsedAG == superBlock->numAGs)
762
superBlock->lastUsedAG = 0;
763
else
764
superBlock->lastUsedAG++;
765
return superBlock->lastUsedAG;
766
767
} // UbixFS::getNextAG
768
769
*/
/*
770
* UbixFS::getFreeBlock(void)
771
* upon success returns a free block based on the next AG after the lastUsedAG
772
* failure returns -1
773
*/
/*
774
775
blockRun
776
UbixFS::getFreeBlock(void) {
777
return getFreeBlock(getNextAG());
778
} // UbixFS::getFreeBlock
779
780
blockRun
781
UbixFS::get8FreeBlocks(uInt32 AG) {
782
// AG == AllocationGroup
783
blockRun br;
784
signed char * ptr;
785
signed char * endPtr;
786
int32 count;
787
788
br.AG = 0;
789
br.start = 0;
790
br.len = 0;
791
792
if (device == NULL || freeBlockList == NULL || superBlock == NULL) return br;
793
794
// Are there any blocks available?
795
if (superBlock->usedBlocks+8 > superBlock->numBlocks) return br;
796
797
*/
/*
798
* count is the block from the base of the list.
799
* Since we're given a specific AG to look through, we start the count at
800
* AG << AGShift, where AGShift is the shift value of the number of blocks
801
* in an AG
802
*/
/*
803
804
count = (AG << superBlock->AGShift);
805
806
ptr = freeBlockList + (count >> 3);
807
808
endPtr = freeBlockList + (superBlock->numBlocks >> 3);
809
810
bool secondTime = false;
811
while (*ptr != 0) {
812
++ptr;
813
count += 8;
814
if (ptr == endPtr) {
815
if (secondTime)
816
return br;
817
else
818
secondTime = true;
819
820
count = 0;
821
ptr = freeBlockList;
822
} // if
823
} // while
824
825
*ptr = -1; // mark 8 blocks as taken
826
827
br.AG = count / superBlock->blocksPerAG;
828
br.start = count % superBlock->blocksPerAG;
829
br.len = 8;
830
return br;
831
} // UbixFS::get8FreeBlocks
832
833
void *
834
UbixFS::mknod(const char *filename, ubixfsInode * parent, mode_t mode) {
835
ubixfsInode * inode = NULL;
836
837
inode = new ubixfsInode;
838
assert(inode);
839
if (inode == NULL) return NULL;
840
memset(inode, 0, sizeof(ubixfsInode));
841
842
inode->magic1 = UBIXFS_INODE_MAGIC;
843
844
*/
/*
845
* in retrospect.. I'm not sure why parent would be null.. only the
846
* root directory would have a null parent, but that's manually allocated
847
* in vfs_format()
848
*/
/*
849
850
if (parent == NULL) {
851
inode->inodeNum = getFreeBlock();
852
inode->parent.iAddr.AG = 0;
853
inode->parent.iAddr.start = 0;
854
inode->parent.iAddr.len = 0;
855
} else {
856
inode->inodeNum = getFreeBlock(parent->inodeNum.AG);
857
inode->parent.iAddr = parent->inodeNum;
858
} // else
859
860
strncpy(inode->name, filename, MAX_FILENAME_LENGTH);
861
862
inode->uid = getuid();
863
inode->gid = getgid();
864
// inode->mode
865
inode->flags = mode;
866
// inode->createTime
867
// inode->lastModifiedTime
868
inode->inodeSize = superBlock->inodeSize;
869
870
inode->attributes.AG = 0;
871
inode->attributes.start = 0;
872
inode->attributes.len = 0;
873
874
// inode->type
875
876
*/
/*
877
* next and prev are used in memory to hold pointers to the next/prev
878
* inodes in this dir. On disk they may have another value, but for
879
* now they should be set to null.
880
*/
/*
881
882
inode->next.offset = 0;
883
inode->prev.offset = 0;
884
inode->refCount = 0;
885
++superBlock->inodeCount;
886
return inode;
887
} // UbixFS::mknod
888
889
int
890
UbixFS::vfs_mkdir(const char * path, mode_t mode) {
891
char name[MAX_FILENAME_LENGTH];
892
unsigned int start, end, len, nameStart;
893
ubixfsInode * dir = static_cast<ubixfsInode *>(root->inode);
894
ubixfsInode * inode = NULL;
895
896
assert(path); // bad input: vfs_mkdir(NULL);
897
assert(*path); // bad input: vfs_mkdir("");
898
899
memset(&name, 0, sizeof(name));
900
// find the dir name
901
len = strlen(path);
902
903
assert(path[0] == '/'); // bad input: vfs isn't doing its job
904
assert(len > 1); // bad input: mkdir /
905
906
// remove trailing "/" if present
907
if (path[len-1] == '/') --len;
908
909
assert(len > 1); // bad input: mkdir //
910
911
nameStart = len-1;
912
913
assert(path[nameStart] != '/'); // bad input: mkdir /a//
914
915
*/
/*
916
* we're guaranteed by the assert() above that there is
917
* at least one "/" before our location. If you remove the assert
918
* you might need to make sure nameStart stays above 0 in the following
919
* while
920
*/
/*
921
922
while (path[nameStart] != '/') --nameStart;
923
++nameStart;
924
assert(len - nameStart > 0);
925
926
*/
/* e.g.
927
* v--------------------- start
928
* v------------------ end
929
* v------ nameStart
930
* /usr/local/data/dirname/ <--- ignores trailing /
931
* <---------23----------> len
932
*/
/*
933
934
start = end = 1; // skip leading /
935
while (end < nameStart) {
936
do { ++end; } while(path[end] != '/');
937
938
assert(end-start+1 < sizeof(name));
939
// this is probably wrong:
940
strncpy(name, &path[start], end-start+1);
941
cout << name << endl;
942
dir = dir->data.btPtr->Find(name);
943
assert(dir);
944
assert(dir->flags & INODE_DIRECTORY == INODE_DIRECTORY);
945
start = ++end;
946
}
947
948
strncpy(name, &path[nameStart], len - nameStart);
949
inode = (ubixfsInode *)mknod(name, dir, mode | INODE_DIRECTORY);
950
951
*/
/*
952
* keep in mind that the reason for passing in the name is because
953
* we thought about allowing key names to be different from inode
954
* names. In retrospect, I don't think that's a good idea since a dir
955
* listing will print the actual dir name instead of . and ..
956
* Thus: the first parameter of btPtr->Insert() may go away.
957
*/
/*
958
959
assert(dir->data.btPtr->Insert(inode->name, inode));
960
961
return 0;
962
} // UbixFS::vfs_mkdir
963
964
void
965
UbixFS::printFreeBlockList(uInt32 AG) {
966
unsigned int j;
967
if (superBlock == NULL || freeBlockList == NULL) return;
968
printf("AG = %d\n", AG);
969
for (unsigned int i = 0; i < superBlock->blocksPerAG / 8; i++) {
970
j = 128;
971
signed char foo = freeBlockList[(AG << superBlock->AGShift)+i];
972
while (j > 0) {
973
if ((foo & j) == j)
974
printf("1");
975
else
976
printf("0");
977
j >>= 1;
978
979
}
980
} // for i
981
printf("\n");
982
return;
983
} // UbixFS::printFreeBlockList
984
985
UbixFS::~UbixFS(void) {
986
delete [] freeBlockList;
987
return;
988
}
989
*/
C:
Dev
git
UbixOS
sys
fs
ubixfsv2
ubixfs.cpp
Generated by
1.8.16