~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/udf/directory.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * directory.c
  3  *
  4  * PURPOSE
  5  *      Directory related functions
  6  *
  7  * COPYRIGHT
  8  *      This file is distributed under the terms of the GNU General Public
  9  *      License (GPL). Copies of the GPL can be obtained from:
 10  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 11  *      Each contributing author retains all rights to their own work.
 12  */
 13 
 14 #include "udfdecl.h"
 15 #include "udf_i.h"
 16 
 17 #include <linux/fs.h>
 18 #include <linux/string.h>
 19 #include <linux/buffer_head.h>
 20 
 21 struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
 22                                          struct udf_fileident_bh *fibh,
 23                                          struct fileIdentDesc *cfi,
 24                                          struct extent_position *epos,
 25                                          struct kernel_lb_addr *eloc, uint32_t *elen,
 26                                          sector_t *offset)
 27 {
 28         struct fileIdentDesc *fi;
 29         int i, num, block;
 30         struct buffer_head *tmp, *bha[16];
 31         struct udf_inode_info *iinfo = UDF_I(dir);
 32 
 33         fibh->soffset = fibh->eoffset;
 34 
 35         if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
 36                 fi = udf_get_fileident(iinfo->i_ext.i_data -
 37                                        (iinfo->i_efe ?
 38                                         sizeof(struct extendedFileEntry) :
 39                                         sizeof(struct fileEntry)),
 40                                        dir->i_sb->s_blocksize,
 41                                        &(fibh->eoffset));
 42                 if (!fi)
 43                         return NULL;
 44 
 45                 *nf_pos += fibh->eoffset - fibh->soffset;
 46 
 47                 memcpy((uint8_t *)cfi, (uint8_t *)fi,
 48                        sizeof(struct fileIdentDesc));
 49 
 50                 return fi;
 51         }
 52 
 53         if (fibh->eoffset == dir->i_sb->s_blocksize) {
 54                 int lextoffset = epos->offset;
 55                 unsigned char blocksize_bits = dir->i_sb->s_blocksize_bits;
 56 
 57                 if (udf_next_aext(dir, epos, eloc, elen, 1) !=
 58                     (EXT_RECORDED_ALLOCATED >> 30))
 59                         return NULL;
 60 
 61                 block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
 62 
 63                 (*offset)++;
 64 
 65                 if ((*offset << blocksize_bits) >= *elen)
 66                         *offset = 0;
 67                 else
 68                         epos->offset = lextoffset;
 69 
 70                 brelse(fibh->sbh);
 71                 fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
 72                 if (!fibh->sbh)
 73                         return NULL;
 74                 fibh->soffset = fibh->eoffset = 0;
 75 
 76                 if (!(*offset & ((16 >> (blocksize_bits - 9)) - 1))) {
 77                         i = 16 >> (blocksize_bits - 9);
 78                         if (i + *offset > (*elen >> blocksize_bits))
 79                                 i = (*elen >> blocksize_bits)-*offset;
 80                         for (num = 0; i > 0; i--) {
 81                                 block = udf_get_lb_pblock(dir->i_sb, eloc,
 82                                                           *offset + i);
 83                                 tmp = udf_tgetblk(dir->i_sb, block);
 84                                 if (tmp && !buffer_uptodate(tmp) &&
 85                                                 !buffer_locked(tmp))
 86                                         bha[num++] = tmp;
 87                                 else
 88                                         brelse(tmp);
 89                         }
 90                         if (num) {
 91                                 ll_rw_block(READA, num, bha);
 92                                 for (i = 0; i < num; i++)
 93                                         brelse(bha[i]);
 94                         }
 95                 }
 96         } else if (fibh->sbh != fibh->ebh) {
 97                 brelse(fibh->sbh);
 98                 fibh->sbh = fibh->ebh;
 99         }
