Import 2.1.118
[davej-history.git] / fs / ntfs / fs.c
blobbb489912b4396bdf8fbe5fde3e59fccfa4f452fd
1 /*
2 * fs.c
3 * NTFS driver for Linux 2.1
5 * Copyright (C) 1995-1997 Martin von Löwis
6 * Copyright (C) 1996 Richard Russon
7 * Copyright (C) 1996-1997 Régis Duchesne
8 */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 #ifdef NTFS_IN_LINUX_KERNEL
14 #include <linux/config.h>
15 #endif
17 #include "types.h"
18 #include "struct.h"
19 #include "util.h"
20 #include "inode.h"
21 #include "super.h"
22 #include "dir.h"
23 #include "support.h"
24 #include "macros.h"
25 #include "sysctl.h"
26 #include <linux/module.h>
27 #include <asm/uaccess.h>
28 #include <linux/nls.h>
29 #include <linux/locks.h>
30 #include <linux/init.h>
32 #define ITEM_SIZE 2040
34 /* io functions to user space */
35 static void ntfs_putuser(ntfs_io* dest,void *src,ntfs_size_t len)
37 copy_to_user(dest->param,src,len);
38 dest->param+=len;
41 #ifdef CONFIG_NTFS_RW
42 static void ntfs_getuser(void *dest,ntfs_io *src,ntfs_size_t len)
44 copy_from_user(dest,src->param,len);
45 src->param+=len;
47 #endif
49 static ssize_t
50 ntfs_read(struct file * filp, char *buf, size_t count, loff_t *off)
52 int error;
53 ntfs_io io;
54 ntfs_inode *ino=NTFS_LINO2NINO(filp->f_dentry->d_inode);
56 /* inode is not properly initialized */
57 if(!ino)return -EINVAL;
58 ntfs_debug(DEBUG_OTHER, "ntfs_read %x,%x,%x ->",
59 (unsigned)ino->i_number,(unsigned)*off,(unsigned)count);
60 /* inode has no unnamed data attribute */
61 if(!ntfs_find_attr(ino,ino->vol->at_data,NULL))
62 return -EINVAL;
64 /* read the data */
65 io.fn_put=ntfs_putuser;
66 io.fn_get=0;
67 io.param=buf;
68 io.size=count;
69 error=ntfs_read_attr(ino,ino->vol->at_data,NULL,*off,&io);
70 if(error)return -error;
72 *off+=io.size;
73 return io.size;
76 #ifdef CONFIG_NTFS_RW
77 static ssize_t
78 ntfs_write(struct file *filp,const char* buf,size_t count,loff_t *pos)
80 struct super_block* sb;
81 int ret;
82 ntfs_io io;
83 ntfs_inode *ino=NTFS_LINO2NINO(filp->f_dentry->d_inode);
85 if(!ino)return -EINVAL;
86 ntfs_debug(DEBUG_OTHER, "ntfs_write %x,%x,%x ->",
87 (unsigned)ino->i_number,(unsigned)*pos,(unsigned)count);
88 sb = filp->f_dentry->d_inode->i_sb;
89 /* Allows to lock fs ro at any time */
90 if(sb->s_flags & MS_RDONLY)
91 return -ENOSPC;
92 if(!ntfs_find_attr(ino,ino->vol->at_data,NULL))
93 return -EINVAL;
95 io.fn_put=0;
96 io.fn_get=ntfs_getuser;
97 io.param=(void*)buf; /* to get rid of the const */
98 io.size=count;
99 ret = ntfs_write_attr(ino,ino->vol->at_data,NULL,*pos,&io);
100 ntfs_debug(DEBUG_OTHER, "%x\n",ret);
101 if(ret<0)return -EINVAL;
103 *pos+=ret;
104 return ret;
106 #endif
108 struct ntfs_filldir{
109 struct inode *dir;
110 filldir_t filldir;
111 unsigned int type;
112 ntfs_u32 ph,pl;
113 void *dirent;
114 char *name;
115 int namelen;
118 static int ntfs_printcb(ntfs_u8 *entry,void *param)
120 struct ntfs_filldir* nf=param;
121 int flags=NTFS_GETU8(entry+0x51);
122 int show_hidden=0,to_lower=0;
123 int length=NTFS_GETU8(entry+0x50);
124 int inum=NTFS_GETU32(entry);
125 int i,error;
126 switch(nf->type){
127 case ngt_dos:
128 /* Don't display long names */
129 if((flags & 2)==0)
130 return 0;
131 break;
132 case ngt_nt:
133 /* Don't display short-only names */
134 switch(flags&3){
135 case 2: return 0;
136 case 3: to_lower=1;
138 break;
139 case ngt_posix:
140 break;
141 case ngt_full:
142 show_hidden=1;
143 break;
145 if(!show_hidden && ((NTFS_GETU8(entry+0x48) & 2)==2)){
146 ntfs_debug(DEBUG_OTHER,"Skipping hidden file\n");
147 return 0;
149 nf->name=0;
150 if(ntfs_encodeuni(NTFS_INO2VOL(nf->dir),(ntfs_u16*)(entry+0x52),
151 length,&nf->name,&nf->namelen)){
152 ntfs_debug(DEBUG_OTHER,"Skipping unrepresentable file\n");
153 if(nf->name)ntfs_free(nf->name);
154 return 0;
156 /* Do not return ".", as this is faked */
157 if(length==1 && *nf->name=='.')
158 return 0;
159 if(to_lower)
160 for(i=0;i<nf->namelen;i++)
161 /* This supports ASCII only. Since only DOS-only
162 names get converted, and since those are restricted
163 to ASCII, this should be correct */
164 if(nf->name[i]>='A' && nf->name[i]<='Z')
165 nf->name[i]+='a'-'A';
166 nf->name[nf->namelen]=0;
167 ntfs_debug(DEBUG_OTHER, "readdir got %s,len %d\n",nf->name,nf->namelen);
168 /* filldir expects an off_t rather than an loff_t.
169 Hope we don't have more than 65535 index records */
170 error=nf->filldir(nf->dirent,nf->name,nf->namelen,
171 (nf->ph<<16)|nf->pl,inum);
172 ntfs_free(nf->name);
173 /* Linux filldir errors are negative, other errors positive */
174 return error;
177 /* readdir returns '..', then '.', then the directory entries in sequence
178 As the root directory contains a entry for itself, '.' is not emulated
179 for the root directory */
180 static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir)
182 struct ntfs_filldir cb;
183 int error;
184 struct inode *dir=filp->f_dentry->d_inode;
186 ntfs_debug(DEBUG_OTHER, "ntfs_readdir ino %x mode %x\n",
187 (unsigned)dir->i_ino,(unsigned int)dir->i_mode);
188 if(!dir || (dir->i_ino==0) || !S_ISDIR(dir->i_mode))return -EBADF;
190 ntfs_debug(DEBUG_OTHER, "readdir: Looking for file %x dircount %d\n",
191 (unsigned)filp->f_pos,dir->i_count);
192 cb.pl=filp->f_pos & 0xFFFF;
193 cb.ph=filp->f_pos >> 16;
194 /* end of directory */
195 if(cb.ph==0xFFFF){
196 /* FIXME: Maybe we can return those with the previous call */
197 switch(cb.pl){
198 case 0: filldir(dirent,".",1,filp->f_pos,dir->i_ino);
199 filp->f_pos=0xFFFF0001;
200 return 0;
201 /* FIXME: parent directory */
202 case 1: filldir(dirent,"..",2,filp->f_pos,0);
203 filp->f_pos=0xFFFF0002;
204 return 0;
206 ntfs_debug(DEBUG_OTHER, "readdir: EOD\n");
207 return 0;
209 cb.dir=dir;
210 cb.filldir=filldir;
211 cb.dirent=dirent;
212 cb.type=NTFS_INO2VOL(dir)->ngt;
214 ntfs_debug(DEBUG_OTHER,"looking for next file\n");
215 error=ntfs_getdir_unsorted(NTFS_LINO2NINO(dir),&cb.ph,&cb.pl,
216 ntfs_printcb,&cb);
217 }while(!error && cb.ph!=0xFFFFFFFF);
218 filp->f_pos=(cb.ph<<16)|cb.pl;
219 ntfs_debug(DEBUG_OTHER, "new position %x\n",(unsigned)filp->f_pos);
220 /* -EINVAL is on user buffer full. This is not considered
221 as an error by sys_getdents */
222 if(error<0)
223 error=0;
224 /* Otherwise (device error, inconsistent data), switch the sign */
225 return -error;
228 /* Copied from vfat driver */
229 static int simple_getbool(char *s, int *setval)
231 if (s) {
232 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
233 *setval = 1;
234 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
235 *setval = 0;
236 } else {
237 return 0;
239 } else {
240 *setval = 1;
242 return 1;
245 /* Parse the (re)mount options */
246 static int parse_options(ntfs_volume* vol,char *opt)
248 char *value;
250 vol->uid=vol->gid=0;
251 vol->umask=0077;
252 vol->ngt=ngt_nt;
253 vol->nls_map=0;
254 vol->nct=0;
255 if(!opt)goto done;
257 for(opt = strtok(opt,",");opt;opt=strtok(NULL,","))
259 if ((value = strchr(opt, '=')) != NULL)
260 *value++='\0';
261 if(strcmp(opt,"uid")==0)
263 if(!value || !*value)goto needs_arg;
264 vol->uid=simple_strtoul(value,&value,0);
265 if(*value){
266 printk(KERN_ERR "NTFS: uid invalid argument\n");
267 return 0;
269 }else if(strcmp(opt, "gid") == 0)
271 if(!value || !*value)goto needs_arg;
272 vol->gid=simple_strtoul(value,&value,0);
273 if(*value){
274 printk(KERN_ERR "gid invalid argument\n");
275 return 0;
277 }else if(strcmp(opt, "umask") == 0)
279 if(!value || !*value)goto needs_arg;
280 vol->umask=simple_strtoul(value,&value,0);
281 if(*value){
282 printk(KERN_ERR "umask invalid argument\n");
283 return 0;
285 }else if(strcmp(opt, "iocharset") == 0){
286 if(!value || !*value)goto needs_arg;
287 vol->nls_map=load_nls(value);
288 vol->nct |= nct_map;
289 if(!vol->nls_map){
290 printk(KERN_ERR "NTFS: charset not found");
291 return 0;
293 }else if(strcmp(opt, "posix") == 0){
294 int val;
295 if(!value || !*value)goto needs_arg;
296 if(!simple_getbool(value,&val))
297 goto needs_bool;
298 vol->ngt=val?ngt_posix:ngt_nt;
299 }else if(strcmp(opt,"utf8") == 0){
300 int val=0;
301 if(!value || !*value)
302 val=1;
303 else if(!simple_getbool(value,&val))
304 goto needs_bool;
305 if(val)
306 vol->nct|=nct_utf8;
307 }else if(strcmp(opt,"uni_xlate") == 0){
308 int val=0;
309 /* no argument: uni_vfat.
310 boolean argument: uni_vfat.
311 "2": uni.
313 if(!value || !*value)
314 val=1;
315 else if(strcmp(value,"2")==0)
316 vol->nct |= nct_uni_xlate;
317 else if(!simple_getbool(value,&val))
318 goto needs_bool;
319 if(val)
320 vol->nct |= nct_uni_xlate_vfat | nct_uni_xlate;
321 }else{
322 printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);
323 return 0;
326 if(vol->nct & nct_utf8 & (nct_map | nct_uni_xlate)){
327 printk(KERN_ERR "utf8 cannot be combined with iocharset or uni_xlate\n");
328 return 0;
330 done:
331 if((vol->nct & (nct_uni_xlate | nct_map | nct_utf8))==0)
332 /* default to UTF-8 */
333 vol->nct=nct_utf8;
334 if(!vol->nls_map)
335 vol->nls_map=load_nls_default();
336 return 1;
338 needs_arg:
339 printk(KERN_ERR "NTFS: %s needs an argument",opt);
340 return 0;
341 needs_bool:
342 printk(KERN_ERR "NTFS: %s needs boolean argument",opt);
343 return 0;
346 static int ntfs_lookup(struct inode *dir, struct dentry *d)
348 struct inode *res=0;
349 char *item=0;
350 ntfs_iterate_s walk;
351 int error;
352 ntfs_debug(DEBUG_OTHER, "Looking up %s in %x\n",d->d_name.name,
353 (unsigned)dir->i_ino);
354 /* convert to wide string */
355 error=ntfs_decodeuni(NTFS_INO2VOL(dir),(char*)d->d_name.name,
356 d->d_name.len,&walk.name,&walk.namelen);
357 if(error)
358 return error;
359 item=ntfs_malloc(ITEM_SIZE);
360 /* ntfs_getdir will place the directory entry into item,
361 and the first long long is the MFT record number */
362 walk.type=BY_NAME;
363 walk.dir=NTFS_LINO2NINO(dir);
364 walk.result=item;
365 if(ntfs_getdir_byname(&walk))
367 res=iget(dir->i_sb,NTFS_GETU32(item));
369 d_add(d,res);
370 ntfs_free(item);
371 ntfs_free(walk.name);
372 return res?0:-ENOENT;
375 struct file_operations ntfs_file_operations_nommap = {
376 NULL, /* lseek */
377 ntfs_read,
378 #ifdef CONFIG_NTFS_RW
379 ntfs_write,
380 #else
381 NULL,
382 #endif
383 NULL, /* readdir */
384 NULL, /* select */
385 NULL, /* ioctl */
386 NULL, /* mmap */
387 NULL, /* open */
388 NULL, /* flush */
389 NULL, /* release */
390 NULL, /* fsync */
391 NULL, /* fasync */
392 NULL, /* check_media_change */
393 NULL, /* revalidate */
394 NULL, /* lock */
397 struct inode_operations ntfs_inode_operations_nobmap = {
398 &ntfs_file_operations_nommap,
399 NULL, /* create */
400 NULL, /* lookup */
401 NULL, /* link */
402 NULL, /* unlink */
403 NULL, /* symlink */
404 NULL, /* mkdir */
405 NULL, /* rmdir */
406 NULL, /* mknod */
407 NULL, /* rename */
408 NULL, /* readlink */
409 NULL, /* follow_link */
410 NULL, /* readpage */
411 NULL, /* writepage */
412 NULL, /* bmap */
413 NULL, /* truncate */
414 NULL, /* permission */
415 NULL, /* smap */
416 NULL, /* updatepage */
417 NULL, /* revalidate */
420 #ifdef CONFIG_NTFS_RW
421 static int
422 ntfs_create(struct inode* dir,struct dentry *d,int mode)
424 struct inode *r=0;
425 ntfs_inode *ino=0;
426 ntfs_volume *vol;
427 int error=0;
428 ntfs_attribute *si;
430 r=get_empty_inode();
431 if(!r){
432 error=ENOMEM;
433 goto fail;
436 ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n",d->d_name.name);
437 vol=NTFS_INO2VOL(dir);
438 #ifdef NTFS_IN_LINUX_KERNEL
439 ino=NTFS_LINO2NINO(r);
440 #else
441 ino=ntfs_malloc(sizeof(ntfs_inode));
442 if(!ino){
443 error=ENOMEM;
444 goto fail;
446 r->u.generic_ip=ino;
447 #endif
448 error=ntfs_alloc_inode(NTFS_LINO2NINO(dir),ino,(char*)d->d_name.name,
449 d->d_name.len);
450 if(error)goto fail;
451 error=ntfs_update_inode(ino);
452 if(error)goto fail;
453 error=ntfs_update_inode(NTFS_LINO2NINO(dir));
454 if(error)goto fail;
456 r->i_uid=vol->uid;
457 r->i_gid=vol->gid;
458 r->i_nlink=1;
459 r->i_sb=dir->i_sb;
460 /* FIXME: dirty? dev? */
461 /* get the file modification times from the standard information */
462 si=ntfs_find_attr(ino,vol->at_standard_information,NULL);
463 if(si){
464 char *attr=si->d.data;
465 r->i_atime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));
466 r->i_ctime=ntfs_ntutc2unixutc(NTFS_GETU64(attr));
467 r->i_mtime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));
469 /* It's not a directory */
470 r->i_op=&ntfs_inode_operations_nobmap;
471 r->i_mode=S_IFREG|S_IRUGO;
472 #ifdef CONFIG_NTFS_RW
473 r->i_mode|=S_IWUGO;
474 #endif
475 r->i_mode &= ~vol->umask;
477 d_instantiate(d,r);
478 return 0;
479 fail:
480 #ifndef NTFS_IN_LINUX_KERNEL
481 if(ino)ntfs_free(ino);
482 #endif
483 if(r)iput(r);
484 return -error;
486 #endif
488 static int
489 ntfs_bmap(struct inode *ino,int block)
491 int ret=ntfs_vcn_to_lcn(NTFS_LINO2NINO(ino),block);
492 ntfs_debug(DEBUG_OTHER, "bmap of %lx,block %x is %x\n",
493 ino->i_ino,block,ret);
494 return (ret==-1) ? 0:ret;
497 struct file_operations ntfs_file_operations = {
498 NULL, /* lseek */
499 ntfs_read,
500 #ifdef CONFIG_NTFS_RW
501 ntfs_write,
502 #else
503 NULL,
504 #endif
505 NULL, /* readdir */
506 NULL, /* select */
507 NULL, /* ioctl */
508 generic_file_mmap,
509 NULL, /* open */
510 NULL, /* flush */
511 NULL, /* release */
512 NULL, /* fsync */
513 NULL, /* fasync */
514 NULL, /* check_media_change */
515 NULL, /* revalidate */
516 NULL, /* lock */
519 struct inode_operations ntfs_inode_operations = {
520 &ntfs_file_operations,
521 NULL, /* create */
522 NULL, /* lookup */
523 NULL, /* link */
524 NULL, /* unlink */
525 NULL, /* symlink */
526 NULL, /* mkdir */
527 NULL, /* rmdir */
528 NULL, /* mknod */
529 NULL, /* rename */
530 NULL, /* readlink */
531 NULL, /* follow_link */
532 generic_readpage,
533 NULL, /* writepage */
534 ntfs_bmap,
535 NULL, /* truncate */
536 NULL, /* permission */
537 NULL, /* smap */
538 NULL, /* updatepage */
539 NULL, /* revalidate */
542 struct file_operations ntfs_dir_operations = {
543 NULL, /* lseek */
544 NULL, /* read */
545 NULL, /* write */
546 ntfs_readdir, /* readdir */
547 NULL, /* poll */
548 NULL, /* ioctl */
549 NULL, /* mmap */
550 NULL, /* open */
551 NULL, /* flush */
552 NULL, /* release */
553 NULL, /* fsync */
554 NULL, /* fasync */
555 NULL, /* check_media_change */
556 NULL, /* revalidate */
557 NULL, /* lock */
560 struct inode_operations ntfs_dir_inode_operations = {
561 &ntfs_dir_operations,
562 #ifdef CONFIG_NTFS_RW
563 ntfs_create, /* create */
564 #else
565 NULL,
566 #endif
567 ntfs_lookup, /* lookup */
568 NULL, /* link */
569 NULL, /* unlink */
570 NULL, /* symlink */
571 NULL, /* mkdir */
572 NULL, /* rmdir */
573 NULL, /* mknod */
574 NULL, /* rename */
575 NULL, /* readlink */
576 NULL, /* follow_link */
577 NULL, /* readpage */
578 NULL, /* writepage */
579 NULL, /* bmap */
580 NULL, /* truncate */
581 NULL, /* permission */
582 NULL, /* smap */
583 NULL, /* updatepage */
584 NULL, /* revalidate */
587 /* ntfs_read_inode is called by the Virtual File System (the kernel layer that
588 * deals with filesystems) when iget is called requesting an inode not already
589 * present in the inode table. Typically filesystems have separate
590 * inode_operations for directories, files and symlinks.
592 static void ntfs_read_inode(struct inode* inode)
594 ntfs_volume *vol;
595 int can_mmap=0;
596 ntfs_inode *ino;
597 ntfs_attribute *data;
598 ntfs_attribute *si;
600 vol=NTFS_INO2VOL(inode);
601 inode->i_op=NULL;
602 inode->i_mode=0;
603 ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n",(unsigned)inode->i_ino);
605 switch(inode->i_ino)
607 /* those are loaded special files */
608 case FILE_MFT:
609 ntfs_error("Trying to open MFT\n");return;
610 default:
611 #ifdef NTFS_IN_LINUX_KERNEL
612 ino=&inode->u.ntfs_i;
613 #else
614 ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
615 inode->u.generic_ip=ino;
616 #endif
617 if(!ino || ntfs_init_inode(ino,
618 NTFS_INO2VOL(inode),inode->i_ino))
620 ntfs_debug(DEBUG_OTHER, "NTFS:Error loading inode %x\n",
621 (unsigned int)inode->i_ino);
622 return;
625 /* Set uid/gid from mount options */
626 inode->i_uid=vol->uid;
627 inode->i_gid=vol->gid;
628 inode->i_nlink=1;
629 /* Use the size of the data attribute as file size */
630 data = ntfs_find_attr(ino,vol->at_data,NULL);
631 if(!data)
633 inode->i_size=0;
634 can_mmap=0;
636 else
638 inode->i_size=data->size;
639 can_mmap=!data->resident && !data->compressed;
641 /* get the file modification times from the standard information */
642 si=ntfs_find_attr(ino,vol->at_standard_information,NULL);
643 if(si){
644 char *attr=si->d.data;
645 inode->i_atime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+0x18));
646 inode->i_ctime=ntfs_ntutc2unixutc(NTFS_GETU64(attr));
647 inode->i_mtime=ntfs_ntutc2unixutc(NTFS_GETU64(attr+8));
649 /* if it has an index root, it's a directory */
650 if(ntfs_find_attr(ino,vol->at_index_root,"$I30"))
652 ntfs_attribute *at;
653 at = ntfs_find_attr (ino, vol->at_index_allocation, "$I30");
654 inode->i_size = at ? at->size : 0;
656 inode->i_op=&ntfs_dir_inode_operations;
657 inode->i_mode=S_IFDIR|S_IRUGO|S_IXUGO;
659 else
661 inode->i_op=can_mmap ? &ntfs_inode_operations :
662 &ntfs_inode_operations_nobmap;
663 inode->i_mode=S_IFREG|S_IRUGO;
665 #ifdef CONFIG_NTFS_RW
666 if(!data || !data->compressed)
667 inode->i_mode|=S_IWUGO;
668 #endif
669 inode->i_mode &= ~vol->umask;
672 static void ntfs_put_inode(struct inode *ino)
676 static void _ntfs_clear_inode(struct inode *ino)
678 ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n",ino->i_ino);
679 #ifdef NTFS_IN_LINUX_KERNEL
680 if(ino->i_ino!=FILE_MFT)
681 ntfs_clear_inode(&ino->u.ntfs_i);
682 #else
683 if(ino->i_ino!=FILE_MFT && ino->u.generic_ip)
685 ntfs_clear_inode(ino->u.generic_ip);
686 ntfs_free(ino->u.generic_ip);
687 ino->u.generic_ip=0;
689 #endif
690 return;
693 /* Called when umounting a filesystem by do_umount() in fs/super.c */
694 static void ntfs_put_super(struct super_block *sb)
696 ntfs_volume *vol;
698 ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
700 vol=NTFS_SB2VOL(sb);
702 ntfs_release_volume(vol);
703 if(vol->nls_map)
704 unload_nls(vol->nls_map);
705 #ifndef NTFS_IN_LINUX_KERNEL
706 ntfs_free(vol);
707 #endif
708 ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
709 MOD_DEC_USE_COUNT;
712 /* Called by the kernel when asking for stats */
713 static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
715 struct statfs fs;
716 struct inode *mft;
717 ntfs_volume *vol;
719 ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
720 vol=NTFS_SB2VOL(sb);
721 memset(&fs,0,sizeof(fs));
722 fs.f_type=NTFS_SUPER_MAGIC;
723 fs.f_bsize=vol->clustersize;
725 fs.f_blocks=ntfs_get_volumesize(NTFS_SB2VOL(sb));
726 fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
727 fs.f_bavail=fs.f_bfree;
729 /* Number of files is limited by free space only, so we lie here */
730 fs.f_ffree=0;
731 mft=iget(sb,FILE_MFT);
732 fs.f_files=mft->i_size/vol->mft_recordsize;
733 iput(mft);
735 /* should be read from volume */
736 fs.f_namelen=255;
737 copy_to_user(sf,&fs,bufsize);
738 return 0;
741 /* Called when remounting a filesystem by do_remount_sb() in fs/super.c */
742 static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
744 if(!parse_options(NTFS_SB2VOL(sb), options))
745 return -EINVAL;
746 return 0;
749 /* Define the super block operation that are implemented */
750 struct super_operations ntfs_super_operations = {
751 ntfs_read_inode,
752 NULL, /* write_inode */
753 ntfs_put_inode,
754 NULL, /* delete_inode */
755 NULL, /* notify_change */
756 ntfs_put_super,
757 NULL, /* write_super */
758 ntfs_statfs,
759 ntfs_remount_fs, /* remount */
760 _ntfs_clear_inode, /* clear_inode */
763 /* Called to mount a filesystem by read_super() in fs/super.c
764 * Return a super block, the main structure of a filesystem
766 * NOTE : Don't store a pointer to an option, as the page containing the
767 * options is freed after ntfs_read_super() returns.
769 * NOTE : A context switch can happen in kernel code only if the code blocks
770 * (= calls schedule() in kernel/sched.c).
772 struct super_block * ntfs_read_super(struct super_block *sb,
773 void *options, int silent)
775 ntfs_volume *vol;
776 struct buffer_head *bh;
777 int i;
779 /* When the driver is compiled as a module, kmod must know when it
780 * can safely remove it from memory. To do this, each module owns a
781 * reference counter.
783 MOD_INC_USE_COUNT;
784 /* Don't put ntfs_debug() before MOD_INC_USE_COUNT, printk() can block
785 * so this could lead to a race condition with kmod.
787 ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
789 #ifdef NTFS_IN_LINUX_KERNEL
790 vol = NTFS_SB2VOL(sb);
791 #else
792 if(!(vol = ntfs_malloc(sizeof(ntfs_volume))))
793 goto ntfs_read_super_dec;
794 NTFS_SB2VOL(sb)=vol;
795 #endif
797 if(!parse_options(vol,(char*)options))
798 goto ntfs_read_super_vol;
800 /* Ensure that the super block won't be used until it is completed */
801 lock_super(sb);
802 ntfs_debug(DEBUG_OTHER, "lock_super\n");
803 #if 0
804 /* Set to read only, user option might reset it */
805 sb->s_flags |= MS_RDONLY;
806 #endif
808 /* Assume a 512 bytes block device for now */
809 set_blocksize(sb->s_dev, 512);
810 /* Read the super block (boot block) */
811 if(!(bh=bread(sb->s_dev,0,512))) {
812 ntfs_error("Reading super block failed\n");
813 goto ntfs_read_super_unl;
815 ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");
817 /* Check for 'NTFS' magic number */
818 if(!IS_NTFS_VOLUME(bh->b_data)){
819 ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");
820 brelse(bh);
821 goto ntfs_read_super_unl;
824 ntfs_debug(DEBUG_OTHER, "Going to init volume\n");
825 ntfs_init_volume(vol,bh->b_data);
826 ntfs_debug(DEBUG_OTHER, "MFT record at cluster 0x%X\n",vol->mft_cluster);
827 brelse(bh);
828 NTFS_SB(vol)=sb;
829 ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
831 /* Inform the kernel that a device block is a NTFS cluster */
832 sb->s_blocksize=vol->clustersize;
833 for(i=sb->s_blocksize,sb->s_blocksize_bits=0;i != 1;i>>=1)
834 sb->s_blocksize_bits++;
835 set_blocksize(sb->s_dev,sb->s_blocksize);
836 ntfs_debug(DEBUG_OTHER, "set_blocksize\n");
838 /* Allocate a MFT record (MFT record can be smaller than a cluster) */
839 if(!(vol->mft=ntfs_malloc(max(vol->mft_recordsize,vol->clustersize))))
840 goto ntfs_read_super_unl;
842 /* Read at least the MFT record for $MFT */
843 for(i=0;i<max(vol->mft_clusters_per_record,1);i++){
844 if(!(bh=bread(sb->s_dev,vol->mft_cluster+i,vol->clustersize))) {
845 ntfs_error("Could not read MFT record 0\n");
846 goto ntfs_read_super_mft;
848 ntfs_memcpy(vol->mft+i*vol->clustersize,bh->b_data,vol->clustersize);
849 brelse(bh);
850 ntfs_debug(DEBUG_OTHER, "Read cluster %x\n",vol->mft_cluster+i);
853 /* Check and fixup this MFT record */
854 if(!ntfs_check_mft_record(vol,vol->mft)){
855 ntfs_error("Invalid MFT record 0\n");
856 goto ntfs_read_super_mft;
859 /* Inform the kernel about which super operations are available */
860 sb->s_op = &ntfs_super_operations;
861 sb->s_magic = NTFS_SUPER_MAGIC;
863 ntfs_debug(DEBUG_OTHER, "Reading special files\n");
864 if(ntfs_load_special_files(vol)){
865 ntfs_error("Error loading special files\n");
866 goto ntfs_read_super_mft;
869 ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");
870 /* Get the root directory */
871 if(!(sb->s_root=d_alloc_root(iget(sb,FILE_ROOT),NULL))){
872 ntfs_error("Could not get root dir inode\n");
873 goto ntfs_read_super_mft;
875 unlock_super(sb);
876 ntfs_debug(DEBUG_OTHER, "unlock_super\n");
877 ntfs_debug(DEBUG_OTHER, "read_super: done\n");
878 return sb;
880 ntfs_read_super_mft:
881 ntfs_free(vol->mft);
882 ntfs_read_super_unl:
883 sb->s_dev = 0;
884 unlock_super(sb);
885 ntfs_debug(DEBUG_OTHER, "unlock_super\n");
886 ntfs_read_super_vol:
887 #ifndef NTFS_IN_LINUX_KERNEL
888 ntfs_free(vol);
889 ntfs_read_super_dec:
890 #endif
891 ntfs_debug(DEBUG_OTHER, "read_super: done\n");
892 MOD_DEC_USE_COUNT;
893 return NULL;
896 /* Define the filesystem
898 * Define SECOND if you cannot unload ntfs, and want to avoid rebooting
899 * for just one more test
901 struct file_system_type ntfs_fs_type = {
902 /* Filesystem name, as used after mount -t */
903 #ifndef SECOND
904 "ntfs",
905 #else
906 "ntfs2",
907 #endif
908 /* This filesystem requires a device (a hard disk)
909 * May want to add FS_IBASKET when it works
911 FS_REQUIRES_DEV,
912 /* Entry point of the filesystem */
913 ntfs_read_super,
914 /* Will point to the next filesystem in the kernel table */
915 NULL
918 /* When this code is not compiled as a module, this is the main entry point,
919 * called by do_sys_setup() in fs/filesystems.c
921 * NOTE : __initfunc() is a macro used to remove this function from memory
922 * once initialization is done
924 __initfunc(int init_ntfs_fs(void))
926 /* Comment this if you trust klogd. There are reasons not to trust it
928 #if defined(DEBUG) && !defined(MODULE)
929 extern int console_loglevel;
930 console_loglevel=15;
931 #endif
932 printk(KERN_NOTICE "NTFS version " NTFS_VERSION "\n");
933 SYSCTL(1);
934 ntfs_debug(DEBUG_OTHER, "registering %s\n",ntfs_fs_type.name);
935 /* add this filesystem to the kernel table of filesystems */
936 return register_filesystem(&ntfs_fs_type);
939 #ifdef MODULE
940 /* A module is a piece of code which can be inserted in and removed
941 * from the running kernel whenever you want using lsmod, or on demand using
942 * kmod
945 /* No function of this module is needed by another module */
946 EXPORT_NO_SYMBOLS;
947 /* Only used for documentation purposes at the moment,
948 * see include/linux/module.h
950 MODULE_AUTHOR("Martin von Löwis");
951 MODULE_DESCRIPTION("NTFS driver");
952 /* no MODULE_SUPPORTED_DEVICE() */
953 /* Load-time parameter */
954 MODULE_PARM(ntdebug, "i");
955 MODULE_PARM_DESC(ntdebug, "Debug level");
957 /* When this code is compiled as a module, if you use mount -t ntfs when no
958 * ntfs filesystem is registered (see /proc/filesystems), get_fs_type() in
959 * fs/super.c asks kmod to load the module named ntfs in memory.
961 * Therefore, this function is the main entry point in this case
963 int init_module(void)
965 return init_ntfs_fs();
968 /* Called by kmod just before the kernel removes the module from memory */
969 void cleanup_module(void)
971 SYSCTL(0);
972 ntfs_debug(DEBUG_OTHER, "unregistering %s\n",ntfs_fs_type.name);
973 unregister_filesystem(&ntfs_fs_type);
975 #endif
978 * Local variables:
979 * c-file-style: "linux"
980 * End: