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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [fs/] [smbfs/] [inode.c] - Blame information for rev 199

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

Line No. Rev Author Line
1 199 simons
/*
2
 *  inode.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
5
 *
6
 */
7
 
8
#include <linux/module.h>
9
 
10
#include <asm/system.h>
11
#include <asm/segment.h>
12
 
13
#include <linux/sched.h>
14
#include <linux/smb_fs.h>
15
#include <linux/smbno.h>
16
#include <linux/kernel.h>
17
#include <linux/mm.h>
18
#include <linux/string.h>
19
#include <linux/stat.h>
20
#include <linux/errno.h>
21
#include <linux/locks.h>
22
#include <linux/fcntl.h>
23
#include <linux/malloc.h>
24
 
25
extern int close_fp(struct file *filp);
26
 
27
static void smb_put_inode(struct inode *);
28
static void smb_read_inode(struct inode *);
29
static void smb_put_super(struct super_block *);
30
static void smb_statfs(struct super_block *, struct statfs *, int bufsiz);
31
 
32
static struct super_operations smb_sops =
33
{
34
        smb_read_inode,         /* read inode */
35
        smb_notify_change,      /* notify change */
36
        NULL,                   /* write inode */
37
        smb_put_inode,          /* put inode */
38
        smb_put_super,          /* put superblock */
39
        NULL,                   /* write superblock */
40
        smb_statfs,             /* stat filesystem */
41
        NULL
42
};
43
 
44
/* smb_read_inode: Called from iget, it only traverses the allocated
45
   smb_inode_info's and initializes the inode from the data found
46
   there.  It does not allocate or deallocate anything. */
47
 
48
static void
49
smb_read_inode(struct inode *inode)
50
{
51
        /* Our task should be extremely simple here. We only have to
52
           look up the information somebody else (smb_iget) put into
53
           the inode tree. */
54
        struct smb_server *server = SMB_SERVER(inode);
55
        struct smb_inode_info *inode_info
56
        = smb_find_inode(server, inode->i_ino);
57
 
58
        if (inode_info == NULL)
59
        {
60
                /* Ok, now we're in trouble. The inode info is not
61
                   there. What should we do now??? */
62
                printk("smb_read_inode: inode %ld info not found\n",
63
                        inode->i_ino);
64
                return;
65
        }
66
        inode_info->state = SMB_INODE_VALID;
67
 
68
        SMB_INOP(inode) = inode_info;
69
        inode->i_mode = inode_info->finfo.f_mode;
70
        inode->i_nlink = inode_info->finfo.f_nlink;
71
        inode->i_uid = inode_info->finfo.f_uid;
72
        inode->i_gid = inode_info->finfo.f_gid;
73
        inode->i_rdev = inode_info->finfo.f_rdev;
74
        inode->i_size = inode_info->finfo.f_size;
75
        inode->i_mtime = inode_info->finfo.f_mtime;
76
        inode->i_ctime = inode_info->finfo.f_ctime;
77
        inode->i_atime = inode_info->finfo.f_atime;
78
        inode->i_blksize = inode_info->finfo.f_blksize;
79
        inode->i_blocks = inode_info->finfo.f_blocks;
80
 
81
        if (S_ISREG(inode->i_mode))
82
        {
83
                inode->i_op = &smb_file_inode_operations;
84
        } else if (S_ISDIR(inode->i_mode))
85
        {
86
                inode->i_op = &smb_dir_inode_operations;
87
        } else
88
        {
89
                inode->i_op = NULL;
90
        }
91
}
92
 
93
static void
94
smb_put_inode(struct inode *inode)
95
{
96
        struct smb_server *server = SMB_SERVER(inode);
97
        struct smb_inode_info *info = SMB_INOP(inode);
98
        __u32 mtime = inode->i_mtime;
99
 
100
        if (inode->i_count > 1) {
101
                printk("smb_put_inode: in use device %s, inode %ld count=%ld\n",
102
                        kdevname(inode->i_dev), inode->i_ino, inode->i_count);
103
                return;
104
        }
105
 
106
        if (S_ISDIR(inode->i_mode))
107
        {
108
                smb_invalid_dir_cache(inode->i_ino);
109
        } else
110
        {
111
                /*
112
                 * Clear the length so the info structure can't be found.
113
                 */
114
                info->finfo.len = 0;
115
        }
116
        clear_inode(inode);
117
 
118
        /*
119
         * We don't want the inode to be reused as free if we block here,
120
         * so temporarily increment i_count.
121
         */
122
        inode->i_count++;
123
        if (info) {
124
                if (info->finfo.opened != 0)
125
                {
126
                        if (smb_proc_close(server, info->finfo.fileid, mtime))
127
                        {
128
                                /* We can't do anything but complain. */
129
                                printk("smb_put_inode: could not close %s\n",
130
                                        info->finfo.name);
131
                        }
132
                }
133
                smb_free_inode_info(info);
134
        } else
135
                printk("smb_put_inode: no inode info??\n");
136
 
137
        inode->i_count--;
138
}
139
 
