2009-11-21 Samuel Thibault <samuel.thibault@ens-lyon.org>
[grub2.git] / kern / file.c
blobf713acbcadae02f499cd81609761cfc64e409c6c
1 /* file.c - file I/O functions */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2002,2006,2007 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/misc.h>
21 #include <grub/err.h>
22 #include <grub/file.h>
23 #include <grub/mm.h>
24 #include <grub/fs.h>
25 #include <grub/device.h>
27 /* Get the device part of the filename NAME. It is enclosed by parentheses. */
28 char *
29 grub_file_get_device_name (const char *name)
31 if (name[0] == '(')
33 char *p = grub_strchr (name, ')');
34 char *ret;
36 if (! p)
38 grub_error (GRUB_ERR_BAD_FILENAME, "missing `)'");
39 return 0;
42 ret = (char *) grub_malloc (p - name);
43 if (! ret)
44 return 0;
46 grub_memcpy (ret, name + 1, p - name - 1);
47 ret[p - name - 1] = '\0';
48 return ret;
51 return 0;
54 grub_file_t
55 grub_file_open (const char *name)
57 grub_device_t device;
58 grub_file_t file = 0;
59 char *device_name;
60 char *file_name;
62 device_name = grub_file_get_device_name (name);
63 if (grub_errno)
64 return 0;
66 /* Get the file part of NAME. */
67 file_name = grub_strchr (name, ')');
68 if (file_name)
69 file_name++;
70 else
71 file_name = (char *) name;
73 device = grub_device_open (device_name);
74 grub_free (device_name);
75 if (! device)
76 goto fail;
78 file = (grub_file_t) grub_zalloc (sizeof (*file));
79 if (! file)
80 goto fail;
82 file->device = device;
84 if (device->disk && file_name[0] != '/')
85 /* This is a block list. */
86 file->fs = &grub_fs_blocklist;
87 else
89 file->fs = grub_fs_probe (device);
90 if (! file->fs)
91 goto fail;
94 if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE)
95 goto fail;
97 return file;
99 fail:
100 if (device)
101 grub_device_close (device);
103 /* if (net) grub_net_close (net); */
105 grub_free (file);
107 return 0;
110 grub_ssize_t
111 grub_file_read (grub_file_t file, void *buf, grub_size_t len)
113 grub_ssize_t res;
115 if (file->offset > file->size)
117 grub_error (GRUB_ERR_OUT_OF_RANGE,
118 "Attempt to read past the end of file.");
119 return -1;
122 if (len == 0 || len > file->size - file->offset)
123 len = file->size - file->offset;
125 /* Prevent an overflow. */
126 if ((grub_ssize_t) len < 0)
127 len >>= 1;
129 if (len == 0)
130 return 0;
132 res = (file->fs->read) (file, buf, len);
133 if (res > 0)
134 file->offset += res;
136 return res;
139 grub_err_t
140 grub_file_close (grub_file_t file)
142 if (file->fs->close)
143 (file->fs->close) (file);
145 if (file->device)
146 grub_device_close (file->device);
147 grub_free (file);
148 return grub_errno;
151 grub_off_t
152 grub_file_seek (grub_file_t file, grub_off_t offset)
154 grub_off_t old;
156 if (offset > file->size)
158 grub_error (GRUB_ERR_OUT_OF_RANGE,
159 "attempt to seek outside of the file");
160 return -1;
163 old = file->offset;
164 file->offset = offset;
165 return old;