]> git.proxmox.com Git - grub2.git/blame - kern/file.c
2007-07-22 Yoshinori K. Okuji <okuji@enbug.org>
[grub2.git] / kern / file.c
CommitLineData
6a161fa9 1/* file.c - file I/O functions */
2/*
4b13b216 3 * GRUB -- GRand Unified Bootloader
5a79f472 4 * Copyright (C) 2002,2006,2007 Free Software Foundation, Inc.
6a161fa9 5 *
5a79f472 6 * GRUB is free software: you can redistribute it and/or modify
6a161fa9 7 * it under the terms of the GNU General Public License as published by
5a79f472 8 * the Free Software Foundation, either version 3 of the License, or
6a161fa9 9 * (at your option) any later version.
10 *
5a79f472 11 * GRUB is distributed in the hope that it will be useful,
6a161fa9 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.
15 *
16 * You should have received a copy of the GNU General Public License
5a79f472 17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
6a161fa9 18 */
19
4b13b216 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>
6a161fa9 26
27/* Get the device part of the filename NAME. It is enclosed by parentheses. */
28char *
4b13b216 29grub_file_get_device_name (const char *name)
6a161fa9 30{
31 if (name[0] == '(')
32 {
4b13b216 33 char *p = grub_strchr (name, ')');
6a161fa9 34 char *ret;
35
36 if (! p)
37 {
4b13b216 38 grub_error (GRUB_ERR_BAD_FILENAME, "missing `)'");
6a161fa9 39 return 0;
40 }
41
4b13b216 42 ret = (char *) grub_malloc (p - name);
6a161fa9 43 if (! ret)
44 return 0;
45
4b13b216 46 grub_memcpy (ret, name + 1, p - name - 1);
6a161fa9 47 ret[p - name - 1] = '\0';
48 return ret;
49 }
50
51 return 0;
52}
53
4b13b216 54grub_file_t
55grub_file_open (const char *name)
6a161fa9 56{
4b13b216 57 grub_device_t device;
58 grub_file_t file = 0;
6a161fa9 59 char *device_name;
60 char *file_name;
61
4b13b216 62 device_name = grub_file_get_device_name (name);
63 if (grub_errno)
6a161fa9 64 return 0;
65
66 /* Get the file part of NAME. */
4b13b216 67 file_name = grub_strchr (name, ')');
6a161fa9 68 if (file_name)
69 file_name++;
70 else
71 file_name = (char *) name;
72
4b13b216 73 device = grub_device_open (device_name);
74 grub_free (device_name);
6a161fa9 75 if (! device)
76 goto fail;
77
4b13b216 78 file = (grub_file_t) grub_malloc (sizeof (*file));
6a161fa9 79 if (! file)
80 goto fail;
81
82 file->device = device;
83 file->offset = 0;
84 file->data = 0;
85 file->read_hook = 0;
86
87 if (device->disk && file_name[0] != '/')
88 /* This is a block list. */
4b13b216 89 file->fs = &grub_fs_blocklist;
6a161fa9 90 else
91 {
4b13b216 92 file->fs = grub_fs_probe (device);
6a161fa9 93 if (! file->fs)
94 goto fail;
95 }
96
4b13b216 97 if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE)
6a161fa9 98 goto fail;
99
100 return file;
101
102 fail:
103 if (device)
4b13b216 104 grub_device_close (device);
6a161fa9 105
4b13b216 106 /* if (net) grub_net_close (net); */
6a161fa9 107
4b13b216 108 grub_free (file);
6a161fa9 109
110 return 0;
111}
112
4b13b216 113grub_ssize_t
524a1e6a 114grub_file_read (grub_file_t file, char *buf, grub_size_t len)
6a161fa9 115{
4b13b216 116 grub_ssize_t res;
6a161fa9 117
118 if (len == 0 || len > file->size - file->offset)
119 len = file->size - file->offset;
120
524a1e6a 121 /* Prevent an overflow. */
122 if ((grub_ssize_t) len < 0)
123 len >>= 1;
124
6a161fa9 125 if (len == 0)
126 return 0;
127
128 res = (file->fs->read) (file, buf, len);
129 if (res > 0)
130 file->offset += res;
131
132 return res;
133}
134
4b13b216 135grub_err_t
136grub_file_close (grub_file_t file)
6a161fa9 137{
138 if (file->fs->close)
139 (file->fs->close) (file);
140
d9864ee1 141 if (file->device)
142 grub_device_close (file->device);
4b13b216 143 grub_free (file);
144 return grub_errno;
6a161fa9 145}
146
524a1e6a 147grub_off_t
148grub_file_seek (grub_file_t file, grub_off_t offset)
6a161fa9 149{
524a1e6a 150 grub_off_t old;
6a161fa9 151
524a1e6a 152 if (offset > file->size)
6a161fa9 153 {
4b13b216 154 grub_error (GRUB_ERR_OUT_OF_RANGE,
6a161fa9 155 "attempt to seek outside of the file");
156 return -1;
157 }
158
159 old = file->offset;
160 file->offset = offset;
161 return old;
162}