140
static void
141
smb_put_super(struct super_block *sb)
142
{
143
        struct smb_server *server = &(SMB_SBP(sb)->s_server);
144
 
145
        smb_proc_disconnect(server);
146
        smb_dont_catch_keepalive(server);
147
        close_fp(server->sock_file);
148
 
149
        lock_super(sb);
150
 
151
        smb_free_all_inodes(server);
152
 
153
        smb_vfree(server->packet);
154
        server->packet = NULL;
155
 
156
        sb->s_dev = 0;
157
        smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
158
 
159
        unlock_super(sb);
160
 
161
        MOD_DEC_USE_COUNT;
162
}
163
 
164
struct smb_mount_data_v4
165
{
166
        int version;
167
        unsigned int fd;
168
        uid_t mounted_uid;
169
        struct sockaddr_in addr;
170
 
171
        char server_name[17];
172
        char client_name[17];
173
        char service[64];
174
        char root_path[64];
175
 
176
        char username[64];
177
        char password[64];
178
 
179
        unsigned short max_xmit;
180
 
181
        uid_t uid;
182
        gid_t gid;
183
        mode_t file_mode;
184
        mode_t dir_mode;
185
};
186
 
187
static int
188
smb_get_mount_data(struct smb_mount_data *target, void *source)
189
{
190
        struct smb_mount_data_v4 *v4 = (struct smb_mount_data_v4 *) source;
191
        struct smb_mount_data *cur = (struct smb_mount_data *) source;
192
 
193
        if (source == NULL)
194
        {
195
                return 1;
196
        }
197
        if (cur->version == SMB_MOUNT_VERSION)
198
        {
199
                memcpy(target, cur, sizeof(struct smb_mount_data));
200
                return 0;
201
        }
202
        if (v4->version == 4)
203
        {
204
                target->version = 5;
205
                target->fd = v4->fd;
206
                target->mounted_uid = v4->mounted_uid;
207
                target->addr = v4->addr;
208
 
209
                memcpy(target->server_name, v4->server_name, 17);
210
                memcpy(target->client_name, v4->client_name, 17);
211
                memcpy(target->service, v4->service, 64);
212
                memcpy(target->root_path, v4->root_path, 64);
213
                memcpy(target->username, v4->username, 64);
214
                memcpy(target->password, v4->password, 64);
215
 
216
                target->max_xmit = v4->max_xmit;
217
                target->uid = v4->uid;
218
                target->gid = v4->gid;
219
                target->file_mode = v4->file_mode;
220
                target->dir_mode = v4->dir_mode;
221
 
222
                memset(target->domain, 0, 64);
223
                strcpy(target->domain, "?");
224
                return 0;
225
        }
226
        return 1;
227
}
228
 
