This source file includes following definitions.
- str_upper
- str_lower
- ncp_dir_read
- ncp_readdir
- ncp_read_volume_list
- ncp_do_readdir
- ncp_init_dir_cache
- ncp_invalid_dir_cache
- ncp_free_dir_cache
- ncp_iget
- ncp_free_inode_info
- ncp_init_root
- ncp_free_all_inodes
- ncp_find_inode
- ncp_lookup
- ncp_create
- ncp_mkdir
- ncp_rmdir
- ncp_unlink
- ncp_rename
- utc2local
- local2utc
- ncp_date_dos2unix
- ncp_date_unix2dos
1
2
3
4
5
6
7
8 #include <linux/sched.h>
9 #include <linux/errno.h>
10 #include <linux/stat.h>
11 #include <linux/kernel.h>
12 #include <linux/malloc.h>
13 #include <linux/mm.h>
14 #include <linux/ncp_fs.h>
15 #include <asm/segment.h>
16 #include <linux/errno.h>
17 #include "ncplib_kernel.h"
18
19 struct ncp_dirent {
20 struct nw_info_struct i;
21 struct nw_search_sequence s;
22 unsigned long f_pos;
23 };
24
25 static int
26 ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
27
28 static int
29 ncp_readdir(struct inode *inode, struct file *filp,
30 void *dirent, filldir_t filldir);
31
32 static int
33 ncp_read_volume_list(struct ncp_server *server, int start_with,
34 int cache_size);
35
36 static int
37 ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
38 int cache_size, struct ncp_dirent *entry);
39
40 static struct inode *
41 ncp_iget(struct inode *dir, struct nw_file_info *finfo);
42
43 static struct ncp_inode_info *
44 ncp_find_inode(struct inode *dir, const char *name);
45
46 static int
47 ncp_lookup(struct inode *dir, const char *__name,
48 int len, struct inode **result);
49
50 static int
51 ncp_create(struct inode *dir, const char *name, int len, int mode,
52 struct inode **result);
53
54 static int
55 ncp_mkdir(struct inode *dir, const char *name, int len, int mode);
56
57 static int
58 ncp_rmdir(struct inode *dir, const char *name, int len);
59
60 static int
61 ncp_unlink(struct inode *dir, const char *name, int len);
62
63 static int
64 ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
65 struct inode *new_dir, const char *new_name, int new_len);
66
67 static inline void
68 str_upper(char *name)
69 {
70 while (*name)
71 {
72 if (*name >= 'a' && *name <= 'z')
73 {
74 *name -= ('a' - 'A');
75 }
76 name++;
77 }
78 }
79
80 static inline void
81 str_lower(char *name)
82 {
83 while (*name)
84 {
85 if (*name >= 'A' && *name <= 'Z')
86 {
87 *name += ('a' - 'A');
88 }
89 name ++;
90 }
91 }
92
93 static struct file_operations ncp_dir_operations = {
94 NULL,
95 ncp_dir_read,
96 NULL,
97 ncp_readdir,
98 NULL,
99 ncp_ioctl,
100 NULL,
101 NULL,
102 NULL,
103 NULL
104 };
105
106 struct inode_operations ncp_dir_inode_operations = {
107 &ncp_dir_operations,
108 ncp_create,
109 ncp_lookup,
110 NULL,
111 ncp_unlink,
112 NULL,
113 ncp_mkdir,
114 ncp_rmdir,
115 NULL,
116 ncp_rename,
117 NULL,
118 NULL,
119 NULL,
120 NULL,
121 NULL,
122 NULL
123 };
124
125
126 static int
127 ncp_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
128 {
129 return -EISDIR;
130 }
131
132
133
134
135
136 static unsigned long c_ino = 0;
137 static int c_size;
138 static int c_seen_eof;
139 static int c_last_returned_index;
140 static struct ncp_dirent* c_entry = NULL;
141
142 static int
143 ncp_readdir(struct inode *inode, struct file *filp,
144 void *dirent, filldir_t filldir)
145 {
146 int result, i = 0;
147 int index = 0;
148 struct ncp_dirent *entry = NULL;
149 struct ncp_server *server = NCP_SERVER(inode);
150 struct ncp_inode_info *dir = (struct ncp_inode_info *)(inode->i_ino);
151
152 DDPRINTK("ncp_readdir: filp->f_pos = %d\n", (int)filp->f_pos);
153 DDPRINTK("ncp_readdir: inode->i_ino = %ld, c_ino = %ld\n",
154 inode->i_ino, c_ino);
155
156 if (!inode || !S_ISDIR(inode->i_mode))
157 {
158 printk("ncp_readdir: inode is NULL or not a directory\n");
159 return -EBADF;
160 }
161
162 if (c_entry == NULL)
163 {
164 i = sizeof (struct ncp_dirent) * NCP_READDIR_CACHE_SIZE;
165 c_entry = (struct ncp_dirent *) ncp_kmalloc(i, GFP_KERNEL);
166 if (c_entry == NULL)
167 {
168 printk("ncp_readdir: no MEMORY for cache\n");
169 return -ENOMEM;
170 }
171 }
172
173 if (filp->f_pos == 0)
174 {
175 ncp_invalid_dir_cache(inode->i_ino);
176 if (filldir(dirent,".",1, filp->f_pos, (int)dir) < 0)
177 {
178 return 0;
179 }
180 filp->f_pos += 1;
181 }
182
183 if (filp->f_pos == 1)
184 {
185 if (filldir(dirent,"..",2, filp->f_pos, (int)(dir->dir)) < 0)
186 {
187 return 0;
188 }
189 filp->f_pos += 1;
190 }
191
192 if (inode->i_ino == c_ino)
193 {
194 for (i = 0; i < c_size; i++)
195 {
196 if (filp->f_pos == c_entry[i].f_pos)
197 {
198 entry = &c_entry[i];
199 c_last_returned_index = i;
200 index = i;
201 break;
202 }
203 }
204 if ((entry == NULL) && c_seen_eof)
205 {
206 return 0;
207 }
208 }
209
210 if (entry == NULL)
211 {
212 DDPRINTK("ncp_readdir: Not found in cache.\n");
213
214 if (inode->i_ino == (int)&(server->root))
215 {
216 result = ncp_read_volume_list(server, filp->f_pos,
217 NCP_READDIR_CACHE_SIZE);
218 DPRINTK("ncp_read_volume_list returned %d\n", result);
219
220 }
221 else
222 {
223 result = ncp_do_readdir(server, inode, filp->f_pos,
224 NCP_READDIR_CACHE_SIZE,
225 c_entry);
226 DPRINTK("ncp_readdir returned %d\n", result);
227 }
228
229 if (result < 0)
230 {
231 c_ino = 0;
232 return result;
233 }
234
235 if (result > 0)
236 {
237 c_seen_eof = (result < NCP_READDIR_CACHE_SIZE);
238 c_ino = inode->i_ino;
239 c_size = result;
240 entry = c_entry;
241 c_last_returned_index = 0;
242 index = 0;
243
244 for (i = 0; i < c_size; i++)
245 {
246 str_lower(c_entry[i].i.entryName);
247 }
248 }
249 }
250
251 if (entry == NULL)
252 {
253
254 return 0;
255 }
256
257 while (index < c_size)
258 {
259
260
261
262
263
264 struct ncp_inode_info *ino_info;
265 ino_info = ncp_find_inode(inode, entry->i.entryName);
266
267
268
269
270 if (ino_info == NULL)
271 {
272 ino_info = (struct ncp_inode_info *) 1;
273 }
274
275 DDPRINTK("ncp_readdir: entry->path= %s\n", entry->i.entryName);
276 DDPRINTK("ncp_readdir: entry->f_pos = %ld\n", entry->f_pos);
277
278 if (filldir(dirent, entry->i.entryName, entry->i.nameLen,
279 entry->f_pos, (ino_t)ino_info) < 0)
280 {
281 break;
282 }
283
284 if ( (inode->i_ino != c_ino)
285 || (entry->f_pos != filp->f_pos))
286 {
287
288
289 break;
290 }
291 filp->f_pos += 1;
292 index += 1;
293 entry += 1;
294 }
295 return 0;
296 }
297
298 static int
299 ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
300 {
301 struct ncp_dirent *entry = c_entry;
302
303 int total_count = 2;
304 int i;
305
306 #if 1
307 if (fpos < 2)
308 {
309 printk("OOPS, we expect fpos >= 2");
310 fpos = 2;
311 }
312 #endif
313
314 for (i=0; i<NCP_NUMBER_OF_VOLUMES; i++)
315 {
316 struct ncp_volume_info info;
317
318 if (ncp_get_volume_info_with_number(server, i, &info) != 0)
319 {
320 return total_count;
321 }
322
323 if (strlen(info.volume_name) > 0)
324 {
325 if (total_count < fpos)
326 {
327 DPRINTK("ncp_read_volumes: skipped vol: %s\n",
328 info.volume_name);
329 }
330 else if (total_count >= fpos + cache_size)
331 {
332 return (total_count - fpos);
333 }
334 else
335 {
336 DPRINTK("ncp_read_volumes: found vol: %s\n",
337 info.volume_name);
338
339 if (ncp_do_lookup(server, NULL,
340 info.volume_name,
341 &(entry->i)) != 0)
342 {
343 printk("ncpfs: could not lookup vol "
344 "%s\n", info.volume_name);
345 continue;
346 }
347
348 entry->f_pos = total_count;
349 entry += 1;
350 }
351 total_count += 1;
352 }
353 }
354 return (total_count - fpos);
355 }
356
357 static int
358 ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos,
359 int cache_size, struct ncp_dirent *entry)
360 {
361 static struct nw_search_sequence seq;
362 static struct inode *last_dir;
363 static int total_count;
364
365 #if 1
366 if (fpos < 2)
367 {
368 printk("OOPS, we expect fpos >= 2");
369 fpos = 2;
370 }
371 #endif
372 DPRINTK("ncp_do_readdir: fpos = %d\n", fpos);
373
374 if (fpos == 2)
375 {
376 last_dir = NULL;
377 total_count = 2;
378 }
379
380 if ((fpos != total_count) || (dir != last_dir))
381 {
382 total_count = 2;
383 last_dir = dir;
384
385 DPRINTK("ncp_do_readdir: re-used seq for %s\n",
386 NCP_ISTRUCT(dir)->entryName);
387
388 if (ncp_initialize_search(server, NCP_ISTRUCT(dir), &seq)!=0)
389 {
390 DPRINTK("ncp_init_search failed\n");
391 return total_count - fpos;
392 }
393 }
394
395 while (total_count < fpos + cache_size)
396 {
397 if (ncp_search_for_file_or_subdir(server, &seq,
398 &(entry->i)) != 0)
399 {
400 return total_count - fpos;
401 }
402
403 if (total_count < fpos)
404 {
405 DPRINTK("ncp_do_readdir: skipped file: %s\n",
406 entry->i.entryName);
407 }
408 else
409 {
410 DDPRINTK("ncp_do_r: file: %s, f_pos=%d,total_count=%d",
411 entry->i.entryName, fpos, total_count);
412 entry->s = seq;
413 entry->f_pos = total_count;
414 entry += 1;
415 }
416 total_count += 1;
417 }
418 return (total_count - fpos);
419 }
420
421 void
422 ncp_init_dir_cache(void)
423 {
424 c_ino = 0;
425 c_entry = NULL;
426 }
427
428 void
429 ncp_invalid_dir_cache(unsigned long ino)
430 {
431 if (ino == c_ino)
432 {
433 c_ino = 0;
434 c_seen_eof = 0;
435 }
436 }
437
438 void
439 ncp_free_dir_cache(void)
440 {
441 DPRINTK("ncp_free_dir_cache: enter\n");
442
443 if (c_entry == NULL)
444 {
445 return;
446 }
447
448 ncp_kfree_s(c_entry,
449 sizeof(struct ncp_dirent) * NCP_READDIR_CACHE_SIZE);
450 c_entry = NULL;
451
452 DPRINTK("ncp_free_dir_cache: exit\n");
453 }
454
455
456 static struct inode *
457 ncp_iget(struct inode *dir, struct nw_file_info *finfo)
458 {
459 struct inode *inode;
460 struct ncp_inode_info *new_inode_info;
461 struct ncp_inode_info *root;
462
463 if (dir == NULL)
464 {
465 printk("ncp_iget: dir is NULL\n");
466 return NULL;
467 }
468
469 if (finfo == NULL)
470 {
471 printk("ncp_iget: finfo is NULL\n");
472 return NULL;
473 }
474
475 new_inode_info = ncp_kmalloc(sizeof(struct ncp_inode_info),
476 GFP_KERNEL);
477
478 if (new_inode_info == NULL)
479 {
480 printk("ncp_iget: could not alloc mem for %s\n",
481 finfo->i.entryName);
482 return NULL;
483 }
484
485 new_inode_info->state = NCP_INODE_LOOKED_UP;
486 new_inode_info->nused = 0;
487 new_inode_info->dir = NCP_INOP(dir);
488 new_inode_info->finfo = *finfo;
489
490 NCP_INOP(dir)->nused += 1;
491
492
493
494
495
496 root = &(NCP_SERVER(dir)->root);
497
498 new_inode_info->prev = root;
499 new_inode_info->next = root->next;
500 root->next->prev = new_inode_info;
501 root->next = new_inode_info;
502
503 if (!(inode = iget(dir->i_sb, (int)new_inode_info)))
504 {
505 printk("ncp_iget: iget failed!");
506 return NULL;
507 }
508
509 return inode;
510 }
511
512 void
513 ncp_free_inode_info(struct ncp_inode_info *i)
514 {
515 if (i == NULL)
516 {
517 printk("ncp_free_inode: i == NULL\n");
518 return;
519 }
520
521 i->state = NCP_INODE_CACHED;
522 while ((i->nused == 0) && (i->state == NCP_INODE_CACHED))
523 {
524 struct ncp_inode_info *dir = i->dir;
525
526 i->next->prev = i->prev;
527 i->prev->next = i->next;
528
529 DDPRINTK("ncp_free_inode_info: freeing %s\n",
530 i->finfo.i.entryName);
531
532 ncp_kfree_s(i, sizeof(struct ncp_inode_info));
533
534 if (dir == i) return;
535
536 (dir->nused)--;
537 i = dir;
538 }
539 }
540
541 void
542 ncp_init_root(struct ncp_server *server)
543 {
544 struct ncp_inode_info *root = &(server->root);
545 struct nw_info_struct *i = &(root->finfo.i);
546 unsigned short dummy;
547
548 DPRINTK("ncp_init_root: server %s\n", server->m.server_name);
549 DPRINTK("ncp_init_root: i = %x\n", (int)i);
550
551 root->finfo.opened = 0;
552 i->attributes = aDIR;
553 i->dataStreamSize = 1024;
554 ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
555 ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
556 ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
557 i->nameLen = 0;
558 i->entryName[0] = '\0';
559
560 root->state = NCP_INODE_LOOKED_UP;
561 root->nused = 1;
562 root->dir = root;
563 root->next = root->prev = root;
564 return;
565 }
566
567 void
568 ncp_free_all_inodes(struct ncp_server *server)
569 {
570
571
572
573 #if 1
574 struct ncp_inode_info *root = &(server->root);
575
576 if (root->next != root)
577 {
578 printk("ncp_free_all_inodes: INODES LEFT!!!\n");
579 }
580
581 while (root->next != root)
582 {
583 printk("ncp_free_all_inodes: freeing inode\n");
584 ncp_free_inode_info(root->next);
585
586 schedule();
587 }
588 #endif
589
590 return;
591 }
592
593
594
595
596 static struct ncp_inode_info *
597 ncp_find_inode(struct inode *dir, const char *name)
598 {
599 struct ncp_server *server = NCP_SERVER(dir);
600 struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
601 struct ncp_inode_info *result = &(server->root);
602
603 if (name == NULL)
604 {
605 return NULL;
606 }
607
608 do
609 {
610 if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
611 && (strcmp(result->finfo.i.entryName, name) == 0))
612 {
613 return result;
614 }
615 result = result->next;
616
617 }
618 while (result != &(server->root));
619
620 return NULL;
621 }
622
623 static int
624 ncp_lookup(struct inode *dir, const char *__name, int len,
625 struct inode **result)
626 {
627 struct nw_file_info finfo;
628 struct ncp_server *server;
629 struct ncp_inode_info *result_info;
630 int found_in_cache;
631
632 *result = NULL;
633
634 if (!dir || !S_ISDIR(dir->i_mode))
635 {
636 printk("ncp_lookup: inode is NULL or not a directory.\n");
637 iput(dir);
638 return -ENOENT;
639 }
640
641 DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
642
643 server = NCP_SERVER(dir);
644
645
646 if (len == 0 || (len == 1 && __name[0] == '.'))
647 {
648 *result = dir;
649 return 0;
650 }
651
652
653 if (len == 2 && __name[0] == '.' && __name[1] == '.')
654 {
655 struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
656
657 if (parent->state == NCP_INODE_CACHED)
658 {
659 parent->state = NCP_INODE_LOOKED_UP;
660 }
661
662 *result = iget(dir->i_sb, (int)parent);
663 iput(dir);
664 if (*result == 0)
665 {
666 return -EACCES;
667 }
668 else
669 {
670 return 0;
671 }
672 }
673
674 result_info = ncp_find_inode(dir, __name);
675
676 if (result_info != 0)
677 {
678 if (result_info->state == NCP_INODE_CACHED)
679 {
680 result_info->state = NCP_INODE_LOOKED_UP;
681 }
682
683
684
685
686 *result = iget(dir->i_sb, (int)result_info);
687 iput(dir);
688
689 if (*result == NULL)
690 {
691 return -EACCES;
692 }
693
694 return 0;
695 }
696
697
698
699
700 found_in_cache = 0;
701
702 if (dir->i_ino == c_ino)
703 {
704 int first = c_last_returned_index;
705 int i;
706
707 i = first;
708 do
709 {
710 DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
711 i, c_entry[i].i.entryName);
712
713 if (strcmp(c_entry[i].i.entryName, __name) == 0)
714 {
715 DPRINTK("ncp_lookup: found in cache!\n");
716 finfo.i = c_entry[i].i;
717 found_in_cache = 1;
718 break;
719 }
720 i = (i + 1) % c_size;
721 }
722 while (i != first);
723 }
724
725 if (found_in_cache == 0)
726 {
727 char this_name[len+1];
728
729 memcpy(this_name, __name, len);
730 this_name[len] = 0;
731 str_upper(this_name);
732
733 DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
734 NCP_ISTRUCT(dir)->entryName, this_name);
735
736 if (ncp_do_lookup(server,
737 dir->i_ino == (int)&(NCP_SERVER(dir)->root)
738 ? NULL : NCP_ISTRUCT(dir),
739 this_name,
740 &(finfo.i)) != 0)
741 {
742 iput(dir);
743 return -ENOENT;
744 }
745 }
746
747 finfo.opened = 0;
748 str_lower(finfo.i.entryName);
749
750 if (!(*result = ncp_iget(dir, &finfo)))
751 {
752 iput(dir);
753 return -EACCES;
754 }
755
756 iput(dir);
757 return 0;
758 }
759
760 static int
761 ncp_create(struct inode *dir, const char *name, int len, int mode,
762 struct inode **result)
763 {
764 struct nw_file_info finfo;
765 __u8 _name[len+1];
766
767 *result = NULL;
768
769 if (!dir || !S_ISDIR(dir->i_mode))
770 {
771 printk("ncp_create: inode is NULL or not a directory\n");
772 iput(dir);
773 return -ENOENT;
774 }
775
776 strncpy(_name, name, len);
777 _name[len] = '\0';
778 str_upper(_name);
779
780 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
781 NCP_ISTRUCT(dir), _name,
782 OC_MODE_CREATE|OC_MODE_OPEN,
783 0, AR_READ|AR_WRITE,
784 &finfo) != 0)
785 {
786 iput(dir);
787 return -EACCES;
788 }
789
790 ncp_invalid_dir_cache(dir->i_ino);
791
792 str_lower(finfo.i.entryName);
793 finfo.access = O_RDWR;
794
795 if (!(*result = ncp_iget(dir, &finfo)) < 0)
796 {
797 ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
798 iput(dir);
799 return -EINVAL;
800 }
801
802 iput(dir);
803 return 0;
804 }
805
806 static int
807 ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
808 {
809 int error;
810 struct nw_file_info new_dir;
811 __u8 _name[len+1];
812
813 if ( (name[0] == '.')
814 && ( (len == 1)
815 || ( (len == 2)
816 && (name[1] == '.'))))
817 {
818 return -EEXIST;
819 }
820
821 strncpy(_name, name, len);
822 _name[len] = '\0';
823 str_upper(_name);
824
825 if (!dir || !S_ISDIR(dir->i_mode))
826 {
827 printk("ncp_mkdir: inode is NULL or not a directory\n");
828 iput(dir);
829 return -ENOENT;
830 }
831
832 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
833 NCP_ISTRUCT(dir), _name,
834 OC_MODE_CREATE, aDIR, 0xffff,
835 &new_dir) != 0)
836 {
837 error = -EACCES;
838 }
839 else
840 {
841 error = 0;
842 ncp_invalid_dir_cache(dir->i_ino);
843 }
844
845 iput(dir);
846 return error;
847 }
848
849 static int
850 ncp_rmdir(struct inode *dir, const char *name, int len)
851 {
852 int error;
853 __u8 _name[len+1];
854
855 if (!dir || !S_ISDIR(dir->i_mode))
856 {
857 printk("ncp_rmdir: inode is NULL or not a directory\n");
858 iput(dir);
859 return -ENOENT;
860 }
861 if (ncp_find_inode(dir, name) != NULL)
862 {
863 error = -EBUSY;
864 }
865 else
866 {
867
868 strncpy(_name, name, len);
869 _name[len] = '\0';
870 str_upper(_name);
871
872 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
873 NCP_ISTRUCT(dir),
874 _name)) == 0)
875 {
876 ncp_invalid_dir_cache(dir->i_ino);
877 }
878 else
879 {
880 error = -EINVAL;
881 }
882 }
883 iput(dir);
884 return error;
885 }
886
887 static int
888 ncp_unlink(struct inode *dir, const char *name, int len)
889 {
890 int error;
891 __u8 _name[len+1];
892
893 if (!dir || !S_ISDIR(dir->i_mode))
894 {
895 printk("ncp_unlink: inode is NULL or not a directory\n");
896 iput(dir);
897 return -ENOENT;
898 }
899 if (ncp_find_inode(dir, name) != NULL)
900 {
901 error = -EBUSY;
902 }
903 else
904 {
905 strncpy(_name, name, len);
906 _name[len] = '\0';
907 str_upper(_name);
908
909 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
910 NCP_ISTRUCT(dir),
911 _name)) == 0)
912 {
913 ncp_invalid_dir_cache(dir->i_ino);
914 }
915 else
916 {
917 error = -EINVAL;
918 }
919 }
920 iput(dir);
921 return error;
922 }
923
924 static int
925 ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
926 struct inode *new_dir, const char *new_name, int new_len)
927 {
928 int res;
929 char _old_name[old_len+1];
930 char _new_name[new_len+1];
931
932 if (!old_dir || !S_ISDIR(old_dir->i_mode))
933 {
934 printk("ncp_rename: old inode is NULL or not a directory\n");
935 res = -ENOENT;
936 goto finished;
937 }
938
939 if (!new_dir || !S_ISDIR(new_dir->i_mode))
940 {
941 printk("ncp_rename: new inode is NULL or not a directory\n");
942 res = -ENOENT;
943 goto finished;
944 }
945
946 if ( (ncp_find_inode(old_dir, old_name) != NULL)
947 || (ncp_find_inode(new_dir, new_name) != NULL))
948 {
949 res = -EBUSY;
950 goto finished;
951 }
952
953 strncpy(_old_name, old_name, old_len);
954 _old_name[old_len] = '\0';
955 str_upper(_old_name);
956
957 strncpy(_new_name, new_name, new_len);
958 _new_name[new_len] = '\0';
959 str_upper(_new_name);
960
961 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
962 NCP_ISTRUCT(old_dir), _old_name,
963 NCP_ISTRUCT(new_dir), _new_name);
964
965 if (res == 0)
966 {
967 ncp_invalid_dir_cache(old_dir->i_ino);
968 ncp_invalid_dir_cache(new_dir->i_ino);
969 }
970 else
971 {
972 res = -EACCES;
973 }
974
975 finished:
976 iput(old_dir);
977 iput(new_dir);
978 return res;
979 }
980
981
982
983
984
985 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
986
987
988
989 extern struct timezone sys_tz;
990
991 static int
992 utc2local(int time)
993 {
994 return time - sys_tz.tz_minuteswest*60;
995 }
996
997 static int
998 local2utc(int time)
999 {
1000 return time + sys_tz.tz_minuteswest*60;
1001 }
1002
1003
1004
1005 int
1006 ncp_date_dos2unix(unsigned short time,unsigned short date)
1007 {
1008 int month,year,secs;
1009
1010 month = ((date >> 5) & 15)-1;
1011 year = date >> 9;
1012 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
1013 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
1014 month < 2 ? 1 : 0)+3653);
1015
1016 return local2utc(secs);
1017 }
1018
1019
1020
1021 void
1022 ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
1023 {
1024 int day,year,nl_day,month;
1025
1026 unix_date = utc2local(unix_date);
1027 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
1028 (((unix_date/3600) % 24) << 11);
1029 day = unix_date/86400-3652;
1030 year = day/365;
1031 if ((year+3)/4+365*year > day) year--;
1032 day -= (year+3)/4+365*year;
1033 if (day == 59 && !(year & 3)) {
1034 nl_day = day;
1035 month = 2;
1036 }
1037 else {
1038 nl_day = (year & 3) || day <= 59 ? day : day-1;
1039 for (month = 0; month < 12; month++)
1040 if (day_n[month] > nl_day) break;
1041 }
1042 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
1043 }