OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [smbfs/] [dir.c] - Blame information for rev 1628

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1628 jcastillo
/*
2
 *  dir.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
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/smb_fs.h>
15
#include <linux/smbno.h>
16
#include <asm/segment.h>
17
#include <asm/semaphore.h>
18
#include <linux/errno.h>
19
 
20
static int
21
 smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count);
22
 
23
static int
24
 smb_readdir(struct inode *inode, struct file *filp,
25
             void *dirent, filldir_t filldir);
26
 
27
static struct smb_inode_info *
28
 smb_find_dir_inode(struct inode *parent, const char *name, int len);
29
 
30
static int
31
 smb_lookup(struct inode *dir, const char *__name,
32
            int len, struct inode **result);
33
 
34
static int
35
 smb_create(struct inode *dir, const char *name, int len, int mode,
36
            struct inode **result);
37
 
38
static int
39
 smb_mkdir(struct inode *dir, const char *name, int len, int mode);
40
 
41
static int
42
 smb_rmdir(struct inode *dir, const char *name, int len);
43
 
44
static int
45
 smb_unlink(struct inode *dir, const char *name, int len);
46
 
47
static int
48
 smb_rename(struct inode *old_dir, const char *old_name, int old_len,
49
            struct inode *new_dir, const char *new_name, int new_len,
50
            int must_be_dir);
51
 
52
static struct file_operations smb_dir_operations =
53
{
54
        NULL,                   /* lseek - default */
55
        smb_dir_read,           /* read - bad */
56
        NULL,                   /* write - bad */
57
        smb_readdir,            /* readdir */
58
        NULL,                   /* select - default */
59
        smb_ioctl,              /* ioctl - default */
60
        NULL,                   /* mmap */
61
        NULL,                   /* no special open code */
62
        NULL,                   /* no special release code */
63
        NULL                    /* fsync */
64
};
65
 
66
struct inode_operations smb_dir_inode_operations =
67
{
68
        &smb_dir_operations,    /* default directory file ops */
69
        smb_create,             /* create */
70
        smb_lookup,             /* lookup */
71
        NULL,                   /* link */
72
        smb_unlink,             /* unlink */
73
        NULL,                   /* symlink */
74
        smb_mkdir,              /* mkdir */
75
        smb_rmdir,              /* rmdir */
76
        NULL,                   /* mknod */
77
        smb_rename,             /* rename */
78
        NULL,                   /* readlink */
79
        NULL,                   /* follow_link */
80
        NULL,                   /* readpage */
81
        NULL,                   /* writepage */
82
        NULL,                   /* bmap */
83
        NULL,                   /* truncate */
84
        NULL,                   /* permission */
85
        NULL                    /* smap */
86
};
87
 
88
static int
89
strncasecmp(const char *s1, const char *s2, int len)
90
{
91
        int result = 0;
92
 
93
        for (; len > 0; len -= 1)
94
        {
95
                char c1, c2;
96
 
97
                c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - ('a' - 'A') : *s1;
98
                c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - ('a' - 'A') : *s2;
99
                s1 += 1;
100
                s2 += 1;
101
 
102
                if ((result = c1 - c2) != 0 || c1 == 0)
103
                {
104
                        return result;
105
                }
106
        }
107
        return result;
108
}
109
 
110
struct smb_inode_info *
111
smb_find_inode(struct smb_server *server, ino_t ino)
112
{
113
        struct smb_inode_info *root = &(server->root);
114
        struct smb_inode_info *this = root;
115
 
116
        do
117
        {
118
                if (ino == smb_info_ino(this))
119
                {
120
                        return this;
121
                }
122
                this = this->next;
123
        }
124
        while (this != root);
125
 
126
        return NULL;
127
}
128
 
129
static ino_t
130
smb_fresh_inodes(struct smb_server *server, int no)
131
{
132
        static ino_t seed = 1;
133
        struct smb_inode_info *root = &(server->root);
134
        struct smb_inode_info *this;
135
 
136
      retry:
137
        if (seed + no <= no)
138
        {
139
                /* avoid inode number of 0 at wrap-around */
140
                seed += no;
141
        }
142
        this = root;
143
        do
144
        {
145
                /* We assume that ino_t is unsigned! */
146
                if (this->finfo.f_ino - seed < no)
147
                {
148
                        seed += no;
149
                        goto retry;
150
                }
151
                this = this->next;
152
        }
153
        while (this != root);
154
 
155
        seed += no;
156
 
157
        return seed - no;
158
}
159
 
