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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [ncpfs/] [inode.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  inode.c
3
 *
4
 *  Copyright (C) 1995, 1996 by Volker Lendecke
5
 *  Modified for big endian by J.F. Chadima and David S. Miller
6
 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
7
 *  Modified 1998 Wolfram Pienkoss for NLS
8
 *
9
 */
10
 
11
#include <linux/config.h>
12
#include <linux/module.h>
13
 
14
#include <asm/system.h>
15
#include <asm/uaccess.h>
16
#include <asm/byteorder.h>
17
 
18
#include <linux/sched.h>
19
#include <linux/kernel.h>
20
#include <linux/mm.h>
21
#include <linux/string.h>
22
#include <linux/stat.h>
23
#include <linux/errno.h>
24
#include <linux/locks.h>
25
#include <linux/file.h>
26
#include <linux/fcntl.h>
27
#include <linux/slab.h>
28
#include <linux/vmalloc.h>
29
#include <linux/init.h>
30
 
31
#include <linux/ncp_fs.h>
32
 
33
#include "ncplib_kernel.h"
34
 
35
static void ncp_delete_inode(struct inode *);
36
static void ncp_put_super(struct super_block *);
37
static int  ncp_statfs(struct super_block *, struct statfs *);
38
 
39
static struct super_operations ncp_sops =
40
{
41
        put_inode:      force_delete,
42
        delete_inode:   ncp_delete_inode,
43
        put_super:      ncp_put_super,
44
        statfs:         ncp_statfs,
45
};
46
 
47
extern struct dentry_operations ncp_root_dentry_operations;
48
#ifdef CONFIG_NCPFS_EXTRAS
49
extern struct address_space_operations ncp_symlink_aops;
50
extern int ncp_symlink(struct inode*, struct dentry*, const char*);
51
#endif
52
 
53
/*
54
 * Fill in the ncpfs-specific information in the inode.
55
 */
56
void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo)
57
{
58
        NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum;
59
        NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum;
60
        NCP_FINFO(inode)->volNumber = nwinfo->i.volNumber;
61
 
62
#ifdef CONFIG_NCPFS_STRONG
63
        NCP_FINFO(inode)->nwattr = nwinfo->i.attributes;
64
#endif
65
        NCP_FINFO(inode)->access = nwinfo->access;
66
        NCP_FINFO(inode)->server_file_handle = nwinfo->server_file_handle;
67
        memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle,
68
                        sizeof(nwinfo->file_handle));
69
        DPRINTK("ncp_update_inode: updated %s, volnum=%d, dirent=%u\n",
70
                nwinfo->i.entryName, NCP_FINFO(inode)->volNumber,
71
                NCP_FINFO(inode)->dirEntNum);
72
}
73
 
74
void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo)
75
{
76
        struct nw_info_struct *nwi = &nwinfo->i;
77
        struct ncp_server *server = NCP_SERVER(inode);
78
 
79
        if (!atomic_read(&NCP_FINFO(inode)->opened)) {
80
#ifdef CONFIG_NCPFS_STRONG
81
                NCP_FINFO(inode)->nwattr = nwi->attributes;
82
#endif
83
                if (nwi->attributes & aDIR) {
84
                        inode->i_mode = server->m.dir_mode;
85
                        inode->i_size = NCP_BLOCK_SIZE;
86
                } else {
87
                        inode->i_mode = server->m.file_mode;
88
                        inode->i_size = le32_to_cpu(nwi->dataStreamSize);
89
#ifdef CONFIG_NCPFS_EXTRAS
90
                        if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) {
91
                                switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
92
                                        case aHIDDEN:
93
                                                if (server->m.flags & NCP_MOUNT_SYMLINKS) {
94
                                                        if ( /* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
95
                                                         && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
96
                                                                inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
97
                                                                break;
98
                                                        }
99
                                                }
100
                                                /* FALLTHROUGH */
101
                                        case 0:
102
                                                if (server->m.flags & NCP_MOUNT_EXTRAS)
103
                                                        inode->i_mode |= 0444;
104
                                                break;
105
                                        case aSYSTEM:
106
                                                if (server->m.flags & NCP_MOUNT_EXTRAS)
107
                                                        inode->i_mode |= (inode->i_mode >> 2) & 0111;
108
                                                break;
109
                                        /* case aSYSTEM|aHIDDEN: */
110
                                        default:
111
                                                /* reserved combination */
112
                                                break;
113
                                }
114
                        }
115
#endif
116
                }
117
                if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
118
        }
119
        inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
120
 
121
        inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
122
                                           le16_to_cpu(nwi->modifyDate));
123
        inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
124
                                           le16_to_cpu(nwi->creationDate));
125
        inode->i_atime = ncp_date_dos2unix(0, le16_to_cpu(nwi->lastAccessDate));
126
 
127
        NCP_FINFO(inode)->DosDirNum = nwi->DosDirNum;
128
        NCP_FINFO(inode)->dirEntNum = nwi->dirEntNum;
129
        NCP_FINFO(inode)->volNumber = nwi->volNumber;
130
}
131
 
132
/*
133
 * Fill in the inode based on the ncp_entry_info structure.
134
 */
135
static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
136
{
137
        struct nw_info_struct *nwi = &nwinfo->i;
138
        struct ncp_server *server = NCP_SERVER(inode);
139
 
140
        if (nwi->attributes & aDIR) {
141
                inode->i_mode = server->m.dir_mode;
142
                /* for directories dataStreamSize seems to be some
143
                   Object ID ??? */
144
                inode->i_size = NCP_BLOCK_SIZE;
145
        } else {
146
                inode->i_mode = server->m.file_mode;
147
                inode->i_size = le32_to_cpu(nwi->dataStreamSize);
148
#ifdef CONFIG_NCPFS_EXTRAS
149
                if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS))
150
                 && (nwi->attributes & aSHARED)) {
151
                        switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
152
                                case aHIDDEN:
153
                                        if (server->m.flags & NCP_MOUNT_SYMLINKS) {
154
                                                if (/* (inode->i_size >= NCP_MIN_SYMLINK_SIZE)
155
                                                 && */ (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
156
                                                        inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
157
                                                        break;
158
                                                }
159
                                        }
160
                                        /* FALLTHROUGH */
161
                                case 0:
162
                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
163
                                                inode->i_mode |= 0444;
164
                                        break;
165
                                case aSYSTEM:
166
                                        if (server->m.flags & NCP_MOUNT_EXTRAS)
167
                                                inode->i_mode |= (inode->i_mode >> 2) & 0111;
168
                                        break;
169
                                /* case aSYSTEM|aHIDDEN: */
170
                                default:
171
                                        /* reserved combination */
172
                                        break;
173
                        }
174
                }
175
#endif
176
        }
177
        if (nwi->attributes & aRONLY) inode->i_mode &= ~0222;
178
 
179
        DDPRINTK("ncp_read_inode: inode->i_mode = %u\n", inode->i_mode);
180
 
181
        inode->i_nlink = 1;
182
        inode->i_uid = server->m.uid;
183
        inode->i_gid = server->m.gid;
184
        inode->i_rdev = 0;
185
        inode->i_blksize = NCP_BLOCK_SIZE;
186
 
187
        inode->i_blocks = (inode->i_size + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT;
188
 
189
        inode->i_mtime = ncp_date_dos2unix(le16_to_cpu(nwi->modifyTime),
190
                                           le16_to_cpu(nwi->modifyDate));
191
        inode->i_ctime = ncp_date_dos2unix(le16_to_cpu(nwi->creationTime),
192
                                           le16_to_cpu(nwi->creationDate));
193
        inode->i_atime = ncp_date_dos2unix(0,
194
                                           le16_to_cpu(nwi->lastAccessDate));
195
        ncp_update_inode(inode, nwinfo);
196
}
197
 
198
static struct inode_operations ncp_symlink_inode_operations = {
199
        readlink:       page_readlink,
200
        follow_link:    page_follow_link,
201
        setattr:        ncp_notify_change,
202
};
203
 
