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