160
static int
161
smb_dir_read(struct inode *inode, struct file *filp, char *buf, int count)
162
{
163
        return -EISDIR;
164
}
165
 
166
 
167
static unsigned long c_ino = 0;
168
static kdev_t c_dev;
169
static int c_size;
170
static int c_seen_eof;
171
static int c_last_returned_index;
172
static struct smb_dirent *c_entry = NULL;
173
 
174
static struct smb_dirent *
175
smb_search_in_cache(struct inode *dir, unsigned long f_pos)
176
{
177
        int i;
178
 
179
        if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino))
180
        {
181
                return NULL;
182
        }
183
        for (i = 0; i < c_size; i++)
184
        {
185
                if (f_pos == c_entry[i].f_pos)
186
                {
187
                        c_last_returned_index = i;
188
                        return &(c_entry[i]);
189
                }
190
        }
191
        return NULL;
192
}
193
 
194
static int
195
smb_refill_dir_cache(struct smb_server *server, struct inode *dir,
196
                     unsigned long f_pos)
197
{
198
        int result;
199
        static struct semaphore sem = MUTEX;
200
        int i;
201
        ino_t ino;
202
 
203
        do
204
        {
205
                down(&sem);
206
                result = smb_proc_readdir(server, dir, f_pos,
207
                                          SMB_READDIR_CACHE_SIZE, c_entry);
208
 
209
                if (result <= 0)
210
                {
211
                        smb_invalid_dir_cache(dir->i_ino);
212
                        up(&sem);
213
                        return result;
214
                }
215
                c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
216
                c_dev = dir->i_dev;
217
                c_ino = dir->i_ino;
218
                c_size = result;
219
                c_last_returned_index = 0;
220
 
221
                ino = smb_fresh_inodes(server, c_size);
222
                for (i = 0; i < c_size; i++)
223
                {
224
                        c_entry[i].f_ino = ino;
225
                        ino += 1;
226
                }
227
 
228
                up(&sem);
229
 
230
        }
231
        while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino));
232
 
233
        return result;
234
}
235
 
236
static int
237
smb_readdir(struct inode *dir, struct file *filp,
238
            void *dirent, filldir_t filldir)
239
{
240
        int result, i = 0;
241
        struct smb_dirent *entry = NULL;
242
        struct smb_server *server = SMB_SERVER(dir);
243
 
244
        DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos);
245
        DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n",
246
                 dir->i_ino, c_ino);
247
 
248
        if ((dir == NULL) || !S_ISDIR(dir->i_mode))
249
        {
250
                printk("smb_readdir: dir is NULL or not a directory\n");
251
                return -EBADF;
252
        }
253
        if (c_entry == NULL)
254
        {
255
                i = sizeof(struct smb_dirent) * SMB_READDIR_CACHE_SIZE;
256
                c_entry = (struct smb_dirent *) smb_vmalloc(i);
257
                if (c_entry == NULL)
258
                {
259
                        printk("smb_readdir: no MEMORY for cache\n");
260
                        return -ENOMEM;
261
                }
262
        }
263
        if (filp->f_pos == 0)
264
        {
265
                c_ino = 0;
266
                c_dev = 0;
267
                c_seen_eof = 0;
268
 
269
                if (filldir(dirent, ".", 1, filp->f_pos,
270
                            smb_info_ino(SMB_INOP(dir))) < 0)
271
                {
272
                        return 0;
273
                }
274
                filp->f_pos += 1;
275
        }
276
        if (filp->f_pos == 1)
277
        {
278
                if (filldir(dirent, "..", 2, filp->f_pos,
279
                            smb_info_ino(SMB_INOP(dir)->dir)) < 0)
280
                {
281
                        return 0;
282
                }
283
                filp->f_pos += 1;
284
        }
285
        entry = smb_search_in_cache(dir, filp->f_pos);
286
 
287
        if (entry == NULL)
