fs.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:32k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * fs.c - NTFS driver for Linux 2.4.x
  3.  *
  4.  * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton
  5.  * Altaparmakov to develop NTFS on Linux since June 2001.
  6.  *
  7.  * Copyright (C) 1995-1997, 1999 Martin von L鰓is
  8.  * Copyright (C) 1996 Richard Russon
  9.  * Copyright (C) 1996-1997 R間is Duchesne
  10.  * Copyright (C) 2000-2001, Anton Altaparmakov (AIA)
  11.  */
  12. #include <linux/config.h>
  13. #include <linux/errno.h>
  14. #include "ntfstypes.h"
  15. #include "struct.h"
  16. #include "util.h"
  17. #include "inode.h"
  18. #include "super.h"
  19. #include "dir.h"
  20. #include "support.h"
  21. #include "macros.h"
  22. #include "sysctl.h"
  23. #include "attr.h"
  24. #include <linux/module.h>
  25. #include <asm/uaccess.h>
  26. #include <linux/locks.h>
  27. #include <linux/init.h>
  28. #include <linux/smp_lock.h>
  29. #include <linux/blkdev.h>
  30. #include <asm/page.h>
  31. #include <linux/nls.h>
  32. #include <linux/ntfs_fs.h>
  33. /* Forward declarations. */
  34. static struct inode_operations ntfs_dir_inode_operations;
  35. static struct file_operations ntfs_dir_operations;
  36. #define ITEM_SIZE 2040
  37. /* Io functions to user space. */
  38. static void ntfs_putuser(ntfs_io* dest, void *src, ntfs_size_t len)
  39. {
  40. copy_to_user(dest->param, src, len);
  41. dest->param += len;
  42. }
  43. #ifdef CONFIG_NTFS_RW
  44. struct ntfs_getuser_update_vm_s {
  45. const char *user;
  46. struct inode *ino;
  47. loff_t off;
  48. };
  49. static void ntfs_getuser_update_vm(void *dest, ntfs_io *src, ntfs_size_t len)
  50. {
  51. struct ntfs_getuser_update_vm_s *p = src->param;
  52. copy_from_user(dest, p->user, len);
  53. p->user += len;
  54. p->off += len;
  55. }
  56. #endif
  57. /* loff_t is 64 bit signed, so is cool. */
  58. static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off)
  59. {
  60. int error;
  61. ntfs_io io;
  62. ntfs_attribute *attr;
  63. ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);
  64. /* Inode is not properly initialized. */
  65. if (!ino)
  66. return -EINVAL;
  67. ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",
  68.    (unsigned)ino->i_number, (unsigned long long)*off,
  69.    (unsigned)count);
  70. attr = ntfs_find_attr(ino, ino->vol->at_data, NULL);
  71. /* Inode has no unnamed data attribute. */
  72. if (!attr) {
  73. ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!n");
  74. return -EINVAL;
  75. }
  76. if (attr->flags & ATTR_IS_ENCRYPTED)
  77. return -EACCES;
  78. /* Read the data. */
  79. io.fn_put = ntfs_putuser;
  80. io.fn_get = 0;
  81. io.param = buf;
  82. io.size = count;
  83. error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);
  84. if (error && !io.size) {
  85. ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "
  86. "error %i, io size %u.n", error, io.size);
  87. return error;
  88. }
  89. *off += io.size;
  90. ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.n",
  91. io.size);
  92. return io.size;
  93. }
  94. #ifdef CONFIG_NTFS_RW
  95. static ssize_t ntfs_write(struct file *filp, const char *buf, size_t count,
  96. loff_t *pos)
  97. {
  98. int err;
  99. struct inode *vfs_ino = filp->f_dentry->d_inode;
  100. ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);
  101. ntfs_attribute *data;
  102. ntfs_io io;
  103. struct ntfs_getuser_update_vm_s param;
  104. if (!ntfs_ino)
  105. return -EINVAL;
  106. ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Entering for inode 0x%lx, "
  107. "*pos 0x%Lx, count 0x%x.n", ntfs_ino->i_number, *pos,
  108. count);
  109. /* Allows to lock fs ro at any time. */
  110. if (vfs_ino->i_sb->s_flags & MS_RDONLY)
  111. return -EROFS;
  112. data = ntfs_find_attr(ntfs_ino, ntfs_ino->vol->at_data, NULL);
  113. if (!data)
  114. return -EINVAL;
  115. /* Evaluating O_APPEND is the file system's job... */
  116. if (filp->f_flags & O_APPEND)
  117. *pos = vfs_ino->i_size;
  118. if (!data->resident && *pos + count > data->allocated) {
  119. err = ntfs_extend_attr(ntfs_ino, data, *pos + count);
  120. if (err < 0)
  121. return err;
  122. }
  123. param.user = buf;
  124. param.ino = vfs_ino;
  125. param.off = *pos;
  126. io.fn_put = 0;
  127. io.fn_get = ntfs_getuser_update_vm;
  128. io.param = &param;
  129. io.size = count;
  130. io.do_read = 0;
  131. err = ntfs_readwrite_attr(ntfs_ino, data, *pos, &io);
  132. ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Returning %in", -err);
  133. if (!err) {
  134. *pos += io.size;
  135. if (*pos > vfs_ino->i_size)
  136. vfs_ino->i_size = *pos;
  137. mark_inode_dirty(vfs_ino);
  138. return io.size;
  139. }
  140. return err;
  141. }
  142. #endif
  143. struct ntfs_filldir {
  144. struct inode *dir;
  145. filldir_t filldir;
  146. unsigned int type;
  147. u32 ph, pl;
  148. void *dirent;
  149. char *name;
  150. int namelen;
  151. int ret_code;
  152. };
  153. static int ntfs_printcb(ntfs_u8 *entry, void *param)
  154. {
  155. unsigned long inum = NTFS_GETU64(entry) & 0xffffffffffff;
  156. struct ntfs_filldir *nf = param;
  157. u32 flags = NTFS_GETU32(entry + 0x48);
  158. char show_sys_files = 0;
  159. u8 name_len = NTFS_GETU8(entry + 0x50);
  160. u8 name_type = NTFS_GETU8(entry + 0x51);
  161. int err;
  162. unsigned file_type;
  163. switch (nf->type) {
  164. case ngt_dos:
  165. /* Don't display long names. */
  166. if (!(name_type & 2))
  167. return 0;
  168. break;
  169. case ngt_nt:
  170. /* Don't display short-only names. */
  171. if ((name_type & 3) == 2)
  172. return 0;
  173. break;
  174. case ngt_posix:
  175. break;
  176. case ngt_full:
  177. show_sys_files = 1;
  178. break;
  179. default:
  180. BUG();
  181. }
  182. err = ntfs_encodeuni(NTFS_INO2VOL(nf->dir), (ntfs_u16*)(entry + 0x52),
  183. name_len, &nf->name, &nf->namelen);
  184. if (err) {
  185. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping "
  186. "unrepresentable file.n");
  187. err = 0;
  188. goto err_ret;
  189. }
  190. if (!show_sys_files && inum < 0x10UL) {
  191. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping system "
  192. "file (%s).n", nf->name);
  193. err = 0;
  194. goto err_ret;
  195. }
  196. /* Do not return ".", as this is faked. */
  197. if (nf->namelen == 1 && nf->name[0] == '.') {
  198. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping "."n");
  199. err = 0;
  200. goto err_ret;
  201. }
  202. nf->name[nf->namelen] = 0;
  203. if (flags & 0x10000000) /* FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT */
  204. file_type = DT_DIR;
  205. else
  206. file_type = DT_REG;
  207. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling filldir for %s with "
  208. "len %i, f_pos 0x%Lx, inode %lu, %s.n",
  209. nf->name, nf->namelen, (loff_t)(nf->ph << 16) | nf->pl,
  210. inum, file_type == DT_DIR ? "DT_DIR" : "DT_REG");
  211. /*
  212.  * Userspace side of filldir expects an off_t rather than an loff_t.
  213.  * And it also doesn't like the most significant bit being set as it
  214.  * then considers the value to be negative. Thus this implementation
  215.  * limits the number of index records to 32766, which should be plenty.
  216.  */
  217. err = nf->filldir(nf->dirent, nf->name, nf->namelen,
  218. (loff_t)(nf->ph << 16) | nf->pl, inum, file_type);
  219. if (err)
  220. nf->ret_code = err;
  221. err_ret:
  222. nf->namelen = 0;
  223. ntfs_free(nf->name);
  224. nf->name = NULL;
  225. return err;
  226. }
  227. /*
  228.  * readdir returns '.', then '..', then the directory entries in sequence.
  229.  * As the root directory contains an entry for itself, '.' is not emulated for
  230.  * the root directory.
  231.  */
  232. static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir)
  233. {
  234. struct inode *dir = filp->f_dentry->d_inode;
  235. int err;
  236. struct ntfs_filldir cb;
  237. cb.ret_code = 0;
  238. cb.pl = filp->f_pos & 0xffff;
  239. cb.ph = (filp->f_pos >> 16) & 0x7fff;
  240. filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  241. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Entering for inode %lu, "
  242. "f_pos 0x%Lx, i_mode 0x%x, i_count %lu.n", dir->i_ino,
  243. filp->f_pos, (unsigned int)dir->i_mode,
  244. atomic_read(&dir->i_count));
  245. if (!cb.ph) {
  246. /* Start of directory. Emulate "." and "..". */
  247. if (!cb.pl) {
  248. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
  249.     "filldir for . with len 1, f_pos 0x%Lx, "
  250.     "inode %lu, DT_DIR.n", filp->f_pos,
  251.     dir->i_ino);
  252. cb.ret_code = filldir(dirent, ".", 1, filp->f_pos,
  253.     dir->i_ino, DT_DIR);
  254. if (cb.ret_code)
  255. goto done;
  256. cb.pl++;
  257. filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  258. }
  259. if (cb.pl == (u32)1) {
  260. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
  261.     "filldir for .. with len 2, f_pos 0x%Lx, "
  262.     "inode %lu, DT_DIR.n", filp->f_pos,
  263.     filp->f_dentry->d_parent->d_inode->i_ino);
  264. cb.ret_code = filldir(dirent, "..", 2, filp->f_pos,
  265.     filp->f_dentry->d_parent->d_inode->i_ino,
  266.     DT_DIR);
  267. if (cb.ret_code)
  268. goto done;
  269. cb.pl++;
  270. filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  271. }
  272. } else if (cb.ph >= 0x7fff)
  273. /* End of directory. */
  274. goto done;
  275. cb.dir = dir;
  276. cb.filldir = filldir;
  277. cb.dirent = dirent;
  278. cb.type = NTFS_INO2VOL(dir)->ngt;
  279. do {
  280. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Looking for next "
  281. "file using ntfs_getdir_unsorted(), f_pos "
  282. "0x%Lx.n", (loff_t)(cb.ph << 16) | cb.pl);
  283. err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl,
  284. ntfs_printcb, &cb);
  285. } while (!err && !cb.ret_code && cb.ph < 0x7fff);
  286. filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  287. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After ntfs_getdir_unsorted()"
  288. " calls, f_pos 0x%Lx.n", filp->f_pos);
  289. if (!err) {
  290. done:
  291. #ifdef DEBUG
  292. if (!cb.ret_code)
  293. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): EOD, f_pos "
  294. "0x%Lx, returning 0.n", filp->f_pos);
  295. else 
  296. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): filldir "
  297. "returned %i, returning 0, f_pos "
  298. "0x%Lx.n", cb.ret_code, filp->f_pos);
  299. #endif
  300. return 0;
  301. }
  302. ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Returning %i, f_pos 0x%Lx.n",
  303. err, filp->f_pos);
  304. return err;
  305. }
  306. /* Copied from vfat driver. */
  307. static int simple_getbool(char *s, int *setval)
  308. {
  309. if (s) {
  310. if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))
  311. *setval = 1;
  312. else if (!strcmp(s, "0") || !strcmp(s, "no") ||
  313. !strcmp(s, "false"))
  314. *setval = 0;
  315. else
  316. return 0;
  317. } else
  318. *setval = 1;
  319. return 1;
  320. }
  321. /*
  322.  * This needs to be outside parse_options() otherwise a remount will reset
  323.  * these unintentionally.
  324.  */
  325. static void init_ntfs_super_block(ntfs_volume* vol)
  326. {
  327. vol->uid = vol->gid = 0;
  328. vol->umask = 0077;
  329. vol->ngt = ngt_nt;
  330. vol->nls_map = (void*)-1;
  331. vol->mft_zone_multiplier = -1;
  332. }
  333. /* Parse the (re)mount options. */
  334. static int parse_options(ntfs_volume *vol, char *opt)
  335. {
  336. char *value; /* Defaults if not specified and !remount. */
  337. ntfs_uid_t uid = -1; /* 0, root user only */
  338. ntfs_gid_t gid = -1; /* 0, root user only */
  339. int umask = -1; /* 0077, owner access only */
  340. unsigned int ngt = -1; /* ngt_nt */
  341. void *nls_map = NULL; /* Try to load the default NLS. */
  342. int use_utf8 = -1; /* If no NLS specified and loading the default
  343.    NLS failed use utf8. */
  344. int mft_zone_mul = -1; /* 1 */
  345. if (!opt)
  346. goto done;
  347. for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
  348. if ((value = strchr(opt, '=')) != NULL)
  349. *value ++= '';
  350. if (strcmp(opt, "uid") == 0) {
  351. if (!value || !*value)
  352. goto needs_arg;
  353. uid = simple_strtoul(value, &value, 0);
  354. if (*value) {
  355. printk(KERN_ERR "NTFS: uid invalid argumentn");
  356. return 0;
  357. }
  358. } else if (strcmp(opt, "gid") == 0) {
  359. if (!value || !*value)
  360. goto needs_arg;
  361. gid = simple_strtoul(value, &value, 0);
  362. if (*value) {
  363. printk(KERN_ERR "NTFS: gid invalid argumentn");
  364. return 0;
  365. }
  366. } else if (strcmp(opt, "umask") == 0) {
  367. if (!value || !*value)
  368. goto needs_arg;
  369. umask = simple_strtoul(value, &value, 0);
  370. if (*value) {
  371. printk(KERN_ERR "NTFS: umask invalid "
  372. "argumentn");
  373. return 0;
  374. }
  375. } else if (strcmp(opt, "mft_zone_multiplier") == 0) {
  376. unsigned long ul;
  377. if (!value || !*value)
  378. goto needs_arg;
  379. ul = simple_strtoul(value, &value, 0);
  380. if (*value) {
  381. printk(KERN_ERR "NTFS: mft_zone_multiplier "
  382. "invalid argumentn");
  383. return 0;
  384. }
  385. if (ul >= 1 && ul <= 4)
  386. mft_zone_mul = ul;
  387. else {
  388. mft_zone_mul = 1;
  389. printk(KERN_WARNING "NTFS: mft_zone_multiplier "
  390.       "out of range. Setting to 1.n");
  391. }
  392. } else if (strcmp(opt, "posix") == 0) {
  393. int val;
  394. if (!value || !*value)
  395. goto needs_arg;
  396. if (!simple_getbool(value, &val))
  397. goto needs_bool;
  398. ngt = val ? ngt_posix : ngt_nt;
  399. } else if (strcmp(opt, "show_sys_files") == 0) {
  400. int val = 0;
  401. if (!value || !*value)
  402. val = 1;
  403. else if (!simple_getbool(value, &val))
  404. goto needs_bool;
  405. ngt = val ? ngt_full : ngt_nt;
  406. } else if (strcmp(opt, "iocharset") == 0) {
  407. if (!value || !*value)
  408. goto needs_arg;
  409. nls_map = load_nls(value);
  410. if (!nls_map) {
  411. printk(KERN_ERR "NTFS: charset not found");
  412. return 0;
  413. }
  414. } else if (strcmp(opt, "utf8") == 0) {
  415. int val = 0;
  416. if (!value || !*value)
  417. val = 1;
  418. else if (!simple_getbool(value, &val))
  419. goto needs_bool;
  420. use_utf8 = val;
  421. } else {
  422. printk(KERN_ERR "NTFS: unkown option '%s'n", opt);
  423. return 0;
  424. }
  425. }
  426. done:
  427. if (use_utf8 == -1) {
  428. /* utf8 was not specified at all. */
  429. if (!nls_map) {
  430. /*
  431.  * No NLS was specified. If first mount, load the
  432.  * default NLS, otherwise don't change the NLS setting.
  433.  */
  434. if (vol->nls_map == (void*)-1)
  435. vol->nls_map = load_nls_default();
  436. } else {
  437. /* If an NLS was already loaded, unload it first. */
  438. if (vol->nls_map && vol->nls_map != (void*)-1)
  439. unload_nls(vol->nls_map);
  440. /* Use the specified NLS. */
  441. vol->nls_map = nls_map;
  442. }
  443. } else {
  444. /* utf8 was specified. */
  445. if (use_utf8 && nls_map) {
  446. unload_nls(nls_map);
  447. printk(KERN_ERR "NTFS: utf8 cannot be combined with "
  448. "iocharset.n");
  449. return 0;
  450. }
  451. /* If an NLS was already loaded, unload it first. */
  452. if (vol->nls_map && vol->nls_map != (void*)-1)
  453. unload_nls(vol->nls_map);
  454. if (!use_utf8) {
  455. /* utf8 was specified as false. */
  456. if (!nls_map)
  457. /* No NLS was specified, load the default. */
  458. vol->nls_map = load_nls_default();
  459. else
  460. /* Use the specified NLS. */
  461. vol->nls_map = nls_map;
  462. } else
  463. /* utf8 was specified as true. */
  464. vol->nls_map = NULL;
  465. }
  466. if (uid != -1)
  467. vol->uid = uid;
  468. if (gid != -1)
  469. vol->gid = gid;
  470. if (umask != -1)
  471. vol->umask = (ntmode_t)umask;
  472. if (ngt != -1)
  473. vol->ngt = ngt;
  474. if (mft_zone_mul != -1) {
  475. /* mft_zone_multiplier was specified. */
  476. if (vol->mft_zone_multiplier != -1) {
  477. /* This is a remount, ignore a change and warn user. */
  478. if (vol->mft_zone_multiplier != mft_zone_mul)
  479. printk(KERN_WARNING "NTFS: Ignoring changes in "
  480. "mft_zone_multiplier on "
  481. "remount. If you want to "
  482. "change this you need to "
  483. "umount and mount again.n");
  484. } else
  485. /* Use the specified multiplier. */
  486. vol->mft_zone_multiplier = mft_zone_mul;
  487. } else if (vol->mft_zone_multiplier == -1)
  488. /* No multiplier specified and first mount, so set default. */
  489. vol->mft_zone_multiplier = 1;
  490. return 1;
  491. needs_arg:
  492. printk(KERN_ERR "NTFS: %s needs an argument", opt);
  493. return 0;
  494. needs_bool:
  495. printk(KERN_ERR "NTFS: %s needs boolean argument", opt);
  496. return 0;
  497. }
  498. static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *d)
  499. {
  500. struct inode *res = 0;
  501. char *item = 0;
  502. ntfs_iterate_s walk;
  503. int err;
  504. ntfs_debug(DEBUG_NAME1, __FUNCTION__ "(): Looking up %s in directory "
  505. "ino 0x%x.n", d->d_name.name, (unsigned)dir->i_ino);
  506. walk.name = NULL;
  507. walk.namelen = 0;
  508. /* Convert to wide string. */
  509. err = ntfs_decodeuni(NTFS_INO2VOL(dir), (char*)d->d_name.name,
  510.        d->d_name.len, &walk.name, &walk.namelen);
  511. if (err)
  512. goto err_ret;
  513. item = ntfs_malloc(ITEM_SIZE);
  514. if (!item) {
  515. err = -ENOMEM;
  516. goto err_ret;
  517. }
  518. /* ntfs_getdir will place the directory entry into item, and the first
  519.  * long long is the MFT record number. */
  520. walk.type = BY_NAME;
  521. walk.dir = NTFS_LINO2NINO(dir);
  522. walk.result = item;
  523. if (ntfs_getdir_byname(&walk))
  524. res = iget(dir->i_sb, NTFS_GETU32(item));
  525. d_add(d, res);
  526. ntfs_free(item);
  527. ntfs_free(walk.name);
  528. /* Always return success, the dcache will handle negative entries. */
  529. return NULL;
  530. err_ret:
  531. ntfs_free(walk.name);
  532. return ERR_PTR(err);
  533. }
  534. static struct file_operations ntfs_file_operations = {
  535. llseek: generic_file_llseek,
  536. read: ntfs_read,
  537. #ifdef CONFIG_NTFS_RW
  538. write: ntfs_write,
  539. #endif
  540. open: generic_file_open,
  541. };
  542. static struct inode_operations ntfs_inode_operations;
  543. #ifdef CONFIG_NTFS_RW
  544. static int ntfs_create(struct inode* dir, struct dentry *d, int mode)
  545. {
  546. struct inode *r = 0;
  547. ntfs_inode *ino = 0;
  548. ntfs_volume *vol;
  549. int error = 0;
  550. ntfs_attribute *si;
  551. r = new_inode(dir->i_sb);
  552. if (!r) {
  553. error = -ENOMEM;
  554. goto fail;
  555. }
  556. ntfs_debug(DEBUG_OTHER, "ntfs_create %sn", d->d_name.name);
  557. vol = NTFS_INO2VOL(dir);
  558. ino = NTFS_LINO2NINO(r);
  559. error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
  560. d->d_name.len);
  561. if (error) {
  562. ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
  563. goto fail;
  564. }
  565. /* Not doing this one was causing a huge amount of corruption! Now the
  566.  * bugger bytes the dust! (-8 (AIA) */
  567. r->i_ino = ino->i_number;
  568. error = ntfs_update_inode(ino);
  569. if (error)
  570. goto fail;
  571. error = ntfs_update_inode(NTFS_LINO2NINO(dir));
  572. if (error)
  573. goto fail;
  574. r->i_uid = vol->uid;
  575. r->i_gid = vol->gid;
  576. /* FIXME: dirty? dev? */
  577. /* Get the file modification times from the standard information. */
  578. si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  579. if (si) {
  580. char *attr = si->d.data;
  581. r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  582. r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  583. r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  584. }
  585. /* It's not a directory */
  586. r->i_op = &ntfs_inode_operations;
  587. r->i_fop = &ntfs_file_operations;
  588. r->i_mode = S_IFREG | S_IRUGO;
  589. #ifdef CONFIG_NTFS_RW
  590. r->i_mode |= S_IWUGO;
  591. #endif
  592. r->i_mode &= ~vol->umask;
  593. insert_inode_hash(r);
  594. d_instantiate(d, r);
  595. return 0;
  596.  fail:
  597. if (r)
  598. iput(r);
  599. return error;
  600. }
  601. static int _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
  602. {
  603. int error;
  604. struct inode *r = 0;
  605. ntfs_volume *vol;
  606. ntfs_inode *ino;
  607. ntfs_attribute *si;
  608. ntfs_debug (DEBUG_DIR1, "mkdir %s in %xn", d->d_name.name, dir->i_ino);
  609. error = -ENAMETOOLONG;
  610. if (d->d_name.len > /* FIXME: */ 255)
  611. goto out;
  612. error = -EIO;
  613. r = new_inode(dir->i_sb);
  614. if (!r)
  615. goto out;
  616. vol = NTFS_INO2VOL(dir);
  617. ino = NTFS_LINO2NINO(r);
  618. error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len,
  619.    ino);
  620. if (error)
  621. goto out;
  622. /* Not doing this one was causing a huge amount of corruption! Now the
  623.  * bugger bytes the dust! (-8 (AIA) */
  624. r->i_ino = ino->i_number;
  625. r->i_uid = vol->uid;
  626. r->i_gid = vol->gid;
  627. si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  628. if (si) {
  629. char *attr = si->d.data;
  630. r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  631. r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  632. r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  633. }
  634. /* It's a directory. */
  635. r->i_op = &ntfs_dir_inode_operations;
  636. r->i_fop = &ntfs_dir_operations;
  637. r->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
  638. #ifdef CONFIG_NTFS_RW
  639. r->i_mode |= S_IWUGO;
  640. #endif
  641. r->i_mode &= ~vol->umask;
  642. insert_inode_hash(r);
  643. d_instantiate(d, r);
  644. error = 0;
  645.  out:
  646.   ntfs_debug (DEBUG_DIR1, "mkdir returns %dn", error);
  647. return error;
  648. }
  649. #endif
  650. static struct file_operations ntfs_dir_operations = {
  651. read: generic_read_dir,
  652. readdir: ntfs_readdir,
  653. };
  654. static struct inode_operations ntfs_dir_inode_operations = {
  655. lookup: ntfs_lookup,
  656. #ifdef CONFIG_NTFS_RW
  657. create: ntfs_create,
  658. mkdir: _linux_ntfs_mkdir,
  659. #endif
  660. };
  661. /* ntfs_read_inode() is called by the Virtual File System (the kernel layer 
  662.  * that deals with filesystems) when iget is called requesting an inode not
  663.  * already present in the inode table. Typically filesystems have separate
  664.  * inode_operations for directories, files and symlinks. */
  665. static void ntfs_read_inode(struct inode* inode)
  666. {
  667. ntfs_volume *vol;
  668. ntfs_inode *ino;
  669. ntfs_attribute *data;
  670. ntfs_attribute *si;
  671. vol = NTFS_INO2VOL(inode);
  672. inode->i_mode = 0;
  673. ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%lxn", inode->i_ino);
  674. switch (inode->i_ino) {
  675. /* Those are loaded special files. */
  676. case FILE_Mft:
  677. if (!vol->mft_ino || ((vol->ino_flags & 1) == 0))
  678. goto sys_file_error;
  679. ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode));
  680. ino = vol->mft_ino;
  681. vol->mft_ino = &inode->u.ntfs_i;
  682. vol->ino_flags &= ~1;
  683. ntfs_free(ino);
  684. ino = vol->mft_ino;
  685. ntfs_debug(DEBUG_OTHER, "Opening $MFT!n");
  686. break;
  687. case FILE_MftMirr:
  688. if (!vol->mftmirr || ((vol->ino_flags & 2) == 0))
  689. goto sys_file_error;
  690. ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode));
  691. ino = vol->mftmirr;
  692. vol->mftmirr = &inode->u.ntfs_i;
  693. vol->ino_flags &= ~2;
  694. ntfs_free(ino);
  695. ino = vol->mftmirr;
  696. ntfs_debug(DEBUG_OTHER, "Opening $MFTMirr!n");
  697. break;
  698. case FILE_BitMap:
  699. if (!vol->bitmap || ((vol->ino_flags & 4) == 0))
  700. goto sys_file_error;
  701. ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode));
  702. ino = vol->bitmap;
  703. vol->bitmap = &inode->u.ntfs_i;
  704. vol->ino_flags &= ~4;
  705. ntfs_free(ino);
  706. ino = vol->bitmap;
  707. ntfs_debug(DEBUG_OTHER, "Opening $Bitmap!n");
  708. break;
  709. case FILE_LogFile ... FILE_AttrDef:
  710. /* No need to log root directory accesses. */
  711. case FILE_Boot ... FILE_UpCase:
  712. ntfs_debug(DEBUG_OTHER, "Opening system file %i!n",
  713. inode->i_ino);
  714. default:
  715. ino = &inode->u.ntfs_i;
  716. if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),
  717. inode->i_ino))
  718. {
  719. ntfs_debug(DEBUG_OTHER, "NTFS: Error loading inode "
  720. "0x%xn", (unsigned int)inode->i_ino);
  721. return;
  722. }
  723. }
  724. /* Set uid/gid from mount options */
  725. inode->i_uid = vol->uid;
  726. inode->i_gid = vol->gid;
  727. inode->i_nlink = 1;
  728. /* Use the size of the data attribute as file size */
  729. data = ntfs_find_attr(ino, vol->at_data, NULL);
  730. if (!data)
  731. inode->i_size = 0;
  732. else
  733. inode->i_size = data->size;
  734. /* Get the file modification times from the standard information. */
  735. si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  736. if (si) {
  737. char *attr = si->d.data;
  738. inode->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  739. inode->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  740. inode->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  741. }
  742. /* If it has an index root, it's a directory. */
  743. if (ntfs_find_attr(ino, vol->at_index_root, "$I30")) {
  744. ntfs_attribute *at;
  745. at = ntfs_find_attr(ino, vol->at_index_allocation, "$I30");
  746. inode->i_size = at ? at->size : 0;
  747. inode->i_op = &ntfs_dir_inode_operations;
  748. inode->i_fop = &ntfs_dir_operations;
  749. inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
  750. } else {
  751. inode->i_op = &ntfs_inode_operations;
  752. inode->i_fop = &ntfs_file_operations;
  753. inode->i_mode = S_IFREG | S_IRUGO;
  754. }
  755. #ifdef CONFIG_NTFS_RW
  756. if (!data || !(data->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)))
  757. inode->i_mode |= S_IWUGO;
  758. #endif
  759. inode->i_mode &= ~vol->umask;
  760. return;
  761. sys_file_error:
  762. ntfs_error("Critical error. Tried to call ntfs_read_inode() before we "
  763. "have completed read_super() or VFS error.n");
  764. // FIXME: Should we panic() at this stage?
  765. }
  766. #ifdef CONFIG_NTFS_RW
  767. static void ntfs_write_inode(struct inode *ino, int unused)
  768. {
  769. lock_kernel();
  770. ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%xn", ino->i_ino);
  771. ntfs_update_inode(NTFS_LINO2NINO(ino));
  772. unlock_kernel();
  773. }
  774. #endif
  775. static void _ntfs_clear_inode(struct inode *inode)
  776. {
  777. ntfs_inode *ino;
  778. ntfs_volume *vol;
  779. lock_kernel();
  780. ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%xn", inode->i_ino);
  781. vol = NTFS_INO2VOL(inode);
  782. if (!vol)
  783. ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is "
  784. "NULL.n");
  785. switch (inode->i_ino) {
  786. case FILE_Mft:
  787. if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
  788. ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  789. ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  790. vol->mft_ino = ino;
  791. vol->ino_flags |= 1;
  792. goto unl_out;
  793. }
  794. break;
  795. case FILE_MftMirr:
  796. if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
  797. ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  798. ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  799. vol->mftmirr = ino;
  800. vol->ino_flags |= 2;
  801. goto unl_out;
  802. }
  803. break;
  804. case FILE_BitMap:
  805. if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
  806. ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  807. ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  808. vol->bitmap = ino;
  809. vol->ino_flags |= 4;
  810. goto unl_out;
  811. }
  812. break;
  813. default:
  814. /* Nothing. Just clear the inode and exit. */
  815. }
  816. ntfs_clear_inode(&inode->u.ntfs_i);
  817. unl_out:
  818. unlock_kernel();
  819. return;
  820. }
  821. /* Called when umounting a filesystem by do_umount() in fs/super.c. */
  822. static void ntfs_put_super(struct super_block *sb)
  823. {
  824. ntfs_volume *vol;
  825. ntfs_debug(DEBUG_OTHER, "ntfs_put_supern");
  826. vol = NTFS_SB2VOL(sb);
  827. ntfs_release_volume(vol);
  828. if (vol->nls_map)
  829. unload_nls(vol->nls_map);
  830. ntfs_debug(DEBUG_OTHER, "ntfs_put_super: donen");
  831. }
  832. /* Called by the kernel when asking for stats. */
  833. static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
  834. {
  835. struct inode *mft;
  836. ntfs_volume *vol;
  837. __s64 size;
  838. int error;
  839. ntfs_debug(DEBUG_OTHER, "ntfs_statfsn");
  840. vol = NTFS_SB2VOL(sb);
  841. sf->f_type = NTFS_SUPER_MAGIC;
  842. sf->f_bsize = vol->cluster_size;
  843. error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size);
  844. if (error)
  845. return error;
  846. sf->f_blocks = size; /* Volumesize is in clusters. */
  847. size = (__s64)ntfs_get_free_cluster_count(vol->bitmap);
  848. /* Just say zero if the call failed. */
  849. if (size < 0LL)
  850. size = 0;
  851. sf->f_bfree = sf->f_bavail = size;
  852. ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, "
  853. "FILE_Mft)n");
  854. mft = iget(sb, FILE_Mft);
  855. ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_Mft) returned "
  856. "0x%xn", mft);
  857. if (!mft)
  858. return -EIO;
  859. sf->f_files = mft->i_size >> vol->mft_record_size_bits;
  860. ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)n");
  861. iput(mft);
  862. /* Should be read from volume. */
  863. sf->f_namelen = 255;
  864. return 0;
  865. }
  866. /* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */
  867. static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
  868. {
  869. if (!parse_options(NTFS_SB2VOL(sb), options))
  870. return -EINVAL;
  871. return 0;
  872. }
  873. /* Define the super block operation that are implemented */
  874. static struct super_operations ntfs_super_operations = {
  875. read_inode: ntfs_read_inode,
  876. #ifdef CONFIG_NTFS_RW
  877. write_inode: ntfs_write_inode,
  878. #endif
  879. put_super: ntfs_put_super,
  880. statfs: ntfs_statfs,
  881. remount_fs: ntfs_remount_fs,
  882. clear_inode: _ntfs_clear_inode,
  883. };
  884. /**
  885.  * is_boot_sector_ntfs - check an NTFS boot sector for validity
  886.  * @b: buffer containing bootsector to check
  887.  * 
  888.  * Check whether @b contains a valid NTFS boot sector.
  889.  * Return 1 if @b is a valid NTFS bootsector or 0 if not.
  890.  */
  891. static int is_boot_sector_ntfs(ntfs_u8 *b)
  892. {
  893. ntfs_u32 i;
  894. /* FIXME: We don't use checksumming yet as NT4(SP6a) doesn't either...
  895.  * But we might as well have the code ready to do it. (AIA) */
  896. #if 0
  897. /* Calculate the checksum. */
  898. if (b < b + 0x50) {
  899. ntfs_u32 *u;
  900. ntfs_u32 *bi = (ntfs_u32 *)(b + 0x50);
  901. for (u = bi, i = 0; u < bi; ++u)
  902. i += NTFS_GETU32(*u);
  903. }
  904. #endif
  905. /* Check magic is "NTFS    " */
  906. if (b[3] != 0x4e) goto not_ntfs;
  907. if (b[4] != 0x54) goto not_ntfs;
  908. if (b[5] != 0x46) goto not_ntfs;
  909. if (b[6] != 0x53) goto not_ntfs;
  910. for (i = 7; i < 0xb; ++i)
  911. if (b[i] != 0x20) goto not_ntfs;
  912. /* Check bytes per sector value is between 512 and 4096. */
  913. if (b[0xb] != 0) goto not_ntfs;
  914. if (b[0xc] > 0x10) goto not_ntfs;
  915. /* Check sectors per cluster value is valid. */
  916. switch (b[0xd]) {
  917. case 1: case 2: case 4: case 8: case 16:
  918. case 32: case 64: case 128:
  919. break;
  920. default:
  921. goto not_ntfs;
  922. }
  923. /* Check reserved sectors value and four other fields are zero. */
  924. for (i = 0xe; i < 0x15; ++i) 
  925. if (b[i] != 0) goto not_ntfs;
  926. if (b[0x16] != 0) goto not_ntfs;
  927. if (b[0x17] != 0) goto not_ntfs;
  928. for (i = 0x20; i < 0x24; ++i)
  929. if (b[i] != 0) goto not_ntfs;
  930. /* Check clusters per file record segment value is valid. */
  931. if (b[0x40] < 0xe1 || b[0x40] > 0xf7) {
  932. switch (b[0x40]) {
  933. case 1: case 2: case 4: case 8: case 16: case 32: case 64:
  934. break;
  935. default:
  936. goto not_ntfs;
  937. }
  938. }
  939. /* Check clusters per index block value is valid. */
  940. if (b[0x44] < 0xe1 || b[0x44] > 0xf7) {
  941. switch (b[0x44]) {
  942. case 1: case 2: case 4: case 8: case 16: case 32: case 64:
  943. break;
  944. default:
  945. goto not_ntfs;
  946. }
  947. }
  948. return 1;
  949. not_ntfs:
  950. return 0;
  951. }
  952. /* Called to mount a filesystem by read_super() in fs/super.c.
  953.  * Return a super block, the main structure of a filesystem.
  954.  *
  955.  * NOTE : Don't store a pointer to an option, as the page containing the
  956.  * options is freed after ntfs_read_super() returns.
  957.  *
  958.  * NOTE : A context switch can happen in kernel code only if the code blocks
  959.  * (= calls schedule() in kernel/sched.c). */
  960. struct super_block *ntfs_read_super(struct super_block *sb, void *options,
  961. int silent)
  962. {
  963. ntfs_volume *vol;
  964. struct buffer_head *bh;
  965. int i, to_read, blocksize;
  966. ntfs_debug(DEBUG_OTHER, "ntfs_read_supern");
  967. vol = NTFS_SB2VOL(sb);
  968. init_ntfs_super_block(vol);
  969. if (!parse_options(vol, (char*)options))
  970. goto ntfs_read_super_vol;
  971. blocksize = get_hardsect_size(sb->s_dev);
  972. if (blocksize < 512)
  973. blocksize = 512;
  974. if (set_blocksize(sb->s_dev, blocksize) < 0) {
  975. ntfs_error("Unable to set blocksize %d.n", blocksize);
  976. goto ntfs_read_super_vol;
  977. }
  978. sb->s_blocksize = blocksize;
  979. /* Read the super block (boot block). */
  980. if (!(bh = sb_bread(sb, 0))) {
  981. ntfs_error("Reading super block failedn");
  982. goto ntfs_read_super_unl;
  983. }
  984. ntfs_debug(DEBUG_OTHER, "Done reading boot blockn");
  985. /* Check for valid 'NTFS' boot sector. */
  986. if (!is_boot_sector_ntfs(bh->b_data)) {
  987. ntfs_debug(DEBUG_OTHER, "Not a NTFS volumen");
  988. bforget(bh);
  989. goto ntfs_read_super_unl;
  990. }
  991. ntfs_debug(DEBUG_OTHER, "Going to init volumen");
  992. if (ntfs_init_volume(vol, bh->b_data) < 0) {
  993. ntfs_debug(DEBUG_OTHER, "Init volume failed.n");
  994. bforget(bh);
  995. goto ntfs_read_super_unl;
  996. }
  997. ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lxn", vol->mft_lcn);
  998. brelse(bh);
  999. NTFS_SB(vol) = sb;
  1000. if (vol->cluster_size > PAGE_SIZE) {
  1001. ntfs_error("Partition cluster size is not supported yet (it "
  1002.    "is > max kernel blocksize).n");
  1003. goto ntfs_read_super_unl;
  1004. }
  1005. ntfs_debug(DEBUG_OTHER, "Done to init volumen");
  1006. /* Inform the kernel that a device block is a NTFS cluster. */
  1007. sb->s_blocksize = vol->cluster_size;
  1008. sb->s_blocksize_bits = vol->cluster_size_bits;
  1009. if (blocksize != vol->cluster_size &&
  1010. set_blocksize(sb->s_dev, sb->s_blocksize) < 0) {
  1011. ntfs_error("Cluster size too small for device.n");
  1012. goto ntfs_read_super_unl;
  1013. }
  1014. ntfs_debug(DEBUG_OTHER, "set_blocksizen");
  1015. /* Allocate an MFT record (MFT record can be smaller than a cluster). */
  1016. i = vol->cluster_size;
  1017. if (i < vol->mft_record_size)
  1018. i = vol->mft_record_size;
  1019. if (!(vol->mft = ntfs_malloc(i)))
  1020. goto ntfs_read_super_unl;
  1021. /* Read at least the MFT record for $Mft. */
  1022. to_read = vol->mft_clusters_per_record;
  1023. if (to_read < 1)
  1024. to_read = 1;
  1025. for (i = 0; i < to_read; i++) {
  1026. if (!(bh = sb_bread(sb, vol->mft_lcn + i))) {
  1027. ntfs_error("Could not read $Mft record 0n");
  1028. goto ntfs_read_super_mft;
  1029. }
  1030. ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits),
  1031. bh->b_data, vol->cluster_size);
  1032. brelse(bh);
  1033. ntfs_debug(DEBUG_OTHER, "Read cluster 0x%xn",
  1034.  vol->mft_lcn + i);
  1035. }
  1036. /* Check and fixup this MFT record */
  1037. if (!ntfs_check_mft_record(vol, vol->mft)){
  1038. ntfs_error("Invalid $Mft record 0n");
  1039. goto ntfs_read_super_mft;
  1040. }
  1041. /* Inform the kernel about which super operations are available. */
  1042. sb->s_op = &ntfs_super_operations;
  1043. sb->s_magic = NTFS_SUPER_MAGIC;
  1044. sb->s_maxbytes = MAX_LFS_FILESIZE;
  1045. ntfs_debug(DEBUG_OTHER, "Reading special filesn");
  1046. if (ntfs_load_special_files(vol)) {
  1047. ntfs_error("Error loading special filesn");
  1048. goto ntfs_read_super_mft;
  1049. }
  1050. ntfs_debug(DEBUG_OTHER, "Getting RootDirn");
  1051. /* Get the root directory. */
  1052. if (!(sb->s_root = d_alloc_root(iget(sb, FILE_root)))) {
  1053. ntfs_error("Could not get root dir inoden");
  1054. goto ntfs_read_super_mft;
  1055. }
  1056. ntfs_read_super_ret:
  1057. ntfs_debug(DEBUG_OTHER, "read_super: donen");
  1058. return sb;
  1059. ntfs_read_super_mft:
  1060. ntfs_free(vol->mft);
  1061. ntfs_read_super_unl:
  1062. ntfs_read_super_vol:
  1063. sb = NULL;
  1064. goto ntfs_read_super_ret;
  1065. }
  1066. /* Define the filesystem */
  1067. static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
  1068. static int __init init_ntfs_fs(void)
  1069. {
  1070. /* Comment this if you trust klogd. There are reasons not to trust it */
  1071. #if defined(DEBUG) && !defined(MODULE)
  1072. console_verbose();
  1073. #endif
  1074. printk(KERN_NOTICE "NTFS driver v" NTFS_VERSION " [Flags: R/"
  1075. #ifdef CONFIG_NTFS_RW
  1076. "W"
  1077. #else
  1078. "O"
  1079. #endif
  1080. #ifdef DEBUG
  1081. " DEBUG"
  1082. #endif
  1083. #ifdef MODULE
  1084. " MODULE"
  1085. #endif
  1086. "]n");
  1087. SYSCTL(1);
  1088. ntfs_debug(DEBUG_OTHER, "registering %sn", ntfs_fs_type.name);
  1089. /* Add this filesystem to the kernel table of filesystems. */
  1090. return register_filesystem(&ntfs_fs_type);
  1091. }
  1092. static void __exit exit_ntfs_fs(void)
  1093. {
  1094. SYSCTL(0);
  1095. ntfs_debug(DEBUG_OTHER, "unregistering %sn", ntfs_fs_type.name);
  1096. unregister_filesystem(&ntfs_fs_type);
  1097. }
  1098. EXPORT_NO_SYMBOLS;
  1099. /*
  1100.  * Not strictly true. The driver was written originally by Martin von L鰓is.
  1101.  * I am just maintaining and rewriting it.
  1102.  */
  1103. MODULE_AUTHOR("Anton Altaparmakov <aia21@cus.cam.ac.uk>");
  1104. MODULE_DESCRIPTION("Linux NTFS driver");
  1105. MODULE_LICENSE("GPL");
  1106. #ifdef DEBUG
  1107. MODULE_PARM(ntdebug, "i");
  1108. MODULE_PARM_DESC(ntdebug, "Debug level");
  1109. #endif
  1110. module_init(init_ntfs_fs)
  1111. module_exit(exit_ntfs_fs)