100 
101         fi = udf_get_fileident(fibh->sbh->b_data, dir->i_sb->s_blocksize,
102                                &(fibh->eoffset));
103 
104         if (!fi)
105                 return NULL;
106 
107         *nf_pos += fibh->eoffset - fibh->soffset;
108 
109         if (fibh->eoffset <= dir->i_sb->s_blocksize) {
110                 memcpy((uint8_t *)cfi, (uint8_t *)fi,
111                        sizeof(struct fileIdentDesc));
112         } else if (fibh->eoffset > dir->i_sb->s_blocksize) {
113                 int lextoffset = epos->offset;
114 
115                 if (udf_next_aext(dir, epos, eloc, elen, 1) !=
116                     (EXT_RECORDED_ALLOCATED >> 30))
117                         return NULL;
118 
119                 block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
120 
121                 (*offset)++;
122 
123                 if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
124                         *offset = 0;
125                 else
126                         epos->offset = lextoffset;
127 
128                 fibh->soffset -= dir->i_sb->s_blocksize;
129                 fibh->eoffset -= dir->i_sb->s_blocksize;
130 
131                 fibh->ebh = udf_tread(dir->i_sb, block);
132                 if (!fibh->ebh)
133                         return NULL;
134 
135                 if (sizeof(struct fileIdentDesc) > -fibh->soffset) {
136                         int fi_len;
137 
138                         memcpy((uint8_t *)cfi, (uint8_t *)fi, -fibh->soffset);
139                         memcpy((uint8_t *)cfi - fibh->soffset,
140                                fibh->ebh->b_data,
141                                sizeof(struct fileIdentDesc) + fibh->soffset);
142 
143                         fi_len = (sizeof(struct fileIdentDesc) +
144                                   cfi->lengthFileIdent +
145                                   le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
146 
147                         *nf_pos += fi_len - (fibh->eoffset - fibh->soffset);
148                         fibh->eoffset = fibh->soffset + fi_len;
149                 } else {
150                         memcpy((uint8_t *)cfi, (uint8_t *)fi,
151                                sizeof(struct fileIdentDesc));
152                 }
153         }
154         return fi;
155 }
156 
157 struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset)
158 {
159         struct fileIdentDesc *fi;
160         int lengthThisIdent;
161         uint8_t *ptr;
162         int padlen;
163 
164         if ((!buffer) || (!offset)) {
165                 udf_debug("invalidparms, buffer=%p, offset=%p\n",
166                           buffer, offset);
167                 return NULL;
168         }
169 
170         ptr = buffer;
171 
172         if ((*offset > 0) && (*offset < bufsize))
173                 ptr += *offset;
174         fi = (struct fileIdentDesc *)ptr;
175         if (fi->descTag.tagIdent != cpu_to_le16(TAG_IDENT_FID)) {
176                 udf_debug("0x%x != TAG_IDENT_FID\n",
177                           le16_to_cpu(fi->descTag.tagIdent));
178                 udf_debug("offset: %u sizeof: %lu bufsize: %u\n",
179                           *offset, (unsigned long)sizeof(struct fileIdentDesc),
180                           bufsize);
181                 return NULL;
182         }
183         if ((*offset + sizeof(struct fileIdentDesc)) > bufsize)
184                 lengthThisIdent = sizeof(struct fileIdentDesc);
185         else
186                 lengthThisIdent = sizeof(struct fileIdentDesc) +
187                         fi->lengthFileIdent + le16_to_cpu(fi->lengthOfImpUse);
188 
189         /* we need to figure padding, too! */
190         padlen = lengthThisIdent % UDF_NAME_PAD;
191         if (padlen)
192                 lengthThisIdent += (UDF_NAME_PAD - padlen);
193         *offset = *offset + lengthThisIdent;
194 
195         return fi;
196 }
197 
198 struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset,
199                               int inc)
200 {
201         struct short_ad *sa;
202 
203         if ((!ptr) || (!offset)) {
204                 pr_err("%s: invalidparms\n", __func__);
205                 return NULL;
206         }
207 
208         if ((*offset + sizeof(struct short_ad)) > maxoffset)
209                 return NULL;
210         else {
211                 sa = (struct short_ad *)ptr;
212                 if (sa->extLength == 0)
213                         return NULL;
214         }
215 
216         if (inc)
217                 *offset += sizeof(struct short_ad);
218         return sa;
219 }
220 
221 struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc)
222 {
223         struct long_ad *la;
224 
225         if ((!ptr) || (!offset)) {
226                 pr_err("%s: invalidparms\n", __func__);
227                 return NULL;
228         }
229 
230         if ((*offset + sizeof(struct long_ad)) > maxoffset)
231                 return NULL;
232         else {
233                 la = (struct long_ad *)ptr;
234                 if (la->extLength == 0)
235                         return NULL;
236         }
237 
238         if (inc)
239                 *offset += sizeof(struct long_ad);
240         return la;
241 }
242 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp