b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/isofs/rock.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * (C) 1992, 1993 Eric Youngdale
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Rock Ridge Extensions to iso9660
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12)
94f2f715771d0 (Al Viro 2005-04-25 18:32:12 -0700 13) #include "isofs.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include "rock.h"
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 16) /*
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 17) * These functions are designed to read the system areas of a directory record
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 18) * and extract relevant information. There are different functions provided
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) * depending upon what information we need at the time. One function fills
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) * out an inode structure, a second one extracts a filename, a third one
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 21) * returns a symbolic link name, and a fourth one returns the extent number
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 22) * for the file.
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 23) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 25) #define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 27) struct rock_state {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 28) void *buffer;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 29) unsigned char *chr;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 30) int len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 31) int cont_size;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 32) int cont_extent;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 33) int cont_offset;
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 34) int cont_loops;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 35) struct inode *inode;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 36) };
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 37)
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 38) /*
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 39) * This is a way of ensuring that we have something in the system
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 40) * use fields that is compatible with Rock Ridge. Return zero on success.
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 41) */
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 42)
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 43) static int check_sp(struct rock_ridge *rr, struct inode *inode)
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 44) {
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 45) if (rr->u.SP.magic[0] != 0xbe)
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 46) return -1;
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 47) if (rr->u.SP.magic[1] != 0xef)
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 48) return -1;
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 49) ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 50) return 0;
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 51) }
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 52)
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 53) static void setup_rock_ridge(struct iso_directory_record *de,
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 54) struct inode *inode, struct rock_state *rs)
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 55) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 56) rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 57) if (rs->len & 1)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 58) (rs->len)++;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 59) rs->chr = (unsigned char *)de + rs->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 60) rs->len = *((unsigned char *)de) - rs->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 61) if (rs->len < 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 62) rs->len = 0;
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 63)
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 64) if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 65) rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 66) rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 67) if (rs->len < 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 68) rs->len = 0;
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 69) }
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 70) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 72) static void init_rock_state(struct rock_state *rs, struct inode *inode)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 73) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 74) memset(rs, 0, sizeof(*rs));
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 75) rs->inode = inode;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 76) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 77)
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 78) /* Maximum number of Rock Ridge continuation entries */
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 79) #define RR_MAX_CE_ENTRIES 32
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 80)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 81) /*
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 82) * Returns 0 if the caller should continue scanning, 1 if the scan must end
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 83) * and -ve on error.
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 84) */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 85) static int rock_continue(struct rock_state *rs)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 86) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 87) int ret = 1;
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 88) int blocksize = 1 << rs->inode->i_blkbits;
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 89) const int min_de_size = offsetof(struct rock_ridge, u);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 90)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 91) kfree(rs->buffer);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 92) rs->buffer = NULL;
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 93)
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 94) if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 95) (unsigned)rs->cont_size > blocksize ||
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 96) (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 97) printk(KERN_NOTICE "rock: corrupted directory entry. "
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 98) "extent=%d, offset=%d, size=%d\n",
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 99) rs->cont_extent, rs->cont_offset, rs->cont_size);
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 100) ret = -EIO;
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 101) goto out;
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 102) }
e595447e177b3 (Andrew Morton 2005-06-21 17:16:50 -0700 103)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 104) if (rs->cont_extent) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 105) struct buffer_head *bh;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 106)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 107) rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 108) if (!rs->buffer) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 109) ret = -ENOMEM;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 110) goto out;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 111) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 112) ret = -EIO;
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 113) if (++rs->cont_loops >= RR_MAX_CE_ENTRIES)
f54e18f1b831c (Jan Kara 2014-12-15 14:22:46 +0100 114) goto out;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 115) bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 116) if (bh) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 117) memcpy(rs->buffer, bh->b_data + rs->cont_offset,
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 118) rs->cont_size);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 119) put_bh(bh);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 120) rs->chr = rs->buffer;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 121) rs->len = rs->cont_size;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 122) rs->cont_extent = 0;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 123) rs->cont_size = 0;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 124) rs->cont_offset = 0;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 125) return 0;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 126) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 127) printk("Unable to read rock-ridge attributes\n");
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 128) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 129) out:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 130) kfree(rs->buffer);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 131) rs->buffer = NULL;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 132) return ret;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 133) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 134)
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 135) /*
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 136) * We think there's a record of type `sig' at rs->chr. Parse the signature
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 137) * and make sure that there's really room for a record of that type.
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 138) */
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 139) static int rock_check_overflow(struct rock_state *rs, int sig)
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 140) {
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 141) int len;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 142)
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 143) switch (sig) {
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 144) case SIG('S', 'P'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 145) len = sizeof(struct SU_SP_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 146) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 147) case SIG('C', 'E'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 148) len = sizeof(struct SU_CE_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 149) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 150) case SIG('E', 'R'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 151) len = sizeof(struct SU_ER_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 152) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 153) case SIG('R', 'R'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 154) len = sizeof(struct RR_RR_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 155) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 156) case SIG('P', 'X'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 157) len = sizeof(struct RR_PX_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 158) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 159) case SIG('P', 'N'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 160) len = sizeof(struct RR_PN_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 161) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 162) case SIG('S', 'L'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 163) len = sizeof(struct RR_SL_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 164) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 165) case SIG('N', 'M'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 166) len = sizeof(struct RR_NM_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 167) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 168) case SIG('C', 'L'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 169) len = sizeof(struct RR_CL_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 170) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 171) case SIG('P', 'L'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 172) len = sizeof(struct RR_PL_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 173) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 174) case SIG('T', 'F'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 175) len = sizeof(struct RR_TF_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 176) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 177) case SIG('Z', 'F'):
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 178) len = sizeof(struct RR_ZF_s);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 179) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 180) default:
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 181) len = 0;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 182) break;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 183) }
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 184) len += offsetof(struct rock_ridge, u);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 185) if (len > rs->len) {
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 186) printk(KERN_NOTICE "rock: directory entry would overflow "
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 187) "storage\n");
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 188) printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 189) sig, len, rs->len);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 190) return -EIO;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 191) }
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 192) return 0;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 193) }
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 194)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 195) /*
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 196) * return length of name field; 0: not found, -1: to be ignored
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 197) */
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 198) int get_rock_ridge_filename(struct iso_directory_record *de,
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 199) char *retname, struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 200) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 201) struct rock_state rs;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 202) struct rock_ridge *rr;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 203) int sig;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 204) int retnamlen = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 205) int truncate = 0;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 206) int ret = 0;
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 207) char *p;
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 208) int len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 210) if (!ISOFS_SB(inode->i_sb)->s_rock)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 211) return 0;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 212) *retname = 0;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 213)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 214) init_rock_state(&rs, inode);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 215) setup_rock_ridge(de, inode, &rs);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 216) repeat:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 217)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 218) while (rs.len > 2) { /* There may be one byte for padding somewhere */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 219) rr = (struct rock_ridge *)rs.chr;
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 220) /*
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 221) * Ignore rock ridge info if rr->len is out of range, but
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 222) * don't return -EIO because that would make the file
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 223) * invisible.
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 224) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 225) if (rr->len < 3)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 226) goto out; /* Something got screwed up here */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 227) sig = isonum_721(rs.chr);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 228) if (rock_check_overflow(&rs, sig))
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 229) goto eio;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 230) rs.chr += rr->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 231) rs.len -= rr->len;
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 232) /*
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 233) * As above, just ignore the rock ridge info if rr->len
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 234) * is bogus.
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 235) */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 236) if (rs.len < 0)
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 237) goto out; /* Something got screwed up here */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 238)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 239) switch (sig) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 240) case SIG('R', 'R'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 241) if ((rr->u.RR.flags[0] & RR_NM) == 0)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 242) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 243) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 244) case SIG('S', 'P'):
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 245) if (check_sp(rr, inode))
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 246) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 247) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 248) case SIG('C', 'E'):
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 249) rs.cont_extent = isonum_733(rr->u.CE.extent);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 250) rs.cont_offset = isonum_733(rr->u.CE.offset);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 251) rs.cont_size = isonum_733(rr->u.CE.size);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 252) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 253) case SIG('N', 'M'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 254) if (truncate)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 255) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 256) if (rr->len < 5)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 257) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 258) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 259) * If the flags are 2 or 4, this indicates '.' or '..'.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 260) * We don't want to do anything with this, because it
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 261) * screws up the code that calls us. We don't really
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 262) * care anyways, since we can just use the non-RR
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 263) * name.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 264) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 265) if (rr->u.NM.flags & 6)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 266) break;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 267)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 268) if (rr->u.NM.flags & ~1) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 269) printk("Unsupported NM flag settings (%d)\n",
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 270) rr->u.NM.flags);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 271) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 272) }
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 273) len = rr->len - 5;
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 274) if (retnamlen + len >= 254) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 275) truncate = 1;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 276) break;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 277) }
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 278) p = memchr(rr->u.NM.name, '\0', len);
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 279) if (unlikely(p))
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 280) len = p - rr->u.NM.name;
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 281) memcpy(retname + retnamlen, rr->u.NM.name, len);
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 282) retnamlen += len;
99d825822eade (Al Viro 2016-05-05 16:25:35 -0400 283) retname[retnamlen] = '\0';
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 284) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 285) case SIG('R', 'E'):
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 286) kfree(rs.buffer);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 287) return -1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 288) default:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 289) break;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 290) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 291) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 292) ret = rock_continue(&rs);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 293) if (ret == 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 294) goto repeat;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 295) if (ret == 1)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 296) return retnamlen; /* If 0, this file did not have a NM field */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 297) out:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 298) kfree(rs.buffer);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 299) return ret;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 300) eio:
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 301) ret = -EIO;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 302) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304)
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 305) #define RR_REGARD_XA 1
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 306) #define RR_RELOC_DE 2
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 307)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308) static int
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 309) parse_rock_ridge_inode_internal(struct iso_directory_record *de,
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 310) struct inode *inode, int flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 311) {
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 312) int symlink_len = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 313) int cnt, sig;
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 314) unsigned int reloc_block;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 315) struct inode *reloc;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 316) struct rock_ridge *rr;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 317) int rootflag;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 318) struct rock_state rs;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 319) int ret = 0;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 320)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 321) if (!ISOFS_SB(inode->i_sb)->s_rock)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 322) return 0;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 323)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 324) init_rock_state(&rs, inode);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 325) setup_rock_ridge(de, inode, &rs);
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 326) if (flags & RR_REGARD_XA) {
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 327) rs.chr += 14;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 328) rs.len -= 14;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 329) if (rs.len < 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 330) rs.len = 0;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 331) }
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 332)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 333) repeat:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 334) while (rs.len > 2) { /* There may be one byte for padding somewhere */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 335) rr = (struct rock_ridge *)rs.chr;
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 336) /*
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 337) * Ignore rock ridge info if rr->len is out of range, but
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 338) * don't return -EIO because that would make the file
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 339) * invisible.
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 340) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 341) if (rr->len < 3)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 342) goto out; /* Something got screwed up here */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 343) sig = isonum_721(rs.chr);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 344) if (rock_check_overflow(&rs, sig))
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 345) goto eio;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 346) rs.chr += rr->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 347) rs.len -= rr->len;
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 348) /*
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 349) * As above, just ignore the rock ridge info if rr->len
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 350) * is bogus.
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 351) */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 352) if (rs.len < 0)
c0a1633b6201e (Adam Greenblatt 2008-07-25 01:46:32 -0700 353) goto out; /* Something got screwed up here */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 354)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 355) switch (sig) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 357) case SIG('R', 'R'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 358) if ((rr->u.RR.flags[0] &
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 359) (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 360) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 361) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 362) #endif
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 363) case SIG('S', 'P'):
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 364) if (check_sp(rr, inode))
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 365) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 366) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 367) case SIG('C', 'E'):
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 368) rs.cont_extent = isonum_733(rr->u.CE.extent);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 369) rs.cont_offset = isonum_733(rr->u.CE.offset);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 370) rs.cont_size = isonum_733(rr->u.CE.size);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 371) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 372) case SIG('E', 'R'):
4e2024624e678 (Jan Kara 2014-12-18 17:26:10 +0100 373) /* Invalid length of ER tag id? */
4e2024624e678 (Jan Kara 2014-12-18 17:26:10 +0100 374) if (rr->u.ER.len_id + offsetof(struct rock_ridge, u.ER.data) > rr->len)
4e2024624e678 (Jan Kara 2014-12-18 17:26:10 +0100 375) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 376) ISOFS_SB(inode->i_sb)->s_rock = 1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 377) printk(KERN_DEBUG "ISO 9660 Extensions: ");
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 378) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 379) int p;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 380) for (p = 0; p < rr->u.ER.len_id; p++)
a107bf8b3905b (Mike Rapoport 2016-11-30 09:52:01 +0200 381) printk(KERN_CONT "%c", rr->u.ER.data[p]);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 382) }
a107bf8b3905b (Mike Rapoport 2016-11-30 09:52:01 +0200 383) printk(KERN_CONT "\n");
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 384) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 385) case SIG('P', 'X'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 386) inode->i_mode = isonum_733(rr->u.PX.mode);
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 387) set_nlink(inode, isonum_733(rr->u.PX.n_links));
ba64e2b9e368f (Eric W. Biederman 2012-02-10 11:35:50 -0800 388) i_uid_write(inode, isonum_733(rr->u.PX.uid));
ba64e2b9e368f (Eric W. Biederman 2012-02-10 11:35:50 -0800 389) i_gid_write(inode, isonum_733(rr->u.PX.gid));
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 390) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 391) case SIG('P', 'N'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 392) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 393) int high, low;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 394) high = isonum_733(rr->u.PN.dev_high);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 395) low = isonum_733(rr->u.PN.dev_low);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 396) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 397) * The Rock Ridge standard specifies that if
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 398) * sizeof(dev_t) <= 4, then the high field is
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 399) * unused, and the device number is completely
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 400) * stored in the low field. Some writers may
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 401) * ignore this subtlety,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 402) * and as a result we test to see if the entire
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 403) * device number is
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 404) * stored in the low field, and use that.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 405) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 406) if ((low & ~0xff) && high == 0) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 407) inode->i_rdev =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 408) MKDEV(low >> 8, low & 0xff);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 409) } else {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 410) inode->i_rdev =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 411) MKDEV(high, low);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 412) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 413) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 414) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 415) case SIG('T', 'F'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 416) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 417) * Some RRIP writers incorrectly place ctime in the
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 418) * TF_CREATE field. Try to handle this correctly for
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 419) * either case.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 420) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 421) /* Rock ridge never appears on a High Sierra disk */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 422) cnt = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 423) if (rr->u.TF.flags & TF_CREATE) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 424) inode->i_ctime.tv_sec =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 425) iso_date(rr->u.TF.times[cnt++].time,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 426) 0);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 427) inode->i_ctime.tv_nsec = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 428) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 429) if (rr->u.TF.flags & TF_MODIFY) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 430) inode->i_mtime.tv_sec =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 431) iso_date(rr->u.TF.times[cnt++].time,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 432) 0);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 433) inode->i_mtime.tv_nsec = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 434) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 435) if (rr->u.TF.flags & TF_ACCESS) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 436) inode->i_atime.tv_sec =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 437) iso_date(rr->u.TF.times[cnt++].time,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 438) 0);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 439) inode->i_atime.tv_nsec = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 440) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 441) if (rr->u.TF.flags & TF_ATTRIBUTES) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 442) inode->i_ctime.tv_sec =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 443) iso_date(rr->u.TF.times[cnt++].time,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 444) 0);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 445) inode->i_ctime.tv_nsec = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 446) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 447) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 448) case SIG('S', 'L'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 449) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 450) int slen;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 451) struct SL_component *slp;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 452) struct SL_component *oldslp;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 453) slen = rr->len - 5;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 454) slp = &rr->u.SL.link;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 455) inode->i_size = symlink_len;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 456) while (slen > 1) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 457) rootflag = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 458) switch (slp->flags & ~1) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 459) case 0:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 460) inode->i_size +=
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 461) slp->len;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 462) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 463) case 2:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 464) inode->i_size += 1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 465) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 466) case 4:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 467) inode->i_size += 2;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 468) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 469) case 8:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 470) rootflag = 1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 471) inode->i_size += 1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 472) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 473) default:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 474) printk("Symlink component flag "
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 475) "not implemented\n");
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 476) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 477) slen -= slp->len + 2;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 478) oldslp = slp;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 479) slp = (struct SL_component *)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 480) (((char *)slp) + slp->len + 2);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 481)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 482) if (slen < 2) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 483) if (((rr->u.SL.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 484) flags & 1) != 0)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 485) &&
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 486) ((oldslp->
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 487) flags & 1) == 0))
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 488) inode->i_size +=
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 489) 1;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 490) break;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 491) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 492)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 493) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 494) * If this component record isn't
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 495) * continued, then append a '/'.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 496) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 497) if (!rootflag
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 498) && (oldslp->flags & 1) == 0)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 499) inode->i_size += 1;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 500) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 501) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 502) symlink_len = inode->i_size;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 503) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 504) case SIG('R', 'E'):
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 505) printk(KERN_WARNING "Attempt to read inode for "
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 506) "relocated directory\n");
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 507) goto out;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 508) case SIG('C', 'L'):
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 509) if (flags & RR_RELOC_DE) {
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 510) printk(KERN_ERR
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 511) "ISOFS: Recursive directory relocation "
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 512) "is not supported\n");
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 513) goto eio;
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 514) }
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 515) reloc_block = isonum_733(rr->u.CL.location);
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 516) if (reloc_block == ISOFS_I(inode)->i_iget5_block &&
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 517) ISOFS_I(inode)->i_iget5_offset == 0) {
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 518) printk(KERN_ERR
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 519) "ISOFS: Directory relocation points to "
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 520) "itself\n");
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 521) goto eio;
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 522) }
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 523) ISOFS_I(inode)->i_first_extent = reloc_block;
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 524) reloc = isofs_iget_reloc(inode->i_sb, reloc_block, 0);
c4386c83bf849 (David Howells 2008-02-07 00:15:41 -0800 525) if (IS_ERR(reloc)) {
c4386c83bf849 (David Howells 2008-02-07 00:15:41 -0800 526) ret = PTR_ERR(reloc);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 527) goto out;
c4386c83bf849 (David Howells 2008-02-07 00:15:41 -0800 528) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 529) inode->i_mode = reloc->i_mode;
bfe8684869601 (Miklos Szeredi 2011-10-28 14:13:29 +0200 530) set_nlink(inode, reloc->i_nlink);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 531) inode->i_uid = reloc->i_uid;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 532) inode->i_gid = reloc->i_gid;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 533) inode->i_rdev = reloc->i_rdev;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 534) inode->i_size = reloc->i_size;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 535) inode->i_blocks = reloc->i_blocks;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 536) inode->i_atime = reloc->i_atime;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 537) inode->i_ctime = reloc->i_ctime;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 538) inode->i_mtime = reloc->i_mtime;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 539) iput(reloc);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 540) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 541) #ifdef CONFIG_ZISOFS
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 542) case SIG('Z', 'F'): {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 543) int algo;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 544)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 545) if (ISOFS_SB(inode->i_sb)->s_nocompress)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 546) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 547) algo = isonum_721(rr->u.ZF.algorithm);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 548) if (algo == SIG('p', 'z')) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 549) int block_shift =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 550) isonum_711(&rr->u.ZF.parms[1]);
59bc055211b8d (Jan Kara 2009-09-23 14:44:56 +0200 551) if (block_shift > 17) {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 552) printk(KERN_WARNING "isofs: "
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 553) "Can't handle ZF block "
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 554) "size of 2^%d\n",
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 555) block_shift);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 556) } else {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 557) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 558) * Note: we don't change
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 559) * i_blocks here
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 560) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 561) ISOFS_I(inode)->i_file_format =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 562) isofs_file_compressed;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 563) /*
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 564) * Parameters to compression
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 565) * algorithm (header size,
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 566) * block size)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 567) */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 568) ISOFS_I(inode)->i_format_parm[0] =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 569) isonum_711(&rr->u.ZF.parms[0]);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 570) ISOFS_I(inode)->i_format_parm[1] =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 571) isonum_711(&rr->u.ZF.parms[1]);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 572) inode->i_size =
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 573) isonum_733(rr->u.ZF.
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 574) real_size);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 575) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 576) } else {
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 577) printk(KERN_WARNING
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 578) "isofs: Unknown ZF compression "
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 579) "algorithm: %c%c\n",
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 580) rr->u.ZF.algorithm[0],
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 581) rr->u.ZF.algorithm[1]);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 582) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 583) break;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 584) }
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 585) #endif
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 586) default:
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 587) break;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 588) }
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 589) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 590) ret = rock_continue(&rs);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 591) if (ret == 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 592) goto repeat;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 593) if (ret == 1)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 594) ret = 0;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 595) out:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 596) kfree(rs.buffer);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 597) return ret;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 598) eio:
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 599) ret = -EIO;
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 600) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 601) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 602)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 603) static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 604) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 605) int slen;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 606) int rootflag;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 607) struct SL_component *oldslp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 608) struct SL_component *slp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 609) slen = rr->len - 5;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 610) slp = &rr->u.SL.link;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 611) while (slen > 1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 612) rootflag = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 613) switch (slp->flags & ~1) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 614) case 0:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 615) if (slp->len > plimit - rpnt)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 616) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 617) memcpy(rpnt, slp->text, slp->len);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 618) rpnt += slp->len;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 620) case 2:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 621) if (rpnt >= plimit)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 622) return NULL;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 623) *rpnt++ = '.';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 624) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 625) case 4:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 626) if (2 > plimit - rpnt)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 627) return NULL;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 628) *rpnt++ = '.';
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 629) *rpnt++ = '.';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 630) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 631) case 8:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 632) if (rpnt >= plimit)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 633) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 634) rootflag = 1;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 635) *rpnt++ = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 636) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 637) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 638) printk("Symlink component flag not implemented (%d)\n",
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 639) slp->flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 640) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 641) slen -= slp->len + 2;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 642) oldslp = slp;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 643) slp = (struct SL_component *)((char *)slp + slp->len + 2);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 644)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 645) if (slen < 2) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 646) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 647) * If there is another SL record, and this component
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 648) * record isn't continued, then add a slash.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 649) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 650) if ((!rootflag) && (rr->u.SL.flags & 1) &&
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 651) !(oldslp->flags & 1)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 652) if (rpnt >= plimit)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 653) return NULL;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 654) *rpnt++ = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 655) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 656) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 657) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 658)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 659) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 660) * If this component record isn't continued, then append a '/'.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 661) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 662) if (!rootflag && !(oldslp->flags & 1)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 663) if (rpnt >= plimit)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 664) return NULL;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 665) *rpnt++ = '/';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 666) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 667) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 668) return rpnt;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 669) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 670)
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 671) int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode,
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 672) int relocated)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 673) {
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 674) int flags = relocated ? RR_RELOC_DE : 0;
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 675) int result = parse_rock_ridge_inode_internal(de, inode, flags);
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 676)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 677) /*
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 678) * if rockridge flag was reset and we didn't look for attributes
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 679) * behind eventual XA attributes, have a look there
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 680) */
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 681) if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 682) && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 683) result = parse_rock_ridge_inode_internal(de, inode,
410dd3cf4c9b3 (Jan Kara 2014-08-17 11:49:57 +0200 684) flags | RR_REGARD_XA);
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 685) }
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 686) return result;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 687) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 688)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 689) /*
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 690) * readpage() for symlinks: reads symlink contents into the page and either
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 691) * makes it uptodate and returns 0 or returns error (-EIO)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 692) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 693) static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 694) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 695) struct inode *inode = page->mapping->host;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 696) struct iso_inode_info *ei = ISOFS_I(inode);
4f819a7899b06 (Arnd Bergmann 2010-09-12 19:05:56 +0200 697) struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
21fc61c73c390 (Al Viro 2015-11-17 01:07:57 -0500 698) char *link = page_address(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 699) unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 700) struct buffer_head *bh;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 701) char *rpnt = link;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 702) unsigned char *pnt;
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 703) struct iso_directory_record *raw_de;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 704) unsigned long block, offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 705) int sig;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 706) struct rock_ridge *rr;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 707) struct rock_state rs;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 708) int ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 709)
4f819a7899b06 (Arnd Bergmann 2010-09-12 19:05:56 +0200 710) if (!sbi->s_rock)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 711) goto error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 712)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 713) init_rock_state(&rs, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 714) block = ei->i_iget5_block;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 715) bh = sb_bread(inode->i_sb, block);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 716) if (!bh)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 717) goto out_noread;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718)
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 719) offset = ei->i_iget5_offset;
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 720) pnt = (unsigned char *)bh->b_data + offset;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 721)
76ab07ebc3ca6 (Andrew Morton 2005-06-21 17:16:46 -0700 722) raw_de = (struct iso_directory_record *)pnt;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 723)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 724) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 725) * If we go past the end of the buffer, there is some sort of error.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 726) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 727) if (offset + *pnt > bufsize)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728) goto out_bad_span;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729)
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 730) /*
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 731) * Now test for possible Rock Ridge extensions which will override
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 732) * some of these numbers in the inode structure.
7373909de403d (Andrew Morton 2005-06-21 17:16:47 -0700 733) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 734)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 735) setup_rock_ridge(raw_de, inode, &rs);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 736)
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 737) repeat:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 738) while (rs.len > 2) { /* There may be one byte for padding somewhere */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 739) rr = (struct rock_ridge *)rs.chr;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740) if (rr->len < 3)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741) goto out; /* Something got screwed up here */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 742) sig = isonum_721(rs.chr);
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 743) if (rock_check_overflow(&rs, sig))
f2966632a134e (Andrew Morton 2005-06-21 17:16:51 -0700 744) goto out;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 745) rs.chr += rr->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 746) rs.len -= rr->len;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 747) if (rs.len < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 748) goto out; /* corrupted isofs */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 749)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 750) switch (sig) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 751) case SIG('R', 'R'):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 752) if ((rr->u.RR.flags[0] & RR_SL) == 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 753) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 754) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 755) case SIG('S', 'P'):
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 756) if (check_sp(rr, inode))
12121714fbf36 (Andrew Morton 2005-06-21 17:16:44 -0700 757) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 758) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 759) case SIG('S', 'L'):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 760) rpnt = get_symlink_chunk(rpnt, rr,
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 761) link + (PAGE_SIZE - 1));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 762) if (rpnt == NULL)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 763) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 764) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 765) case SIG('C', 'E'):
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 766) /* This tells is if there is a continuation record */
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 767) rs.cont_extent = isonum_733(rr->u.CE.extent);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 768) rs.cont_offset = isonum_733(rr->u.CE.offset);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 769) rs.cont_size = isonum_733(rr->u.CE.size);
b4ca4c01780b1 (Gustavo A. R. Silva 2021-05-06 18:04:10 -0700 770) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 771) default:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 772) break;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 773) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 774) }
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 775) ret = rock_continue(&rs);
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 776) if (ret == 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 777) goto repeat;
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 778) if (ret < 0)
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 779) goto fail;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 780)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 781) if (rpnt == link)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 782) goto fail;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 783) brelse(bh);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 784) *rpnt = '\0';
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 785) SetPageUptodate(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 786) unlock_page(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 787) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 788)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 789) /* error exit from macro */
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 790) out:
ba40aaf04314e (Andrew Morton 2005-06-21 17:16:46 -0700 791) kfree(rs.buffer);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 792) goto fail;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 793) out_noread:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 794) printk("unable to read i-node block");
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 795) goto fail;
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 796) out_bad_span:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 797) printk("symlink spans iso9660 blocks\n");
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 798) fail:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 799) brelse(bh);
7fa393a1d3d94 (Andrew Morton 2005-06-21 17:16:43 -0700 800) error:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 801) SetPageError(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 802) unlock_page(page);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 803) return -EIO;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 804) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 805)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 806) const struct address_space_operations isofs_symlink_aops = {
1d372116383f7 (Andrew Morton 2005-06-21 17:16:42 -0700 807) .readpage = rock_ridge_symlink_readpage
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 808) };