288
        {
289
                if (c_seen_eof)
290
                {
291
                        /* End of directory */
292
                        return 0;
293
                }
294
                result = smb_refill_dir_cache(server, dir, filp->f_pos);
295
                if (result <= 0)
296
                {
297
                        return result;
298
                }
299
                entry = c_entry;
300
        }
301
        while (entry < &(c_entry[c_size]))
302
        {
303
                /* We found it.  For getwd(), we have to return the
304
                   correct inode in d_ino if the inode is currently in
305
                   use. Otherwise the inode number does not
306
                   matter. (You can argue a lot about this..) */
307
 
308
                struct smb_inode_info *ino_info
309
                = smb_find_dir_inode(dir, entry->name, entry->len);
310
 
311
                ino_t ino = entry->f_ino;
312
 
313
                if (ino_info != NULL)
314
                {
315
                        ino = smb_info_ino(ino_info);
316
                }
317
                DDPRINTK("smb_readdir: entry->name = %s\n", entry->name);
318
                DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
319
 
320
                if (filldir(dirent, entry->name, strlen(entry->name),
321
                            entry->f_pos, ino) < 0)
322
                {
323
                        break;
324
                }
325
                if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino)
326
                    || (entry->f_pos != filp->f_pos))
327
                {
328
                        /* Someone has destroyed the cache while we slept
329
                           in filldir */
330
                        break;
331
                }
332
                filp->f_pos += 1;
333
                entry += 1;
334
        }
335
        return 0;
336
}
337
 
338
void
339
smb_init_dir_cache(void)
340
{
341
        c_ino = 0;
342
        c_dev = 0;
343
        c_entry = NULL;
344
}
345
 
346
void
347
smb_invalid_dir_cache(unsigned long ino)
348
{
349
        /* TODO: check for dev as well */
350
        if (ino == c_ino)
351
        {
352
                c_ino = 0;
353
                c_seen_eof = 0;
354
        }
355
}
356
 
357
void
358
smb_free_dir_cache(void)
359
{
360
        if (c_entry != NULL)
361
        {
362
                smb_vfree(c_entry);
363
        }
364
        c_entry = NULL;
365
}
366
 
367
/* Insert a NEW smb_inode_info into the inode tree of our filesystem,
368
   under dir. The caller must assure that it's not already there. We
369
   assume that path is allocated for us. */
370
 
371
static struct inode *
372
smb_iget(struct inode *dir, struct smb_inode_info *new_inode_info)
373
{
374
        struct inode *inode;
375
        struct smb_inode_info *root;
376
 
377
        if ((dir == NULL) || (new_inode_info == NULL))
378
        {
379
                printk("smb_iget: parameter is NULL\n");
380
                return NULL;
381
        }
382
        new_inode_info->state = SMB_INODE_LOOKED_UP;
383
        new_inode_info->nused = 0;
384
        new_inode_info->dir = SMB_INOP(dir);
385
 
386
        SMB_INOP(dir)->nused += 1;
387
 
388
        /*
389
         * We have to link the new inode_info into the doubly linked
390
         * list of inode_infos to make a complete linear search possible.
391
         */
392
        root = &(SMB_SERVER(dir)->root);
393
 
394
        new_inode_info->prev = root;
395
        new_inode_info->next = root->next;
396
        root->next->prev = new_inode_info;
397
        root->next = new_inode_info;
398
 
399
        if (!(inode = iget(dir->i_sb, smb_info_ino(new_inode_info))))
400
        {
401
                printk("smb_iget: iget failed!");
402
                /*
403
                 * If we blocked in iget(), another task may have referenced
404
                 * the info structure ... clean up with smb_free_inode_info.
405
                 */
406
                smb_free_inode_info(new_inode_info);
407
                return NULL;
408
        }
409
 
410
        return inode;
411
}
412
 
413
void
414
smb_free_inode_info(struct smb_inode_info *i)
415
{
416
        if (i == NULL)
417
        {
418
                printk("smb_free_inode: i == NULL\n");
419
                return;
420
        }
421
        i->state = SMB_INODE_CACHED;
422
        while ((i->nused == 0) && (i->state == SMB_INODE_CACHED))
423
        {
424
                struct smb_inode_info *dir = i->dir;
425
 
426
                i->next->prev = i->prev;
427
                i->prev->next = i->next;
428
 
429
                smb_kfree_s(i, sizeof(struct smb_inode_info));
430
 
431
                if (dir == NULL)
432
                {
433
                        return;
434
                }
435
                dir->nused -= 1;
436
                i = dir;
437
        }
438
}
439
 
440
void
441
smb_init_root(struct smb_server *server)
442
{
443
        struct smb_inode_info *root = &(server->root);
444
 
445
        root->state = SMB_INODE_LOOKED_UP;
446
        root->nused = 1;
447
        root->dir = NULL;
448
        root->next = root->prev = root;
449
 
450
        return;
451
}
452
 
453
void
454
smb_free_all_inodes(struct smb_server *server)
455
{
456
        /* Here nothing should be to do. I do not know whether it's
457
           better to leave some memory allocated or be stuck in an
458
           endless loop */
459
#if 1
460
        struct smb_inode_info *root = &(server->root);
461
 
462
        if (root->next != root)
463
        {
464
                printk("smb_free_all_inodes: INODES LEFT!!!\n");
465
        }
466
        while (root->next != root)
467
        {
468
                printk("smb_free_all_inodes: freeing inode\n");
469
                smb_free_inode_info(root->next);
470
                /* In case we have an endless loop.. */
471
                schedule();
472
        }
473
#endif
474
 
475
        return;
476
}
477
 
478
/* This has to be called when a connection has gone down, so that all
479
   file-handles we got from the server are invalid */
480
void
481
smb_invalidate_all_inodes(struct smb_server *server)
482
{
483
        struct smb_inode_info *ino = &(server->root);
484
 
485
        do
486
        {
487
                ino->finfo.opened = 0;
488
                ino = ino->next;
489
        }
490
        while (ino != &(server->root));
491
 
492
        return;
493
}
494
 
495
static int
496
compare_filename(const struct smb_server *server,
497
                 const char *s1, int len, struct smb_dirent *entry)
498
{
499
        if (len != entry->len)
500
        {
501
#if 0
502
                /* Check whether the entry is about to be removed */
503
                if (!entry->len)
504
                        printk("SMBFS: dead entry %s\n", entry->name);
505
#endif
506
                return 1;
507
        }
508
        if (server->case_handling == CASE_DEFAULT)
509
        {
510
                return strncasecmp(s1, entry->name, len);
511
        }
512
        return strncmp(s1, entry->name, len);
513
}
514
 
515
/*
516
 * Search for the smb_inode_info that belongs to this name,
517
 * currently by a complete linear search through the inodes
518
 * belonging to this filesystem.
519
 *
520
 * Note that this returns files as well as directories.
521
 */
522
static struct smb_inode_info *
523
smb_find_dir_inode(struct inode *parent, const char *name, int len)
524
{
525
        struct smb_server *server = SMB_SERVER(parent);
526
        struct smb_inode_info *dir = SMB_INOP(parent);
527
        struct smb_inode_info *result = &(server->root);
528
 
529
        if (name == NULL)
530
        {
531
                return NULL;
532
        }
533
        if ((len == 1) && (name[0] == '.'))
534
        {
535
                return dir;
536
        }
537
        if ((len == 2) && (name[0] == '.') && (name[1] == '.'))
538
        {
539
                return dir->dir;
540
        }
541
        do
542
        {
543
                if (result->dir == dir)
544
                {
545
                        if (compare_filename(server, name, len,
546
                                             &(result->finfo)) == 0)
547
                        {
548
                                return result;
549
                        }
550
                }
551
                result = result->next;
552
        }
553
        while (result != &(server->root));
554
 
555
        return NULL;
556
}
557
 
558
static int
559
smb_lookup(struct inode *dir, const char *name, int len,
560
           struct inode **result)
