~ubuntu-branches/ubuntu/utopic/xfsprogs/utopic-proposed

« back to all changes in this revision

Viewing changes to libdisk/fstype.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Scott
  • Date: 2002-04-13 09:45:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020413094506-t8dhemv41gkeg4kx
Tags: 2.0.3-1
New upstream bugfix release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
 
3
 * 
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of version 2 of the GNU General Public License as
 
6
 * published by the Free Software Foundation.
 
7
 * 
 
8
 * This program is distributed in the hope that it would be useful, but
 
9
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
11
 * 
 
12
 * Further, this software is distributed without any warranty that it is
 
13
 * free of the rightful claim of any third person regarding infringement
 
14
 * or the like.  Any license provided herein, whether implied or
 
15
 * otherwise, applies only to this software file.  Patent licenses, if
 
16
 * any, provided herein do not apply to combinations of this program with
 
17
 * other software, or any other product whatsoever.
 
18
 * 
 
19
 * You should have received a copy of the GNU General Public License along
 
20
 * with this program; if not, write the Free Software Foundation, Inc., 59
 
21
 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
 
22
 * 
 
23
 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
 
24
 * Mountain View, CA  94043, or:
 
25
 * 
 
26
 * http://www.sgi.com 
 
27
 * 
 
28
 * For further information regarding this notice, see: 
 
29
 * 
 
30
 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
 
31
 */
 
32
 
 
33
#include <stdio.h>
 
34
#include <fcntl.h>
 
35
#include <unistd.h>
 
36
#include <stdlib.h>
 
37
#include <string.h>
 
38
#include <sys/stat.h>
 
39
#include "fstype.h"
 
40
 
 
41
/*
 
42
 * From mount(8) source by Andries Brouwer.  Hacked for XFS by mkp.
 
43
 * Recent sync's to mount source:
 
44
 *      - util-linux-2.10o ... 06 Sep 00
 
45
 *      - util-linux-2.10r ... 06 Dec 00
 
46
 *      - util-linux-2.11g ... 02 Jul 01
 
47
 */
 
48
 
 
49
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
 
50
 
 
51
static inline unsigned short
 
52
swapped(unsigned short a) {
 
53
     return (a>>8) | (a<<8);
 
54
}
 
55
 
 
56
static inline int
 
57
assemble4le(unsigned char *p) {
 
58
        return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
 
59
}
 
60
 
 
61
/*
 
62
    Probes the device and attempts to determine the type of filesystem
 
63
    contained within.
 
64
 
 
65
    Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
 
66
    for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
 
67
    Read the superblock only once - aeb
 
68
    Added iso9660, romfs, qnx4, udf, swap - aeb
 
69
    Added a test for high sierra (iso9660) - quinlan@bucknell.edu
 
70
    Corrected the test for xiafs - aeb
 
71
    Added ufs from a patch by jj. But maybe there are several types of ufs?
 
72
    Added ntfs from a patch by Richard Russon.
 
73
    Added a very weak heuristic for vfat - aeb
 
74
    Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
 
75
    Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
 
76
    Added ext3 - Andrew Morton
 
77
*/
 
78
 
 
79
/* udf magic - I find that trying to mount garbage as an udf fs
 
80
   causes a very large kernel delay, almost killing the machine.
 
81
   So, we do not try udf unless there is positive evidence that it
 
82
   might work. Try iso9660 first, it is much more likely.
 
83
   Strings below taken from ECMA 167. */
 
84
static char
 
85
*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
 
86
                 "NSR03", "TEA01" };
 
87
 
 
88
static int
 
89
may_be_udf(const char *id) {
 
90
    char **m;
 
91
 
 
92
    for (m = udf_magic; m - udf_magic < SIZE(udf_magic); m++)
 
93
       if (!strncmp(*m, id, 5))
 
94
          return 1;
 
95
    return 0;
 
96
}
 
97
 
 
98
static int
 
99
may_be_swap(const char *s) {
 
100
        return (strncmp(s-10, "SWAP-SPACE", 10) == 0 ||
 
101
                strncmp(s-10, "SWAPSPACE2", 10) == 0);
 
102
}
 
103
 
 
104
/* rather weak necessary condition */
 
105
static int
 
106
may_be_adfs(const u_char *s) {
 
107
        u_char *p;
 
108
        int sum;
 
109
 
 
110
        p = (u_char *) s + 511;
 
111
        sum = 0;
 
112
        while(--p != s)
 
113
                sum = (sum >> 8) + (sum & 0xff) + *p;
 
114
 
 
115
        return (sum == p[511]);
 
116
}
 
