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