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 printk("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 return result;
715 }
716 result = result->next;
717
718 }
719 while (result != &(server->root));
720
721 return NULL;
722 }
723
724 static int
725 ncp_lookup(struct inode *dir, const char *__name, int len,
726 struct inode **result)
727 {
728 struct nw_file_info finfo;
729 struct ncp_server *server;
730 struct ncp_inode_info *result_info;
731 int found_in_cache;
732 char name[len+1];
733
734 *result = NULL;
735
736 if (!dir || !S_ISDIR(dir->i_mode))
737 {
738 printk("ncp_lookup: inode is NULL or not a directory.\n");
739 iput(dir);
740 return -ENOENT;
741 }
742
743 server = NCP_SERVER(dir);
744
745 if (!ncp_conn_valid(server))
746 {
747 iput(dir);
748 return -EIO;
749 }
750
751 DPRINTK("ncp_lookup: %s, len %d\n", __name, len);
752
753
754 if (len == 0 || (len == 1 && __name[0] == '.'))
755 {
756 *result = dir;
757 return 0;
758 }
759
760
761 if (len == 2 && __name[0] == '.' && __name[1] == '.')
762 {
763 struct ncp_inode_info *parent = NCP_INOP(dir)->dir;
764
765 if (parent->state == NCP_INODE_CACHED)
766 {
767 parent->state = NCP_INODE_LOOKED_UP;
768 }
769
770 *result = iget(dir->i_sb, ncp_info_ino(server, parent));
771 iput(dir);
772 if (*result == 0)
773 {
774 return -EACCES;
775 }
776 else
777 {
778 return 0;
779 }
780 }
781
782 memcpy(name, __name, len);
783 name[len] = 0;
784 result_info = ncp_find_dir_inode(dir, name);
785
786 if (result_info != 0)
787 {
788 if (result_info->state == NCP_INODE_CACHED)
789 {
790 result_info->state = NCP_INODE_LOOKED_UP;
791 }
792
793
794
795
796 *result = iget(dir->i_sb, ncp_info_ino(server, result_info));
797 iput(dir);
798
799 if (*result == NULL)
800 {
801 return -EACCES;
802 }
803
804 return 0;
805 }
806
807
808
809
810 found_in_cache = 0;
811
812 if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino))
813 {
814 int first = c_last_returned_index;
815 int i;
816
817 i = first;
818 do
819 {
820 DDPRINTK("ncp_lookup: trying index: %d, name: %s\n",
821 i, c_entry[i].i.entryName);
822
823 if (strcmp(c_entry[i].i.entryName, name) == 0)
824 {
825 DPRINTK("ncp_lookup: found in cache!\n");
826 finfo.i = c_entry[i].i;
827 found_in_cache = 1;
828 break;
829 }
830 i = (i + 1) % c_size;
831 }
832 while (i != first);
833 }
834
835 if (found_in_cache == 0)
836 {
837 int res;
838 str_upper(name);
839
840 DDPRINTK("ncp_lookup: do_lookup on %s/%s\n",
841 NCP_ISTRUCT(dir)->entryName, name);
842
843 if (ncp_is_server_root(dir))
844 {
845 res = ncp_lookup_volume(server, name, &(finfo.i));
846 }
847 else
848 {
849 res = ncp_obtain_info(server,
850 NCP_ISTRUCT(dir)->volNumber,
851 NCP_ISTRUCT(dir)->DosDirNum,
852 name, &(finfo.i));
853 }
854 if (res != 0)
855 {
856 iput(dir);
857 return -ENOENT;
858 }
859 }
860
861 finfo.opened = 0;
862 str_lower(finfo.i.entryName);
863
864 if (!(*result = ncp_iget(dir, &finfo)))
865 {
866 iput(dir);
867 return -EACCES;
868 }
869
870 iput(dir);
871 return 0;
872 }
873
874 static int
875 ncp_create(struct inode *dir, const char *name, int len, int mode,
876 struct inode **result)
877 {
878 struct nw_file_info finfo;
879 __u8 _name[len+1];
880
881 *result = NULL;
882
883 if (!dir || !S_ISDIR(dir->i_mode))
884 {
885 printk("ncp_create: inode is NULL or not a directory\n");
886 iput(dir);
887 return -ENOENT;
888 }
889 if (!ncp_conn_valid(NCP_SERVER(dir)))
890 {
891 iput(dir);
892 return -EIO;
893 }
894
895 strncpy(_name, name, len);
896 _name[len] = '\0';
897 str_upper(_name);
898
899 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
900 NCP_ISTRUCT(dir), _name,
901 OC_MODE_CREATE|OC_MODE_OPEN|
902 OC_MODE_REPLACE,
903 0, AR_READ|AR_WRITE,
904 &finfo) != 0)
905 {
906 iput(dir);
907 return -EACCES;
908 }
909
910 ncp_invalid_dir_cache(dir);
911
912 str_lower(finfo.i.entryName);
913 finfo.access = O_RDWR;
914
915 if (!(*result = ncp_iget(dir, &finfo)) < 0)
916 {
917 ncp_close_file(NCP_SERVER(dir), finfo.file_handle);
918 iput(dir);
919 return -EINVAL;
920 }
921
922 iput(dir);
923 return 0;
924 }
925
926 static int
927 ncp_mkdir(struct inode *dir, const char *name, int len, int mode)
928 {
929 int error;
930 struct nw_file_info new_dir;
931 __u8 _name[len+1];
932
933 if ( (name[0] == '.')
934 && ( (len == 1)
935 || ( (len == 2)
936 && (name[1] == '.'))))
937 {
938 return -EEXIST;
939 }
940
941 strncpy(_name, name, len);
942 _name[len] = '\0';
943 str_upper(_name);
944
945 if (!dir || !S_ISDIR(dir->i_mode))
946 {
947 printk("ncp_mkdir: inode is NULL or not a directory\n");
948 iput(dir);
949 return -ENOENT;
950 }
951 if (!ncp_conn_valid(NCP_SERVER(dir)))
952 {
953 iput(dir);
954 return -EIO;
955 }
956
957 if (ncp_open_create_file_or_subdir(NCP_SERVER(dir),
958 NCP_ISTRUCT(dir), _name,
959 OC_MODE_CREATE, aDIR, 0xffff,
960 &new_dir) != 0)
961 {
962 error = -EACCES;
963 }
964 else
965 {
966 error = 0;
967 ncp_invalid_dir_cache(dir);
968 }
969
970 iput(dir);
971 return error;
972 }
973
974 static int
975 ncp_rmdir(struct inode *dir, const char *name, int len)
976 {
977 int error;
978 __u8 _name[len+1];
979
980 if (!dir || !S_ISDIR(dir->i_mode))
981 {
982 printk("ncp_rmdir: inode is NULL or not a directory\n");
983 iput(dir);
984 return -ENOENT;
985 }
986 if (!ncp_conn_valid(NCP_SERVER(dir)))
987 {
988 iput(dir);
989 return -EIO;
990 }
991 if (ncp_find_dir_inode(dir, name) != NULL)
992 {
993 iput(dir);
994 error = -EBUSY;
995 }
996 else
997 {
998
999 strncpy(_name, name, len);
1000 _name[len] = '\0';
1001 str_upper(_name);
1002
1003 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
1004 NCP_ISTRUCT(dir),
1005 _name)) == 0)
1006 {
1007 ncp_invalid_dir_cache(dir);
1008 }
1009 else
1010 {
1011 error = -EACCES;
1012 }
1013 }
1014 iput(dir);
1015 return error;
1016 }
1017
1018 static int
1019 ncp_unlink(struct inode *dir, const char *name, int len)
1020 {
1021 int error;
1022 __u8 _name[len+1];
1023
1024 if (!dir || !S_ISDIR(dir->i_mode))
1025 {
1026 printk("ncp_unlink: inode is NULL or not a directory\n");
1027 iput(dir);
1028 return -ENOENT;
1029 }
1030 if (!ncp_conn_valid(NCP_SERVER(dir)))
1031 {
1032 iput(dir);
1033 return -EIO;
1034 }
1035 if (ncp_find_dir_inode(dir, name) != NULL)
1036 {
1037 iput(dir);
1038 error = -EBUSY;
1039 }
1040 else
1041 {
1042 strncpy(_name, name, len);
1043 _name[len] = '\0';
1044 str_upper(_name);
1045
1046 if ((error = ncp_del_file_or_subdir(NCP_SERVER(dir),
1047 NCP_ISTRUCT(dir),
1048 _name)) == 0)
1049 {
1050 ncp_invalid_dir_cache(dir);
1051 }
1052 else
1053 {
1054 error = -EACCES;
1055 }
1056 }
1057 iput(dir);
1058 return error;
1059 }
1060
1061 static int
1062 ncp_rename(struct inode *old_dir, const char *old_name, int old_len,
1063 struct inode *new_dir, const char *new_name, int new_len)
1064 {
1065 int res;
1066 char _old_name[old_len+1];
1067 char _new_name[new_len+1];
1068
1069 if (!old_dir || !S_ISDIR(old_dir->i_mode))
1070 {
1071 printk("ncp_rename: old inode is NULL or not a directory\n");
1072 res = -ENOENT;
1073 goto finished;
1074 }
1075
1076 if (!ncp_conn_valid(NCP_SERVER(old_dir)))
1077 {
1078 res = -EIO;
1079 goto finished;
1080 }
1081
1082 if (!new_dir || !S_ISDIR(new_dir->i_mode))
1083 {
1084 printk("ncp_rename: new inode is NULL or not a directory\n");
1085 res = -ENOENT;
1086 goto finished;
1087 }
1088
1089 if ( (ncp_find_dir_inode(old_dir, old_name) != NULL)
1090 || (ncp_find_dir_inode(new_dir, new_name) != NULL))
1091 {
1092 res = -EBUSY;
1093 goto finished;
1094 }
1095
1096 strncpy(_old_name, old_name, old_len);
1097 _old_name[old_len] = '\0';
1098 str_upper(_old_name);
1099
1100 strncpy(_new_name, new_name, new_len);
1101 _new_name[new_len] = '\0';
1102 str_upper(_new_name);
1103
1104 res = ncp_ren_or_mov_file_or_subdir(NCP_SERVER(old_dir),
1105 NCP_ISTRUCT(old_dir), _old_name,
1106 NCP_ISTRUCT(new_dir), _new_name);
1107
1108 if (res == 0)
1109 {
1110 ncp_invalid_dir_cache(old_dir);
1111 ncp_invalid_dir_cache(new_dir);
1112 }
1113 else
1114 {
1115 res = -EACCES;
1116 }
1117
1118 finished:
1119 iput(old_dir);
1120 iput(new_dir);
1121 return res;
1122 }
1123
1124
1125
1126
1127
1128 static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
1129
1130
1131
1132 extern struct timezone sys_tz;
1133
1134 static int
1135 utc2local(int time)
1136 {
1137 return time - sys_tz.tz_minuteswest*60;
1138 }
1139
1140 static int
1141 local2utc(int time)
1142 {
1143 return time + sys_tz.tz_minuteswest*60;
1144 }
1145
1146
1147
1148 int
1149 ncp_date_dos2unix(unsigned short time,unsigned short date)
1150 {
1151 int month,year,secs;
1152
1153 month = ((date >> 5) & 15)-1;
1154 year = date >> 9;
1155 secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400*
1156 ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
1157 month < 2 ? 1 : 0)+3653);
1158
1159 return local2utc(secs);
1160 }
1161
1162
1163
1164 void
1165 ncp_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date)
1166 {
1167 int day,year,nl_day,month;
1168
1169 unix_date = utc2local(unix_date);
1170 *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+
1171 (((unix_date/3600) % 24) << 11);
1172 day = unix_date/86400-3652;
1173 year = day/365;
1174 if ((year+3)/4+365*year > day) year--;
1175 day -= (year+3)/4+365*year;
1176 if (day == 59 && !(year & 3)) {
1177 nl_day = day;
1178 month = 2;
1179 }
1180 else {
1181 nl_day = (year & 3) || day <= 59 ? day : day-1;
1182 for (month = 0; month < 12; month++)
1183 if (day_n[month] > nl_day) break;
1184 }
1185 *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);
1186 }