117
 
 
118
static int is_reiserfs_magic_string (struct reiserfs_super_block * rs)
 
119
{
 
120
    return (!strncmp (rs->s_magic, REISERFS_SUPER_MAGIC_STRING, 
 
121
                      strlen ( REISERFS_SUPER_MAGIC_STRING)) ||
 
122
            !strncmp (rs->s_magic, REISER2FS_SUPER_MAGIC_STRING, 
 
123
                      strlen ( REISER2FS_SUPER_MAGIC_STRING)));
 
124
}
 
125
 
 
126
char *
 
127
fstype(const char *device) {
 
128
    int fd;
 
129
    char *type = NULL;
 
130
    union {
 
131
        struct minix_super_block ms;
 
132
        struct ext_super_block es;
 
133
        struct ext2_super_block e2s;
 
134
        struct reiserfs_super_block rs;
 
135
    } sb;
 
136
    union {
 
137
        struct xiafs_super_block xiasb;
 
138
        char romfs_magic[8];
 
139
        char qnx4fs_magic[10];  /* ignore first 4 bytes */
 
140
        long bfs_magic;
 
141
        struct ntfs_super_block ntfssb;
 
142
        struct fat_super_block fatsb;
 
143
        struct xfs_super_block xfsb;
 
144
        struct cramfs_super_block cramfssb;
 
145
    } xsb;
 
146
    struct ufs_super_block ufssb;
 
147
    union {
 
148
        struct iso_volume_descriptor iso;
 
149
        struct hs_volume_descriptor hs;
 
150
    } isosb;
 
151
    struct hfs_super_block hfssb;
 
152
    struct hpfs_super_block hpfssb;
 
153
    struct adfs_super_block adfssb;
 
154
    struct stat statbuf;
 
155
 
 
156
    /* opening and reading an arbitrary unknown path can have
 
157
       undesired side effects - first check that `device' refers
 
158
       to a block device */
 
159
    if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode))
 
160
      return 0;
 
161
 
 
162
    fd = open(device, O_RDONLY);
 
163
    if (fd < 0)
 
164
      return 0;
 
165
 
 
166
    if (lseek(fd, 1024, SEEK_SET) != 1024
 
167
        || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
 
168
         goto io_error;
 
169
 
 
170
    /* ext2 has magic in little-endian on disk, so "swapped" is
 
171
       superfluous; however, there have existed strange byteswapped
 
172
       PPC ext2 systems */
 
173
    if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC
 
174
        || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC
 
175
        || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) {
 
176
         type = "ext2";
 
177
 
 
178
         /* maybe even ext3? */
 
179
         if ((assemble4le(sb.e2s.s_feature_compat)
 
180
              & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
 
181
             assemble4le(sb.e2s.s_journal_inum) != 0)
 
182
                 type = "ext3,ext2";
 
183
    }
 
184
 
 
185
    else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC
 
186
             || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2
 
187
             || minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2))
 
188
         type = "minix";
 
189
 
 
190
    else if (extmagic(sb.es) == EXT_SUPER_MAGIC)
 
191
         type = "ext";
 
192
 
 
193
    if (!type) {
 
194
        if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
 
195
                                REISERFS_DISK_OFFSET_IN_BYTES
 
196
                || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
 
197
            goto io_error;
 
198
        if (is_reiserfs_magic_string(&sb.rs))
 
199
            type = "reiserfs";
 
200
    }
 
201
 
 
202
    if (!type) {
 
203
        if (lseek(fd, REISERFS_OLD_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
 
204
                                REISERFS_OLD_DISK_OFFSET_IN_BYTES
 
205
                || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
 
206
            goto io_error;
 
207
        if (is_reiserfs_magic_string(&sb.rs))
 
208
            type = "reiserfs";
 
209
    }
 
210
 
 
211
    if (!type) {
 
212
         if (lseek(fd, 0, SEEK_SET) != 0
 
213
             || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb))
 
214
              goto io_error;
 
215
 
 
216
         if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC)
 
217
              type = "xiafs";
 
218
         else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8))
 
219
              type = "romfs";
 
220
         else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4))
 
221
              type = "xfs";
 
222
         else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
 
223
              type = "qnx4fs";
 
224
         else if(xsb.bfs_magic == 0x1badface)
 
225
              type = "bfs";
 
226
         else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC,
 
227
                          sizeof(xsb.ntfssb.s_magic)))
 
228
              type = "ntfs";
 
229
         else if(cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC)
 
230
              type = "cramfs";
 
231
         else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) ||
 
232
                   !strncmp(xsb.fatsb.s_os, "MSWIN", 5) ||
 