204
/*
205
 * Get a new inode.
206
 */
207
struct inode *
208
ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
209
{
210
        struct inode *inode;
211
 
212
        if (info == NULL) {
213
                printk(KERN_ERR "ncp_iget: info is NULL\n");
214
                return NULL;
215
        }
216
 
217
        inode = new_inode(sb);
218
        if (inode) {
219
                init_MUTEX(&NCP_FINFO(inode)->open_sem);
220
                atomic_set(&NCP_FINFO(inode)->opened, info->opened);
221
 
222
                inode->i_ino = info->ino;
223
                ncp_set_attr(inode, info);
224
                if (S_ISREG(inode->i_mode)) {
225
                        inode->i_op = &ncp_file_inode_operations;
226
                        inode->i_fop = &ncp_file_operations;
227
                } else if (S_ISDIR(inode->i_mode)) {
228
                        inode->i_op = &ncp_dir_inode_operations;
229
                        inode->i_fop = &ncp_dir_operations;
230
#ifdef CONFIG_NCPFS_EXTRAS
231
                } else if (S_ISLNK(inode->i_mode)) {
232
                        inode->i_op = &ncp_symlink_inode_operations;
233
                        inode->i_data.a_ops = &ncp_symlink_aops;
234
#endif
235
                }
236
                insert_inode_hash(inode);
237
        } else
238
                printk(KERN_ERR "ncp_iget: iget failed!\n");
239
        return inode;
240
}
241
 
242
static void
243
ncp_delete_inode(struct inode *inode)
244
{
245
        if (S_ISDIR(inode->i_mode)) {
246
                DDPRINTK("ncp_delete_inode: put directory %ld\n", inode->i_ino);
247
        }
248
 
249
        if (ncp_make_closed(inode) != 0) {
250
                /* We can't do anything but complain. */
251
                printk(KERN_ERR "ncp_delete_inode: could not close\n");
252
        }
253
        clear_inode(inode);
254
}
255
 
