Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/util-linux/volume_id/util.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 983 by niro, Fri Apr 24 18:33:46 2009 UTC revision 984 by niro, Sun May 30 11:32:42 2010 UTC
# Line 195  set: Line 195  set:
195   * It's better to ignore such fs and continue.  */   * It's better to ignore such fs and continue.  */
196  void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)  void *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
197  {  {
198   ssize_t buf_len;   uint8_t *dst;
199     unsigned small_off;
200     ssize_t read_len;
201    
202     dbg("get buffer off 0x%llx(%llu), len 0x%zx",
203     (unsigned long long) off, (unsigned long long) off, len);
204    
  dbg("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len);  
205   /* check if requested area fits in superblock buffer */   /* check if requested area fits in superblock buffer */
206   if (off + len <= SB_BUFFER_SIZE) {   if (off + len <= SB_BUFFER_SIZE
207     /* && off <= SB_BUFFER_SIZE - want this paranoid overflow check? */
208     ) {
209   if (id->sbbuf == NULL) {   if (id->sbbuf == NULL) {
210   id->sbbuf = xmalloc(SB_BUFFER_SIZE);   id->sbbuf = xmalloc(SB_BUFFER_SIZE);
211   }   }
212     small_off = off;
213     dst = id->sbbuf;
214    
215   /* check if we need to read */   /* check if we need to read */
216   if ((off + len) > id->sbbuf_len) {   len += off;
217   dbg("read sbbuf len:0x%llx", (unsigned long long) (off + len));   if (len <= id->sbbuf_len)
218   if (lseek(id->fd, 0, SEEK_SET) != 0) {   goto ret; /* we already have it */
219   dbg("seek(0) failed");  
220   return NULL;   dbg("read sbbuf len:0x%x", (unsigned) len);
221   }   id->sbbuf_len = len;
222   buf_len = full_read(id->fd, id->sbbuf, off + len);   off = 0;
223   if (buf_len < 0) {   goto do_read;
  dbg("read failed (%s)", strerror(errno));  
  return NULL;  
  }  
  dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);  
  id->sbbuf_len = buf_len;  
  if ((uint64_t)buf_len < off + len) {  
  dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);  
  return NULL;  
  }  
  }  
   
  return &(id->sbbuf[off]);  
224   }   }
225    
226   if (len > SEEK_BUFFER_SIZE) {   if (len > SEEK_BUFFER_SIZE) {
227   dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);   dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
228   return NULL;   return NULL;
229   }   }
230     dst = id->seekbuf;
  /* get seek buffer */  
  if (id->seekbuf == NULL) {  
  id->seekbuf = xmalloc(SEEK_BUFFER_SIZE);  
  }  
231    
232   /* check if we need to read */   /* check if we need to read */
233   if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {   if ((off >= id->seekbuf_off)
234   dbg("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len);   && ((off + len) <= (id->seekbuf_off + id->seekbuf_len))
235   if (lseek(id->fd, off, SEEK_SET) != off) {   ) {
236   dbg("seek(0x%llx) failed", (unsigned long long) off);   small_off = off - id->seekbuf_off; /* can't overflow */
237   return NULL;   goto ret; /* we already have it */
  }  
  buf_len = full_read(id->fd, id->seekbuf, len);  
  if (buf_len < 0) {  
  dbg("read failed (%s)", strerror(errno));  
  return NULL;  
  }  
  dbg("got 0x%zx (%zi) bytes", buf_len, buf_len);  
  id->seekbuf_off = off;  
  id->seekbuf_len = buf_len;  
  if ((size_t)buf_len < len) {  
  dbg("requested 0x%zx bytes, got only 0x%zx bytes", len, buf_len);  
  return NULL;  
  }  
238   }   }
239    
240   return &(id->seekbuf[off - id->seekbuf_off]);   id->seekbuf_off = off;
241     id->seekbuf_len = len;
242     id->seekbuf = xrealloc(id->seekbuf, len);
243     small_off = 0;
244     dst = id->seekbuf;
245     dbg("read seekbuf off:0x%llx len:0x%zx",
246     (unsigned long long) off, len);
247     do_read:
248     if (lseek(id->fd, off, SEEK_SET) != off) {
249     dbg("seek(0x%llx) failed", (unsigned long long) off);
250     goto err;
251     }
252     read_len = full_read(id->fd, dst, len);
253     if (read_len != len) {
254     dbg("requested 0x%x bytes, got 0x%x bytes",
255     (unsigned) len, (unsigned) read_len);
256     err:
257     /* No filesystem can be this tiny. It's most likely
258     * non-associated loop device, empty drive and so on.
259     * Flag it, making it possible to short circuit future
260     * accesses. Rationale:
261     * users complained of slow blkid due to empty floppy drives.
262     */
263     if (off < 64*1024)
264     id->error = 1;
265     /* id->seekbuf_len or id->sbbuf_len is wrong now! Fixing. */
266     volume_id_free_buffer(id);
267     return NULL;
268     }
269     ret:
270     return dst + small_off;
271  }  }
272    
273  void volume_id_free_buffer(struct volume_id *id)  void volume_id_free_buffer(struct volume_id *id)
# Line 269  void volume_id_free_buffer(struct volume Line 278  void volume_id_free_buffer(struct volume
278   free(id->seekbuf);   free(id->seekbuf);
279   id->seekbuf = NULL;   id->seekbuf = NULL;
280   id->seekbuf_len = 0;   id->seekbuf_len = 0;
281     id->seekbuf_off = 0; /* paranoia */
282  }  }

Legend:
Removed from v.983  
changed lines
  Added in v.984