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