256
struct super_block *
257
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
258
{
259
        struct ncp_mount_data_kernel data;
260
        struct ncp_server *server;
261
        struct file *ncp_filp;
262
        struct inode *root_inode;
263
        struct inode *sock_inode;
264
        struct socket *sock;
265
        int error;
266
        int default_bufsize;
267
#ifdef CONFIG_NCPFS_PACKET_SIGNING
268
        int options;
269
#endif
270
        struct ncp_entry_info finfo;
271
 
272
        if (raw_data == NULL)
273
                goto out_no_data;
274
        switch (*(int*)raw_data) {
275
                case NCP_MOUNT_VERSION:
276
                        {
277
                                struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
278
 
279
                                data.flags = md->flags;
280
                                data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
281
                                data.mounted_uid = md->mounted_uid;
282
                                data.wdog_pid = md->wdog_pid;
283
                                data.ncp_fd = md->ncp_fd;
284
                                data.time_out = md->time_out;
285
                                data.retry_count = md->retry_count;
286
                                data.uid = md->uid;
287
                                data.gid = md->gid;
288
                                data.file_mode = md->file_mode;
289
                                data.dir_mode = md->dir_mode;
290
                                memcpy(data.mounted_vol, md->mounted_vol,
291
                                        NCP_VOLNAME_LEN+1);
292
                        }
293
                        break;
294
                case NCP_MOUNT_VERSION_V4:
295
                        {
296
                                struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
297
 
298
                                data.flags = md->flags;
299
                                data.int_flags = 0;
300
                                data.mounted_uid = md->mounted_uid;
301
                                data.wdog_pid = md->wdog_pid;
302
                                data.ncp_fd = md->ncp_fd;
303
                                data.time_out = md->time_out;
304
                                data.retry_count = md->retry_count;
305
                                data.uid = md->uid;
306
                                data.gid = md->gid;
307
                                data.file_mode = md->file_mode;
308
                                data.dir_mode = md->dir_mode;
309
                                data.mounted_vol[0] = 0;
310
                        }
311
                        break;
312
                default:
313
                        goto out_bad_mount;
314
        }
315
        ncp_filp = fget(data.ncp_fd);
316
        if (!ncp_filp)
317
                goto out_bad_file;
318
        sock_inode = ncp_filp->f_dentry->d_inode;
319
        if (!S_ISSOCK(sock_inode->i_mode))
320
                goto out_bad_file2;
321
        sock = &sock_inode->u.socket_i;
322
        if (!sock)
323
                goto out_bad_file2;
324
 
325
        if (sock->type == SOCK_STREAM)
326
                default_bufsize = 61440;
327
        else
328
                default_bufsize = 1024;
329
 
330
        sb->s_blocksize = 1024; /* Eh...  Is this correct? */
331
        sb->s_blocksize_bits = 10;
332
        sb->s_magic = NCP_SUPER_MAGIC;
333
        sb->s_op = &ncp_sops;
334
 
335
        server = NCP_SBP(sb);
336
        memset(server, 0, sizeof(*server));
337
 
338
        server->ncp_filp = ncp_filp;
339
/*      server->lock = 0;       */
340
        init_MUTEX(&server->sem);
341
        server->packet = NULL;
342
/*      server->buffer_size = 0;        */
343
/*      server->conn_status = 0;        */
344
/*      server->root_dentry = NULL;     */
345
/*      server->root_setuped = 0;       */
346
#ifdef CONFIG_NCPFS_PACKET_SIGNING
347
/*      server->sign_wanted = 0;        */
348
/*      server->sign_active = 0;        */
349
#endif
350
        server->auth.auth_type = NCP_AUTH_NONE;
351
/*      server->auth.object_name_len = 0;       */
352
/*      server->auth.object_name = NULL;        */
353
/*      server->auth.object_type = 0;           */
354
/*      server->priv.len = 0;                   */
355
/*      server->priv.data = NULL;               */
356
 
357
        server->m = data;
358
        /* Althought anything producing this is buggy, it happens
359
           now because of PATH_MAX changes.. */
360
        if (server->m.time_out < 1) {
361
                server->m.time_out = 10;
362
                printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
363
        }
364
        server->m.time_out = server->m.time_out * HZ / 100;
365
        server->m.file_mode = (server->m.file_mode &
366
                               (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
367
        server->m.dir_mode = (server->m.dir_mode &
368
                              (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;
369
 
370
#ifdef CONFIG_NCPFS_NLS
371
        /* load the default NLS charsets */
372
        server->nls_vol = load_nls_default();
373
        server->nls_io = load_nls_default();
374
#endif /* CONFIG_NCPFS_NLS */
375
 
376
        server->dentry_ttl = 0;  /* no caching */
377
 
378
#undef NCP_PACKET_SIZE
379
#define NCP_PACKET_SIZE 65536
380
        server->packet_size = NCP_PACKET_SIZE;
381
        server->packet = vmalloc(NCP_PACKET_SIZE);
382
        if (server->packet == NULL)
383
                goto out_no_packet;
384
 
385
        ncp_lock_server(server);
386
        error = ncp_connect(server);
387
        ncp_unlock_server(server);
388
        if (error < 0)
389
                goto out_no_connect;
390
        DPRINTK("ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));
391
 
392
#ifdef CONFIG_NCPFS_PACKET_SIGNING
393
        if (ncp_negotiate_size_and_options(server, default_bufsize,
394
                NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
395
        {
396
                if (options != NCP_DEFAULT_OPTIONS)
397
                {
398
                        if (ncp_negotiate_size_and_options(server,
399
                                default_bufsize,
400
                                options & 2,
401
                                &(server->buffer_size), &options) != 0)
402
 
403
                        {
404
                                goto out_no_bufsize;
405
                        }
406
                }
407
                if (options & 2)
408
                        server->sign_wanted = 1;
409
        }
410
        else
411
#endif  /* CONFIG_NCPFS_PACKET_SIGNING */
412
        if (ncp_negotiate_buffersize(server, default_bufsize,
413
                                     &(server->buffer_size)) != 0)
414
                goto out_no_bufsize;
415
        DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);
416
 
417
        memset(&finfo, 0, sizeof(finfo));
418
        finfo.i.attributes      = aDIR;
419
        finfo.i.dataStreamSize  = NCP_BLOCK_SIZE;
420
        finfo.i.dirEntNum       = 0;
421
        finfo.i.DosDirNum       = 0;
422
#ifdef CONFIG_NCPFS_SMALLDOS
423
        finfo.i.NSCreator       = NW_NS_DOS;
424
#endif
425
        finfo.i.volNumber       = NCP_NUMBER_OF_VOLUMES + 1;    /* illegal volnum */
426
        /* set dates of mountpoint to Jan 1, 1986; 00:00 */
427
        finfo.i.creationTime    = finfo.i.modifyTime
428
                                = cpu_to_le16(0x0000);
429
        finfo.i.creationDate    = finfo.i.modifyDate
430
                                = finfo.i.lastAccessDate
431
                                = cpu_to_le16(0x0C21);
432
        finfo.i.nameLen         = 0;
433
        finfo.i.entryName[0]     = '\0';
434
 
435
        finfo.opened            = 0;
436
        finfo.ino               = 2;    /* tradition */
437
 
438
        server->name_space[finfo.i.volNumber] = NW_NS_DOS;
439
        root_inode = ncp_iget(sb, &finfo);
440
        if (!root_inode)
441
                goto out_no_root;
442
        DPRINTK("ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
443
        sb->s_root = d_alloc_root(root_inode);
444
        if (!sb->s_root)
445
                goto out_no_root;
446
        sb->s_root->d_op = &ncp_root_dentry_operations;
447
        return sb;
448
 
449
out_no_root:
450
        printk(KERN_ERR "ncp_read_super: get root inode failed\n");
451
        iput(root_inode);
452
        goto out_disconnect;
453
out_no_bufsize:
454
        printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
455
out_disconnect:
456
        ncp_lock_server(server);
457
        ncp_disconnect(server);
458
        ncp_unlock_server(server);
459
        goto out_free_packet;
460
out_no_connect:
461
        printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
462
out_free_packet:
463
        vfree(server->packet);
464
        goto out_free_server;
465
out_no_packet:
466
        printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
467
out_free_server:
468
#ifdef CONFIG_NCPFS_NLS
469
        unload_nls(server->nls_io);
470
        unload_nls(server->nls_vol);
471
#endif
472
        /* 23/12/1998 Marcin Dalecki <dalecki@cs.net.pl>:
473
         *
474
         * The previously used put_filp(ncp_filp); was bogous, since
475
         * it doesn't proper unlocking.
476
         */
477
        fput(ncp_filp);
478
        goto out;
479
 
480
out_bad_file2:
481
        fput(ncp_filp);
482
out_bad_file:
483
        printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
484
        goto out;
485
out_bad_mount:
486
        printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
487
                NCP_MOUNT_VERSION);
488
        goto out;
489
out_no_data:
490
        printk(KERN_ERR "ncp_read_super: missing data argument\n");
491
out:
492
        return NULL;
493
}
494
 
495
static void ncp_put_super(struct super_block *sb)
496
{
497
        struct ncp_server *server = NCP_SBP(sb);
498
 
499
        ncp_lock_server(server);
500
        ncp_disconnect(server);
501
        ncp_unlock_server(server);
502
 
503
#ifdef CONFIG_NCPFS_NLS
504
        /* unload the NLS charsets */
505
        if (server->nls_vol)
506
        {
507
                unload_nls(server->nls_vol);
508
                server->nls_vol = NULL;
509
        }
510
        if (server->nls_io)
511
        {
512
                unload_nls(server->nls_io);
513
                server->nls_io = NULL;
514
        }
515
#endif /* CONFIG_NCPFS_NLS */
516
 
517
        fput(server->ncp_filp);
518
        kill_proc(server->m.wdog_pid, SIGTERM, 1);
519
 
520
        if (server->priv.data)
521
                ncp_kfree_s(server->priv.data, server->priv.len);
522
        if (server->auth.object_name)
523
                ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
524
        vfree(server->packet);
525
 
526
}
527
 
528
static int ncp_statfs(struct super_block *sb, struct statfs *buf)
529
{
530
        /* We cannot say how much disk space is left on a mounted
531
           NetWare Server, because free space is distributed over
532
           volumes, and the current user might have disk quotas. So
533
           free space is not that simple to determine. Our decision
534
           here is to err conservatively. */
535
 
536
        buf->f_type = NCP_SUPER_MAGIC;
537
        buf->f_bsize = NCP_BLOCK_SIZE;
538
        buf->f_blocks = 0;
539
        buf->f_bfree = 0;
540
        buf->f_bavail = 0;
541
        buf->f_namelen = 12;
542
        return 0;
543
}
544
 
545
int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
546
{
547
        struct inode *inode = dentry->d_inode;
548
        int result = 0;
549
        int info_mask;
550
        struct nw_modify_dos_info info;
551
        struct ncp_server *server;
552
 
553
        result = -EIO;
554
 
555
        server = NCP_SERVER(inode);
556
        if ((!server) || !ncp_conn_valid(server))
557
                goto out;
558
 
559
        /* ageing the dentry to force validation */
560
        ncp_age_dentry(server, dentry);
561
 
562
        result = inode_change_ok(inode, attr);
563
        if (result < 0)
564
                goto out;
565
 
566
        result = -EPERM;
567
        if (((attr->ia_valid & ATTR_UID) &&
568
             (attr->ia_uid != server->m.uid)))
569
                goto out;
570
 
571
        if (((attr->ia_valid & ATTR_GID) &&
572
             (attr->ia_gid != server->m.gid)))
573
                goto out;
574
 
575
        if (((attr->ia_valid & ATTR_MODE) &&
576
             (attr->ia_mode &
577
              ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
578
                goto out;
579
 
580
        info_mask = 0;
581
        memset(&info, 0, sizeof(info));
582
 
583
#if 1 
584
        if ((attr->ia_valid & ATTR_MODE) != 0)
585
        {
586
                if (S_ISDIR(inode->i_mode)) {
587
                        umode_t newmode;
588
 
589
                        info_mask |= DM_ATTRIBUTES;
590
                        newmode = attr->ia_mode;
591
                        newmode &= NCP_SERVER(inode)->m.dir_mode;
592
 
593
                        if (newmode & 0222)
594
                                info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
595
                        else
596
                                info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
597
                } else if (!S_ISREG(inode->i_mode))
598
                {
599
                        return -EPERM;
600
                }
601
                else
602
                {
603
                        umode_t newmode;
604
#ifdef CONFIG_NCPFS_EXTRAS                      
605
                        int extras;
606
 
607
                        extras = server->m.flags & NCP_MOUNT_EXTRAS;
608
#endif
609
                        info_mask |= DM_ATTRIBUTES;
610
                        newmode=attr->ia_mode;
611
#ifdef CONFIG_NCPFS_EXTRAS
612
                        if (!extras)
613
#endif
614
                                newmode &= server->m.file_mode;
615
 
616
                        if (newmode & 0222) /* any write bit set */
617
                        {
618
                                info.attributes &= ~(aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
619
                        }
620
                        else
621
                        {
622
                                info.attributes |=  (aRONLY|aRENAMEINHIBIT|aDELETEINHIBIT);
623
                        }
624
#ifdef CONFIG_NCPFS_EXTRAS
625
                        if (extras) {
626
                                if (newmode & 0111) /* any execute bit set */
627
                                        info.attributes |= aSHARED | aSYSTEM;
628
                                /* read for group/world and not in default file_mode */
629
                                else if (newmode & ~server->m.file_mode & 0444)
630
                                        info.attributes |= aSHARED;
631
                        }
632
#endif
633
                }
634
        }
635
#endif
636
 
637
        if ((attr->ia_valid & ATTR_CTIME) != 0) {
638
                info_mask |= (DM_CREATE_TIME | DM_CREATE_DATE);
639
                ncp_date_unix2dos(attr->ia_ctime,
640
                             &(info.creationTime), &(info.creationDate));
641
                info.creationTime = le16_to_cpu(info.creationTime);
642
                info.creationDate = le16_to_cpu(info.creationDate);
643
        }
644
        if ((attr->ia_valid & ATTR_MTIME) != 0) {
645
                info_mask |= (DM_MODIFY_TIME | DM_MODIFY_DATE);
646
                ncp_date_unix2dos(attr->ia_mtime,
647
                                  &(info.modifyTime), &(info.modifyDate));
648
                info.modifyTime = le16_to_cpu(info.modifyTime);
649
                info.modifyDate = le16_to_cpu(info.modifyDate);
650
        }
651
        if ((attr->ia_valid & ATTR_ATIME) != 0) {
652
                __u16 dummy;
653
                info_mask |= (DM_LAST_ACCESS_DATE);
654
                ncp_date_unix2dos(attr->ia_atime,
655
                                  &(dummy), &(info.lastAccessDate));
656
                info.lastAccessDate = le16_to_cpu(info.lastAccessDate);
657
        }
658
        if (info_mask != 0) {
659
                result = ncp_modify_file_or_subdir_dos_info(NCP_SERVER(inode),
660
                                      inode, info_mask, &info);
661
                if (result != 0) {
662
                        result = -EACCES;
663
 
664
                        if (info_mask == (DM_CREATE_TIME | DM_CREATE_DATE)) {
665
                                /* NetWare seems not to allow this. I
666
                                   do not know why. So, just tell the
667
                                   user everything went fine. This is
668
                                   a terrible hack, but I do not know
669
                                   how to do this correctly. */
670
                                result = 0;
671
                        }
672
                }
673
#ifdef CONFIG_NCPFS_STRONG              
674
                if ((!result) && (info_mask & DM_ATTRIBUTES))
675
                        NCP_FINFO(inode)->nwattr = info.attributes;
676
#endif
677
        }
678
        if ((attr->ia_valid & ATTR_SIZE) != 0) {
679
                int written;
680
 
681
                DPRINTK("ncpfs: trying to change size to %ld\n",
682
                        attr->ia_size);
683
 
684
                if ((result = ncp_make_open(inode, O_WRONLY)) < 0) {
685
                        return -EACCES;
686
                }
687
                ncp_write_kernel(NCP_SERVER(inode), NCP_FINFO(inode)->file_handle,
688
                          attr->ia_size, 0, "", &written);
689
 
690
                /* According to ndir, the changes only take effect after
691
                   closing the file */
692
                ncp_inode_close(inode);
693
                result = ncp_make_closed(inode);
694
                if (!result)
695
                        result = vmtruncate(inode, attr->ia_size);
696
        }
697
out:
698
        return result;
699
}
700
 
701
#ifdef DEBUG_NCP_MALLOC
702
int ncp_malloced;
703
int ncp_current_malloced;
704
#endif
705
 
706
static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
707
 
708
static int __init init_ncp_fs(void)
709
{
710
        DPRINTK("ncpfs: init_module called\n");
711
 
712
#ifdef DEBUG_NCP_MALLOC
713
        ncp_malloced = 0;
714
        ncp_current_malloced = 0;
715
#endif
716
        return register_filesystem(&ncp_fs_type);
717
}
718
 
719
static void __exit exit_ncp_fs(void)
720
{
721
        DPRINTK("ncpfs: cleanup_module called\n");
722
        unregister_filesystem(&ncp_fs_type);
723
#ifdef DEBUG_NCP_MALLOC
724
        PRINTK("ncp_malloced: %d\n", ncp_malloced);
725
        PRINTK("ncp_current_malloced: %d\n", ncp_current_malloced);
726
#endif
727
}
728
 
729
EXPORT_NO_SYMBOLS;
730
 
731
module_init(init_ncp_fs)
732
module_exit(exit_ncp_fs)
733
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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