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