561
{
562
        struct smb_dirent finfo;
563
        struct smb_inode_info *result_info;
564
        int error;
565
        int found_in_cache;
566
 
567
        struct smb_inode_info *new_inode_info = NULL;
568
 
569
        *result = NULL;
570
 
571
        if (!dir || !S_ISDIR(dir->i_mode))
572
        {
573
                printk("smb_lookup: inode is NULL or not a directory.\n");
574
                iput(dir);
575
                return -ENOENT;
576
        }
577
        DDPRINTK("smb_lookup: %s\n", name);
578
 
579
        /* Fast cheat for . */
580
        if (len == 0 || (len == 1 && name[0] == '.'))
581
        {
582
                *result = dir;
583
                return 0;
584
        }
585
        /* ..and for .. */
586
        if (len == 2 && name[0] == '.' && name[1] == '.')
587
        {
588
                struct smb_inode_info *parent = SMB_INOP(dir)->dir;
589
 
590
                if (parent->state == SMB_INODE_CACHED)
591
                {
592
                        parent->state = SMB_INODE_LOOKED_UP;
593
                }
594
                *result = iget(dir->i_sb, smb_info_ino(parent));
595
                iput(dir);
596
                if (*result == 0)
597
                {
598
                        return -EACCES;
599
                }
600
                return 0;
601
        }
602
        result_info = smb_find_dir_inode(dir, name, len);
603
 
604
      in_tree:
605
        if (result_info != NULL)
606
        {
607
                if (result_info->state == SMB_INODE_CACHED)
608
                {
609
                        result_info->state = SMB_INODE_LOOKED_UP;
610
                }
611
                *result = iget(dir->i_sb, smb_info_ino(result_info));
612
                iput(dir);
613
 
614
                if (new_inode_info != NULL)
615
                {
616
                        smb_kfree_s(new_inode_info,
617
                                    sizeof(struct smb_inode_info));
618
                }
619
                if (*result == NULL)
620
                {
621
                        return -EACCES;
622
                }
623
                return 0;
624
        }
625
        /* If the file is in the dir cache, we do not have to ask the
626
           server. */
627
        found_in_cache = 0;
628
 
629
        if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0))
630
        {
631
                int first = c_last_returned_index;
632
                int i;
633
 
634
                i = first;
635
                do
636
                {
637
                        if (compare_filename(SMB_SERVER(dir), name, len,
638
                                             &(c_entry[i])) == 0)
639
                        {
640
                                finfo = c_entry[i];
641
                                found_in_cache = 1;
642
                                break;
643
                        }
644
                        i = (i + 1) % c_size;
645
                }
646
                while (i != first);
647
        }
648
        if (found_in_cache == 0)
649
        {
650
                DPRINTK("smb_lookup: not found in cache: %s\n", name);
651
                if (len > SMB_MAXNAMELEN)
652
                {
653
                        iput(dir);
654
                        return -ENAMETOOLONG;
655
                }
656
                error = smb_proc_getattr(dir, name, len, &finfo);
657
                if (error < 0)
658
                {
659
                        iput(dir);
660
                        return error;
661
                }
662
                finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
663
        }
664
        new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
665
                                     GFP_KERNEL);
666
 
667
        /* Here somebody else might have inserted the inode */
668
 
669
        result_info = smb_find_dir_inode(dir, name, len);
670
        if (result_info != NULL)
671
        {
672
                goto in_tree;
673
        }
674
 
675
        if (new_inode_info == NULL)
676
        {
677
                iput(dir);
678
                return -ENOMEM;
679
        }
680
        new_inode_info->finfo = finfo;
681
 
682
        DPRINTK("attr: %x\n", finfo.attr);
683
 
684
        if ((*result = smb_iget(dir, new_inode_info)) == NULL)
685
        {
686
                iput(dir);
687
                return -EACCES;
688
        }
689
        DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info);
690
        iput(dir);
691
        return 0;
692
}
693
 
694
static int
695
smb_create(struct inode *dir, const char *name, int len, int mode,
696
           struct inode **result)
697
{
698
        int error;
699
        struct smb_dirent entry;
700
        struct smb_inode_info *new_inode_info;
701
 
702
        *result = NULL;
703
 
704
        if (!dir || !S_ISDIR(dir->i_mode))
705
        {
706
                printk("smb_create: inode is NULL or not a directory\n");
707
                iput(dir);
708
                return -ENOENT;
709
        }
710
        new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
711
                                     GFP_KERNEL);
712
        if (new_inode_info == NULL)
713
        {
714
                iput(dir);
715
                return -ENOMEM;
716
        }
717
        error = smb_proc_create(dir, name, len, 0, CURRENT_TIME);
718
        if (error < 0)
