xref: /minix3/minix/fs/ext2/utility.c (revision 6c46a77d9509a6aefda1522eee2103e194ced4b3)
1433d6423SLionel Sambuc /* Created (MFS based):
2433d6423SLionel Sambuc  *   February 2010 (Evgeniy Ivanov)
3433d6423SLionel Sambuc  */
4433d6423SLionel Sambuc 
5433d6423SLionel Sambuc #include "fs.h"
6433d6423SLionel Sambuc #include "buf.h"
7433d6423SLionel Sambuc #include "inode.h"
8433d6423SLionel Sambuc #include "super.h"
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc 
11433d6423SLionel Sambuc /*===========================================================================*
12*6c46a77dSDavid van Moolenbroek  *				get_block				     *
13*6c46a77dSDavid van Moolenbroek  *===========================================================================*/
get_block(dev_t dev,block_t block,int how)14*6c46a77dSDavid van Moolenbroek struct buf *get_block(dev_t dev, block_t block, int how)
15*6c46a77dSDavid van Moolenbroek {
16*6c46a77dSDavid van Moolenbroek /* Wrapper routine for lmfs_get_block(). This ext2 implementation does not deal
17*6c46a77dSDavid van Moolenbroek  * well with block read errors pretty much anywhere. To prevent corruption due
18*6c46a77dSDavid van Moolenbroek  * to unchecked error conditions, we panic upon an I/O failure here.
19*6c46a77dSDavid van Moolenbroek  */
20*6c46a77dSDavid van Moolenbroek   struct buf *bp;
21*6c46a77dSDavid van Moolenbroek   int r;
22*6c46a77dSDavid van Moolenbroek 
23*6c46a77dSDavid van Moolenbroek   if ((r = lmfs_get_block(&bp, dev, block, how)) != OK && r != ENOENT)
24*6c46a77dSDavid van Moolenbroek 	panic("ext2: error getting block (%llu,%u): %d", dev, block, r);
25*6c46a77dSDavid van Moolenbroek 
26*6c46a77dSDavid van Moolenbroek   assert(r == OK || how == PEEK);
27*6c46a77dSDavid van Moolenbroek 
28*6c46a77dSDavid van Moolenbroek   return (r == OK) ? bp : NULL;
29*6c46a77dSDavid van Moolenbroek }
30*6c46a77dSDavid van Moolenbroek 
31*6c46a77dSDavid van Moolenbroek 
32*6c46a77dSDavid van Moolenbroek 
33*6c46a77dSDavid van Moolenbroek /*===========================================================================*
34433d6423SLionel Sambuc  *				conv2					     *
35433d6423SLionel Sambuc  *===========================================================================*/
conv2(norm,w)36433d6423SLionel Sambuc unsigned conv2(norm, w)
37433d6423SLionel Sambuc int norm;			/* TRUE if no swap, FALSE for byte swap */
38433d6423SLionel Sambuc int w;				/* promotion of 16-bit word to be swapped */
39433d6423SLionel Sambuc {
40433d6423SLionel Sambuc /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
41433d6423SLionel Sambuc   if (norm) return( (unsigned) w & 0xFFFF);
42433d6423SLionel Sambuc   return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
43433d6423SLionel Sambuc }
44433d6423SLionel Sambuc 
45433d6423SLionel Sambuc 
46433d6423SLionel Sambuc /*===========================================================================*
47433d6423SLionel Sambuc  *				conv4					     *
48433d6423SLionel Sambuc  *===========================================================================*/
conv4(norm,x)49433d6423SLionel Sambuc long conv4(norm, x)
50433d6423SLionel Sambuc int norm;			/* TRUE if no swap, FALSE for byte swap */
51433d6423SLionel Sambuc long x;				/* 32-bit long to be byte swapped */
52433d6423SLionel Sambuc {
53433d6423SLionel Sambuc /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
54433d6423SLionel Sambuc   unsigned lo, hi;
55433d6423SLionel Sambuc   long l;
56433d6423SLionel Sambuc 
57433d6423SLionel Sambuc   if (norm) return(x);			/* byte order was already ok */
58433d6423SLionel Sambuc   lo = conv2(FALSE, (int) x & 0xFFFF);	/* low-order half, byte swapped */
59433d6423SLionel Sambuc   hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);	/* high-order half, swapped */
60433d6423SLionel Sambuc   l = ( (long) lo <<16) | hi;
61433d6423SLionel Sambuc   return(l);
62433d6423SLionel Sambuc }
63433d6423SLionel Sambuc 
64433d6423SLionel Sambuc 
65433d6423SLionel Sambuc /*===========================================================================*
66433d6423SLionel Sambuc  *				ansi_strcmp				     *
67433d6423SLionel Sambuc  *===========================================================================*/
ansi_strcmp(register const char * ansi_s,register const char * s2,register size_t ansi_s_length)68433d6423SLionel Sambuc int ansi_strcmp(register const char* ansi_s, register const char *s2,
69433d6423SLionel Sambuc 			register size_t ansi_s_length)
70433d6423SLionel Sambuc {
71433d6423SLionel Sambuc /* Compare non null-terminated string ansi_s (length=ansi_s_length)
72433d6423SLionel Sambuc  * with C-string s2.
73433d6423SLionel Sambuc  * It returns 0 if strings are equal, otherwise -1 is returned.
74433d6423SLionel Sambuc  */
75433d6423SLionel Sambuc 	if (ansi_s_length) {
76433d6423SLionel Sambuc 		do {
77433d6423SLionel Sambuc 			if (*s2 == '\0')
78433d6423SLionel Sambuc 				return -1;
79433d6423SLionel Sambuc 			if (*ansi_s++ != *s2++)
80433d6423SLionel Sambuc 				return -1;
81433d6423SLionel Sambuc 		} while (--ansi_s_length > 0);
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc 		if (*s2 == '\0')
84433d6423SLionel Sambuc 			return 0;
85433d6423SLionel Sambuc 		else
86433d6423SLionel Sambuc 			return -1;
87433d6423SLionel Sambuc 	}
88433d6423SLionel Sambuc 	return 0;
89433d6423SLionel Sambuc }
90433d6423SLionel Sambuc 
91433d6423SLionel Sambuc 
92433d6423SLionel Sambuc /*===========================================================================*
93433d6423SLionel Sambuc  *				setbit   				     *
94433d6423SLionel Sambuc  *===========================================================================*/
setbit(bitchunk_t * bitmap,bit_t max_bits,unsigned int word)95433d6423SLionel Sambuc bit_t setbit(bitchunk_t *bitmap, bit_t max_bits, unsigned int word)
96433d6423SLionel Sambuc {
97433d6423SLionel Sambuc   /* Find free bit in bitmap and set. Return number of the bit,
98433d6423SLionel Sambuc    * if failed return -1.
99433d6423SLionel Sambuc    */
100433d6423SLionel Sambuc   bitchunk_t *wptr, *wlim;
101433d6423SLionel Sambuc   bit_t b = -1;
102433d6423SLionel Sambuc 
103433d6423SLionel Sambuc   /* TODO: do we need to add 1? I saw a situation, when it was
104433d6423SLionel Sambuc    * required, and since we check bit number with max_bits it
105433d6423SLionel Sambuc    * should be safe.
106433d6423SLionel Sambuc    */
107433d6423SLionel Sambuc   wlim = &bitmap[FS_BITMAP_CHUNKS(max_bits >> 3)];
108433d6423SLionel Sambuc 
109433d6423SLionel Sambuc   /* Iterate over the words in block. */
110433d6423SLionel Sambuc   for (wptr = &bitmap[word]; wptr < wlim; wptr++) {
111433d6423SLionel Sambuc 	bit_t i;
112433d6423SLionel Sambuc 	bitchunk_t k;
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	/* Does this word contain a free bit? */
115433d6423SLionel Sambuc 	if (*wptr == (bitchunk_t) ~0)
116433d6423SLionel Sambuc 		continue;
117433d6423SLionel Sambuc 
118433d6423SLionel Sambuc 	/* Find and allocate the free bit. */
119433d6423SLionel Sambuc 	k = (int) *wptr;
120433d6423SLionel Sambuc 	for (i = 0; (k & (1 << i)) != 0; ++i) {}
121433d6423SLionel Sambuc 
122433d6423SLionel Sambuc 	/* Bit number from the start of the bit map. */
123433d6423SLionel Sambuc 	b = (wptr - &bitmap[0]) * FS_BITCHUNK_BITS + i;
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc 	/* Don't allocate bits beyond the end of the map. */
126433d6423SLionel Sambuc 	if (b >= max_bits) {
127433d6423SLionel Sambuc 		b = -1;
128433d6423SLionel Sambuc 		continue;
129433d6423SLionel Sambuc 	}
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc 	/* Allocate bit number. */
132433d6423SLionel Sambuc 	k |= 1 << i;
133433d6423SLionel Sambuc 	*wptr = (int) k;
134433d6423SLionel Sambuc 	break;
135433d6423SLionel Sambuc   }
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc   return b;
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc 
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc /*===========================================================================*
142433d6423SLionel Sambuc  *				setbyte   				     *
143433d6423SLionel Sambuc  *===========================================================================*/
setbyte(bitchunk_t * bitmap,bit_t max_bits)144433d6423SLionel Sambuc bit_t setbyte(bitchunk_t *bitmap, bit_t max_bits)
145433d6423SLionel Sambuc {
146433d6423SLionel Sambuc   /* Find free byte in bitmap and set it. Return number of the starting bit,
147433d6423SLionel Sambuc    * if failed return -1.
148433d6423SLionel Sambuc    */
149433d6423SLionel Sambuc   unsigned char *wptr, *wlim;
150433d6423SLionel Sambuc   bit_t b = -1;
151433d6423SLionel Sambuc 
152433d6423SLionel Sambuc   wptr = (unsigned char*) &bitmap[0];
153433d6423SLionel Sambuc   /* TODO: do we need to add 1? I saw a situation, when it was
154433d6423SLionel Sambuc    * required, and since we check bit number with max_bits it
155433d6423SLionel Sambuc    * should be safe.
156433d6423SLionel Sambuc    */
157433d6423SLionel Sambuc   wlim = &wptr[(max_bits >> 3)];
158433d6423SLionel Sambuc 
159433d6423SLionel Sambuc   /* Iterate over the words in block. */
160433d6423SLionel Sambuc   for ( ; wptr < wlim; wptr++) {
161433d6423SLionel Sambuc 	/* Is it a free byte? */
162433d6423SLionel Sambuc 	if (*wptr | 0)
163433d6423SLionel Sambuc 		continue;
164433d6423SLionel Sambuc 
165433d6423SLionel Sambuc 	/* Bit number from the start of the bit map. */
166433d6423SLionel Sambuc 	b = (wptr - (unsigned char*) &bitmap[0]) * CHAR_BIT;
167433d6423SLionel Sambuc 
168433d6423SLionel Sambuc 	/* Don't allocate bits beyond the end of the map. */
169433d6423SLionel Sambuc 	if (b + CHAR_BIT >= max_bits) {
170433d6423SLionel Sambuc 		b = -1;
171433d6423SLionel Sambuc 		continue;
172433d6423SLionel Sambuc 	}
173433d6423SLionel Sambuc 
174433d6423SLionel Sambuc 	/* Allocate byte number. */
175433d6423SLionel Sambuc 	*wptr = (unsigned char) ~0;
176433d6423SLionel Sambuc 	break;
177433d6423SLionel Sambuc   }
178433d6423SLionel Sambuc   return b;
179433d6423SLionel Sambuc }
180433d6423SLionel Sambuc 
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc /*===========================================================================*
183433d6423SLionel Sambuc  *				unsetbit   				     *
184433d6423SLionel Sambuc  *===========================================================================*/
unsetbit(bitchunk_t * bitmap,bit_t bit)185433d6423SLionel Sambuc int unsetbit(bitchunk_t *bitmap, bit_t bit)
186433d6423SLionel Sambuc {
187433d6423SLionel Sambuc   /* Unset specified bit. If requested bit is already free return -1,
188433d6423SLionel Sambuc    * otherwise return 0.
189433d6423SLionel Sambuc    */
190433d6423SLionel Sambuc   unsigned int word;		/* bit_returned word in bitmap */
191433d6423SLionel Sambuc   bitchunk_t k, mask;
192433d6423SLionel Sambuc 
193433d6423SLionel Sambuc   word = bit / FS_BITCHUNK_BITS;
194433d6423SLionel Sambuc   bit = bit % FS_BITCHUNK_BITS; /* index in word */
195433d6423SLionel Sambuc   mask = 1 << bit;
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc   k = (int) bitmap[word];
198433d6423SLionel Sambuc   if (!(k & mask))
199433d6423SLionel Sambuc 	return -1;
200433d6423SLionel Sambuc 
201433d6423SLionel Sambuc   k &= ~mask;
202433d6423SLionel Sambuc   bitmap[word] = (int) k;
203433d6423SLionel Sambuc   return 0;
204433d6423SLionel Sambuc }
205