233
                   !strncmp(xsb.fatsb.s_os, "MTOOL", 5) ||
 
234
                   !strncmp(xsb.fatsb.s_os, "mkdosfs", 7) ||
 
235
                   !strncmp(xsb.fatsb.s_os, "kmkdosfs", 8) ||
 
236
                   /* Michal Svec: created by fdformat, old msdos utility for
 
237
                      formatting large (1.7) floppy disks. */
 
238
                   !strncmp(xsb.fatsb.s_os, "CH-FOR18", 8))
 
239
                  && (!strncmp(xsb.fatsb.s_fs, "FAT12   ", 8) ||
 
240
                      !strncmp(xsb.fatsb.s_fs, "FAT16   ", 8) ||
 
241
                      !strncmp(xsb.fatsb.s_fs2, "FAT32   ", 8)))
 
242
              type = "vfat";    /* only guessing - might as well be fat or umsdos */
 
243
    }
 
244
 
 
245
    if (!type) {
 
246
         if (lseek(fd, 8192, SEEK_SET) != 8192
 
247
             || read(fd, (char *) &ufssb, sizeof(ufssb)) != sizeof(ufssb))
 
248
              goto io_error;
 
249
 
 
250
         if (ufsmagic(ufssb) == UFS_SUPER_MAGIC) /* also test swapped version? */
 
251
              type = "ufs";
 
252
    }
 
253
 
 
254
    if (!type) {
 
255
         if (lseek(fd, 0x8000, SEEK_SET) != 0x8000
 
256
             || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb))
 
257
              goto io_error;
 
258
 
 
259
         if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0
 
260
            || strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0)
 
261
              type = "iso9660";
 
262
         else if (may_be_udf(isosb.iso.id))
 
263
              type = "udf";
 
264
    }
 
265
 
 
266
    if (!type) {
 
267
        if (lseek(fd, 0x400, SEEK_SET) != 0x400
 
268
            || read(fd, (char *) &hfssb, sizeof(hfssb)) != sizeof(hfssb))
 
269
             goto io_error;
 
270
 
 
271
        /* also check if block size is equal to 512 bytes,
 
272
           since the hfs driver currently only has support
 
273
           for block sizes of 512 bytes long, and to be
 
274
           more accurate (sb magic is only a short int) */
 
275
        if ((hfsmagic(hfssb) == HFS_SUPER_MAGIC &&
 
276
             hfsblksize(hfssb) == 0x20000) ||
 
277
            (swapped(hfsmagic(hfssb)) == HFS_SUPER_MAGIC &&
 
278
             hfsblksize(hfssb) == 0x200))
 
279
             type = "hfs";
 
280
    }
 
281
 
 
282
    if (!type) {
 
283
        if (lseek(fd, 0x2000, SEEK_SET) != 0x2000
 
284
            || read(fd, (char *) &hpfssb, sizeof(hpfssb)) != sizeof(hpfssb))
 
285
             goto io_error;
 
286
 
 
287
        if (hpfsmagic(hpfssb) == HPFS_SUPER_MAGIC)
 
288
             type = "hpfs";
 
289
    }
 
290
 
 
291
    if (!type) {
 
292
        if (lseek(fd, 0xc00, SEEK_SET) != 0xc00
 
293
            || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb))
 
294
             goto io_error;
 
295
 
 
296
        /* only a weak test */
 
297
        if (may_be_adfs((u_char *) &adfssb)
 
298
            && (adfsblksize(adfssb) >= 8 &&
 
299
                adfsblksize(adfssb) <= 10))
 
300
             type = "adfs";
 
301
    }
 
302
 
 
303
    if (!type) {
 
304
            /* perhaps the user tries to mount the swap space
 
305
               on a new disk; warn her before she does mkfs on it */
 
306
            int pagesize = getpagesize();
 
307
            int rd;
 
308
            char buf[32768];
 
309
 
 
310
            rd = pagesize;
 
311
            if (rd < 8192)
 
312
                    rd = 8192;
 
313
            if (rd > sizeof(buf))
 
314
                    rd = sizeof(buf);
 
315
            if (lseek(fd, 0, SEEK_SET) != 0
 
316
                || read(fd, buf, rd) != rd)
 
317
                    goto io_error;
 
318
            if (may_be_swap(buf+pagesize) ||
 
319
                may_be_swap(buf+4096) || may_be_swap(buf+8192))
 
320
                    type = "swap";
 
321
    }
 
322
 
 
323
    close (fd);
 
324
    return(type);
 
325
 
 
326
io_error:
 
327
    close(fd);
 
328
    return 0;
 
329
}