229
struct super_block *
230
smb_read_super(struct super_block *sb, void *raw_data, int silent)
231
{
232
        struct smb_mount_data data;
233
        struct smb_server *server;
234
        struct smb_sb_info *smb_sb;
235
        unsigned int fd;
236
        struct file *filp;
237
        kdev_t dev = sb->s_dev;
238
        int error;
239
 
240
        MOD_INC_USE_COUNT;
241
 
242
        if (smb_get_mount_data(&data, raw_data) != 0)
243
        {
244
                printk("smb_read_super: wrong data argument\n");
245
                sb->s_dev = 0;
246
                MOD_DEC_USE_COUNT;
247
                return NULL;
248
        }
249
        fd = data.fd;
250
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
251
        {
252
                printk("smb_read_super: invalid file descriptor\n");
253
                sb->s_dev = 0;
254
                MOD_DEC_USE_COUNT;
255
                return NULL;
256
        }
257
        if (!S_ISSOCK(filp->f_inode->i_mode))
258
        {
259
                printk("smb_read_super: not a socket!\n");
260
                sb->s_dev = 0;
261
                MOD_DEC_USE_COUNT;
262
                return NULL;
263
        }
264
        /* We must malloc our own super-block info */
265
        smb_sb = (struct smb_sb_info *) smb_kmalloc(sizeof(struct smb_sb_info),
266
                                                    GFP_KERNEL);
267
 
268
        if (smb_sb == NULL)
269
        {
270
                printk("smb_read_super: could not alloc smb_sb_info\n");
271
                sb->s_dev = 0;
272
                MOD_DEC_USE_COUNT;
273
                return NULL;
274
        }
275
        filp->f_count += 1;
276
 
277
        lock_super(sb);
278
 
279
        SMB_SBP(sb) = smb_sb;
280
 
281
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
282
        sb->s_blocksize_bits = 10;
283
        sb->s_magic = SMB_SUPER_MAGIC;
284
        sb->s_dev = dev;
285
        sb->s_op = &smb_sops;
286
 
287
        server = &(SMB_SBP(sb)->s_server);
288
        server->sock_file = filp;
289
        server->lock = 0;
290
        server->wait = NULL;
291
        server->packet = NULL;
292
        server->max_xmit = data.max_xmit;
293
        if (server->max_xmit <= 0)
294
        {
295
                server->max_xmit = SMB_DEF_MAX_XMIT;
296
        }
297
        server->tid = 0;
298
        server->pid = current->pid;
299
        server->mid = current->pid + 20;
300
 
301
        server->m = data;
302
        server->m.file_mode = (server->m.file_mode &
303
                               (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
304
        server->m.dir_mode = (server->m.dir_mode &
305
                              (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
306
 
307
        smb_init_root(server);
308
 
309
        error = smb_proc_connect(server);
310
 
311
        unlock_super(sb);
312
 
313
        if (error < 0)
314
        {
315
                sb->s_dev = 0;
316
                DPRINTK("smb_read_super: Failed connection, bailing out "
317
                        "(error = %d).\n", -error);
318
                goto fail;
319
        }
320
        if (server->protocol >= PROTOCOL_LANMAN2)
321
        {
322
                server->case_handling = CASE_DEFAULT;
323
        } else
324
        {
325
                server->case_handling = CASE_LOWER;
326
        }
327
 
328
        if ((error = smb_proc_dskattr(sb, &(SMB_SBP(sb)->s_attr))) < 0)
329
        {
330
                sb->s_dev = 0;
331
                printk("smb_read_super: could not get super block "
332
                       "attributes\n");
333
                goto fail;
334
        }
335
        smb_init_root_dirent(server, &(server->root.finfo));
336
 
337
        if (!(sb->s_mounted = iget(sb, smb_info_ino(&(server->root)))))
338
        {
339
                sb->s_dev = 0;
340
                printk("smb_read_super: get root inode failed\n");
341
                goto fail;
342
        }
343
        return sb;
344
 
345
      fail:
346
        if (server->packet != NULL)
347
        {
348
                smb_vfree(server->packet);
349
                server->packet = NULL;
350
        }
351
        filp->f_count -= 1;
352
        smb_dont_catch_keepalive(server);
353
        smb_kfree_s(SMB_SBP(sb), sizeof(struct smb_sb_info));
354
        MOD_DEC_USE_COUNT;
355
        return NULL;
356
}
357
 
358
static void
359
smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
360
{
361
        int error;
362
        struct smb_dskattr attr;
363
        struct statfs tmp;
364
 
365
        error = smb_proc_dskattr(sb, &attr);
366
 
367
        if (error)
368
        {
369
                printk("smb_statfs: dskattr error = %d\n", -error);
370
                attr.total = attr.allocblocks = attr.blocksize =
371
                    attr.free = 0;
372
        }
373
        tmp.f_type = SMB_SUPER_MAGIC;
374
        tmp.f_bsize = attr.blocksize * attr.allocblocks;
375
        tmp.f_blocks = attr.total;
376
        tmp.f_bfree = attr.free;
377
        tmp.f_bavail = attr.free;
378
        tmp.f_files = -1;
379
        tmp.f_ffree = -1;
380
        tmp.f_namelen = SMB_MAXPATHLEN;
381
        memcpy_tofs(buf, &tmp, bufsiz);
382
}
383
 
384
int
385
smb_notify_change(struct inode *inode, struct iattr *attr)
386
{
387
        int error = 0;
388
 
389
        if ((error = inode_change_ok(inode, attr)) < 0)
390
                return error;
391
 
392
        if (((attr->ia_valid & ATTR_UID) &&
393
             (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
394
                return -EPERM;
395
 
396
        if (((attr->ia_valid & ATTR_GID) &&
397
             (attr->ia_gid != SMB_SERVER(inode)->m.gid)))
398
                return -EPERM;
399
 
400
        if (attr->ia_valid & ATTR_MODE) {
401
                struct smb_dirent *fold = SMB_FINFO(inode);
402
                struct smb_dirent finfo;
403
 
404
                if (attr->ia_mode & ~(S_IFREG | S_IFDIR |
405
                                      S_IRWXU | S_IRWXG | S_IRWXO))
406
                        return -EPERM;
407
 
408
                memset((char *)&finfo, 0, sizeof(finfo));
409
                finfo.attr = fold->attr;
410
 
411
                if((attr->ia_mode & 0200) == 0)
412
                    finfo.attr |= aRONLY;
413
                else
414
                    finfo.attr &= ~aRONLY;
415
 
416
                if ((error = smb_proc_setattr(SMB_SERVER(inode),
417
                                              inode, &finfo)) >= 0)
418
                {
419
                        fold->attr = finfo.attr;
420
                        if ((attr->ia_mode & 0200) == 0)
421
                                inode->i_mode &= ~0222;
422
                        else
423
                                inode->i_mode |= 0222;
424
                }
425
        }
426
 
427
        if ((attr->ia_valid & ATTR_SIZE) != 0)
428
        {
429
 
430
                if ((error = smb_make_open(inode, O_WRONLY)) < 0)
431
                        goto fail;
432
 
433
                if ((error = smb_proc_trunc(SMB_SERVER(inode),
434
                                            SMB_FINFO(inode)->fileid,
435
                                            attr->ia_size)) < 0)
436
                        goto fail;
437
 
438
        }
439
 
440
        /* ATTR_CTIME and ATTR_ATIME can not be set via SMB, so ignore it. */
441
 
442
        if (attr->ia_valid & ATTR_MTIME)
443
        {
444
                if (smb_make_open(inode, O_WRONLY) != 0)
445
                        error = -EACCES;
446
                else
447
                        inode->i_mtime = attr->ia_mtime;
448
        }
449
      fail:
450
        smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));
451
        return error;
452
}
453
 
454
 
455
#ifdef DEBUG_SMB_MALLOC
456
int smb_malloced;
457
int smb_current_kmalloced;
458
int smb_current_vmalloced;
459
#endif
460
 
461
static struct file_system_type smb_fs_type =
462
{
463
        smb_read_super, "smbfs", 0, NULL
464
};
465
 
466
int
467
init_smb_fs(void)
468
{
469
        return register_filesystem(&smb_fs_type);
470
}
471
 
472
#ifdef MODULE
473
int
474
init_module(void)
475
{
476
        int status;
477
 
478
        DPRINTK("smbfs: init_module called\n");
479
 
480
#ifdef DEBUG_SMB_MALLOC
481
        smb_malloced = 0;
482
        smb_current_kmalloced = 0;
483
        smb_current_vmalloced = 0;
484
#endif
485
 
486
        smb_init_dir_cache();
487
 
488
        if ((status = init_smb_fs()) == 0)
489
                register_symtab(0);
490
        return status;
491
}
492
 
493
void
494
cleanup_module(void)
495
{
496
        DPRINTK("smbfs: cleanup_module called\n");
497
        smb_free_dir_cache();
498
        unregister_filesystem(&smb_fs_type);
499
#ifdef DEBUG_SMB_MALLOC
500
        printk("smb_malloced: %d\n", smb_malloced);
501
        printk("smb_current_kmalloced: %d\n", smb_current_kmalloced);
502
        printk("smb_current_vmalloced: %d\n", smb_current_vmalloced);
503
#endif
504
}
505
 
506
#endif

powered by: WebSVN 2.1.0

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