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 i->volNumber = NCP_NUMBER_OF_VOLUMES+1;
555 ncp_date_unix2dos(0, &(i->creationTime), &(i->creationDate));
556 ncp_date_unix2dos(0, &(i->modifyTime), &(i->modifyDate));
557 ncp_date_unix2dos(0, &dummy, &(i->lastAccessDate));
558 i->nameLen = 0;
559 i->entryName[0] = '\0';
560
561 root->state = NCP_INODE_LOOKED_UP;
562 root->nused = 1;
563 root->dir = root;
564 root->next = root->prev = root;
565 return;
566 }
567
568 void
569 ncp_free_all_inodes(struct ncp_server *server)
570 {
571
572
573
574 #if 1
575 struct ncp_inode_info *root = &(server->root);
576
577 if (root->next != root)
578 {
579 printk("ncp_free_all_inodes: INODES LEFT!!!\n");
580 }
581
582 while (root->next != root)
583 {
584 printk("ncp_free_all_inodes: freeing inode\n");
585 ncp_free_inode_info(root->next);
586
587 schedule();
588 }
589 #endif
590
591 return;
592 }
593
594
595
596
597 static struct ncp_inode_info *
598 ncp_find_inode(struct inode *dir, const char *name)
599 {
600 struct ncp_server *server = NCP_SERVER(dir);
601 struct nw_info_struct *dir_info = NCP_ISTRUCT(dir);
602 struct ncp_inode_info *result = &(server->root);
603
604 if (name == NULL)
605 {
606 return NULL;
607 }
608
609 do
610 {
611 if ( (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
612 && (result->dir->finfo.i.volNumber == dir_info->volNumber)
613 && (strcmp(result->finfo.i.entryName, name) == 0))
614 {
615 return result;
616 }
617 result = result->next;
618
619 }
620 while (result != &(server->root));
621
622 return NULL;
623 }
624
625 static int
626 ncp_lookup(struct inode *dir, const char *__name, int len,
627 struct inode **result)
628 {
629 struct nw_file_info finfo;
630 struct ncp_server *server;
631 struct ncp_inode_info *result_info;
632 int found_in_cache;
633 char name[len+1];
634
635 *result = NULL;
636
637 if (!dir || !S_ISDIR(dir->i_mode))
638 {
639 printk("ncp_lookup: inode is NULL or not a directory.\n");
640 iput(dir);
641 return -ENOENT;
642 }
643
644 DDPRINTK("ncp_lookup: %s, len %d\n", __name, len);
645
646 server = NCP_SERVER(dir);
647
648
649 if (len == 0 || (len == 1 && __name[0] == '.'))
650 {
651 *result = dir;
652 return 0;
653 }
654
655
656 if (len == 2 && __name[0] == '.' && __name[1] == '.')
657 {
658 struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
659
660 if (parent->state == NCP_INODE_CACHED)
661 {
662 parent->state = NCP_INODE_LOOKED_UP;
663 }
664
665 *result = iget(dir->i_sb, (int)parent);
666 iput(dir);
667 if (*result == 0)
668 {
669 return -EACCES;
670 }
671 else
672 {
673 return 0;
674 }
675 }
676
677 memcpy(name, __name, len);
678 name[len] = 0;
679 result_info = ncp_find_inode(dir, name);
680
681 if (result_info != 0)
682 {
683 if (result_info->state == NCP_INODE_CACHED)
684 {
685 result_info->state = NCP_INODE_LOOKED_UP;
686 }
687
688
689
690
691 *result = iget(dir->i_sb, (int)result_info);
692 iput(dir);
693
694 if (*result == NULL)
695 {
696 return -EACCES;
697 }
698
699 return 0;
700 }
701
702
703
704
705 found_in_cache = 0;
706
707 if (dir->i_ino == c_ino)
708 {
709 int first = c_last_returned_index;
710 int i;
711
712 i = first;
713 do
714 {
715 DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
716 i, c_entry[i].i.entryName);
717
718 if (strcmp(c_entry[i].i.entryName, name) == 0)
719 {
720 DPRINTK("ncp_lookup: found in cache!\n");
721 finfo.i = c_entry[i].i;
722 found_in_cache = 1;
723 break;
724 }
725 i = (i + 1) % c_size;
726 }
727 while (i != first);
728 }
729
730 if (found_in_cache == 0)
731 {
732 str_upper(name);
733
734 DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
735 NCP_ISTRUCT(dir)->entryName, name);
736
737 if (ncp_do_lookup(server,
738 dir->i_ino == (int)&(NCP_SERVER(dir)->root)
739 ? NULL : NCP_ISTRUCT(dir),
740 name, &(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 }