dir.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. /*
  2. * dir.c
  3. *
  4. * Copyright (C) 1995, 1996 by Volker Lendecke
  5. * Modified for big endian by J.F. Chadima and David S. Miller
  6. * Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
  7. * Modified 1998, 1999 Wolfram Pienkoss for NLS
  8. * Modified 1999 Wolfram Pienkoss for directory caching
  9. * Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
  10. *
  11. */
  12. #include <linux/config.h>
  13. #include <linux/time.h>
  14. #include <linux/errno.h>
  15. #include <linux/stat.h>
  16. #include <linux/kernel.h>
  17. #include <linux/slab.h>
  18. #include <linux/vmalloc.h>
  19. #include <linux/mm.h>
  20. #include <asm/uaccess.h>
  21. #include <asm/byteorder.h>
  22. #include <linux/smp_lock.h>
  23. #include <linux/ncp_fs.h>
  24. #include "ncplib_kernel.h"
  25. static void ncp_read_volume_list(struct file *, void *, filldir_t,
  26. struct ncp_cache_control *);
  27. static void ncp_do_readdir(struct file *, void *, filldir_t,
  28. struct ncp_cache_control *);
  29. static int ncp_readdir(struct file *, void *, filldir_t);
  30. static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
  31. static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
  32. static int ncp_unlink(struct inode *, struct dentry *);
  33. static int ncp_mkdir(struct inode *, struct dentry *, int);
  34. static int ncp_rmdir(struct inode *, struct dentry *);
  35. static int ncp_rename(struct inode *, struct dentry *,
  36. struct inode *, struct dentry *);
  37. static int ncp_mknod(struct inode * dir, struct dentry *dentry,
  38. int mode, dev_t rdev);
  39. #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
  40. extern int ncp_symlink(struct inode *, struct dentry *, const char *);
  41. #else
  42. #define ncp_symlink NULL
  43. #endif
  44. struct file_operations ncp_dir_operations =
  45. {
  46. .read = generic_read_dir,
  47. .readdir = ncp_readdir,
  48. .ioctl = ncp_ioctl,
  49. };
  50. struct inode_operations ncp_dir_inode_operations =
  51. {
  52. .create = ncp_create,
  53. .lookup = ncp_lookup,
  54. .unlink = ncp_unlink,
  55. .symlink = ncp_symlink,
  56. .mkdir = ncp_mkdir,
  57. .rmdir = ncp_rmdir,
  58. .mknod = ncp_mknod,
  59. .rename = ncp_rename,
  60. .setattr = ncp_notify_change,
  61. };
  62. /*
  63. * Dentry operations routines
  64. */
  65. static int ncp_lookup_validate(struct dentry *, struct nameidata *);
  66. static int ncp_hash_dentry(struct dentry *, struct qstr *);
  67. static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
  68. static int ncp_delete_dentry(struct dentry *);
  69. static struct dentry_operations ncp_dentry_operations =
  70. {
  71. .d_revalidate = ncp_lookup_validate,
  72. .d_hash = ncp_hash_dentry,
  73. .d_compare = ncp_compare_dentry,
  74. .d_delete = ncp_delete_dentry,
  75. };
  76. struct dentry_operations ncp_root_dentry_operations =
  77. {
  78. .d_hash = ncp_hash_dentry,
  79. .d_compare = ncp_compare_dentry,
  80. .d_delete = ncp_delete_dentry,
  81. };
  82. /*
  83. * Note: leave the hash unchanged if the directory
  84. * is case-sensitive.
  85. */
  86. static int
  87. ncp_hash_dentry(struct dentry *dentry, struct qstr *this)
  88. {
  89. struct nls_table *t;
  90. unsigned long hash;
  91. int i;
  92. t = NCP_IO_TABLE(dentry);
  93. if (!ncp_case_sensitive(dentry->d_inode)) {
  94. hash = init_name_hash();
  95. for (i=0; i<this->len ; i++)
  96. hash = partial_name_hash(ncp_tolower(t, this->name[i]),
  97. hash);
  98. this->hash = end_name_hash(hash);
  99. }
  100. return 0;
  101. }
  102. static int
  103. ncp_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b)
  104. {
  105. if (a->len != b->len)
  106. return 1;
  107. if (ncp_case_sensitive(dentry->d_inode))
  108. return strncmp(a->name, b->name, a->len);
  109. return ncp_strnicmp(NCP_IO_TABLE(dentry), a->name, b->name, a->len);
  110. }
  111. /*
  112. * This is the callback from dput() when d_count is going to 0.
  113. * We use this to unhash dentries with bad inodes.
  114. * Closing files can be safely postponed until iput() - it's done there anyway.
  115. */
  116. static int
  117. ncp_delete_dentry(struct dentry * dentry)
  118. {
  119. struct inode *inode = dentry->d_inode;
  120. if (inode) {
  121. if (is_bad_inode(inode))
  122. return 1;
  123. } else
  124. {
  125. /* N.B. Unhash negative dentries? */
  126. }
  127. return 0;
  128. }
  129. static inline int
  130. ncp_single_volume(struct ncp_server *server)
  131. {
  132. return (server->m.mounted_vol[0] != '\0');
  133. }
  134. static inline int ncp_is_server_root(struct inode *inode)
  135. {
  136. return (!ncp_single_volume(NCP_SERVER(inode)) &&
  137. inode == inode->i_sb->s_root->d_inode);
  138. }
  139. /*
  140. * This is the callback when the dcache has a lookup hit.
  141. */
  142. #ifdef CONFIG_NCPFS_STRONG
  143. /* try to delete a readonly file (NW R bit set) */
  144. static int
  145. ncp_force_unlink(struct inode *dir, struct dentry* dentry)
  146. {
  147. int res=0x9c,res2;
  148. struct nw_modify_dos_info info;
  149. __le32 old_nwattr;
  150. struct inode *inode;
  151. memset(&info, 0, sizeof(info));
  152. /* remove the Read-Only flag on the NW server */
  153. inode = dentry->d_inode;
  154. old_nwattr = NCP_FINFO(inode)->nwattr;
  155. info.attributes = old_nwattr & ~(aRONLY|aDELETEINHIBIT|aRENAMEINHIBIT);
  156. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
  157. if (res2)
  158. goto leave_me;
  159. /* now try again the delete operation */
  160. res = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
  161. if (res) /* delete failed, set R bit again */
  162. {
  163. info.attributes = old_nwattr;
  164. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(inode), inode, NULL, DM_ATTRIBUTES, &info);
  165. if (res2)
  166. goto leave_me;
  167. }
  168. leave_me:
  169. return(res);
  170. }
  171. #endif /* CONFIG_NCPFS_STRONG */
  172. #ifdef CONFIG_NCPFS_STRONG
  173. static int
  174. ncp_force_rename(struct inode *old_dir, struct dentry* old_dentry, char *_old_name,
  175. struct inode *new_dir, struct dentry* new_dentry, char *_new_name)
  176. {
  177. struct nw_modify_dos_info info;
  178. int res=0x90,res2;
  179. struct inode *old_inode = old_dentry->d_inode;
  180. __le32 old_nwattr = NCP_FINFO(old_inode)->nwattr;
  181. __le32 new_nwattr = 0; /* shut compiler warning */
  182. int old_nwattr_changed = 0;
  183. int new_nwattr_changed = 0;
  184. memset(&info, 0, sizeof(info));
  185. /* remove the Read-Only flag on the NW server */
  186. info.attributes = old_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  187. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
  188. if (!res2)
  189. old_nwattr_changed = 1;
  190. if (new_dentry && new_dentry->d_inode) {
  191. new_nwattr = NCP_FINFO(new_dentry->d_inode)->nwattr;
  192. info.attributes = new_nwattr & ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
  193. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
  194. if (!res2)
  195. new_nwattr_changed = 1;
  196. }
  197. /* now try again the rename operation */
  198. /* but only if something really happened */
  199. if (new_nwattr_changed || old_nwattr_changed) {
  200. res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
  201. old_dir, _old_name,
  202. new_dir, _new_name);
  203. }
  204. if (res)
  205. goto leave_me;
  206. /* file was successfully renamed, so:
  207. do not set attributes on old file - it no longer exists
  208. copy attributes from old file to new */
  209. new_nwattr_changed = old_nwattr_changed;
  210. new_nwattr = old_nwattr;
  211. old_nwattr_changed = 0;
  212. leave_me:;
  213. if (old_nwattr_changed) {
  214. info.attributes = old_nwattr;
  215. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(old_inode), old_inode, NULL, DM_ATTRIBUTES, &info);
  216. /* ignore errors */
  217. }
  218. if (new_nwattr_changed) {
  219. info.attributes = new_nwattr;
  220. res2 = ncp_modify_file_or_subdir_dos_info_path(NCP_SERVER(new_dir), new_dir, _new_name, DM_ATTRIBUTES, &info);
  221. /* ignore errors */
  222. }
  223. return(res);
  224. }
  225. #endif /* CONFIG_NCPFS_STRONG */
  226. static int
  227. __ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
  228. {
  229. struct ncp_server *server;
  230. struct dentry *parent;
  231. struct inode *dir;
  232. struct ncp_entry_info finfo;
  233. int res, val = 0, len;
  234. __u8 __name[NCP_MAXPATHLEN + 1];
  235. parent = dget_parent(dentry);
  236. dir = parent->d_inode;
  237. if (!dentry->d_inode)
  238. goto finished;
  239. server = NCP_SERVER(dir);
  240. if (!ncp_conn_valid(server))
  241. goto finished;
  242. /*
  243. * Inspired by smbfs:
  244. * The default validation is based on dentry age:
  245. * We set the max age at mount time. (But each
  246. * successful server lookup renews the timestamp.)
  247. */
  248. val = NCP_TEST_AGE(server, dentry);
  249. if (val)
  250. goto finished;
  251. DDPRINTK("ncp_lookup_validate: %s/%s not valid, age=%ld, server lookup\n",
  252. dentry->d_parent->d_name.name, dentry->d_name.name,
  253. NCP_GET_AGE(dentry));
  254. len = sizeof(__name);
  255. if (ncp_is_server_root(dir)) {
  256. res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  257. dentry->d_name.len, 1);
  258. if (!res)
  259. res = ncp_lookup_volume(server, __name, &(finfo.i));
  260. } else {
  261. res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  262. dentry->d_name.len, !ncp_preserve_case(dir));
  263. if (!res)
  264. res = ncp_obtain_info(server, dir, __name, &(finfo.i));
  265. }
  266. finfo.volume = finfo.i.volNumber;
  267. DDPRINTK("ncp_lookup_validate: looked for %s/%s, res=%d\n",
  268. dentry->d_parent->d_name.name, __name, res);
  269. /*
  270. * If we didn't find it, or if it has a different dirEntNum to
  271. * what we remember, it's not valid any more.
  272. */
  273. if (!res) {
  274. if (finfo.i.dirEntNum == NCP_FINFO(dentry->d_inode)->dirEntNum) {
  275. ncp_new_dentry(dentry);
  276. val=1;
  277. } else
  278. DDPRINTK("ncp_lookup_validate: found, but dirEntNum changed\n");
  279. ncp_update_inode2(dentry->d_inode, &finfo);
  280. }
  281. finished:
  282. DDPRINTK("ncp_lookup_validate: result=%d\n", val);
  283. dput(parent);
  284. return val;
  285. }
  286. static int
  287. ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
  288. {
  289. int res;
  290. lock_kernel();
  291. res = __ncp_lookup_validate(dentry, nd);
  292. unlock_kernel();
  293. return res;
  294. }
  295. static struct dentry *
  296. ncp_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
  297. {
  298. struct dentry *dent = dentry;
  299. struct list_head *next;
  300. if (d_validate(dent, parent)) {
  301. if (dent->d_name.len <= NCP_MAXPATHLEN &&
  302. (unsigned long)dent->d_fsdata == fpos) {
  303. if (!dent->d_inode) {
  304. dput(dent);
  305. dent = NULL;
  306. }
  307. return dent;
  308. }
  309. dput(dent);
  310. }
  311. /* If a pointer is invalid, we search the dentry. */
  312. spin_lock(&dcache_lock);
  313. next = parent->d_subdirs.next;
  314. while (next != &parent->d_subdirs) {
  315. dent = list_entry(next, struct dentry, d_child);
  316. if ((unsigned long)dent->d_fsdata == fpos) {
  317. if (dent->d_inode)
  318. dget_locked(dent);
  319. else
  320. dent = NULL;
  321. spin_unlock(&dcache_lock);
  322. goto out;
  323. }
  324. next = next->next;
  325. }
  326. spin_unlock(&dcache_lock);
  327. return NULL;
  328. out:
  329. return dent;
  330. }
  331. static time_t ncp_obtain_mtime(struct dentry *dentry)
  332. {
  333. struct inode *inode = dentry->d_inode;
  334. struct ncp_server *server = NCP_SERVER(inode);
  335. struct nw_info_struct i;
  336. if (!ncp_conn_valid(server) || ncp_is_server_root(inode))
  337. return 0;
  338. if (ncp_obtain_info(server, inode, NULL, &i))
  339. return 0;
  340. return ncp_date_dos2unix(i.modifyTime, i.modifyDate);
  341. }
  342. static int ncp_readdir(struct file *filp, void *dirent, filldir_t filldir)
  343. {
  344. struct dentry *dentry = filp->f_dentry;
  345. struct inode *inode = dentry->d_inode;
  346. struct page *page = NULL;
  347. struct ncp_server *server = NCP_SERVER(inode);
  348. union ncp_dir_cache *cache = NULL;
  349. struct ncp_cache_control ctl;
  350. int result, mtime_valid = 0;
  351. time_t mtime = 0;
  352. lock_kernel();
  353. ctl.page = NULL;
  354. ctl.cache = NULL;
  355. DDPRINTK("ncp_readdir: reading %s/%s, pos=%d\n",
  356. dentry->d_parent->d_name.name, dentry->d_name.name,
  357. (int) filp->f_pos);
  358. result = -EIO;
  359. if (!ncp_conn_valid(server))
  360. goto out;
  361. result = 0;
  362. if (filp->f_pos == 0) {
  363. if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR))
  364. goto out;
  365. filp->f_pos = 1;
  366. }
  367. if (filp->f_pos == 1) {
  368. if (filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR))
  369. goto out;
  370. filp->f_pos = 2;
  371. }
  372. page = grab_cache_page(&inode->i_data, 0);
  373. if (!page)
  374. goto read_really;
  375. ctl.cache = cache = kmap(page);
  376. ctl.head = cache->head;
  377. if (!PageUptodate(page) || !ctl.head.eof)
  378. goto init_cache;
  379. if (filp->f_pos == 2) {
  380. if (jiffies - ctl.head.time >= NCP_MAX_AGE(server))
  381. goto init_cache;
  382. mtime = ncp_obtain_mtime(dentry);
  383. mtime_valid = 1;
  384. if ((!mtime) || (mtime != ctl.head.mtime))
  385. goto init_cache;
  386. }
  387. if (filp->f_pos > ctl.head.end)
  388. goto finished;
  389. ctl.fpos = filp->f_pos + (NCP_DIRCACHE_START - 2);
  390. ctl.ofs = ctl.fpos / NCP_DIRCACHE_SIZE;
  391. ctl.idx = ctl.fpos % NCP_DIRCACHE_SIZE;
  392. for (;;) {
  393. if (ctl.ofs != 0) {
  394. ctl.page = find_lock_page(&inode->i_data, ctl.ofs);
  395. if (!ctl.page)
  396. goto invalid_cache;
  397. ctl.cache = kmap(ctl.page);
  398. if (!PageUptodate(ctl.page))
  399. goto invalid_cache;
  400. }
  401. while (ctl.idx < NCP_DIRCACHE_SIZE) {
  402. struct dentry *dent;
  403. int res;
  404. dent = ncp_dget_fpos(ctl.cache->dentry[ctl.idx],
  405. dentry, filp->f_pos);
  406. if (!dent)
  407. goto invalid_cache;
  408. res = filldir(dirent, dent->d_name.name,
  409. dent->d_name.len, filp->f_pos,
  410. dent->d_inode->i_ino, DT_UNKNOWN);
  411. dput(dent);
  412. if (res)
  413. goto finished;
  414. filp->f_pos += 1;
  415. ctl.idx += 1;
  416. if (filp->f_pos > ctl.head.end)
  417. goto finished;
  418. }
  419. if (ctl.page) {
  420. kunmap(ctl.page);
  421. SetPageUptodate(ctl.page);
  422. unlock_page(ctl.page);
  423. page_cache_release(ctl.page);
  424. ctl.page = NULL;
  425. }
  426. ctl.idx = 0;
  427. ctl.ofs += 1;
  428. }
  429. invalid_cache:
  430. if (ctl.page) {
  431. kunmap(ctl.page);
  432. unlock_page(ctl.page);
  433. page_cache_release(ctl.page);
  434. ctl.page = NULL;
  435. }
  436. ctl.cache = cache;
  437. init_cache:
  438. ncp_invalidate_dircache_entries(dentry);
  439. if (!mtime_valid) {
  440. mtime = ncp_obtain_mtime(dentry);
  441. mtime_valid = 1;
  442. }
  443. ctl.head.mtime = mtime;
  444. ctl.head.time = jiffies;
  445. ctl.head.eof = 0;
  446. ctl.fpos = 2;
  447. ctl.ofs = 0;
  448. ctl.idx = NCP_DIRCACHE_START;
  449. ctl.filled = 0;
  450. ctl.valid = 1;
  451. read_really:
  452. if (ncp_is_server_root(inode)) {
  453. ncp_read_volume_list(filp, dirent, filldir, &ctl);
  454. } else {
  455. ncp_do_readdir(filp, dirent, filldir, &ctl);
  456. }
  457. ctl.head.end = ctl.fpos - 1;
  458. ctl.head.eof = ctl.valid;
  459. finished:
  460. if (page) {
  461. cache->head = ctl.head;
  462. kunmap(page);
  463. SetPageUptodate(page);
  464. unlock_page(page);
  465. page_cache_release(page);
  466. }
  467. if (ctl.page) {
  468. kunmap(ctl.page);
  469. SetPageUptodate(ctl.page);
  470. unlock_page(ctl.page);
  471. page_cache_release(ctl.page);
  472. }
  473. out:
  474. unlock_kernel();
  475. return result;
  476. }
  477. static int
  478. ncp_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
  479. struct ncp_cache_control *ctrl, struct ncp_entry_info *entry)
  480. {
  481. struct dentry *newdent, *dentry = filp->f_dentry;
  482. struct inode *newino, *inode = dentry->d_inode;
  483. struct ncp_cache_control ctl = *ctrl;
  484. struct qstr qname;
  485. int valid = 0;
  486. int hashed = 0;
  487. ino_t ino = 0;
  488. __u8 __name[NCP_MAXPATHLEN + 1];
  489. qname.len = sizeof(__name);
  490. if (ncp_vol2io(NCP_SERVER(inode), __name, &qname.len,
  491. entry->i.entryName, entry->i.nameLen,
  492. !ncp_preserve_entry_case(inode, entry->i.NSCreator)))
  493. return 1; /* I'm not sure */
  494. qname.name = __name;
  495. qname.hash = full_name_hash(qname.name, qname.len);
  496. if (dentry->d_op && dentry->d_op->d_hash)
  497. if (dentry->d_op->d_hash(dentry, &qname) != 0)
  498. goto end_advance;
  499. newdent = d_lookup(dentry, &qname);
  500. if (!newdent) {
  501. newdent = d_alloc(dentry, &qname);
  502. if (!newdent)
  503. goto end_advance;
  504. } else {
  505. hashed = 1;
  506. memcpy((char *) newdent->d_name.name, qname.name,
  507. newdent->d_name.len);
  508. }
  509. if (!newdent->d_inode) {
  510. entry->opened = 0;
  511. entry->ino = iunique(inode->i_sb, 2);
  512. newino = ncp_iget(inode->i_sb, entry);
  513. if (newino) {
  514. newdent->d_op = &ncp_dentry_operations;
  515. d_instantiate(newdent, newino);
  516. if (!hashed)
  517. d_rehash(newdent);
  518. }
  519. } else
  520. ncp_update_inode2(newdent->d_inode, entry);
  521. if (newdent->d_inode) {
  522. ino = newdent->d_inode->i_ino;
  523. newdent->d_fsdata = (void *) ctl.fpos;
  524. ncp_new_dentry(newdent);
  525. }
  526. if (ctl.idx >= NCP_DIRCACHE_SIZE) {
  527. if (ctl.page) {
  528. kunmap(ctl.page);
  529. SetPageUptodate(ctl.page);
  530. unlock_page(ctl.page);
  531. page_cache_release(ctl.page);
  532. }
  533. ctl.cache = NULL;
  534. ctl.idx -= NCP_DIRCACHE_SIZE;
  535. ctl.ofs += 1;
  536. ctl.page = grab_cache_page(&inode->i_data, ctl.ofs);
  537. if (ctl.page)
  538. ctl.cache = kmap(ctl.page);
  539. }
  540. if (ctl.cache) {
  541. ctl.cache->dentry[ctl.idx] = newdent;
  542. valid = 1;
  543. }
  544. dput(newdent);
  545. end_advance:
  546. if (!valid)
  547. ctl.valid = 0;
  548. if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
  549. if (!ino)
  550. ino = find_inode_number(dentry, &qname);
  551. if (!ino)
  552. ino = iunique(inode->i_sb, 2);
  553. ctl.filled = filldir(dirent, qname.name, qname.len,
  554. filp->f_pos, ino, DT_UNKNOWN);
  555. if (!ctl.filled)
  556. filp->f_pos += 1;
  557. }
  558. ctl.fpos += 1;
  559. ctl.idx += 1;
  560. *ctrl = ctl;
  561. return (ctl.valid || !ctl.filled);
  562. }
  563. static void
  564. ncp_read_volume_list(struct file *filp, void *dirent, filldir_t filldir,
  565. struct ncp_cache_control *ctl)
  566. {
  567. struct dentry *dentry = filp->f_dentry;
  568. struct inode *inode = dentry->d_inode;
  569. struct ncp_server *server = NCP_SERVER(inode);
  570. struct ncp_volume_info info;
  571. struct ncp_entry_info entry;
  572. int i;
  573. DPRINTK("ncp_read_volume_list: pos=%ld\n",
  574. (unsigned long) filp->f_pos);
  575. for (i = 0; i < NCP_NUMBER_OF_VOLUMES; i++) {
  576. if (ncp_get_volume_info_with_number(server, i, &info) != 0)
  577. return;
  578. if (!strlen(info.volume_name))
  579. continue;
  580. DPRINTK("ncp_read_volume_list: found vol: %s\n",
  581. info.volume_name);
  582. if (ncp_lookup_volume(server, info.volume_name,
  583. &entry.i)) {
  584. DPRINTK("ncpfs: could not lookup vol %s\n",
  585. info.volume_name);
  586. continue;
  587. }
  588. entry.volume = entry.i.volNumber;
  589. if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
  590. return;
  591. }
  592. }
  593. static void
  594. ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
  595. struct ncp_cache_control *ctl)
  596. {
  597. struct dentry *dentry = filp->f_dentry;
  598. struct inode *dir = dentry->d_inode;
  599. struct ncp_server *server = NCP_SERVER(dir);
  600. struct nw_search_sequence seq;
  601. struct ncp_entry_info entry;
  602. int err;
  603. void* buf;
  604. int more;
  605. size_t bufsize;
  606. DPRINTK("ncp_do_readdir: %s/%s, fpos=%ld\n",
  607. dentry->d_parent->d_name.name, dentry->d_name.name,
  608. (unsigned long) filp->f_pos);
  609. PPRINTK("ncp_do_readdir: init %s, volnum=%d, dirent=%u\n",
  610. dentry->d_name.name, NCP_FINFO(dir)->volNumber,
  611. NCP_FINFO(dir)->dirEntNum);
  612. err = ncp_initialize_search(server, dir, &seq);
  613. if (err) {
  614. DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
  615. return;
  616. }
  617. #ifdef USE_OLD_SLOW_DIRECTORY_LISTING
  618. for (;;) {
  619. err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
  620. if (err) {
  621. DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
  622. break;
  623. }
  624. entry.volume = entry.i.volNumber;
  625. if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
  626. break;
  627. }
  628. #else
  629. /* We MUST NOT use server->buffer_size handshaked with server if we are
  630. using UDP, as for UDP server uses max. buffer size determined by
  631. MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
  632. So we use 128KB, just to be sure, as there is no way how to know
  633. this value in advance. */
  634. bufsize = 131072;
  635. buf = vmalloc(bufsize);
  636. if (!buf)
  637. return;
  638. do {
  639. int cnt;
  640. char* rpl;
  641. size_t rpls;
  642. err = ncp_search_for_fileset(server, &seq, &more, &cnt, buf, bufsize, &rpl, &rpls);
  643. if (err) /* Error */
  644. break;
  645. if (!cnt) /* prevent endless loop */
  646. break;
  647. while (cnt--) {
  648. size_t onerpl;
  649. if (rpls < offsetof(struct nw_info_struct, entryName))
  650. break; /* short packet */
  651. ncp_extract_file_info(rpl, &entry.i);
  652. onerpl = offsetof(struct nw_info_struct, entryName) + entry.i.nameLen;
  653. if (rpls < onerpl)
  654. break; /* short packet */
  655. (void)ncp_obtain_nfs_info(server, &entry.i);
  656. rpl += onerpl;
  657. rpls -= onerpl;
  658. entry.volume = entry.i.volNumber;
  659. if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
  660. break;
  661. }
  662. } while (more);
  663. vfree(buf);
  664. #endif
  665. return;
  666. }
  667. int ncp_conn_logged_in(struct super_block *sb)
  668. {
  669. struct ncp_server* server = NCP_SBP(sb);
  670. int result;
  671. if (ncp_single_volume(server)) {
  672. int len;
  673. struct dentry* dent;
  674. __u32 volNumber;
  675. __le32 dirEntNum;
  676. __le32 DosDirNum;
  677. __u8 __name[NCP_MAXPATHLEN + 1];
  678. len = sizeof(__name);
  679. result = ncp_io2vol(server, __name, &len, server->m.mounted_vol,
  680. strlen(server->m.mounted_vol), 1);
  681. if (result)
  682. goto out;
  683. result = -ENOENT;
  684. if (ncp_get_volume_root(server, __name, &volNumber, &dirEntNum, &DosDirNum)) {
  685. PPRINTK("ncp_conn_logged_in: %s not found\n",
  686. server->m.mounted_vol);
  687. goto out;
  688. }
  689. dent = sb->s_root;
  690. if (dent) {
  691. struct inode* ino = dent->d_inode;
  692. if (ino) {
  693. NCP_FINFO(ino)->volNumber = volNumber;
  694. NCP_FINFO(ino)->dirEntNum = dirEntNum;
  695. NCP_FINFO(ino)->DosDirNum = DosDirNum;
  696. } else {
  697. DPRINTK("ncpfs: sb->s_root->d_inode == NULL!\n");
  698. }
  699. } else {
  700. DPRINTK("ncpfs: sb->s_root == NULL!\n");
  701. }
  702. }
  703. result = 0;
  704. out:
  705. return result;
  706. }
  707. static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  708. {
  709. struct ncp_server *server = NCP_SERVER(dir);
  710. struct inode *inode = NULL;
  711. struct ncp_entry_info finfo;
  712. int error, res, len;
  713. __u8 __name[NCP_MAXPATHLEN + 1];
  714. lock_kernel();
  715. error = -EIO;
  716. if (!ncp_conn_valid(server))
  717. goto finished;
  718. PPRINTK("ncp_lookup: server lookup for %s/%s\n",
  719. dentry->d_parent->d_name.name, dentry->d_name.name);
  720. len = sizeof(__name);
  721. if (ncp_is_server_root(dir)) {
  722. res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  723. dentry->d_name.len, 1);
  724. if (!res)
  725. res = ncp_lookup_volume(server, __name, &(finfo.i));
  726. } else {
  727. res = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  728. dentry->d_name.len, !ncp_preserve_case(dir));
  729. if (!res)
  730. res = ncp_obtain_info(server, dir, __name, &(finfo.i));
  731. }
  732. PPRINTK("ncp_lookup: looked for %s/%s, res=%d\n",
  733. dentry->d_parent->d_name.name, __name, res);
  734. /*
  735. * If we didn't find an entry, make a negative dentry.
  736. */
  737. if (res)
  738. goto add_entry;
  739. /*
  740. * Create an inode for the entry.
  741. */
  742. finfo.opened = 0;
  743. finfo.ino = iunique(dir->i_sb, 2);
  744. finfo.volume = finfo.i.volNumber;
  745. error = -EACCES;
  746. inode = ncp_iget(dir->i_sb, &finfo);
  747. if (inode) {
  748. ncp_new_dentry(dentry);
  749. add_entry:
  750. dentry->d_op = &ncp_dentry_operations;
  751. d_add(dentry, inode);
  752. error = 0;
  753. }
  754. finished:
  755. PPRINTK("ncp_lookup: result=%d\n", error);
  756. unlock_kernel();
  757. return ERR_PTR(error);
  758. }
  759. /*
  760. * This code is common to create, mkdir, and mknod.
  761. */
  762. static int ncp_instantiate(struct inode *dir, struct dentry *dentry,
  763. struct ncp_entry_info *finfo)
  764. {
  765. struct inode *inode;
  766. int error = -EINVAL;
  767. finfo->ino = iunique(dir->i_sb, 2);
  768. inode = ncp_iget(dir->i_sb, finfo);
  769. if (!inode)
  770. goto out_close;
  771. d_instantiate(dentry,inode);
  772. error = 0;
  773. out:
  774. return error;
  775. out_close:
  776. PPRINTK("ncp_instantiate: %s/%s failed, closing file\n",
  777. dentry->d_parent->d_name.name, dentry->d_name.name);
  778. ncp_close_file(NCP_SERVER(dir), finfo->file_handle);
  779. goto out;
  780. }
  781. int ncp_create_new(struct inode *dir, struct dentry *dentry, int mode,
  782. dev_t rdev, __le32 attributes)
  783. {
  784. struct ncp_server *server = NCP_SERVER(dir);
  785. struct ncp_entry_info finfo;
  786. int error, result, len;
  787. int opmode;
  788. __u8 __name[NCP_MAXPATHLEN + 1];
  789. PPRINTK("ncp_create_new: creating %s/%s, mode=%x\n",
  790. dentry->d_parent->d_name.name, dentry->d_name.name, mode);
  791. error = -EIO;
  792. lock_kernel();
  793. if (!ncp_conn_valid(server))
  794. goto out;
  795. ncp_age_dentry(server, dentry);
  796. len = sizeof(__name);
  797. error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  798. dentry->d_name.len, !ncp_preserve_case(dir));
  799. if (error)
  800. goto out;
  801. error = -EACCES;
  802. if (S_ISREG(mode) &&
  803. (server->m.flags & NCP_MOUNT_EXTRAS) &&
  804. (mode & S_IXUGO))
  805. attributes |= aSYSTEM | aSHARED;
  806. result = ncp_open_create_file_or_subdir(server, dir, __name,
  807. OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
  808. attributes, AR_READ | AR_WRITE, &finfo);
  809. opmode = O_RDWR;
  810. if (result) {
  811. result = ncp_open_create_file_or_subdir(server, dir, __name,
  812. OC_MODE_CREATE | OC_MODE_OPEN | OC_MODE_REPLACE,
  813. attributes, AR_WRITE, &finfo);
  814. if (result) {
  815. if (result == 0x87)
  816. error = -ENAMETOOLONG;
  817. DPRINTK("ncp_create: %s/%s failed\n",
  818. dentry->d_parent->d_name.name, dentry->d_name.name);
  819. goto out;
  820. }
  821. opmode = O_WRONLY;
  822. }
  823. finfo.access = opmode;
  824. if (ncp_is_nfs_extras(server, finfo.volume)) {
  825. finfo.i.nfs.mode = mode;
  826. finfo.i.nfs.rdev = new_encode_dev(rdev);
  827. if (ncp_modify_nfs_info(server, finfo.volume,
  828. finfo.i.dirEntNum,
  829. mode, new_encode_dev(rdev)) != 0)
  830. goto out;
  831. }
  832. error = ncp_instantiate(dir, dentry, &finfo);
  833. out:
  834. unlock_kernel();
  835. return error;
  836. }
  837. static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
  838. struct nameidata *nd)
  839. {
  840. return ncp_create_new(dir, dentry, mode, 0, 0);
  841. }
  842. static int ncp_mkdir(struct inode *dir, struct dentry *dentry, int mode)
  843. {
  844. struct ncp_entry_info finfo;
  845. struct ncp_server *server = NCP_SERVER(dir);
  846. int error, len;
  847. __u8 __name[NCP_MAXPATHLEN + 1];
  848. DPRINTK("ncp_mkdir: making %s/%s\n",
  849. dentry->d_parent->d_name.name, dentry->d_name.name);
  850. error = -EIO;
  851. lock_kernel();
  852. if (!ncp_conn_valid(server))
  853. goto out;
  854. ncp_age_dentry(server, dentry);
  855. len = sizeof(__name);
  856. error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  857. dentry->d_name.len, !ncp_preserve_case(dir));
  858. if (error)
  859. goto out;
  860. error = -EACCES;
  861. if (ncp_open_create_file_or_subdir(server, dir, __name,
  862. OC_MODE_CREATE, aDIR,
  863. cpu_to_le16(0xffff),
  864. &finfo) == 0)
  865. {
  866. if (ncp_is_nfs_extras(server, finfo.volume)) {
  867. mode |= S_IFDIR;
  868. finfo.i.nfs.mode = mode;
  869. if (ncp_modify_nfs_info(server,
  870. finfo.volume,
  871. finfo.i.dirEntNum,
  872. mode, 0) != 0)
  873. goto out;
  874. }
  875. error = ncp_instantiate(dir, dentry, &finfo);
  876. }
  877. out:
  878. unlock_kernel();
  879. return error;
  880. }
  881. static int ncp_rmdir(struct inode *dir, struct dentry *dentry)
  882. {
  883. struct ncp_server *server = NCP_SERVER(dir);
  884. int error, result, len;
  885. __u8 __name[NCP_MAXPATHLEN + 1];
  886. DPRINTK("ncp_rmdir: removing %s/%s\n",
  887. dentry->d_parent->d_name.name, dentry->d_name.name);
  888. error = -EIO;
  889. lock_kernel();
  890. if (!ncp_conn_valid(server))
  891. goto out;
  892. error = -EBUSY;
  893. if (!d_unhashed(dentry))
  894. goto out;
  895. len = sizeof(__name);
  896. error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
  897. dentry->d_name.len, !ncp_preserve_case(dir));
  898. if (error)
  899. goto out;
  900. result = ncp_del_file_or_subdir(server, dir, __name);
  901. switch (result) {
  902. case 0x00:
  903. error = 0;
  904. break;
  905. case 0x85: /* unauthorized to delete file */
  906. case 0x8A: /* unauthorized to delete file */
  907. error = -EACCES;
  908. break;
  909. case 0x8F:
  910. case 0x90: /* read only */
  911. error = -EPERM;
  912. break;
  913. case 0x9F: /* in use by another client */
  914. error = -EBUSY;
  915. break;
  916. case 0xA0: /* directory not empty */
  917. error = -ENOTEMPTY;
  918. break;
  919. case 0xFF: /* someone deleted file */
  920. error = -ENOENT;
  921. break;
  922. default:
  923. error = -EACCES;
  924. break;
  925. }
  926. out:
  927. unlock_kernel();
  928. return error;
  929. }
  930. static int ncp_unlink(struct inode *dir, struct dentry *dentry)
  931. {
  932. struct inode *inode = dentry->d_inode;
  933. struct ncp_server *server;
  934. int error;
  935. lock_kernel();
  936. server = NCP_SERVER(dir);
  937. DPRINTK("ncp_unlink: unlinking %s/%s\n",
  938. dentry->d_parent->d_name.name, dentry->d_name.name);
  939. error = -EIO;
  940. if (!ncp_conn_valid(server))
  941. goto out;
  942. /*
  943. * Check whether to close the file ...
  944. */
  945. if (inode) {
  946. PPRINTK("ncp_unlink: closing file\n");
  947. ncp_make_closed(inode);
  948. }
  949. error = ncp_del_file_or_subdir2(server, dentry);
  950. #ifdef CONFIG_NCPFS_STRONG
  951. /* 9C is Invalid path.. It should be 8F, 90 - read only, but
  952. it is not :-( */
  953. if ((error == 0x9C || error == 0x90) && server->m.flags & NCP_MOUNT_STRONG) { /* R/O */
  954. error = ncp_force_unlink(dir, dentry);
  955. }
  956. #endif
  957. switch (error) {
  958. case 0x00:
  959. DPRINTK("ncp: removed %s/%s\n",
  960. dentry->d_parent->d_name.name, dentry->d_name.name);
  961. break;
  962. case 0x85:
  963. case 0x8A:
  964. error = -EACCES;
  965. break;
  966. case 0x8D: /* some files in use */
  967. case 0x8E: /* all files in use */
  968. error = -EBUSY;
  969. break;
  970. case 0x8F: /* some read only */
  971. case 0x90: /* all read only */
  972. case 0x9C: /* !!! returned when in-use or read-only by NW4 */
  973. error = -EPERM;
  974. break;
  975. case 0xFF:
  976. error = -ENOENT;
  977. break;
  978. default:
  979. error = -EACCES;
  980. break;
  981. }
  982. out:
  983. unlock_kernel();
  984. return error;
  985. }
  986. static int ncp_rename(struct inode *old_dir, struct dentry *old_dentry,
  987. struct inode *new_dir, struct dentry *new_dentry)
  988. {
  989. struct ncp_server *server = NCP_SERVER(old_dir);
  990. int error;
  991. int old_len, new_len;
  992. __u8 __old_name[NCP_MAXPATHLEN + 1], __new_name[NCP_MAXPATHLEN + 1];
  993. DPRINTK("ncp_rename: %s/%s to %s/%s\n",
  994. old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
  995. new_dentry->d_parent->d_name.name, new_dentry->d_name.name);
  996. error = -EIO;
  997. lock_kernel();
  998. if (!ncp_conn_valid(server))
  999. goto out;
  1000. ncp_age_dentry(server, old_dentry);
  1001. ncp_age_dentry(server, new_dentry);
  1002. old_len = sizeof(__old_name);
  1003. error = ncp_io2vol(server, __old_name, &old_len,
  1004. old_dentry->d_name.name, old_dentry->d_name.len,
  1005. !ncp_preserve_case(old_dir));
  1006. if (error)
  1007. goto out;
  1008. new_len = sizeof(__new_name);
  1009. error = ncp_io2vol(server, __new_name, &new_len,
  1010. new_dentry->d_name.name, new_dentry->d_name.len,
  1011. !ncp_preserve_case(new_dir));
  1012. if (error)
  1013. goto out;
  1014. error = ncp_ren_or_mov_file_or_subdir(server, old_dir, __old_name,
  1015. new_dir, __new_name);
  1016. #ifdef CONFIG_NCPFS_STRONG
  1017. if ((error == 0x90 || error == 0x8B || error == -EACCES) &&
  1018. server->m.flags & NCP_MOUNT_STRONG) { /* RO */
  1019. error = ncp_force_rename(old_dir, old_dentry, __old_name,
  1020. new_dir, new_dentry, __new_name);
  1021. }
  1022. #endif
  1023. switch (error) {
  1024. case 0x00:
  1025. DPRINTK("ncp renamed %s -> %s.\n",
  1026. old_dentry->d_name.name,new_dentry->d_name.name);
  1027. break;
  1028. case 0x9E:
  1029. error = -ENAMETOOLONG;
  1030. break;
  1031. case 0xFF:
  1032. error = -ENOENT;
  1033. break;
  1034. default:
  1035. error = -EACCES;
  1036. break;
  1037. }
  1038. out:
  1039. unlock_kernel();
  1040. return error;
  1041. }
  1042. static int ncp_mknod(struct inode * dir, struct dentry *dentry,
  1043. int mode, dev_t rdev)
  1044. {
  1045. if (!new_valid_dev(rdev))
  1046. return -EINVAL;
  1047. if (ncp_is_nfs_extras(NCP_SERVER(dir), NCP_FINFO(dir)->volNumber)) {
  1048. DPRINTK(KERN_DEBUG "ncp_mknod: mode = 0%o\n", mode);
  1049. return ncp_create_new(dir, dentry, mode, rdev, 0);
  1050. }
  1051. return -EPERM; /* Strange, but true */
  1052. }
  1053. /* The following routines are taken directly from msdos-fs */
  1054. /* Linear day numbers of the respective 1sts in non-leap years. */
  1055. static int day_n[] =
  1056. {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};
  1057. /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
  1058. extern struct timezone sys_tz;
  1059. static int utc2local(int time)
  1060. {
  1061. return time - sys_tz.tz_minuteswest * 60;
  1062. }
  1063. static int local2utc(int time)
  1064. {
  1065. return time + sys_tz.tz_minuteswest * 60;
  1066. }
  1067. /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
  1068. int
  1069. ncp_date_dos2unix(__le16 t, __le16 d)
  1070. {
  1071. unsigned short time = le16_to_cpu(t), date = le16_to_cpu(d);
  1072. int month, year, secs;
  1073. /* first subtract and mask after that... Otherwise, if
  1074. date == 0, bad things happen */
  1075. month = ((date >> 5) - 1) & 15;
  1076. year = date >> 9;
  1077. secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 +
  1078. 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) +
  1079. year * 365 - ((year & 3) == 0 && month < 2 ? 1 : 0) + 3653);
  1080. /* days since 1.1.70 plus 80's leap day */
  1081. return local2utc(secs);
  1082. }
  1083. /* Convert linear UNIX date to a MS-DOS time/date pair. */
  1084. void
  1085. ncp_date_unix2dos(int unix_date, __le16 *time, __le16 *date)
  1086. {
  1087. int day, year, nl_day, month;
  1088. unix_date = utc2local(unix_date);
  1089. *time = cpu_to_le16(
  1090. (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) +
  1091. (((unix_date / 3600) % 24) << 11));
  1092. day = unix_date / 86400 - 3652;
  1093. year = day / 365;
  1094. if ((year + 3) / 4 + 365 * year > day)
  1095. year--;
  1096. day -= (year + 3) / 4 + 365 * year;
  1097. if (day == 59 && !(year & 3)) {
  1098. nl_day = day;
  1099. month = 2;
  1100. } else {
  1101. nl_day = (year & 3) || day <= 59 ? day : day - 1;
  1102. for (month = 0; month < 12; month++)
  1103. if (day_n[month] > nl_day)
  1104. break;
  1105. }
  1106. *date = cpu_to_le16(nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9));
  1107. }