source: grub-pc/trunk/fuentes/grub-core/osdep/aros/hostdisk.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 12.2 KB
Line 
1/*
2 *  GRUB  --  GRand Unified Bootloader
3 *  Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010,2011,2012,2013  Free Software Foundation, Inc.
4 *
5 *  GRUB is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  GRUB is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <config-util.h>
20
21#include <grub/disk.h>
22#include <grub/partition.h>
23#include <grub/msdos_partition.h>
24#include <grub/types.h>
25#include <grub/err.h>
26#include <grub/emu/misc.h>
27#include <grub/emu/hostdisk.h>
28#include <grub/emu/getroot.h>
29#include <grub/misc.h>
30#include <grub/i18n.h>
31#include <grub/list.h>
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <ctype.h>
37#include <assert.h>
38#include <unistd.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include <errno.h>
43#include <limits.h>
44#include <time.h>
45
46#include <string.h>
47#include <dos/dos.h>
48#include <dos/filesystem.h>
49#include <dos/exall.h>
50#include <proto/dos.h>
51#include <devices/hardblocks.h>
52#include <devices/newstyle.h>
53#include <proto/exec.h>
54#include <proto/utility.h>
55#include <proto/partition.h>
56#include <devices/trackdisk.h>
57#include <exec/errors.h>
58
59#define BOUNCE_SIZE 1048576
60
61static ULONG *bounce;
62
63char *
64canonicalize_file_name (const char *path)
65{
66  char *ret;
67  BPTR lck;
68
69  if (path[0] == '/' && path[1] == '/' && path[2] == ':')
70    return xstrdup (path);
71
72  ret = xmalloc (2048);
73  lck = Lock ((const unsigned char *) path, SHARED_LOCK);
74
75  if (!lck || !NameFromLock (lck, (unsigned char *) ret, 2040))
76    {
77      free (ret);
78      ret = xstrdup (path);
79    }
80  if (lck)
81    UnLock (lck);
82
83  return ret;
84}
85
86static grub_uint64_t
87grub_util_get_fd_size_volume (grub_util_fd_t fd __attribute__ ((unused)),
88                              const char *dev,
89                              unsigned *log_secsize)
90{
91  struct DriveGeometry *geo;
92  LONG err;
93  unsigned sector_size, log_sector_size;
94
95  if (!bounce)
96    bounce = AllocVec (BOUNCE_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
97  if (!bounce)
98    grub_util_error ("out of memory");
99
100  fd->ioreq->iotd_Req.io_Command = TD_GETGEOMETRY;
101  fd->ioreq->iotd_Req.io_Length = sizeof (*geo);
102  fd->ioreq->iotd_Req.io_Data = bounce;
103  fd->ioreq->iotd_Req.io_Offset = 0;
104  fd->ioreq->iotd_Req.io_Actual = 0;
105  err = DoIO ((struct IORequest *) fd->ioreq);
106  if (err)
107    {
108      grub_util_info ("I/O failed with error %d, IoErr=%d", (int)err, (int) IoErr ());
109      return -1;
110    }
111
112  geo = (struct DriveGeometry *) bounce;
113
114  sector_size = geo->dg_SectorSize;
115
116  if (sector_size & (sector_size - 1) || !sector_size)
117    return -1;
118
119  for (log_sector_size = 0;
120       (1 << log_sector_size) < sector_size;
121       log_sector_size++);
122
123  if (log_secsize)
124    *log_secsize = log_sector_size;
125
126  return (grub_uint64_t) geo->dg_TotalSectors * (grub_uint64_t) geo->dg_SectorSize;
127}
128
129static grub_uint64_t
130grub_util_get_fd_size_file (grub_util_fd_t fd,
131                            const char *dev __attribute__ ((unused)),
132                            unsigned *log_secsize)
133{
134  off_t oo, ro;
135  *log_secsize = 9;
136  /* FIXME: support 64-bit offsets.  */
137  oo = lseek (fd->fd, 0, SEEK_CUR);
138  ro = lseek (fd->fd, 0, SEEK_END);
139  lseek (fd->fd, oo, SEEK_SET);
140  return ro;
141}
142
143int
144grub_util_fd_seek (grub_util_fd_t fd, grub_uint64_t off)
145{
146  switch (fd->type)
147    {
148    case GRUB_UTIL_FD_FILE:
149      if (lseek (fd->fd, 0, SEEK_SET) == (off_t) -1)
150        return -1;
151      fd->off = off;
152      return 0;
153    case GRUB_UTIL_FD_DISK:
154      fd->off = off;
155      return 0;
156    }
157
158  return -1;
159}
160
161grub_util_fd_t
162grub_util_fd_open (const char *dev, int flg)
163{
164  grub_util_fd_t ret = xmalloc (sizeof (*ret));
165  const char *p1, *p2;
166  const char *dname;
167  char *tmp;
168  IPTR unit = 0;
169  ULONG flags = 0;
170
171#ifdef O_LARGEFILE
172  flg |= O_LARGEFILE;
173#endif
174#ifdef O_BINARY
175  flg |= O_BINARY;
176#endif
177
178  ret->off = 0;
179
180  if (dev[0] != '/' || dev[1] != '/' || dev[2] != ':')
181    {
182      ret->type = GRUB_UTIL_FD_FILE;
183      ret->fd = open (dev, flg, S_IROTH | S_IRGRP | S_IRUSR | S_IWUSR);
184      if (ret->fd < 0)
185        {
186          free (ret);
187          return NULL;
188        }
189      return ret;
190    }
191
192  p1 = strchr (dev + 3, '/');
193  if (!p1)
194    p1 = dev + strlen (dev);
195  else
196    {
197      unit = grub_strtoul (p1 + 1, (char **) &p2, 16);
198      if (p2 && *p2 == '/')
199        flags = grub_strtoul (p2 + 1, 0, 16);
200    }
201
202  ret->mp = CreateMsgPort();
203  if (!ret->mp)
204    {
205      free (ret);
206      return NULL;
207    }
208  ret->ioreq = (struct IOExtTD *) CreateIORequest(ret->mp,
209                                                 sizeof(struct IOExtTD));
210  if (!ret->ioreq)
211    {
212      free (ret);
213      DeleteMsgPort (ret->mp);
214      return NULL;
215    }
216
217  dname = dev + 3;
218  ret->type = GRUB_UTIL_FD_DISK;
219
220  tmp = xmalloc (p1 - dname + 1);
221  memcpy (tmp, dname, p1 - dname);
222  tmp[p1 - dname] = '\0';
223
224  ret->is_floppy = (strcmp (tmp, TD_NAME) == 0);
225  ret->is_64 = 1;
226
227  if (OpenDevice ((unsigned char *) tmp, unit,
228                  (struct IORequest *) ret->ioreq, flags))
229    {
230      free (tmp);
231      free (ret);
232      DeleteMsgPort (ret->mp);
233      return NULL;
234    }
235  free (tmp);
236  return ret;
237}
238
239static ssize_t
240grub_util_fd_read_file (grub_util_fd_t fd, char *buf, size_t len)
241{
242  ssize_t size = len;
243
244  while (len)
245    {
246      ssize_t ret = read (fd->fd, buf, len);
247
248      if (ret <= 0)
249        {
250          if (errno == EINTR)
251            continue;
252          else
253            return ret;
254        }
255
256      fd->off += ret;
257      len -= ret;
258      buf += ret;
259    }
260
261  return size;
262}
263
264/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
265   error occurs, otherwise return LEN.  */
266static ssize_t
267grub_util_fd_write_file (grub_util_fd_t fd, const char *buf, size_t len)
268{
269  ssize_t size = len;
270
271  while (len)
272    {
273      ssize_t ret = write (fd->fd, buf, len);
274
275      if (ret <= 0)
276        {
277          if (errno == EINTR)
278            continue;
279          else
280            return ret;
281        }
282
283      fd->off += ret;
284      len -= ret;
285      buf += ret;
286    }
287
288  return size;
289}
290
291static void
292stop_motor (grub_util_fd_t fd)
293{
294  if (!fd->is_floppy)
295    return;
296  fd->ioreq->iotd_Req.io_Command = TD_MOTOR;
297  fd->ioreq->iotd_Req.io_Length = 0;
298  fd->ioreq->iotd_Req.io_Data = 0;
299  fd->ioreq->iotd_Req.io_Offset = 0;
300  fd->ioreq->iotd_Req.io_Actual = 0;
301  DoIO ((struct IORequest *) fd->ioreq);
302}
303
304static ssize_t
305grub_util_fd_read_volume (grub_util_fd_t fd, char *buf, size_t len)
306{
307  grub_uint64_t adj = 0;
308
309  if (!bounce)
310    bounce = AllocVec (BOUNCE_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
311  if (!bounce)
312    grub_util_error ("out of memory");
313
314  while (len)
315    {
316      size_t cr = len;
317      LONG err;
318      if (cr > BOUNCE_SIZE)
319        cr = BOUNCE_SIZE;
320    retry:
321      if (fd->is_64)
322        fd->ioreq->iotd_Req.io_Command = NSCMD_TD_READ64;
323      else
324        fd->ioreq->iotd_Req.io_Command = CMD_READ;
325      fd->ioreq->iotd_Req.io_Length = cr;
326      fd->ioreq->iotd_Req.io_Data = bounce;
327      fd->ioreq->iotd_Req.io_Offset = fd->off & 0xFFFFFFFF;
328      fd->ioreq->iotd_Req.io_Actual = fd->off >> 32;
329      err = DoIO ((struct IORequest *) fd->ioreq);
330      if (err == IOERR_NOCMD && fd->is_64)
331        {
332          fd->is_64 = 0;
333          goto retry;
334        }
335      if (err)
336        {
337          grub_util_info ("I/O failed with error %d, IoErr=%d", (int)err, (int) IoErr ());
338          stop_motor (fd);
339          return -1;
340        }
341      memcpy (buf, bounce, cr);
342      adj += cr;
343      len -= cr;
344      buf += cr;
345    }
346
347  fd->off += adj;
348  stop_motor (fd);
349  return adj;
350}
351
352static ssize_t
353grub_util_fd_write_volume (grub_util_fd_t fd, const char *buf, size_t len)
354{
355  grub_uint64_t adj = 0;
356  if (!bounce)
357    bounce = AllocVec (BOUNCE_SIZE, MEMF_PUBLIC | MEMF_CLEAR);
358  if (!bounce)
359    grub_util_error ("out of memory");
360
361  while (len)
362    {
363      size_t cr = len;
364      LONG err;
365      if (cr > BOUNCE_SIZE)
366        cr = BOUNCE_SIZE;
367    retry:
368      if (fd->is_64)
369        fd->ioreq->iotd_Req.io_Command = NSCMD_TD_WRITE64;
370      else
371        fd->ioreq->iotd_Req.io_Command = CMD_WRITE;
372      fd->ioreq->iotd_Req.io_Length = cr;
373      fd->ioreq->iotd_Req.io_Data = bounce;
374      fd->ioreq->iotd_Req.io_Offset = fd->off & 0xFFFFFFFF;
375      fd->ioreq->iotd_Req.io_Actual = fd->off >> 32;
376      memcpy (bounce, buf, cr);
377      err = DoIO ((struct IORequest *) fd->ioreq);
378      if (err == IOERR_NOCMD && fd->is_64)
379        {
380          fd->is_64 = 0;
381          goto retry;
382        }
383      if (err)
384        {
385          grub_util_info ("I/O failed with error %d", err);
386          stop_motor (fd);
387          return -1;
388        }
389
390      adj += cr;
391      len -= cr;
392      buf += cr;
393    }
394
395  fd->off += adj;
396  stop_motor (fd);
397  return adj;
398}
399
400ssize_t
401grub_util_fd_read (grub_util_fd_t fd, char *buf, size_t len)
402{
403  switch (fd->type)
404    {
405    case GRUB_UTIL_FD_FILE:
406      return grub_util_fd_read_file (fd, buf, len);
407    case GRUB_UTIL_FD_DISK:
408      return grub_util_fd_read_volume (fd, buf, len);
409    }
410  return -1;
411}
412
413ssize_t
414grub_util_fd_write (grub_util_fd_t fd, const char *buf, size_t len)
415{
416  switch (fd->type)
417    {
418    case GRUB_UTIL_FD_FILE:
419      return grub_util_fd_write_file (fd, buf, len);
420    case GRUB_UTIL_FD_DISK:
421      return grub_util_fd_write_volume (fd, buf, len);
422    }
423  return -1;
424}
425
426grub_uint64_t
427grub_util_get_fd_size (grub_util_fd_t fd,
428                       const char *dev,
429                       unsigned *log_secsize)
430{
431  switch (fd->type)
432    {
433    case GRUB_UTIL_FD_FILE:
434      return grub_util_get_fd_size_file (fd, dev, log_secsize);
435
436    case GRUB_UTIL_FD_DISK:
437      return grub_util_get_fd_size_volume (fd, dev, log_secsize);
438    }
439  return -1;
440}
441
442void
443grub_util_fd_close (grub_util_fd_t fd)
444{
445  switch (fd->type)
446    {
447    case GRUB_UTIL_FD_FILE:
448      close (fd->fd);
449      return;
450    case GRUB_UTIL_FD_DISK:
451      CloseDevice ((struct IORequest *) fd->ioreq);
452      DeleteIORequest((struct IORequest *) fd->ioreq);
453      DeleteMsgPort (fd->mp);
454      return;
455    }
456}
457
458static int allow_fd_syncs = 1;
459
460static void
461grub_util_fd_sync_volume (grub_util_fd_t fd)
462{
463  fd->ioreq->iotd_Req.io_Command = CMD_UPDATE;
464  fd->ioreq->iotd_Req.io_Length = 0;
465  fd->ioreq->iotd_Req.io_Data = 0;
466  fd->ioreq->iotd_Req.io_Offset = 0;
467  fd->ioreq->iotd_Req.io_Actual = 0;
468  DoIO ((struct IORequest *) fd->ioreq);
469}
470
471void
472grub_util_fd_sync (grub_util_fd_t fd)
473{
474  if (allow_fd_syncs)
475    {
476      switch (fd->type)
477        {
478        case GRUB_UTIL_FD_FILE:
479          fsync (fd->fd);
480          return;
481        case GRUB_UTIL_FD_DISK:
482          grub_util_fd_sync_volume (fd);
483          return;
484        }
485    }
486}
487
488void
489grub_util_file_sync (FILE *f)
490{
491  fflush (f);
492  if (!allow_fd_syncs)
493    return;
494  fsync (fileno (f));
495}
496
497void
498grub_util_disable_fd_syncs (void)
499{
500  allow_fd_syncs = 0;
501}
502
503void
504grub_hostdisk_flush_initial_buffer (const char *os_dev __attribute__ ((unused)))
505{
506}
507
508
509const char *
510grub_util_fd_strerror (void)
511{
512  static char buf[201];
513  LONG err = IoErr ();
514  if (!err)
515    return _("Success");
516  memset (buf, '\0', sizeof (buf));
517  Fault (err, (const unsigned char *) "", (STRPTR) buf, sizeof (buf));
518  if (buf[0] == ':')
519    return buf + 1;
520  return buf;
521}
522
523FILE *
524grub_util_fopen (const char *path, const char *mode)
525{
526  return fopen (path, mode);
527}
528
529int
530grub_util_is_directory (const char *path)
531{
532  struct stat st;
533
534  if (stat (path, &st) == -1)
535    return 0;
536
537  return S_ISDIR (st.st_mode);
538}
539
540int
541grub_util_is_regular (const char *path)
542{
543  struct stat st;
544
545  if (stat (path, &st) == -1)
546    return 0;
547
548  return S_ISREG (st.st_mode);
549}
550
551int
552grub_util_is_special_file (const char *path)
553{
554  struct stat st;
555
556  if (lstat (path, &st) == -1)
557    return 1;
558  return (!S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode));
559}
560
561static char *
562get_temp_name (void)
563{
564  static int ctr = 0;
565  char *t;
566  struct stat st;
567 
568  while (1)
569    {
570      t = xasprintf ("T:grub.%d.%d.%d.%d", (int) getpid (), (int) getppid (),
571                     ctr++, time (0));
572      if (stat (t, &st) == -1)
573        return t;
574      free (t);
575    }
576}
577
578char *
579grub_util_make_temporary_file (void)
580{
581  char *ret = get_temp_name ();
582  FILE *f;
583
584  f = grub_util_fopen (ret, "wb");
585  if (f)
586    fclose (f);
587  return ret;
588}
589
590char *
591grub_util_make_temporary_dir (void)
592{
593  char *ret = get_temp_name ();
594
595  grub_util_mkdir (ret);
596
597  return ret;
598}
599
600grub_uint32_t
601grub_util_get_mtime (const char *path)
602{
603  struct stat st;
604
605  if (stat (path, &st) == -1)
606    return 0;
607
608  return st.st_mtime;
609}
Note: See TracBrowser for help on using the repository browser.