719
        {
720
                smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
721
                iput(dir);
722
                return error;
723
        }
724
        smb_invalid_dir_cache(dir->i_ino);
725
 
726
        if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0)
727
        {
728
                smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
729
                iput(dir);
730
                return error;
731
        }
732
        entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
733
 
734
        new_inode_info->finfo = entry;
735
 
736
        if ((*result = smb_iget(dir, new_inode_info)) == NULL)
737
        {
738
                iput(dir);
739
                return error;
740
        }
741
        iput(dir);
742
        return 0;
743
}
744
 
745
static int
746
smb_mkdir(struct inode *dir, const char *name, int len, int mode)
747
{
748
        int error;
749
 
750
        if (!dir || !S_ISDIR(dir->i_mode))
751
        {
752
                iput(dir);
753
                return -EINVAL;
754
        }
755
        if ((error = smb_proc_mkdir(dir, name, len)) == 0)
756
        {
757
                smb_invalid_dir_cache(dir->i_ino);
758
        }
759
        iput(dir);
760
        return error;
761
}
762
 
763
static int
764
smb_rmdir(struct inode *dir, const char *name, int len)
765
{
766
        int error;
767
 
768
        if (!dir || !S_ISDIR(dir->i_mode))
769
        {
770
                printk("smb_rmdir: inode is NULL or not a directory\n");
771
                iput(dir);
772
                return -ENOENT;
773
        }
774
        if (smb_find_dir_inode(dir, name, len) != NULL)
775
        {
776
                error = -EBUSY;
777
        } else
778
        {
779
                if ((error = smb_proc_rmdir(dir, name, len)) == 0)
780
                {
781
                        smb_invalid_dir_cache(dir->i_ino);
782
                }
783
        }
784
        iput(dir);
785
        return error;
786
}
787
 
788
static int
789
smb_unlink(struct inode *dir, const char *name, int len)
790
{
791
        int error;
792
 
793
        if (!dir || !S_ISDIR(dir->i_mode))
794
        {
795
                printk("smb_unlink: inode is NULL or not a directory\n");
796
                iput(dir);
797
                return -ENOENT;
798
        }
799
        if (smb_find_dir_inode(dir, name, len) != NULL)
800
        {
801
                error = -EBUSY;
802
        } else
803
        {
804
                if ((error = smb_proc_unlink(dir, name, len)) == 0)
805
                {
806
                        smb_invalid_dir_cache(dir->i_ino);
807
                }
808
        }
809
        iput(dir);
810
        return error;
811
}
812
 
813
static int
814
smb_rename(struct inode *old_dir, const char *old_name, int old_len,
815
           struct inode *new_dir, const char *new_name, int new_len,
816
           int must_be_dir)
817
{
818
        int res;
819
 
820
        if (!old_dir || !S_ISDIR(old_dir->i_mode))
821
        {
822
                printk("smb_rename: old inode is NULL or not a directory\n");
823
                res = -ENOENT;
824
                goto finished;
825
        }
826
        if (!new_dir || !S_ISDIR(new_dir->i_mode))
827
        {
828
                printk("smb_rename: new inode is NULL or not a directory\n");
829
                res = -ENOENT;
830
                goto finished;
831
        }
832
        if ((smb_find_dir_inode(old_dir, old_name, old_len) != NULL)
833
            || (smb_find_dir_inode(new_dir, new_name, new_len) != NULL))
834
        {
835
                res = -EBUSY;
836
                goto finished;
837
        }
838
        res = smb_proc_mv(old_dir, old_name, old_len,
839
                          new_dir, new_name, new_len);
840
 
841
        if (res == -EEXIST)
842
        {
843
                int res1 = smb_proc_unlink(old_dir, new_name, new_len);
844
 
845
                if (res1 == 0)
846
                {
847
                        res = smb_proc_mv(old_dir, old_name, old_len,
848
                                          new_dir, new_name, new_len);
849
                }
850
        }
851
        if (res == 0)
852
        {
853
                smb_invalid_dir_cache(old_dir->i_ino);
854
                smb_invalid_dir_cache(new_dir->i_ino);
855
        }
856
      finished:
857
        iput(old_dir);
858
        iput(new_dir);
859
        return res;
860
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.