sblock.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /*
  2. * Copyright (c) 2002 Juli Mallett. All rights reserved.
  3. *
  4. * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the
  5. * FreeBSD project. Redistribution and use in source and binary forms, with
  6. * or without modification, are permitted provided that the following
  7. * conditions are met:
  8. *
  9. * 1. Redistribution of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistribution in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  17. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  19. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  24. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  25. * POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <u.h>
  28. #include <libc.h>
  29. #include <ufs/libufsdat.h>
  30. #include <ufs/fs.h>
  31. #include <ufs/libufs.h>
  32. static int superblocks[] = SBLOCKSEARCH;
  33. #define HOWMANY(x, y) (((x)+((y)-1))/(y))
  34. int
  35. sbread(Uufsd *disk)
  36. {
  37. uint8_t block[MAXBSIZE];
  38. Fs *fs;
  39. int sb, superblock;
  40. int i, size, blks;
  41. uint8_t *space;
  42. libufserror(disk, nil);
  43. fs = &disk->d_fs;
  44. superblock = superblocks[0];
  45. for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) {
  46. if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) {
  47. libufserror(disk, "non-existent or truncated superblock");
  48. return (-1);
  49. }
  50. if (fs->fs_magic == FS_UFS1_MAGIC)
  51. disk->d_ufs = 1;
  52. if (fs->fs_magic == FS_UFS2_MAGIC &&
  53. fs->fs_sblockloc == superblock)
  54. disk->d_ufs = 2;
  55. if (fs->fs_bsize <= MAXBSIZE &&
  56. (size_t)fs->fs_bsize >= sizeof(*fs)) {
  57. if (disk->d_ufs)
  58. break;
  59. }
  60. disk->d_ufs = 0;
  61. }
  62. if (superblock == -1 || disk->d_ufs == 0) {
  63. libufserror(disk, "no usable known superblock found");
  64. return (-1);
  65. }
  66. disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1);
  67. disk->d_sblock = superblock / disk->d_bsize;
  68. /*
  69. * Read in the superblock summary information.
  70. */
  71. size = fs->fs_cssize;
  72. blks = HOWMANY(size, fs->fs_fsize);
  73. size += fs->fs_ncg * sizeof(int32_t);
  74. space = malloc(size);
  75. if (space == nil) {
  76. libufserror(disk, "failed to allocate space for summary information");
  77. return (-1);
  78. }
  79. fs->fs_csp = (struct csum *)space;
  80. for (i = 0; i < blks; i += fs->fs_frag) {
  81. size = fs->fs_bsize;
  82. if (i + fs->fs_frag > blks)
  83. size = (blks - i) * fs->fs_fsize;
  84. if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size)
  85. == -1) {
  86. libufserror(disk, "Failed to read sb summary information");
  87. free(fs->fs_csp);
  88. return (-1);
  89. }
  90. memcpy(space, block, size);
  91. space += size;
  92. }
  93. fs->fs_maxcluster = (int32_t *)space;
  94. disk->d_sbcsum = fs->fs_csp;
  95. return (0);
  96. }
  97. int
  98. sbwrite(Uufsd *disk, int all)
  99. {
  100. Fs *fs;
  101. int blks, size;
  102. uint8_t *space;
  103. unsigned i;
  104. libufserror(disk, nil);
  105. fs = &disk->d_fs;
  106. if (!disk->d_sblock) {
  107. disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize;
  108. }
  109. if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) {
  110. libufserror(disk, "failed to write superblock");
  111. return (-1);
  112. }
  113. /*
  114. * Write superblock summary information.
  115. */
  116. blks = HOWMANY(fs->fs_cssize, fs->fs_fsize);
  117. space = (uint8_t *)disk->d_sbcsum;
  118. for (i = 0; i < blks; i += fs->fs_frag) {
  119. size = fs->fs_bsize;
  120. if (i + fs->fs_frag > blks)
  121. size = (blks - i) * fs->fs_fsize;
  122. if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size)
  123. == -1) {
  124. libufserror(disk, "Failed to write sb summary information");
  125. return (-1);
  126. }
  127. space += size;
  128. }
  129. if (all) {
  130. for (i = 0; i < fs->fs_ncg; i++)
  131. if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)),
  132. fs, SBLOCKSIZE) == -1) {
  133. libufserror(disk, "failed to update a superblock");
  134. return (-1);
  135. }
  136. }
  137. return (0);
  138. }