Lines 168-173
udf_open(struct vop_open_args *ap) {
Link Here
|
168 |
struct udf_node *np = VTON(ap->a_vp); |
168 |
struct udf_node *np = VTON(ap->a_vp); |
169 |
off_t fsize; |
169 |
off_t fsize; |
170 |
|
170 |
|
|
|
171 |
/* |
172 |
* We currently do not support any other strategy type, so |
173 |
* udf_bmap_internal, udf_bmap, udf_strategy would fail. |
174 |
* I.e. we can not access content of this file anyway. |
175 |
*/ |
176 |
if (le16toh(np->fentry->icbtag.strat_type) != 4) { |
177 |
printf("Unsupported strategy type %d\n", le16toh(np->fentry->icbtag.strat_type)); |
178 |
return EINVAL; |
179 |
} |
180 |
|
181 |
if (np->fentry->tag.id == TAGID_EXTFENTRY && |
182 |
np->fentry->inf_len != ((struct extfile_entry *)np->fentry)->obj_size) { |
183 |
printf("Files with multiple streams are not supported\n"); |
184 |
return EINVAL; |
185 |
} |
171 |
fsize = le64toh(np->fentry->inf_len); |
186 |
fsize = le64toh(np->fentry->inf_len); |
172 |
vnode_create_vobject(ap->a_vp, fsize, ap->a_td); |
187 |
vnode_create_vobject(ap->a_vp, fsize, ap->a_td); |
173 |
return 0; |
188 |
return 0; |
Lines 206-214
udf_timetotimespec(struct timestamp *time, struct timespec *t)
Link Here
|
206 |
|
221 |
|
207 |
t->tv_nsec = 0; |
222 |
t->tv_nsec = 0; |
208 |
|
223 |
|
209 |
/* DirectCD seems to like using bogus year values */ |
224 |
/* |
|
|
225 |
* DirectCD seems to like using bogus year values. |
226 |
* Distrust time->month especially, since it will be used for an |
227 |
* array index. |
228 |
*/ |
210 |
year = le16toh(time->year); |
229 |
year = le16toh(time->year); |
211 |
if (year < 1970) { |
230 |
if (year < 1970 || time->month > 12) { |
212 |
t->tv_sec = 0; |
231 |
t->tv_sec = 0; |
213 |
return; |
232 |
return; |
214 |
} |
233 |
} |
Lines 217-237
udf_timetotimespec(struct timestamp *time, struct timespec *t)
Link Here
|
217 |
t->tv_sec = time->second; |
236 |
t->tv_sec = time->second; |
218 |
t->tv_sec += time->minute * 60; |
237 |
t->tv_sec += time->minute * 60; |
219 |
t->tv_sec += time->hour * 3600; |
238 |
t->tv_sec += time->hour * 3600; |
220 |
t->tv_sec += time->day * 3600 * 24; |
239 |
t->tv_sec += (time->day - 1) * 3600 * 24; |
221 |
|
240 |
|
222 |
/* Calculate the month */ |
241 |
/* Calculate the month */ |
223 |
lpyear = udf_isaleapyear(year); |
242 |
lpyear = udf_isaleapyear(year); |
224 |
for (i = 1; i < time->month; i++) |
243 |
for (i = 1; i < time->month; i++) |
225 |
t->tv_sec += mon_lens[lpyear][i] * 3600 * 24; |
244 |
t->tv_sec += mon_lens[lpyear][i - 1] * 3600 * 24; |
226 |
|
245 |
|
227 |
/* Speed up the calculation */ |
246 |
for (i = 1970; i < year; i++) { |
228 |
if (year > 1979) |
|
|
229 |
t->tv_sec += 315532800; |
230 |
if (year > 1989) |
231 |
t->tv_sec += 315619200; |
232 |
if (year > 1999) |
233 |
t->tv_sec += 315532800; |
234 |
for (i = 2000; i < year; i++) { |
235 |
daysinyear = udf_isaleapyear(i) + 365 ; |
247 |
daysinyear = udf_isaleapyear(i) + 365 ; |
236 |
t->tv_sec += daysinyear * 3600 * 24; |
248 |
t->tv_sec += daysinyear * 3600 * 24; |
237 |
} |
249 |
} |
Lines 276-284
udf_getattr(struct vop_getattr_args *a)
Link Here
|
276 |
*/ |
288 |
*/ |
277 |
vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); |
289 |
vap->va_uid = (le32toh(fentry->uid) == -1) ? 0 : le32toh(fentry->uid); |
278 |
vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); |
290 |
vap->va_gid = (le32toh(fentry->gid) == -1) ? 0 : le32toh(fentry->gid); |
279 |
udf_timetotimespec(&fentry->atime, &vap->va_atime); |
291 |
if (fentry->tag.id == TAGID_FENTRY) { |
280 |
udf_timetotimespec(&fentry->mtime, &vap->va_mtime); |
292 |
udf_timetotimespec(&fentry->atime, &vap->va_atime); |
281 |
vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ |
293 |
udf_timetotimespec(&fentry->mtime, &vap->va_mtime); |
|
|
294 |
vap->va_ctime = vap->va_mtime; /* XXX Stored as an Extended Attribute */ |
295 |
} |
296 |
else { /*TAGID_EXTFENTRY*/ |
297 |
udf_timetotimespec(&((struct extfile_entry *)fentry)->atime, &vap->va_atime); |
298 |
udf_timetotimespec(&((struct extfile_entry *)fentry)->mtime, &vap->va_atime); |
299 |
udf_timetotimespec(&((struct extfile_entry *)fentry)->ctime, &vap->va_ctime); |
300 |
} |
282 |
vap->va_rdev = 0; /* XXX */ |
301 |
vap->va_rdev = 0; /* XXX */ |
283 |
if (vp->v_type & VDIR) { |
302 |
if (vp->v_type & VDIR) { |
284 |
/* |
303 |
/* |
Lines 287-295
udf_getattr(struct vop_getattr_args *a)
Link Here
|
287 |
* that directories consume at least one logical block, |
306 |
* that directories consume at least one logical block, |
288 |
* make it appear so. |
307 |
* make it appear so. |
289 |
*/ |
308 |
*/ |
290 |
if (fentry->logblks_rec != 0) { |
309 |
if (GET_FENTRY_FIELD(fentry, logblks_rec) != 0) { |
291 |
vap->va_size = |
310 |
vap->va_size = |
292 |
le64toh(fentry->logblks_rec) * node->udfmp->bsize; |
311 |
GET_FENTRY_FIELD(fentry, logblks_rec) * node->udfmp->bsize; |
293 |
} else { |
312 |
} else { |
294 |
vap->va_size = node->udfmp->bsize; |
313 |
vap->va_size = node->udfmp->bsize; |
295 |
} |
314 |
} |
Lines 343-349
udf_pathconf(struct vop_pathconf_args *a)
Link Here
|
343 |
|
362 |
|
344 |
#define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift) |
363 |
#define lblkno(udfmp, loc) ((loc) >> (udfmp)->bshift) |
345 |
#define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) |
364 |
#define blkoff(udfmp, loc) ((loc) & (udfmp)->bmask) |
346 |
#define lblktosize(imp, blk) ((blk) << (udfmp)->bshift) |
365 |
#define lblktosize(udfmp, blk) ((blk) << (udfmp)->bshift) |
|
|
366 |
|
367 |
#define HAS_EMBEDDED_DATA(node) ((le16toh((node)->fentry->icbtag.flags) & 0x7) == 3) |
347 |
|
368 |
|
348 |
static int |
369 |
static int |
349 |
udf_read(struct vop_read_args *ap) |
370 |
udf_read(struct vop_read_args *ap) |
Lines 362-367
udf_read(struct vop_read_args *ap)
Link Here
|
362 |
return (0); |
383 |
return (0); |
363 |
if (uio->uio_offset < 0) |
384 |
if (uio->uio_offset < 0) |
364 |
return (EINVAL); |
385 |
return (EINVAL); |
|
|
386 |
|
387 |
if (HAS_EMBEDDED_DATA(node)) { |
388 |
uint8_t *data; |
389 |
|
390 |
if (node->fentry->tag.id == TAGID_FENTRY) { |
391 |
struct file_entry *fentry = node->fentry; |
392 |
data = &fentry->data[le32toh(fentry->l_ea)]; |
393 |
fsize = le32toh(fentry->l_ad); |
394 |
} |
395 |
else { |
396 |
struct extfile_entry *fentry = (struct extfile_entry *)node->fentry; |
397 |
data = &fentry->data[le32toh(fentry->l_ea)]; |
398 |
fsize = le32toh(fentry->l_ad); |
399 |
} |
400 |
|
401 |
n = uio->uio_resid; |
402 |
diff = fsize - uio->uio_offset; |
403 |
if (diff <= 0) |
404 |
return (0); |
405 |
if (diff < n) |
406 |
n = diff; |
407 |
|
408 |
error = uiomove(data + uio->uio_offset, (int)n, uio); |
409 |
return (error); |
410 |
} |
411 |
|
365 |
fsize = le64toh(node->fentry->inf_len); |
412 |
fsize = le64toh(node->fentry->inf_len); |
366 |
udfmp = node->udfmp; |
413 |
udfmp = node->udfmp; |
367 |
do { |
414 |
do { |
Lines 758-764
udf_readdir(struct vop_readdir_args *a)
Link Here
|
758 |
ds->this_off); |
805 |
ds->this_off); |
759 |
} |
806 |
} |
760 |
if (error) { |
807 |
if (error) { |
761 |
printf("uiomove returned %d\n", error); |
808 |
if(error > 0) |
|
|
809 |
printf("uiomove returned %d\n", error); |
762 |
break; |
810 |
break; |
763 |
} |
811 |
} |
764 |
|
812 |
|
Lines 768-773
udf_readdir(struct vop_readdir_args *a)
Link Here
|
768 |
*a->a_eofflag = uiodir.eofflag; |
816 |
*a->a_eofflag = uiodir.eofflag; |
769 |
uio->uio_offset = ds->offset + ds->off; |
817 |
uio->uio_offset = ds->offset + ds->off; |
770 |
|
818 |
|
|
|
819 |
if(error < 0) |
820 |
error = 0; |
771 |
if (!error) |
821 |
if (!error) |
772 |
error = ds->error; |
822 |
error = ds->error; |
773 |
|
823 |
|
Lines 799-808
udf_strategy(struct vop_strategy_args *a)
Link Here
|
799 |
struct buf *bp; |
849 |
struct buf *bp; |
800 |
struct vnode *vp; |
850 |
struct vnode *vp; |
801 |
struct udf_node *node; |
851 |
struct udf_node *node; |
|
|
852 |
struct bufobj *bo; |
802 |
int maxsize; |
853 |
int maxsize; |
803 |
daddr_t sector; |
854 |
daddr_t sector; |
804 |
struct bufobj *bo; |
855 |
int error; |
805 |
int multiplier; |
|
|
806 |
|
856 |
|
807 |
bp = a->a_bp; |
857 |
bp = a->a_bp; |
808 |
vp = a->a_vp; |
858 |
vp = a->a_vp; |
Lines 813-836
udf_strategy(struct vop_strategy_args *a)
Link Here
|
813 |
* Files that are embedded in the fentry don't translate well |
863 |
* Files that are embedded in the fentry don't translate well |
814 |
* to a block number. Reject. |
864 |
* to a block number. Reject. |
815 |
*/ |
865 |
*/ |
816 |
if (udf_bmap_internal(node, bp->b_lblkno * node->udfmp->bsize, |
866 |
error = udf_bmap_internal(node, lblktosize(node->udfmp, bp->b_lblkno), §or, &maxsize); |
817 |
§or, &maxsize)) { |
867 |
if (error) { |
|
|
868 |
if (error == UDF_INVALID_BMAP) |
869 |
printf("udf_strategy called for file with data embedded in fentry\n"); |
818 |
clrbuf(bp); |
870 |
clrbuf(bp); |
819 |
bp->b_blkno = -1; |
871 |
bp->b_blkno = -1; |
|
|
872 |
bufdone(bp); |
873 |
return (0); |
820 |
} |
874 |
} |
821 |
|
875 |
/* udf_bmap_internal gives sector numbers, bio works with device blocks */ |
822 |
/* bmap gives sector numbers, bio works with device blocks */ |
876 |
bp->b_blkno = sector << (node->udfmp->bshift - DEV_BSHIFT); |
823 |
multiplier = node->udfmp->bsize / DEV_BSIZE; |
|
|
824 |
bp->b_blkno = sector * multiplier; |
825 |
|
826 |
} |
827 |
if ((long)bp->b_blkno == -1) { |
828 |
bufdone(bp); |
829 |
return (0); |
830 |
} |
877 |
} |
|
|
878 |
|
831 |
bo = node->udfmp->im_bo; |
879 |
bo = node->udfmp->im_bo; |
832 |
bp->b_iooffset = dbtob(bp->b_blkno); |
880 |
bp->b_iooffset = dbtob(bp->b_blkno); |
833 |
BO_STRATEGY(bo, bp); |
881 |
BO_STRATEGY(bo, bp); |
|
|
882 |
|
834 |
return (0); |
883 |
return (0); |
835 |
} |
884 |
} |
836 |
|
885 |
|
Lines 851-867
udf_bmap(struct vop_bmap_args *a)
Link Here
|
851 |
if (a->a_runb) |
900 |
if (a->a_runb) |
852 |
*a->a_runb = 0; |
901 |
*a->a_runb = 0; |
853 |
|
902 |
|
854 |
error = udf_bmap_internal(node, a->a_bn * node->udfmp->bsize, &lsector, |
903 |
/* |
855 |
&max_size); |
904 |
* UDF_INVALID_BMAP means data embedded into fentry, this is an internal |
|
|
905 |
* error that should not be propagated to calling code. |
906 |
* Most obvious mapping for this error is EOPNOTSUPP as we can not truly |
907 |
* translate block numbers in this case. |
908 |
* Incidentally, this return code will make vnode pager to use VOP_READ |
909 |
* to get data for mmap-ed pages and udf_read knows how to do the right |
910 |
* thing for this kind of files. |
911 |
*/ |
912 |
error = udf_bmap_internal(node, a->a_bn << node->udfmp->bshift, &lsector, &max_size); |
913 |
if (error == UDF_INVALID_BMAP) |
914 |
return EOPNOTSUPP; |
856 |
if (error) |
915 |
if (error) |
857 |
return (error); |
916 |
return (error); |
858 |
|
917 |
|
859 |
/* Translate logical to physical sector number */ |
918 |
/* Translate logical to physical sector number */ |
860 |
*a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); |
919 |
*a->a_bnp = lsector << (node->udfmp->bshift - DEV_BSHIFT); |
861 |
|
920 |
|
862 |
/* Punt on read-ahead for now */ |
921 |
/* |
863 |
if (a->a_runp) |
922 |
* Determine maximum number of readahead blocks following the |
864 |
*a->a_runp = 0; |
923 |
* requested block. |
|
|
924 |
*/ |
925 |
if (a->a_runp) { |
926 |
int nblk; |
927 |
|
928 |
nblk = (max_size >> node->udfmp->bshift) - 1; |
929 |
if (nblk <= 0) |
930 |
*a->a_runp = 0; |
931 |
else if (nblk >= (MAXBSIZE >> node->udfmp->bshift)) |
932 |
*a->a_runp = (MAXBSIZE >> node->udfmp->bshift) - 1; |
933 |
else |
934 |
*a->a_runp = nblk; |
935 |
} |
936 |
|
937 |
if (a->a_runb) { |
938 |
*a->a_runb = 0; |
939 |
} |
865 |
|
940 |
|
866 |
return (0); |
941 |
return (0); |
867 |
} |
942 |
} |
Lines 1052-1058
udf_readatoffset(struct udf_node *node, int *size, off_t offset,
Link Here
|
1052 |
struct buf **bp, uint8_t **data) |
1127 |
struct buf **bp, uint8_t **data) |
1053 |
{ |
1128 |
{ |
1054 |
struct udf_mnt *udfmp; |
1129 |
struct udf_mnt *udfmp; |
1055 |
struct file_entry *fentry = NULL; |
|
|
1056 |
struct buf *bp1; |
1130 |
struct buf *bp1; |
1057 |
uint32_t max_size; |
1131 |
uint32_t max_size; |
1058 |
daddr_t sector; |
1132 |
daddr_t sector; |
Lines 1060-1075
udf_readatoffset(struct udf_node *node, int *size, off_t offset,
Link Here
|
1060 |
|
1134 |
|
1061 |
udfmp = node->udfmp; |
1135 |
udfmp = node->udfmp; |
1062 |
|
1136 |
|
1063 |
*bp = NULL; |
1137 |
/* |
|
|
1138 |
* This call is made not only to detect UDF_INVALID_BMAP case, |
1139 |
* max_size is used as an ad-hoc read-ahead hint for "normal" case. |
1140 |
*/ |
1064 |
error = udf_bmap_internal(node, offset, §or, &max_size); |
1141 |
error = udf_bmap_internal(node, offset, §or, &max_size); |
1065 |
if (error == UDF_INVALID_BMAP) { |
1142 |
if (error == UDF_INVALID_BMAP) { |
1066 |
/* |
1143 |
/* |
1067 |
* This error means that the file *data* is stored in the |
1144 |
* This error means that the file *data* is stored in the |
1068 |
* allocation descriptor field of the file entry. |
1145 |
* allocation descriptor field of the file entry. |
1069 |
*/ |
1146 |
*/ |
1070 |
fentry = node->fentry; |
1147 |
if (node->fentry->tag.id == TAGID_FENTRY) { |
1071 |
*data = &fentry->data[le32toh(fentry->l_ea)]; |
1148 |
struct file_entry *fentry = node->fentry; |
1072 |
*size = le32toh(fentry->l_ad); |
1149 |
*data = &fentry->data[le32toh(fentry->l_ea)]; |
|
|
1150 |
*size = le32toh(fentry->l_ad); |
1151 |
} |
1152 |
else { |
1153 |
struct extfile_entry *fentry = (struct extfile_entry *)node->fentry; |
1154 |
*data = &fentry->data[le32toh(fentry->l_ea)]; |
1155 |
*size = le32toh(fentry->l_ad); |
1156 |
} |
1073 |
return (0); |
1157 |
return (0); |
1074 |
} else if (error != 0) { |
1158 |
} else if (error != 0) { |
1075 |
return (error); |
1159 |
return (error); |
Lines 1078-1086
udf_readatoffset(struct udf_node *node, int *size, off_t offset,
Link Here
|
1078 |
/* Adjust the size so that it is within range */ |
1162 |
/* Adjust the size so that it is within range */ |
1079 |
if (*size == 0 || *size > max_size) |
1163 |
if (*size == 0 || *size > max_size) |
1080 |
*size = max_size; |
1164 |
*size = max_size; |
1081 |
*size = min(*size, MAXBSIZE); |
1165 |
*size = min(*size, MAXBSIZE - blkoff(udfmp, offset)); |
1082 |
|
1166 |
|
1083 |
if ((error = udf_readlblks(udfmp, sector, *size + (offset & udfmp->bmask), bp))) { |
1167 |
*bp = NULL; |
|
|
1168 |
if ((error = bread(node->i_vnode, lblkno(udfmp, offset), (*size + blkoff(udfmp, offset) + udfmp->bmask) & ~udfmp->bmask, NOCRED, bp))) { |
1084 |
printf("warning: udf_readlblks returned error %d\n", error); |
1169 |
printf("warning: udf_readlblks returned error %d\n", error); |
1085 |
/* note: *bp may be non-NULL */ |
1170 |
/* note: *bp may be non-NULL */ |
1086 |
return (error); |
1171 |
return (error); |
Lines 1137-1148
udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector,
Link Here
|
1137 |
do { |
1222 |
do { |
1138 |
offset -= icblen; |
1223 |
offset -= icblen; |
1139 |
ad_offset = sizeof(struct short_ad) * ad_num; |
1224 |
ad_offset = sizeof(struct short_ad) * ad_num; |
1140 |
if (ad_offset > le32toh(fentry->l_ad)) { |
1225 |
if (ad_offset > le32toh(GET_FENTRY_FIELD(fentry, l_ad))) { |
1141 |
printf("File offset out of bounds\n"); |
1226 |
printf("File offset out of bounds\n"); |
1142 |
return (EINVAL); |
1227 |
return (EINVAL); |
1143 |
} |
1228 |
} |
1144 |
icb = GETICB(short_ad, fentry, |
1229 |
icb = GETICB(short_ad, fentry, |
1145 |
le32toh(fentry->l_ea) + ad_offset); |
1230 |
le32toh(GET_FENTRY_FIELD(fentry, l_ea)) + ad_offset); |
1146 |
icblen = GETICBLEN(short_ad, icb); |
1231 |
icblen = GETICBLEN(short_ad, icb); |
1147 |
ad_num++; |
1232 |
ad_num++; |
1148 |
} while(offset >= icblen); |
1233 |
} while(offset >= icblen); |
Lines 1162-1173
udf_bmap_internal(struct udf_node *node, off_t offset, daddr_t *sector,
Link Here
|
1162 |
do { |
1247 |
do { |
1163 |
offset -= icblen; |
1248 |
offset -= icblen; |
1164 |
ad_offset = sizeof(struct long_ad) * ad_num; |
1249 |
ad_offset = sizeof(struct long_ad) * ad_num; |
1165 |
if (ad_offset > le32toh(fentry->l_ad)) { |
1250 |
if (ad_offset > le32toh(GET_FENTRY_FIELD(fentry, l_ad))) { |
1166 |
printf("File offset out of bounds\n"); |
1251 |
printf("File offset out of bounds\n"); |
1167 |
return (EINVAL); |
1252 |
return (EINVAL); |
1168 |
} |
1253 |
} |
1169 |
icb = GETICB(long_ad, fentry, |
1254 |
icb = GETICB(long_ad, fentry, |
1170 |
le32toh(fentry->l_ea) + ad_offset); |
1255 |
le32toh(GET_FENTRY_FIELD(fentry, l_ea)) + ad_offset); |
1171 |
icblen = GETICBLEN(long_ad, icb); |
1256 |
icblen = GETICBLEN(long_ad, icb); |
1172 |
ad_num++; |
1257 |
ad_num++; |
1173 |
} while(offset >= icblen); |
1258 |
} while(offset >= icblen); |