Import 2.3.2
[davej-history.git] / fs / hpfs / file.c
blob1f1cbb6f2f903820613a3ad14764206030038350
1 /*
2 * linux/fs/hpfs/file.c
4 * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
6 * file VFS functions
7 */
9 #include "hpfs_fn.h"
11 int hpfs_open(struct inode *i, struct file *f)
13 hpfs_lock_inode(i);
14 hpfs_unlock_inode(i); /* make sure nobody is deleting the file */
15 if (!i->i_nlink) return -ENOENT;
16 return 0;
19 int hpfs_file_release(struct inode *inode, struct file *file)
21 hpfs_write_if_changed(inode);
22 return 0;
25 int hpfs_file_fsync(struct file *file, struct dentry *dentry)
27 /*return file_fsync(file, dentry);*/
28 return 0; /* Don't fsync :-) */
32 * generic_file_read often calls bmap with non-existing sector,
33 * so we must ignore such errors.
36 secno hpfs_bmap(struct inode *inode, unsigned file_secno)
38 unsigned n, disk_secno;
39 struct fnode *fnode;
40 struct buffer_head *bh;
41 if (((inode->i_size + 511) >> 9) <= file_secno) return 0;
42 n = file_secno - inode->i_hpfs_file_sec;
43 if (n < inode->i_hpfs_n_secs) return inode->i_hpfs_disk_sec + n;
44 if (!(fnode = hpfs_map_fnode(inode->i_sb, inode->i_ino, &bh))) return 0;
45 disk_secno = hpfs_bplus_lookup(inode->i_sb, inode, &fnode->btree, file_secno, bh);
46 if (disk_secno == -1) return 0;
47 if (hpfs_chk_sectors(inode->i_sb, disk_secno, 1, "bmap")) return 0;
48 return disk_secno;
51 void hpfs_truncate(struct inode *i)
53 if (IS_IMMUTABLE(i)) return /*-EPERM*/;
54 i->i_hpfs_n_secs = 0;
55 hpfs_truncate_btree(i->i_sb, i->i_ino, 1, ((i->i_size + 511) >> 9));
56 i->i_blocks = 1 + ((i->i_size + 511) >> 9);
57 /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
58 hpfs_write_inode(i);
61 ssize_t hpfs_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
63 struct inode *inode = filp->f_dentry->d_inode;
64 int i,j;
65 int a = generic_file_read(filp, buf, count, ppos);
66 if (inode->i_hpfs_conv != CONV_TEXT || a < 0) {
67 return a;
69 for (i = 0, j = 0; i < a; i++) {
70 char c;
71 int error;
72 if ((error = get_user(c, buf + i))) return error;
73 if (c != '\r') {
74 if (i != j) put_user(c, buf + j);
75 j++;
78 return j;
81 ssize_t hpfs_file_write(struct file *filp, const char *buf, size_t count,
82 loff_t *ppos)
84 struct inode *i = filp->f_dentry->d_inode;
85 int carry, error = 0;
86 const char *start = buf;
87 if (!i) return -EINVAL;
88 if (!S_ISREG(i->i_mode)) return -EINVAL;
89 if (IS_IMMUTABLE(i)) return -EPERM;
90 if (filp->f_flags & O_APPEND) *ppos = i->i_size;
91 if (count <= 0) return 0;
92 if ((unsigned)(*ppos+count) >= 0x80000000U || (unsigned)count >= 0x80000000U) return -EFBIG;
93 carry = 0;
94 while (count || carry) {
95 int ii, add = 0;
96 secno sec = 0; /* Go away, uninitialized variable warning */
97 int offset, size, written;
98 char ch;
99 struct buffer_head *bh;
100 char *data;
101 offset = *ppos & 0x1ff;
102 size = count > 0x200 - offset ? 0x200 - offset : count;
103 if ((*ppos >> 9) < ((i->i_size + 0x1ff) >> 9)) {
104 i->i_hpfs_n_secs = 0;
105 if (!(sec = hpfs_bmap(i, *ppos >> 9))) {
106 hpfs_error(i->i_sb, "bmap failed, file %08x, fsec %08x",
107 i->i_ino, *ppos >> 9);
108 error =- EFSERROR;
109 break;
111 } else for (ii = (i->i_size + 0x1ff) >> 9, add = 1; ii <= *ppos >> 9; ii++) {
112 if ((sec = hpfs_add_sector_to_btree(i->i_sb, i->i_ino, 1, ii)) == -1) {
113 hpfs_truncate(i);
114 return -ENOSPC;
116 if (*ppos != i->i_size)
117 if ((data = hpfs_get_sector(i->i_sb, sec, &bh))) {
118 memset(data, 0, 512);
119 mark_buffer_dirty(bh, 0);
120 brelse(bh);
122 i->i_size = 0x200 * ii + 1;
123 i->i_blocks++;
124 /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
125 if (i->i_sb->s_hpfs_chk >= 2) {
126 secno bsec;
127 bsec = hpfs_bmap(i, ii);
128 if (sec != bsec) {
129 hpfs_error(i->i_sb, "sec == %08x, bmap returns %08x", sec, bsec);
130 error = -EFSERROR;
131 break;
134 PRINTK(("file_write: added %08x\n", sec));
136 if (!sec || sec == 15) {
137 hpfs_error(i->i_sb, "bmap returned empty sector");
138 error = -EFSERROR;
139 break;
141 if (i->i_sb->s_hpfs_chk)
142 if (hpfs_chk_sectors(i->i_sb, sec, 1, "data")) {
143 error = -EFSERROR;
144 break;
146 if ((!offset && size == 0x200) || add)
147 data = hpfs_get_sector(i->i_sb, sec, &bh);
148 else data = hpfs_map_sector(i->i_sb, sec, &bh, 0);
149 if (!data) {
150 error = -EIO;
151 break;
153 if (i->i_hpfs_conv != CONV_TEXT) {
154 memcpy_fromfs(data + offset, buf, written = size);
155 buf += size;
156 } else {
157 int left;
158 char *to;
159 /* LF->CR/LF conversion, stolen from fat fs */
160 written = left = 0x200 - offset;
161 to = (char *) bh->b_data + (*ppos & 0x1ff);
162 if (carry) {
163 *to++ = '\n';
164 left--;
165 carry = 0;
167 for (size = 0; size < count && left; size++) {
168 if ((error = get_user(ch, buf++))) break;
169 if (ch == '\n') {
170 *to++ = '\r';
171 left--;
173 if (!left) carry = 1;
174 else {
175 *to++ = ch;
176 left--;
179 written -= left;
181 update_vm_cache(i, *ppos, bh->b_data + (*ppos & 0x1ff), written);
182 *ppos += written;
183 if (*ppos > i->i_size) {
184 i->i_size = *ppos;
185 /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
187 mark_buffer_dirty(bh, 0);
188 brelse(bh);
189 count -= size;
191 if (start == buf) return error;
192 i->i_mtime = CURRENT_TIME;
193 /*mark_inode_dirty(i);*/i->i_hpfs_dirty = 1;
194 return buf - start;