xref: /minix/minix/fs/ext2/utility.c (revision 0a6a1f1d)
1 /* Created (MFS based):
2  *   February 2010 (Evgeniy Ivanov)
3  */
4 
5 #include "fs.h"
6 #include "buf.h"
7 #include "inode.h"
8 #include "super.h"
9 
10 
11 /*===========================================================================*
12  *				get_block				     *
13  *===========================================================================*/
14 struct buf *get_block(dev_t dev, block_t block, int how)
15 {
16 /* Wrapper routine for lmfs_get_block(). This ext2 implementation does not deal
17  * well with block read errors pretty much anywhere. To prevent corruption due
18  * to unchecked error conditions, we panic upon an I/O failure here.
19  */
20   struct buf *bp;
21   int r;
22 
23   if ((r = lmfs_get_block(&bp, dev, block, how)) != OK && r != ENOENT)
24 	panic("ext2: error getting block (%llu,%u): %d", dev, block, r);
25 
26   assert(r == OK || how == PEEK);
27 
28   return (r == OK) ? bp : NULL;
29 }
30 
31 
32 
33 /*===========================================================================*
34  *				conv2					     *
35  *===========================================================================*/
36 unsigned conv2(norm, w)
37 int norm;			/* TRUE if no swap, FALSE for byte swap */
38 int w;				/* promotion of 16-bit word to be swapped */
39 {
40 /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
41   if (norm) return( (unsigned) w & 0xFFFF);
42   return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
43 }
44 
45 
46 /*===========================================================================*
47  *				conv4					     *
48  *===========================================================================*/
49 long conv4(norm, x)
50 int norm;			/* TRUE if no swap, FALSE for byte swap */
51 long x;				/* 32-bit long to be byte swapped */
52 {
53 /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
54   unsigned lo, hi;
55   long l;
56 
57   if (norm) return(x);			/* byte order was already ok */
58   lo = conv2(FALSE, (int) x & 0xFFFF);	/* low-order half, byte swapped */
59   hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);	/* high-order half, swapped */
60   l = ( (long) lo <<16) | hi;
61   return(l);
62 }
63 
64 
65 /*===========================================================================*
66  *				ansi_strcmp				     *
67  *===========================================================================*/
68 int ansi_strcmp(register const char* ansi_s, register const char *s2,
69 			register size_t ansi_s_length)
70 {
71 /* Compare non null-terminated string ansi_s (length=ansi_s_length)
72  * with C-string s2.
73  * It returns 0 if strings are equal, otherwise -1 is returned.
74  */
75 	if (ansi_s_length) {
76 		do {
77 			if (*s2 == '\0')
78 				return -1;
79 			if (*ansi_s++ != *s2++)
80 				return -1;
81 		} while (--ansi_s_length > 0);
82 
83 		if (*s2 == '\0')
84 			return 0;
85 		else
86 			return -1;
87 	}
88 	return 0;
89 }
90 
91 
92 /*===========================================================================*
93  *				setbit   				     *
94  *===========================================================================*/
95 bit_t setbit(bitchunk_t *bitmap, bit_t max_bits, unsigned int word)
96 {
97   /* Find free bit in bitmap and set. Return number of the bit,
98    * if failed return -1.
99    */
100   bitchunk_t *wptr, *wlim;
101   bit_t b = -1;
102 
103   /* TODO: do we need to add 1? I saw a situation, when it was
104    * required, and since we check bit number with max_bits it
105    * should be safe.
106    */
107   wlim = &bitmap[FS_BITMAP_CHUNKS(max_bits >> 3)];
108 
109   /* Iterate over the words in block. */
110   for (wptr = &bitmap[word]; wptr < wlim; wptr++) {
111 	bit_t i;
112 	bitchunk_t k;
113 
114 	/* Does this word contain a free bit? */
115 	if (*wptr == (bitchunk_t) ~0)
116 		continue;
117 
118 	/* Find and allocate the free bit. */
119 	k = (int) *wptr;
120 	for (i = 0; (k & (1 << i)) != 0; ++i) {}
121 
122 	/* Bit number from the start of the bit map. */
123 	b = (wptr - &bitmap[0]) * FS_BITCHUNK_BITS + i;
124 
125 	/* Don't allocate bits beyond the end of the map. */
126 	if (b >= max_bits) {
127 		b = -1;
128 		continue;
129 	}
130 
131 	/* Allocate bit number. */
132 	k |= 1 << i;
133 	*wptr = (int) k;
134 	break;
135   }
136 
137   return b;
138 }
139 
140 
141 /*===========================================================================*
142  *				setbyte   				     *
143  *===========================================================================*/
144 bit_t setbyte(bitchunk_t *bitmap, bit_t max_bits)
145 {
146   /* Find free byte in bitmap and set it. Return number of the starting bit,
147    * if failed return -1.
148    */
149   unsigned char *wptr, *wlim;
150   bit_t b = -1;
151 
152   wptr = (unsigned char*) &bitmap[0];
153   /* TODO: do we need to add 1? I saw a situation, when it was
154    * required, and since we check bit number with max_bits it
155    * should be safe.
156    */
157   wlim = &wptr[(max_bits >> 3)];
158 
159   /* Iterate over the words in block. */
160   for ( ; wptr < wlim; wptr++) {
161 	/* Is it a free byte? */
162 	if (*wptr | 0)
163 		continue;
164 
165 	/* Bit number from the start of the bit map. */
166 	b = (wptr - (unsigned char*) &bitmap[0]) * CHAR_BIT;
167 
168 	/* Don't allocate bits beyond the end of the map. */
169 	if (b + CHAR_BIT >= max_bits) {
170 		b = -1;
171 		continue;
172 	}
173 
174 	/* Allocate byte number. */
175 	*wptr = (unsigned char) ~0;
176 	break;
177   }
178   return b;
179 }
180 
181 
182 /*===========================================================================*
183  *				unsetbit   				     *
184  *===========================================================================*/
185 int unsetbit(bitchunk_t *bitmap, bit_t bit)
186 {
187   /* Unset specified bit. If requested bit is already free return -1,
188    * otherwise return 0.
189    */
190   unsigned int word;		/* bit_returned word in bitmap */
191   bitchunk_t k, mask;
192 
193   word = bit / FS_BITCHUNK_BITS;
194   bit = bit % FS_BITCHUNK_BITS; /* index in word */
195   mask = 1 << bit;
196 
197   k = (int) bitmap[word];
198   if (!(k & mask))
199 	return -1;
200 
201   k &= ~mask;
202   bitmap[word] = (int) k;
203   return 0;
204 }
205