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