summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.travis.yml6
-rw-r--r--.whitesource11
-rw-r--r--Makefile.am50
-rw-r--r--README.md4
-rw-r--r--README_dev_photorec.txt2
-rwxr-xr-xautogen.sh3
-rw-r--r--blacklist_cfi.txt5
-rw-r--r--configure.ac2
-rw-r--r--copr/testdisk.spec2
m---------doc0
-rw-r--r--doc/favicon.icobin2238 -> 0 bytes
-rw-r--r--doc/photorec.icobin2238 -> 0 bytes
-rw-r--r--src/Makefile.am79
-rw-r--r--src/addpart.h8
-rw-r--r--src/adv.c89
-rw-r--r--src/adv.h10
-rw-r--r--src/alignio.h64
-rw-r--r--src/analyse.c2
-rw-r--r--src/analyse.h2
-rw-r--r--src/askloc.h4
-rw-r--r--src/autoset.h4
-rw-r--r--src/bfs.c56
-rw-r--r--src/bfs.h15
-rw-r--r--src/bsd.c43
-rw-r--r--src/bsd.h18
-rw-r--r--src/btrfs.c2
-rw-r--r--src/btrfs.h2
-rw-r--r--src/chgarch.h5
-rw-r--r--src/common.c120
-rw-r--r--src/common.h115
-rw-r--r--src/cramfs.c2
-rw-r--r--src/cramfs.h2
-rw-r--r--src/crc.c1
-rw-r--r--src/crc.h5
-rw-r--r--src/dfxml.c28
-rw-r--r--src/dfxml.h2
-rw-r--r--src/dimage.c5
-rw-r--r--src/dir.c6
-rw-r--r--src/dir.h103
-rw-r--r--src/dir_common.h123
-rw-r--r--src/dirn.c14
-rw-r--r--src/ewf.c243
-rw-r--r--src/ewf.h4
-rw-r--r--src/ext2.c2
-rw-r--r--src/ext2.h2
-rw-r--r--src/ext2_dir.c10
-rw-r--r--src/ext2_inc.h4
-rw-r--r--src/ext2_sb.c2
-rw-r--r--src/ext2_sb.h2
-rw-r--r--src/ext2grp.c4
-rw-r--r--src/ext2grp.h4
-rw-r--r--src/ext2p.c7
-rw-r--r--src/fat.c202
-rw-r--r--src/fat.h230
-rw-r--r--src/fat1x.c4
-rw-r--r--src/fat_adv.c2
-rw-r--r--src/fat_cluster.c2
-rw-r--r--src/fat_cluster.h2
-rw-r--r--src/fat_common.c1
-rw-r--r--src/fat_common.h134
-rw-r--r--src/fat_dir.c1
-rw-r--r--src/fat_dir.h1
-rw-r--r--src/fat_unformat.c11
-rw-r--r--src/fatn.c1
-rw-r--r--src/fidentify.c124
-rw-r--r--src/file_1cd.c4
-rw-r--r--src/file_3dm.c8
-rw-r--r--src/file_3ds.c76
-rw-r--r--src/file_7z.c5
-rw-r--r--src/file_DB.c2
-rw-r--r--src/file_a.c2
-rw-r--r--src/file_ab.c15
-rw-r--r--src/file_abr.c15
-rw-r--r--src/file_acb.c2
-rw-r--r--src/file_ace.c130
-rw-r--r--src/file_ado.c2
-rw-r--r--src/file_afdesign.c2
-rw-r--r--src/file_ahn.c2
-rw-r--r--src/file_aif.c2
-rw-r--r--src/file_all.c2
-rw-r--r--src/file_als.c2
-rw-r--r--src/file_amd.c2
-rw-r--r--src/file_amr.c15
-rw-r--r--src/file_apa.c2
-rw-r--r--src/file_ape.c2
-rw-r--r--src/file_apple.c2
-rw-r--r--src/file_ari.c2
-rw-r--r--src/file_arj.c2
-rw-r--r--src/file_asf.c49
-rw-r--r--src/file_asl.c2
-rw-r--r--src/file_asm.c19
-rw-r--r--src/file_atd.c2
-rw-r--r--src/file_au.c2
-rw-r--r--src/file_axp.c15
-rw-r--r--src/file_axx.c17
-rw-r--r--src/file_bac.c38
-rw-r--r--src/file_bdm.c2
-rw-r--r--src/file_berkeley.c2
-rw-r--r--src/file_bfa.c78
-rw-r--r--src/file_bim.c2
-rw-r--r--src/file_bin.c2
-rw-r--r--src/file_binvox.c2
-rw-r--r--src/file_bkf.c52
-rw-r--r--src/file_bld.c85
-rw-r--r--src/file_bmp.c39
-rw-r--r--src/file_bpg.c52
-rw-r--r--src/file_bvr.c5
-rw-r--r--src/file_bz2.c4
-rw-r--r--src/file_c4d.c2
-rw-r--r--src/file_cab.c2
-rw-r--r--src/file_caf.c9
-rw-r--r--src/file_cam.c2
-rw-r--r--src/file_catdrawing.c2
-rw-r--r--src/file_cdt.c2
-rw-r--r--src/file_che.c2
-rw-r--r--src/file_chm.c2
-rw-r--r--src/file_class.c2
-rw-r--r--src/file_cm.c2
-rw-r--r--src/file_compress.c2
-rw-r--r--src/file_cow.c2
-rw-r--r--src/file_cpi.c2
-rw-r--r--src/file_crw.c2
-rw-r--r--src/file_csh.c2
-rw-r--r--src/file_ctg.c2
-rw-r--r--src/file_cwk.c2
-rw-r--r--src/file_d2s.c4
-rw-r--r--src/file_dad.c5
-rw-r--r--src/file_dar.c2
-rw-r--r--src/file_dat.c2
-rw-r--r--src/file_dbf.c2
-rw-r--r--src/file_dbn.c2
-rw-r--r--src/file_dcm.c2
-rw-r--r--src/file_ddf.c2
-rw-r--r--src/file_dex.c2
-rw-r--r--src/file_dim.c2
-rw-r--r--src/file_dir.c32
-rw-r--r--src/file_djv.c2
-rw-r--r--src/file_dmp.c3
-rw-r--r--src/file_doc.c1634
-rw-r--r--src/file_dpx.c2
-rw-r--r--src/file_drw.c2
-rw-r--r--src/file_ds2.c2
-rw-r--r--src/file_ds_store.c2
-rw-r--r--src/file_dsc.c2
-rw-r--r--src/file_dss.c2
-rw-r--r--src/file_dst.c2
-rw-r--r--src/file_dta.c2
-rw-r--r--src/file_dump.c2
-rw-r--r--src/file_dv.c23
-rw-r--r--src/file_dvi.c2
-rw-r--r--src/file_dvr.c2
-rw-r--r--src/file_dwg.c2
-rw-r--r--src/file_dxf.c5
-rw-r--r--src/file_e01.c29
-rw-r--r--src/file_ecryptfs.c2
-rw-r--r--src/file_edb.c2
-rw-r--r--src/file_elf.c2
-rw-r--r--src/file_emf.c195
-rw-r--r--src/file_ess.c2
-rw-r--r--src/file_evt.c9
-rw-r--r--src/file_evtx.c2
-rw-r--r--src/file_exe.c41
-rw-r--r--src/file_exr.c2
-rw-r--r--src/file_exs.c4
-rw-r--r--src/file_ext.c3
-rw-r--r--src/file_ext2.c4
-rw-r--r--src/file_fat.c16
-rw-r--r--src/file_fbf.c2
-rw-r--r--src/file_fbk.c2
-rw-r--r--src/file_fcp.c2
-rw-r--r--src/file_fcs.c87
-rw-r--r--src/file_fdb.c2
-rw-r--r--src/file_fds.c2
-rw-r--r--src/file_fh10.c2
-rw-r--r--src/file_fh5.c2
-rw-r--r--src/file_filevault.c2
-rw-r--r--src/file_fit.c2
-rw-r--r--src/file_fits.c36
-rw-r--r--src/file_flac.c9
-rw-r--r--src/file_flp.c2
-rw-r--r--src/file_flv.c5
-rw-r--r--src/file_fm.c4
-rw-r--r--src/file_fob.c2
-rw-r--r--src/file_fos.c2
-rw-r--r--src/file_fp5.c2
-rw-r--r--src/file_fp7.c2
-rw-r--r--src/file_freeway.c2
-rw-r--r--src/file_frm.c2
-rw-r--r--src/file_fs.c5
-rw-r--r--src/file_fwd.c2
-rw-r--r--src/file_gam.c2
-rw-r--r--src/file_gct.c2
-rw-r--r--src/file_gho.c2
-rw-r--r--src/file_gi.c4
-rw-r--r--src/file_gif.c111
-rw-r--r--src/file_gm6.c2
-rw-r--r--src/file_gp2.c2
-rw-r--r--src/file_gp5.c2
-rw-r--r--src/file_gpg.c131
-rw-r--r--src/file_gpx.c2
-rw-r--r--src/file_gsm.c25
-rw-r--r--src/file_gz.c79
-rw-r--r--src/file_hdf.c36
-rw-r--r--src/file_hdr.c2
-rw-r--r--src/file_hds.c2
-rw-r--r--src/file_hfsp.c2
-rw-r--r--src/file_hm.c2
-rw-r--r--src/file_hr9.c2
-rw-r--r--src/file_http.c2
-rw-r--r--src/file_ibd.c4
-rw-r--r--src/file_icc.c2
-rw-r--r--src/file_icns.c14
-rw-r--r--src/file_ico.c2
-rw-r--r--src/file_idx.c2
-rw-r--r--src/file_ifo.c2
-rw-r--r--src/file_imb.c2
-rw-r--r--src/file_indd.c15
-rw-r--r--src/file_info.c2
-rw-r--r--src/file_iso.c16
-rw-r--r--src/file_it.c2
-rw-r--r--src/file_itu.c2
-rw-r--r--src/file_jks.c2
-rw-r--r--src/file_jpg.c1327
-rw-r--r--src/file_jsonlz4.c2
-rw-r--r--src/file_kdb.c2
-rw-r--r--src/file_kdbx.c2
-rw-r--r--src/file_key.c2
-rw-r--r--src/file_ldf.c2
-rw-r--r--src/file_list.c713
-rw-r--r--src/file_lit.c2
-rw-r--r--src/file_lnk.c37
-rw-r--r--src/file_logic.c2
-rw-r--r--src/file_lso.c2
-rw-r--r--src/file_luks.c2
-rw-r--r--src/file_lxo.c4
-rw-r--r--src/file_lzh.c11
-rw-r--r--src/file_lzo.c2
-rw-r--r--src/file_m2ts.c2
-rw-r--r--src/file_mat.c2
-rw-r--r--src/file_max.c2
-rw-r--r--src/file_mb.c2
-rw-r--r--src/file_mcd.c2
-rw-r--r--src/file_mdb.c2
-rw-r--r--src/file_mdf.c2
-rw-r--r--src/file_mdp.c69
-rw-r--r--src/file_mfa.c2
-rw-r--r--src/file_mfg.c2
-rw-r--r--src/file_mft.c4
-rw-r--r--src/file_mid.c2
-rw-r--r--src/file_mig.c2
-rw-r--r--src/file_mk5.c2
-rw-r--r--src/file_mkv.c2
-rw-r--r--src/file_mlv.c43
-rw-r--r--src/file_mobi.c2
-rw-r--r--src/file_mov.c24
-rw-r--r--src/file_mp3.c701
-rw-r--r--src/file_mpg.c2
-rw-r--r--src/file_mpl.c2
-rw-r--r--src/file_mrw.c2
-rw-r--r--src/file_msa.c2
-rw-r--r--src/file_mus.c2
-rw-r--r--src/file_mxf.c2
-rw-r--r--src/file_myo.c2
-rw-r--r--src/file_mysql.c2
-rw-r--r--src/file_nd2.c2
-rw-r--r--src/file_nds.c2
-rw-r--r--src/file_nes.c2
-rw-r--r--src/file_njx.c2
-rw-r--r--src/file_nk2.c2
-rw-r--r--src/file_nsf.c2
-rw-r--r--src/file_oci.c2
-rw-r--r--src/file_ogg.c2
-rw-r--r--src/file_one.c2
-rw-r--r--src/file_orf.c4
-rw-r--r--src/file_paf.c2
-rw-r--r--src/file_pap.c2
-rw-r--r--src/file_par2.c2
-rw-r--r--src/file_pcap.c2
-rw-r--r--src/file_pcb.c2
-rw-r--r--src/file_pct.c2
-rw-r--r--src/file_pcx.c3
-rw-r--r--src/file_pdb.c2
-rw-r--r--src/file_pdf.c8
-rw-r--r--src/file_pds.c2
-rw-r--r--src/file_pf.c21
-rw-r--r--src/file_pfx.c2
-rw-r--r--src/file_pgdump.c2
-rw-r--r--src/file_plist.c2
-rw-r--r--src/file_plr.c2
-rw-r--r--src/file_plt.c2
-rw-r--r--src/file_png.c2
-rw-r--r--src/file_pnm.c2
-rw-r--r--src/file_prc.c2
-rw-r--r--src/file_prd.c2
-rw-r--r--src/file_prt.c2
-rw-r--r--src/file_ps.c2
-rw-r--r--src/file_psb.c2
-rw-r--r--src/file_psd.c2
-rw-r--r--src/file_psf.c2
-rw-r--r--src/file_psp.c2
-rw-r--r--src/file_pst.c2
-rw-r--r--src/file_ptb.c2
-rw-r--r--src/file_ptf.c2
-rw-r--r--src/file_pyc.c2
-rw-r--r--src/file_pzf.c2
-rw-r--r--src/file_pzh.c2
-rw-r--r--src/file_qbb.c9
-rw-r--r--src/file_qdf.c6
-rw-r--r--src/file_qkt.c2
-rw-r--r--src/file_qxd.c2
-rw-r--r--src/file_r3d.c2
-rw-r--r--src/file_ra.c2
-rw-r--r--src/file_raf.c2
-rw-r--r--src/file_rar.c2
-rw-r--r--src/file_raw.c2
-rw-r--r--src/file_rdc.c2
-rw-r--r--src/file_reg.c2
-rw-r--r--src/file_res.c2
-rw-r--r--src/file_rfp.c2
-rw-r--r--src/file_riff.c2
-rw-r--r--src/file_rlv.c2
-rw-r--r--src/file_rm.c2
-rw-r--r--src/file_rns.c2
-rw-r--r--src/file_rpm.c2
-rw-r--r--src/file_rw2.c4
-rw-r--r--src/file_rx2.c2
-rw-r--r--src/file_save.c2
-rw-r--r--src/file_sdsk.c68
-rw-r--r--src/file_ses.c2
-rw-r--r--src/file_sgcta.c2
-rw-r--r--src/file_shn.c2
-rw-r--r--src/file_sib.c2
-rw-r--r--src/file_sig.c17
-rw-r--r--src/file_sit.c2
-rw-r--r--src/file_skd.c2
-rw-r--r--src/file_skp.c4
-rw-r--r--src/file_snag.c2
-rw-r--r--src/file_sp3.c2
-rw-r--r--src/file_spe.c179
-rw-r--r--src/file_spf.c2
-rw-r--r--src/file_spss.c2
-rw-r--r--src/file_sql.c2
-rw-r--r--src/file_sqm.c2
-rw-r--r--src/file_steuer2014.c39
-rw-r--r--src/file_stl.c2
-rw-r--r--src/file_stu.c2
-rw-r--r--src/file_studio.c2
-rw-r--r--src/file_swf.c189
-rw-r--r--src/file_tar.c14
-rw-r--r--src/file_tax.c2
-rw-r--r--src/file_template.c2
-rw-r--r--src/file_tg.c2
-rw-r--r--src/file_tib.c2
-rw-r--r--src/file_tiff.c57
-rw-r--r--src/file_tiff.h86
-rw-r--r--src/file_tiff_be.c395
-rw-r--r--src/file_tiff_le.c336
-rw-r--r--src/file_tivo.c2
-rw-r--r--src/file_torrent.c2
-rw-r--r--src/file_tph.c2
-rw-r--r--src/file_tpl.c2
-rw-r--r--src/file_ttf.c2
-rw-r--r--src/file_txt.c3823
-rw-r--r--src/file_txt.h9
-rw-r--r--src/file_tz.c2
-rw-r--r--src/file_v2i.c2
-rw-r--r--src/file_vault.c2
-rw-r--r--src/file_vdi.c2
-rw-r--r--src/file_vdj.c2
-rw-r--r--src/file_veg.c2
-rw-r--r--src/file_vfb.c2
-rw-r--r--src/file_vib.c2
-rw-r--r--src/file_vmdk.c2
-rw-r--r--src/file_vmg.c2
-rw-r--r--src/file_wallet.c2
-rw-r--r--src/file_wdp.c4
-rw-r--r--src/file_wee.c2
-rw-r--r--src/file_wim.c2
-rw-r--r--src/file_win.c7
-rw-r--r--src/file_wks.c2
-rw-r--r--src/file_wld.c2
-rw-r--r--src/file_wmf.c52
-rw-r--r--src/file_wnk.c2
-rw-r--r--src/file_woff.c2
-rw-r--r--src/file_wpb.c2
-rw-r--r--src/file_wpd.c2
-rw-r--r--src/file_wtv.c2
-rw-r--r--src/file_wv.c2
-rw-r--r--src/file_x3f.c2
-rw-r--r--src/file_x3i.c2
-rw-r--r--src/file_x4a.c2
-rw-r--r--src/file_xar.c2
-rw-r--r--src/file_xcf.c2
-rw-r--r--src/file_xfi.c2
-rw-r--r--src/file_xfs.c2
-rw-r--r--src/file_xm.c2
-rw-r--r--src/file_xml.c2
-rw-r--r--src/file_xpt.c2
-rw-r--r--src/file_xsv.c2
-rw-r--r--src/file_xv.c2
-rw-r--r--src/file_xz.c2
-rw-r--r--src/file_z2d.c2
-rw-r--r--src/file_zcode.c2
-rw-r--r--src/file_zip.c433
-rw-r--r--src/file_zpr.c2
-rw-r--r--src/filegen.c454
-rw-r--r--src/filegen.h55
-rw-r--r--src/fnctdsk.c28
-rw-r--r--src/fnctdsk.h163
-rw-r--r--src/fuzzerfidentify.cpp6
-rw-r--r--src/geometry.c1
-rw-r--r--src/geometry.h21
-rw-r--r--src/gfs2.c4
-rw-r--r--src/gfs2.h2
-rw-r--r--src/godmode.c15
-rw-r--r--src/godmode.h2
-rw-r--r--src/guid_cmp.h4
-rw-r--r--src/guid_cpy.h9
-rw-r--r--src/hdaccess.c36
-rw-r--r--src/hdaccess.h78
-rw-r--r--src/hdcache.c91
-rw-r--r--src/hdcache.h4
-rw-r--r--src/hfs.c4
-rw-r--r--src/hfs.h26
-rw-r--r--src/hfsp.c5
-rw-r--r--src/hfsp.h4
-rw-r--r--src/hpa_dco.c14
-rw-r--r--src/hpfs.c6
-rw-r--r--src/hpfs.h2
-rw-r--r--src/intrf.c4
-rw-r--r--src/intrf.h11
-rw-r--r--src/intrfn.c13
-rw-r--r--src/intrfn.h2
-rw-r--r--src/iso.c24
-rw-r--r--src/iso.h11
-rw-r--r--src/iso9660.h6
-rw-r--r--src/jfs.c77
-rw-r--r--src/jfs.h14
-rw-r--r--src/list.h59
-rw-r--r--src/log.c11
-rw-r--r--src/log.h21
-rw-r--r--src/luks.c55
-rw-r--r--src/luks.h2
-rw-r--r--src/lvm.c128
-rw-r--r--src/lvm.h30
-rw-r--r--src/md.c362
-rw-r--r--src/md.h22
-rw-r--r--src/memmem.h8
-rw-r--r--src/misc.c16
-rw-r--r--src/misc.h5
-rw-r--r--src/msdos.c16
-rw-r--r--src/netware.c2
-rw-r--r--src/netware.h14
-rw-r--r--src/nodisk.c8
-rw-r--r--src/ntfs.c11
-rw-r--r--src/ntfs_adv.c85
-rw-r--r--src/ntfs_dir.c12
-rw-r--r--src/ntfs_io.c7
-rw-r--r--src/ntfs_udl.c21
-rw-r--r--src/ntfs_utl.c6
-rw-r--r--src/ntfsp.c10
-rw-r--r--src/partauto.c14
-rw-r--r--src/partauto.h5
-rw-r--r--src/partgpt.c75
-rw-r--r--src/partgpt.h15
-rw-r--r--src/parthumax.c70
-rw-r--r--src/parthumax.h2
-rw-r--r--src/parti386.c208
-rw-r--r--src/parti386.h21
-rw-r--r--src/partmac.c67
-rw-r--r--src/partmac.h2
-rw-r--r--src/partnone.c72
-rw-r--r--src/partsun.c78
-rw-r--r--src/partsun.h2
-rw-r--r--src/partxbox.c73
-rw-r--r--src/partxbox.h2
-rw-r--r--src/partxboxn.c6
-rw-r--r--src/pdiskseln.c34
-rw-r--r--src/pdiskseln.h8
-rw-r--r--src/phbf.c5
-rw-r--r--src/phbs.c8
-rw-r--r--src/phcfg.c33
-rw-r--r--src/phcfg.h2
-rw-r--r--src/phcli.c8
-rw-r--r--src/phcli.h6
-rw-r--r--src/phmain.c76
-rw-r--r--src/phnc.h6
-rw-r--r--src/photorec.c33
-rw-r--r--src/photorec.h28
-rw-r--r--src/photorec_check_header.h55
-rw-r--r--src/phrecn.c8
-rw-r--r--src/pnext.h8
-rw-r--r--src/poptions.c1
-rw-r--r--src/poptions.h10
-rw-r--r--src/ppartseln.c3
-rw-r--r--src/psearch.h2
-rw-r--r--src/psearchn.c61
-rw-r--r--src/qphotorec.cpp12
-rw-r--r--src/qpsearch.cpp56
-rw-r--r--src/rfs.c2
-rw-r--r--src/rfs.h16
-rw-r--r--src/savehdr.c6
-rw-r--r--src/savehdr.h4
-rw-r--r--src/sessionp.c14
-rw-r--r--src/setdate.c7
-rw-r--r--src/sudo.c5
-rw-r--r--src/sun.c2
-rw-r--r--src/sun.h16
-rw-r--r--src/suspend_no.c3
-rw-r--r--src/swap.h11
-rw-r--r--src/sysv.c2
-rw-r--r--src/sysv.h2
-rw-r--r--src/tdisksel.c8
-rw-r--r--src/testdisk.c56
-rw-r--r--src/texfat.c2
-rw-r--r--src/thfs.c2
-rw-r--r--src/tntfs.c2
-rw-r--r--src/ufs.c2
-rw-r--r--src/ufs.h15
-rw-r--r--src/vmfs.c46
-rw-r--r--src/vmfs.h2
-rw-r--r--src/wbfs.c34
-rw-r--r--src/wbfs.h2
-rw-r--r--src/win32.c6
-rw-r--r--src/xfs.c112
-rw-r--r--src/xfs.h17
-rw-r--r--src/zfs.c47
-rw-r--r--src/zfs.h17
529 files changed, 13830 insertions, 4454 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..8d98afa
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "doc"]
+ path = doc
+ url = https://github.com/cgsecurity/testdisk_documentation.git
diff --git a/.travis.yml b/.travis.yml
index f2c022a..3c9bd38 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,14 +2,12 @@ dist: trusty
sudo: true
addons:
- sonarqube:
+ sonarcloud:
organization: "cgsecurity-github"
token:
secure: "HGnOsSSghmeMHCbigtEAgkV6oaJZ1xFUhvZun0oPOv7Y2XCpIPw376G5wTppgzZUZdcSsNcu63FAnWmZZDBH29mAd6K4tIw6MDqAe9UyLzWHMEMWrMQjqSMOaqetLCw4e1Zqa0kSYyZAdg4Fp7NrNjPLho1fVUJBCCrBtU1AxaPmMNkGpSZ1d9YK6rz58jNBnm7dKp0LSUFfcas88aXKuGhGYdttdPmD4/E6XQprFGMzBMk7XXV2guKgziAprhaIAF7QOs24FhAq6IKSu00JH5UAqtgeQ9+K7srv4lHeHz/N2SzLJldrei3+WNo72T8g10enJpcerZ/lS0Tl/J+5YPsC0TAXRqZmWlbSs7CR/N6CTMlckox8tUTeDyptIYhh50xZYwR+WB4ODW5vROz7EKXVfd7YHprnMZuGMw8eJaenTZ8wm/erms38rmZNsRKqoHWXxP4QwjOJumMFJVKyq1/5MkT18lA2Ajy57WcS6SjWGyRhdirV/IGbsFdS8A21PQ0ASDA7UjJrDYclmiEfy7G1OItMv739llM2z23mN/UnKO9ijPPfi3quCSEeozQiOLQpwsdmGUhAkPfBN6dAutqIrgXl/rFV3y2KNhDprWd0GBrtNhcTLWr3/5+0rrh8ntkF904QCBvR1XwOUH4z8nmGq35WXVs4Y2aafrRw1dM="
- branches:
- - master
- - dev
+os: linux
language: c
compiler:
- gcc
diff --git a/.whitesource b/.whitesource
new file mode 100644
index 0000000..004ba82
--- /dev/null
+++ b/.whitesource
@@ -0,0 +1,11 @@
+{
+ "scanSettings": {
+ "baseBranches": []
+ },
+ "checkRunSettings": {
+ "vulnerableCheckRunConclusionLevel": "failure"
+ },
+ "issueSettings": {
+ "minSeverityLevel": "LOW"
+ }
+} \ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
index 0ccabc1..94e0926 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,24 +1,3 @@
-.PRECIOUS: session_%.framac
-FRAMA_C_FLAGS=-machdep x86_64 \
- -warn-left-shift-negative \
- -warn-right-shift-negative \
- -warn-signed-downcast \
- -warn-signed-overflow \
- -warn-unsigned-downcast \
- -warn-unsigned-overflow \
- -rte \
- -eva \
- -eva-slevel 6 \
- -eva-warn-undefined-pointer-comparison none \
- -eva-ignore-recursive-calls \
- -then \
- -wp \
- -wp-dynamic \
- -wp-steps 100000 -wp-depth 100000 \
- -wp-split -wp-literals \
- -wp-timeout 20 -pp-annot \
- -kernel-msg-key pp
-
SUBDIRS = icons man src
docdir ?= $(datadir)/doc/$(PACKAGE)
@@ -80,32 +59,11 @@ extras:
extrasstatic:
$(MAKE) LDFLAGS="$(LDFLAGS) -static" LIBS="$(PTHREAD_LIBS) $(LIBS)" CFLAGS="$(PTHREAD_CFLAGS) $(CFLAGS)" CXXFLAGS="$(PTHREAD_CFLAGS) $(CXXFLAGS)" extras
-session_doc.framac: src/file_doc.c src/common.c src/filegen.c src/log.c src/setdate.c
- gcc -W -Wall -DMAIN_doc -DHAVE_CONFIG_H -O -o demo -I. $^
- frama-c $^ -cpp-extra-args="-DMAIN_doc -DHAVE_CONFIG_H -D__x86_64__" $(FRAMA_C_FLAGS) -save $@
-
-session_id3.framac: src/file_mp3.c src/common.c src/filegen.c src/log.c
- gcc -W -Wall -DMAIN_id3 -DHAVE_CONFIG_H -O -o demo -I. $^
- frama-c $^ -cpp-extra-args="-DMAIN_id3 -DHAVE_CONFIG_H -D__x86_64__" $(FRAMA_C_FLAGS) -save $@
-
-session_jpg.framac: src/file_jpg.c src/common.c src/filegen.c src/log.c src/suspend_no.c src/setdate.c
- gcc -W -Wall -DMAIN_jpg -DHAVE_CONFIG_H -O -o demo -I. $^ -ljpeg
- frama-c $^ -cpp-extra-args="-DMAIN_jpg -DHAVE_CONFIG_H -D__x86_64__ -I/usr/include -I $(frama-c -print-path)/libc" $(FRAMA_C_FLAGS) -save $@
-
-session_tiff_be.framac: src/file_tiff.c src/file_tiff_be.c src/file_tiff_le.c src/common.c src/filegen.c src/log.c
- gcc -W -Wall -DMAIN_tiff_le -DHAVE_CONFIG_H -O -o demo -I. $^
- frama-c $^ -cpp-extra-args="-DMAIN_tiff_le -DHAVE_CONFIG_H -D__x86_64__" $(FRAMA_C_FLAGS) -save $@
-
-session_tiff_le.framac: src/file_tiff.c src/file_tiff_be.c src/file_tiff_le.c src/common.c src/filegen.c src/log.c
- gcc -W -Wall -DMAIN_tiff_le -DHAVE_CONFIG_H -O -o demo -I. $^
- frama-c $^ -cpp-extra-args="-DMAIN_tiff_le -DHAVE_CONFIG_H -D__x86_64__" $(FRAMA_C_FLAGS) -save $@
-
-session_%.framac: src/file_%.c src/common.c src/filegen.c src/log.c
- gcc -W -Wall -DMAIN_$* -DHAVE_CONFIG_H -O -o demo -I. $^
- frama-c $^ -cpp-extra-args="-DMAIN_$* -DHAVE_CONFIG_H -D__x86_64__" $(FRAMA_C_FLAGS) -save $@
+session_%.framac:
+ (cd src && $(MAKE) $@) || exit 1;
-frama-c-%: session_%.framac
- frama-c-gui -load $^
+frama-c-%:
+ (cd src && $(MAKE) $@) || exit 1;
cppcheck:
cppcheck --quiet --enable=all -DHAVE_CONFIG_H -I$(builddir) -I/usr/include $(srcdir)/src
diff --git a/README.md b/README.md
index a139291..f1a6577 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,10 @@ TestDisk and PhotoRec run under:
Both are under GNU General Public License.
+To build from source, read [INSTALL](INSTALL)
+
+See also [latest documentation](https://github.com/cgsecurity/testdisk_documentation)
+
Christophe GRENIER
[grenier@cgsecurity.org](mailto:grenier@cgsecurity.org)
[https://www.cgsecurity.org/](https://www.cgsecurity.org/)
diff --git a/README_dev_photorec.txt b/README_dev_photorec.txt
index 04d64e9..a080fdf 100644
--- a/README_dev_photorec.txt
+++ b/README_dev_photorec.txt
@@ -3,7 +3,7 @@ PhotoRec - Theory of operation:
Carvers are plugable. Each carver consists of:
struct file_hint_t - describes extension, name, max size, enable by default, etc.
-file_enable_t list_file_enable[] - array with all file hints and whether enabled or not.
+file_enable_t array_file_enable[] - array with all file hints and whether enabled or not.
phmain.c - Contains the main() and driver logic for photorec.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..9022bc3
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+mkdir config
+autoreconf --install -W all -I config
diff --git a/blacklist_cfi.txt b/blacklist_cfi.txt
new file mode 100644
index 0000000..e785280
--- /dev/null
+++ b/blacklist_cfi.txt
@@ -0,0 +1,5 @@
+# https://clang.llvm.org/docs/ControlFlowIntegrity.html
+# export CC="clang -flto -fsanitize=cfi -fvisibility=default -fsanitize-blacklist=blacklist_cfi.txt"
+# export CXX="clang++ -flto -fsanitize=cfi -fvisibility=default -fsanitize-blacklist=blacklist_cfi.txt"
+[cfi-icall]
+fun:jpeg_testdisk_alloc_src
diff --git a/configure.ac b/configure.ac
index 40ee68d..0c006eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,7 +6,7 @@ AC_INIT([testdisk],[7.2-WIP],[grenier@cgsecurity.org])
AC_LANG(C)
sinclude(acx_pthread.m4)
sinclude(mkdir.m4)
-TESTDISKDATE="November 2019"
+TESTDISKDATE="September 2020"
AC_SUBST(TESTDISKDATE)
AC_DEFINE_UNQUOTED([TESTDISKDATE],"$TESTDISKDATE",[Date of release])
AC_CONFIG_AUX_DIR(config)
diff --git a/copr/testdisk.spec b/copr/testdisk.spec
index e20f914..0609124 100644
--- a/copr/testdisk.spec
+++ b/copr/testdisk.spec
@@ -12,7 +12,9 @@ URL: https://www.cgsecurity.org/wiki/TestDisk
BuildRequires: libtool autoconf automake
BuildRequires: desktop-file-utils
BuildRequires: e2fsprogs-devel
+%if 0%{?rhel} < 8
BuildRequires: libewf-devel
+%endif
BuildRequires: libjpeg-devel
BuildRequires: ncurses-devel >= 5.2
BuildRequires: ntfs-3g-devel
diff --git a/doc b/doc
new file mode 160000
+Subproject becbcc35956102e064fc603720182113d887a18
diff --git a/doc/favicon.ico b/doc/favicon.ico
deleted file mode 100644
index d9c1441..0000000
--- a/doc/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/doc/photorec.ico b/doc/photorec.ico
deleted file mode 100644
index 74aa854..0000000
--- a/doc/photorec.ico
+++ /dev/null
Binary files differ
diff --git a/src/Makefile.am b/src/Makefile.am
index a7c2a2b..a9736d2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,3 +1,24 @@
+.PRECIOUS: session_%.framac session_fidentify-%.framac
+FRAMA_C_FLAGS=-machdep x86_64 \
+ -warn-left-shift-negative \
+ -warn-right-shift-negative \
+ -warn-signed-downcast \
+ -warn-signed-overflow \
+ -warn-unsigned-downcast \
+ -warn-unsigned-overflow \
+ -rte \
+ -eva \
+ -eva-slevel 6 \
+ -eva-warn-undefined-pointer-comparison none \
+ -eva-ignore-recursive-calls \
+ -then \
+ -wp \
+ -wp-dynamic \
+ -wp-steps 100000 \
+ -wp-split -wp-literals \
+ -wp-timeout 5 -pp-annot \
+ -kernel-msg-key pp
+
.rc.o:
$(WINDRES) --include-dir $(srcdir) $< $@
@@ -23,12 +44,13 @@ fs_H = analyse.h bfs.h bsd.h btrfs.h cramfs.h exfat.h ext2.h ext2_common.h fat
testdisk_ncurses_C = addpart.c addpartn.c adv.c askloc.c chgarch.c chgarchn.c chgtype.c chgtypen.c dimage.c dirn.c dirpart.c diskacc.c diskcapa.c edit.c ext2_sb.c ext2_sbn.c fat1x.c fat32.c fat_adv.c fat_cluster.c fatn.c geometry.c geometryn.c godmode.c hiddenn.c intrface.c intrfn.c nodisk.c ntfs_adv.c ntfs_fix.c ntfs_udl.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c tanalyse.c tbanner.c tdelete.c tdiskop.c tdisksel.c testdisk.c texfat.c thfs.c tload.c tlog.c tmbrcode.c tntfs.c toptions.c tpartwr.c
testdisk_ncurses_H = addpart.h addpartn.h adv.h askloc.h chgarch.h chgarchn.h chgtype.h chgtypen.h dimage.h dirn.h dirpart.h diskacc.h diskcapa.h edit.h ext2_sb.h ext2_sbn.h fat1x.h fat32.h fat_adv.h fat_cluster.h fatn.h geometry.h geometryn.h godmode.h hiddenn.h intrface.h intrfn.h nodisk.h ntfs_fix.h ntfs_udl.h partgptn.h parti386n.h partmacn.h partsunn.h partxboxn.h tanalyse.h tdelete.h tdiskop.h tdisksel.h texfat.h thfs.h tload.h tlog.h tmbrcode.h tntfs.h toptions.h tpartwr.h
-testdisk_SOURCES = $(base_C) $(base_H) $(fs_C) $(fs_H) $(testdisk_ncurses_C) $(testdisk_ncurses_H) dir.c dir.h exfat_dir.c exfat_dir.h ext2_dir.c ext2_dir.h ext2_inc.h fat_dir.c fat_dir.h ntfs_dir.c ntfs_dir.h ntfs_inc.h partgptw.c rfs_dir.c rfs_dir.h setdate.c setdate.h $(ICON_TESTDISK) next.c next.h
+testdisk_SOURCES = $(base_C) $(base_H) $(fs_C) $(fs_H) $(testdisk_ncurses_C) $(testdisk_ncurses_H) dir.c dir.h dir_common.h exfat_dir.c exfat_dir.h ext2_dir.c ext2_dir.h ext2_inc.h fat_dir.c fat_dir.h ntfs_dir.c ntfs_dir.h ntfs_inc.h partgptw.c rfs_dir.c rfs_dir.h setdate.c setdate.h $(ICON_TESTDISK) next.c next.h
file_C = filegen.c \
file_list.c \
file_1cd.c \
file_3dm.c \
+ file_3ds.c \
file_7z.c \
file_DB.c \
file_a.c \
@@ -59,6 +81,7 @@ file_C = filegen.c \
file_bac.c \
file_bdm.c \
file_berkeley.c \
+ file_bfa.c \
file_bim.c \
file_bin.c \
file_binvox.c \
@@ -203,6 +226,7 @@ file_C = filegen.c \
file_mcd.c \
file_mdb.c \
file_mdf.c \
+ file_mdp.c \
file_mfa.c \
file_mfg.c \
file_mft.c \
@@ -285,6 +309,7 @@ file_C = filegen.c \
file_rw2.c \
file_rx2.c \
file_save.c \
+ file_sdsk.c \
file_ses.c \
file_sgcta.c \
file_shn.c \
@@ -362,12 +387,12 @@ file_C = filegen.c \
file_H = ext2.h ext2_common.h filegen.h file_doc.h file_jpg.h file_gz.h file_sp3.h file_tar.h file_tiff.h file_txt.h ole.h pe.h suspend.h
-photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c geometry.c ntfs_dir.c ntfsp.c pdisksel.c phcli.c poptions.c sessionp.c setdate.c dfxml.c
+photorec_C = photorec.c phcfg.c addpart.c chgarch.c dir.c exfatp.c ext2grp.c ext2_dir.c ext2p.c fat_dir.c fatp.c file_found.c geometry.c ntfs_dir.c ntfsp.c pdisksel.c poptions.c sessionp.c setdate.c dfxml.c
-photorec_H = photorec.h phcfg.h addpart.h chgarch.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h geometry.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h pdisksel.h phcli.h poptions.h sessionp.h setdate.h dfxml.h
+photorec_H = photorec.h phcfg.h addpart.h chgarch.h dir_common.h dir.h exfatp.h ext2grp.h ext2p.h ext2_dir.h ext2_inc.h fat_dir.h fatp.h file_found.h geometry.h memmem.h ntfs_dir.h ntfsp.h ntfs_inc.h pdisksel.h poptions.h sessionp.h setdate.h dfxml.h
-photorec_ncurses_C = addpartn.c askloc.c chgarchn.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometryn.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdiskseln.c pfree_whole.c phbf.c phbs.c phnc.c phrecn.c ppartseln.c psearchn.c
-photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h photorec_check_header.h
+photorec_ncurses_C = addpartn.c askloc.c chgarchn.c chgtype.c chgtypen.c fat_cluster.c fat_unformat.c geometryn.c hiddenn.c intrfn.c nodisk.c parti386n.c partgptn.c partmacn.c partsunn.c partxboxn.c pbanner.c pblocksize.c pdiskseln.c pfree_whole.c phbf.c phbs.c phcli.c phnc.c phrecn.c ppartseln.c psearchn.c
+photorec_ncurses_H = addpartn.h askloc.h chgarchn.h chgtype.h chgtypen.h fat_cluster.h fat_unformat.h geometryn.h hiddenn.h intrfn.h nodisk.h parti386n.h partgptn.h partmacn.h partsunn.h partxboxn.h pblocksize.h pdiskseln.h pfree_whole.h pnext.h phbf.h phbs.h phcli.h phnc.h phrecn.h ppartseln.h psearch.h psearchn.h photorec_check_header.h
QT_TS = \
lang/qphotorec.ca.ts \
@@ -389,10 +414,13 @@ qphotorec_SOURCES = qmainrec.cpp qphotorec.cpp qphotorec.h qphotorec.qrc qphotor
nodist_qphotorec_SOURCES = moc_qphotorec.cpp rcc_qphotorec.cpp rcc_qphotorec_locale.cpp
-fidentify_SOURCES = fidentify.c common.c common.h misc.c misc.h phcfg.c phcfg.h setdate.c setdate.h $(file_C) $(file_H) log.c log.h crc.c crc.h ext2_common.c fat_common.c fat_common.h suspend_no.c
+fidentify_C_SOURCES = fidentify.c common.c misc.c phcfg.c setdate.c $(file_C) log.c crc.c ext2_common.c fat_common.c suspend_no.c
+fidentify_H_SOURCES = common.h misc.h phcfg.h setdate.h $(file_H) log.h crc.h fat_common.h
+fidentify_SOURCES = $(fidentify_C_SOURCES) $(fidentify_H_SOURCES)
fuzzerfidentify_SOURCES = fuzzerfidentify.cpp common.c common.h misc.c misc.h phcfg.c phcfg.h setdate.c setdate.h $(file_C) $(file_H) log.c log.h crc.c crc.h ext2_common.c fat_common.c fat_common.h suspend_no.c
+
QT_QM=$(QT_TS:.ts=.qm)
SECONDARY: $(QT_QM)
@@ -404,6 +432,45 @@ small: $(sbin_PROGRAMS) $(bin_PROGRAMS)
extras: $(EXTRA_PROGRAMS)
+frama-c-%: session_%.framac
+ frama-c-gui -load $^
+
+session_doc.framac: file_doc.c common.c filegen.c log.c setdate.c
+ gcc $(CFLAGS) -DMAIN_doc -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_doc -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_doc -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_doc -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_jpg.framac: file_jpg.c file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c suspend_no.c setdate.c
+ gcc $(CFLAGS) -DMAIN_jpg -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_jpg -O -o demo -I.. $^ -ljpeg
+ frama-c $^ -cpp-extra-args="-DMAIN_jpg -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_jpg -D__x86_64__ -I/usr/include -I.. -I $(frama-c -print-path)/libc" $(FRAMA_C_FLAGS) -save $@
+
+session_swf.framac: file_swf.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_swf -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_swf -O -o demo -I.. $^ -lz
+ frama-c $^ -cpp-extra-args="-DMAIN_swf -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_swf -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_tiff_be.framac: file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_tiff_le -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_tiff -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_tiff_be -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_tiff -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_tiff_le.framac: file_tiff.c file_tiff_be.c file_tiff_le.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_tiff_le -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_tiff -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_tiff_le -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_tiff -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_%.framac: file_%.c common.c filegen.c log.c
+ gcc $(CFLAGS) -DMAIN_$* -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_$* -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_$* -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_$* -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_fidentify-%.framac: $(fidentify_C_SOURCES)
+ gcc -o fidentify_$* -O -DMAIN_fidentify -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_$* -D__x86_64__ -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_fidentify -DHAVE_CONFIG_H -DSINGLE_FORMAT -DSINGLE_FORMAT_$* -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_fidentify.framac: fidentify.c common.c misc.c log.c setdate.c filegen.c file_list.c file_gz.c
+ gcc -O $(CFLAGS) -DMAIN_fidentify -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_fidentify -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
+session_photorec.framac: phmain.c $(photorec_C) filegen.c file_list.c file_bmp.c file_tar.c $(base_C) partgptro.c $(fs_C) chgtype.c pdiskseln.c phcli.c ppartseln.c askloc.c phrecn.c psearchn.c phbs.c phbf.c fat_unformat.c fat_cluster.c intrfn.c file_dir.c
+# gcc $(CFLAGS) -DMAIN_photorec -DHAVE_CONFIG_H -O -o demo -I.. $^
+ frama-c $^ -cpp-extra-args="-DMAIN_photorec -DHAVE_CONFIG_H -D__x86_64__ -I.." $(FRAMA_C_FLAGS) -save $@
+
moc_qphotorec.cpp: qphotorec.h
$(AM_V_GEN) QT_SELECT=$(QT_SELECT) $(MOC) $< -o $@
diff --git a/src/addpart.h b/src/addpart.h
index ab66262..cae5f1c 100644
--- a/src/addpart.h
+++ b/src/addpart.h
@@ -20,4 +20,12 @@
*/
+/*@
+ @ requires \valid(disk);
+ @ requires list_part == \null || \valid_read(list_part);
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ requires separation: \separated(disk, list_part, current_cmd);
+ @ ensures valid_read_string(*current_cmd);
+ @*/
list_part_t *add_partition_cli(disk_t *disk, list_part_t *list_part, char **current_cmd);
diff --git a/src/adv.c b/src/adv.c
index 0d53068..163cd68 100644
--- a/src/adv.c
+++ b/src/adv.c
@@ -79,12 +79,43 @@ extern const arch_fnct_t arch_xbox;
#define DEFAULT_IMAGE_NAME "image.dd"
-static int is_exfat(const partition_t *partition);
-static int is_hfs(const partition_t *partition);
-static int is_hfsp(const partition_t *partition);
-static int is_linux(const partition_t *partition);
-static int is_part_hfs(const partition_t *partition);
-static int is_part_hfsp(const partition_t *partition);
+static int is_part_hfs(const partition_t *partition)
+{
+ if( partition->part_type_i386 == P_HFS ||
+ partition->part_type_mac == PMAC_HFS)
+ return 1;
+ if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
+ return 1;
+ return 0;
+}
+
+static int is_part_hfsp(const partition_t *partition)
+{
+ if( partition->part_type_i386 == P_HFSP ||
+ partition->part_type_mac == PMAC_HFS )
+ return 1;
+ if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
+ return 1;
+ return 0;
+}
+
+int is_part_linux(const partition_t *partition)
+{
+ if(partition->arch==&arch_i386 && partition->part_type_i386==P_LINUX)
+ return 1;
+ if(partition->arch==&arch_sun && partition->part_type_sun==PSUN_LINUX)
+ return 1;
+ if(partition->arch==&arch_mac && partition->part_type_mac==PMAC_LINUX)
+ return 1;
+ if(partition->arch==&arch_gpt &&
+ (
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_DATA)==0 ||
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_HOME)==0 ||
+ guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_SRV)==0
+ ))
+ return 1;
+ return 0;
+}
static int is_exfat(const partition_t *partition)
{
@@ -128,46 +159,8 @@ static int is_linux(const partition_t *partition)
return 0;
}
-static int is_part_hfs(const partition_t *partition)
-{
- if( partition->part_type_i386 == P_HFS ||
- partition->part_type_mac == PMAC_HFS)
- return 1;
- if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
- return 1;
- return 0;
-}
-
-static int is_part_hfsp(const partition_t *partition)
-{
- if( partition->part_type_i386 == P_HFSP ||
- partition->part_type_mac == PMAC_HFS )
- return 1;
- if(guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_MAC_HFS)==0)
- return 1;
- return 0;
-}
-
-int is_part_linux(const partition_t *partition)
-{
- if(partition->arch==&arch_i386 && partition->part_type_i386==P_LINUX)
- return 1;
- if(partition->arch==&arch_sun && partition->part_type_sun==PSUN_LINUX)
- return 1;
- if(partition->arch==&arch_mac && partition->part_type_mac==PMAC_LINUX)
- return 1;
- if(partition->arch==&arch_gpt &&
- (
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_DATA)==0 ||
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_HOME)==0 ||
- guid_cmp(partition->part_type_gpt,GPT_ENT_TYPE_LINUX_SRV)==0
- ))
- return 1;
- return 0;
-}
-
#ifdef HAVE_NCURSES
-static void interface_adv_ncurses(disk_t *disk, const int rewrite, list_part_t *list_part, list_part_t *current_element, const int offset)
+static void interface_adv_ncurses(disk_t *disk, const int rewrite, list_part_t *list_part, const list_part_t *current_element, const int offset)
{
list_part_t *element;
int i;
@@ -369,7 +362,7 @@ static int adv_menu_boot_selected(disk_t *disk, partition_t *partition, const in
return 0;
}
-static void adv_menu_image_selected(disk_t *disk, partition_t *partition, char **current_cmd)
+static void adv_menu_image_selected(disk_t *disk, const partition_t *partition, char **current_cmd)
{
char *dst_path;
#ifdef HAVE_NCURSES
@@ -398,7 +391,7 @@ static void adv_menu_image_selected(disk_t *disk, partition_t *partition, char *
}
}
-static void adv_menu_undelete_selected(disk_t *disk, partition_t *partition, const int verbose, char **current_cmd)
+static void adv_menu_undelete_selected(disk_t *disk, const partition_t *partition, const int verbose, char **current_cmd)
{
if(partition->sb_offset!=0 && partition->sb_size>0)
{
@@ -424,7 +417,7 @@ static void adv_menu_undelete_selected(disk_t *disk, partition_t *partition, con
}
}
-static void adv_menu_list_selected(disk_t *disk, partition_t *partition, const int verbose, const int expert, char **current_cmd)
+static void adv_menu_list_selected(disk_t *disk, const partition_t *partition, const int verbose, const int expert, char **current_cmd)
{
if(partition->sb_offset!=0 && partition->sb_size>0)
{
diff --git a/src/adv.h b/src/adv.h
index 339ecf5..b62033e 100644
--- a/src/adv.h
+++ b/src/adv.h
@@ -23,7 +23,17 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(current_cmd);
+ @ requires valid_string(*current_cmd);
+ @*/
void interface_adv(disk_t *disk_car, const int verbose,const int dump_ind, const unsigned int expert, char**current_cmd);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_linux(const partition_t *partition);
#ifdef __cplusplus
diff --git a/src/alignio.h b/src/alignio.h
index 8bd1344..0541f6b 100644
--- a/src/alignio.h
+++ b/src/alignio.h
@@ -19,11 +19,26 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-static int align_pread(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
+
+/*@
+ @ requires \valid_function(fnct_pread);
+ @ requires \valid(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->offset < 0x8000000000000000;
+ @ requires 0 < count < 0x8000000000000000;
+ @ requires offset < 0x8000000000000000;
+ @ requires \valid((char *)buf + (0 .. count -1));
+ @ requires disk_car->rbuffer == \null || (\freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0);
+ @ ensures disk_car->rbuffer == \null || (\freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0);
+ @*/
+static int align_pread(int (*fnct_pread)(const disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
disk_t *disk_car, void*buf, const unsigned int count, const uint64_t offset)
{
const uint64_t offset_new=offset+disk_car->offset;
const unsigned int count_new=((offset_new%disk_car->sector_size)+count+disk_car->sector_size-1)/disk_car->sector_size*disk_car->sector_size;
+ /*@ assert count_new >= count; */
+ /*@ assert count_new >= disk_car->sector_size; */
+ /*@ assert count_new > 0; */
if(count!=count_new ||
((disk_car->access_mode&TESTDISK_O_DIRECT)!=0 &&
(((size_t)(buf) & (disk_car->sector_size-1))!=0) &&
@@ -31,24 +46,44 @@ static int align_pread(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsi
)
{
int res;
- if(disk_car->rbuffer==NULL)
- disk_car->rbuffer_size=128*512;
- while(disk_car->rbuffer_size < count_new)
+ if(disk_car->rbuffer_size < count_new)
{
free(disk_car->rbuffer);
disk_car->rbuffer=NULL;
- disk_car->rbuffer_size*=2;
}
if(disk_car->rbuffer==NULL)
+ {
+ disk_car->rbuffer_size=128*512;
+ /*@ loop assigns disk_car->rbuffer_size; */
+ while(disk_car->rbuffer_size < count_new)
+ {
+ disk_car->rbuffer_size*=2;
+ }
+ /*@ assert disk_car->rbuffer_size >= count_new; */
disk_car->rbuffer=(char*)MALLOC(disk_car->rbuffer_size);
+ }
+ /*@ assert \freeable(disk_car->rbuffer); */
res=fnct_pread(disk_car, disk_car->rbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size);
memcpy(buf,(char*)disk_car->rbuffer+(offset_new%disk_car->sector_size),count);
+ /*@ assert \freeable(disk_car->rbuffer) && disk_car->rbuffer_size > 0; */
return (res < (signed)count ? res : (signed)count );
}
return fnct_pread(disk_car, buf, count, offset_new);
}
-static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
+/*@
+ @ requires \valid_function(fnct_pread);
+ @ requires \valid_function(fnct_pwrite);
+ @ requires \valid(disk_car);
+ @ requires disk_car->sector_size > 0;
+ @ requires disk_car->offset < 0x8000000000000000;
+ @ requires 0 < count < 0x8000000000000000;
+ @ requires offset < 0x8000000000000000;
+ @ requires \valid_read((char *)buf + (0 .. count -1));
+ @ requires disk_car->wbuffer == \null || \freeable(disk_car->wbuffer);
+ @ ensures disk_car->wbuffer == \null || \freeable(disk_car->wbuffer);
+ @*/
+static int align_pwrite(int (*fnct_pread)(const disk_t *disk_car, void *buf, const unsigned int count, const uint64_t offset),
int (*fnct_pwrite)(disk_t *disk_car, const void *buf, const unsigned int count, const uint64_t offset),
disk_t *disk_car, const void*buf, const unsigned int count, const uint64_t offset)
{
@@ -60,16 +95,23 @@ static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const uns
)
{
int tmp;
- if(disk_car->wbuffer==NULL)
- disk_car->wbuffer_size=128*512;
- while(disk_car->wbuffer_size < count_new)
+ if(disk_car->wbuffer_size < count_new)
{
free(disk_car->wbuffer);
disk_car->wbuffer=NULL;
- disk_car->wbuffer_size*=2;
}
if(disk_car->wbuffer==NULL)
+ {
+ disk_car->wbuffer_size=128*512;
+ /*@ loop assigns disk_car->wbuffer_size; */
+ while(disk_car->wbuffer_size < count_new)
+ {
+ disk_car->wbuffer_size*=2;
+ }
+ /*@ assert disk_car->wbuffer_size >= count_new; */
disk_car->wbuffer=(char*)MALLOC(disk_car->wbuffer_size);
+ }
+ /*@ assert \freeable(disk_car->wbuffer); */
if(fnct_pread(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size)<0)
{
log_error("read failed but trying to write anyway");
@@ -77,8 +119,8 @@ static int align_pwrite(int (*fnct_pread)(disk_t *disk_car, void *buf, const uns
}
memcpy((char*)disk_car->wbuffer+(offset_new%disk_car->sector_size),buf,count);
tmp=fnct_pwrite(disk_car, disk_car->wbuffer, count_new, offset_new/disk_car->sector_size*disk_car->sector_size);
+ /*@ assert \freeable(disk_car->wbuffer) && disk_car->wbuffer_size > 0; */
return (tmp < (signed)count ? tmp : (signed)count);
}
return fnct_pwrite(disk_car, buf, count, offset_new);
}
-
diff --git a/src/analyse.c b/src/analyse.c
index b121986..46cf036 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -220,7 +220,7 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
return 0;
}
-int search_type_1(const unsigned char *buffer, disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
+int search_type_1(const unsigned char *buffer, const disk_t *disk, partition_t *partition, const int verbose, const int dump_ind)
{
const struct disklabel *bsd_header=(const struct disklabel *)(buffer+0x200);
const struct disk_super_block *beos_block=(const struct disk_super_block*)(buffer+0x200);
diff --git a/src/analyse.h b/src/analyse.h
index 82c1b61..aaf1002 100644
--- a/src/analyse.h
+++ b/src/analyse.h
@@ -24,7 +24,7 @@ extern "C" {
#endif
int search_type_0(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
-int search_type_1(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
+int search_type_1(const unsigned char *buffer, const disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind);
int search_type_2(const unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
int search_type_8(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
int search_type_16(unsigned char *buffer, disk_t *disk_car,partition_t *partition,const int verbose, const int dump_ind);
diff --git a/src/askloc.h b/src/askloc.h
index 7671883..5dcc8d4 100644
--- a/src/askloc.h
+++ b/src/askloc.h
@@ -24,6 +24,10 @@ extern "C" {
#endif
char *ask_location(const char*msg, const char *src_dir, const char *dst_org);
+
+/*@
+ @ ensures \result == \null || (\result != \null && \freeable(\result) && valid_string(\result));
+ @*/
char *get_default_location(void);
#ifdef __cplusplus
diff --git a/src/autoset.h b/src/autoset.h
index 8f9e150..a5b4a56 100644
--- a/src/autoset.h
+++ b/src/autoset.h
@@ -19,5 +19,9 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/*@
+ @ requires \valid(disk_car);
+ @ assigns disk_car->unit;
+ @*/
void autoset_unit(disk_t *disk_car);
diff --git a/src/bfs.c b/src/bfs.c
index 1854ee8..fb8f35d 100644
--- a/src/bfs.c
+++ b/src/bfs.c
@@ -34,8 +34,31 @@
#include "fnctdsk.h"
#include "log.h"
-static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition);
-static int test_BeFS(disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind);
+static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition)
+{
+ partition->upart_type=UP_BEOS;
+ partition->blocksize= 1 << le32(beos_block->block_shift);
+ partition->info[0]='\0';
+ snprintf(partition->info, sizeof(partition->info), "BeFS blocksize=%u", partition->blocksize);
+ set_part_name(partition,beos_block->name,B_OS_NAME_LENGTH);
+}
+
+static int test_BeFS(const disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind)
+{
+ if(beos_block->magic1!=le32(SUPER_BLOCK_MAGIC1) &&
+ beos_block->magic2!=le32(SUPER_BLOCK_MAGIC2) &&
+ beos_block->magic3!=le32(SUPER_BLOCK_MAGIC3))
+ return 1;
+ if(partition==NULL)
+ return 0;
+ if(dump_ind!=0)
+ {
+ log_info("\nBeFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
+ dump_log(beos_block,DEFAULT_SECTOR_SIZE);
+ }
+ return 0;
+}
+
int check_BeFS(disk_t *disk_car,partition_t *partition)
{
@@ -56,37 +79,14 @@ int check_BeFS(disk_t *disk_car,partition_t *partition)
return 0;
}
-int recover_BeFS(disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind)
+int recover_BeFS(const disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind)
{
if(test_BeFS(disk_car,beos_block,partition,dump_ind)!=0)
return 1;
set_BeFS_info(beos_block, partition);
partition->part_size=le64(beos_block->num_blocks) << le32(beos_block->block_shift);
partition->part_type_i386=(unsigned char)P_BEOS;
+ partition->part_type_mac=PMAC_BEOS;
+ partition->part_type_gpt=GPT_ENT_TYPE_BEOS_BFS;
return 0;
}
-
-static int test_BeFS(disk_t *disk_car, const struct disk_super_block*beos_block, const partition_t *partition, const int dump_ind)
-{
- if(beos_block->magic1!=le32(SUPER_BLOCK_MAGIC1) &&
- beos_block->magic2!=le32(SUPER_BLOCK_MAGIC2) &&
- beos_block->magic3!=le32(SUPER_BLOCK_MAGIC3))
- return 1;
- if(partition==NULL)
- return 0;
- if(dump_ind!=0)
- {
- log_info("\nBeFS magic value at %u/%u/%u\n", offset2cylinder(disk_car,partition->part_offset),offset2head(disk_car,partition->part_offset),offset2sector(disk_car,partition->part_offset));
- dump_log(beos_block,DEFAULT_SECTOR_SIZE);
- }
- return 0;
-}
-
-static void set_BeFS_info(const struct disk_super_block *beos_block, partition_t *partition)
-{
- partition->upart_type=UP_BEOS;
- partition->blocksize= 1 << le32(beos_block->block_shift);
- partition->info[0]='\0';
- snprintf(partition->info, sizeof(partition->info), "BeFS blocksize=%u", partition->blocksize);
- set_part_name(partition,beos_block->name,B_OS_NAME_LENGTH);
-}
diff --git a/src/bfs.h b/src/bfs.h
index 14087a2..7117d4c 100644
--- a/src/bfs.h
+++ b/src/bfs.h
@@ -82,8 +82,21 @@ struct disk_super_block /* super block as it is on disk */
/* this is stored in the fs_byte_order field... it's kind of dumb */
#define BFS_BIG_ENDIAN 0x42494745 /* BIGE */
/* int test_beos(struct disk_super_block *,partition_t); */
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
int check_BeFS(disk_t *disk_car, partition_t *partition);
-int recover_BeFS(disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(beos_block);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, beos_block, partition);
+ @*/
+int recover_BeFS(const disk_t *disk_car, const struct disk_super_block *beos_block, partition_t *partition, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/bsd.c b/src/bsd.c
index e67d9b0..13dd9b9 100644
--- a/src/bsd.c
+++ b/src/bsd.c
@@ -33,28 +33,8 @@
#include "bsd.h"
#include "intrf.h"
#include "log.h"
-static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition, const int verbose, const int dump_ind, const unsigned int max_partitions);
-int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
-{
- unsigned char *buffer;
- buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
- if(disk_car->pread(disk_car, buffer, BSD_DISKLABEL_SIZE, partition->part_offset + 0x200) != BSD_DISKLABEL_SIZE)
- {
- free(buffer);
- return 1;
- }
- if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
- {
- free(buffer);
- return 1;
- }
- set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
- free(buffer);
- return 0;
-}
-
-static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
+static int test_BSD(const disk_t *disk_car, const struct disklabel*bsd_header, const partition_t *partition,const int verbose, const int dump_ind, const unsigned int max_partitions)
{
unsigned int i;
const uint16_t* cp;
@@ -125,7 +105,26 @@ static int test_BSD(disk_t *disk_car, const struct disklabel*bsd_header, const p
return 0;
}
-int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
+int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose, const unsigned int max_partitions)
+{
+ unsigned char *buffer;
+ buffer=(unsigned char*)MALLOC(BSD_DISKLABEL_SIZE);
+ if(disk_car->pread(disk_car, buffer, BSD_DISKLABEL_SIZE, partition->part_offset + 0x200) != BSD_DISKLABEL_SIZE)
+ {
+ free(buffer);
+ return 1;
+ }
+ if(test_BSD(disk_car,(const struct disklabel*)buffer,partition,verbose,0,max_partitions))
+ {
+ free(buffer);
+ return 1;
+ }
+ set_part_name(partition,((const struct disklabel*)buffer)->d_packname,16);
+ free(buffer);
+ return 0;
+}
+
+int recover_BSD(const disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind)
{
int i;
int i_max_p_offset=-1;
diff --git a/src/bsd.h b/src/bsd.h
index 1a14807..4554864 100644
--- a/src/bsd.h
+++ b/src/bsd.h
@@ -168,8 +168,22 @@ struct disklabel {
#define TST_FS_VINUM 14 /* Vinum drive */
#define TST_FS_RAID 15 /* RAIDFrame drive */
#define TST_FS_JFS2 21 /* IBM JFS2 */
-int check_BSD(disk_t *disk_car,partition_t *partition,const int verbose,const unsigned int max_partitions);
-int recover_BSD(disk_t *disk_car, const struct disklabel*bsd_header,partition_t *partition,const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk_car);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, partition);
+ @*/
+int check_BSD(disk_t *disk_car, partition_t *partition, const int verbose, const unsigned int max_partitions);
+
+/*@
+ @ requires \valid_read(disk_car);
+ @ requires \valid_read(bsd_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk_car, bsd_header, partition);
+ @*/
+int recover_BSD(const disk_t *disk_car, const struct disklabel*bsd_header, partition_t *partition, const int verbose, const int dump_ind);
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/btrfs.c b/src/btrfs.c
index 062b52e..4eef0bb 100644
--- a/src/btrfs.c
+++ b/src/btrfs.c
@@ -74,7 +74,7 @@ int check_btrfs(disk_t *disk_car,partition_t *partition)
Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
Group 0 begin at s_first_data_block
*/
-int recover_btrfs(disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
+int recover_btrfs(const disk_t *disk, const struct btrfs_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_btrfs(sb)!=0)
return 1;
diff --git a/src/btrfs.h b/src/btrfs.h
index d28c590..83ad564 100644
--- a/src/btrfs.h
+++ b/src/btrfs.h
@@ -139,7 +139,7 @@ struct btrfs_super_block {
} __attribute__ ((gcc_struct, __packed__));
int check_btrfs(disk_t *disk_car,partition_t *partition);
-int recover_btrfs(disk_t *disk_car, const struct btrfs_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_btrfs(const disk_t *disk_car, const struct btrfs_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/chgarch.h b/src/chgarch.h
index 5324933..e1b459e 100644
--- a/src/chgarch.h
+++ b/src/chgarch.h
@@ -24,6 +24,11 @@
extern "C" {
#endif
+/*@
+ @ requires \valid(disk);
+ @ requires current_cmd == \null || valid_read_string(*current_cmd);
+ @ ensures current_cmd == \null || valid_read_string(*current_cmd);
+ @*/
int change_arch_type_cli(disk_t *disk, const int verbose, char**current_cmd);
#ifdef __cplusplus
diff --git a/src/common.c b/src/common.c
index afcf387..6d78832 100644
--- a/src/common.c
+++ b/src/common.c
@@ -24,6 +24,11 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_POSIX_MEMALIGN
+#undef HAVE_MEMALIGN
+#endif
#include <stdio.h>
#include <ctype.h>
@@ -51,8 +56,6 @@
static int32_t secwest=0;
-static unsigned int up2power_aux(const unsigned int number);
-
/* coverity[+alloc] */
void *MALLOC(size_t size)
{
@@ -61,7 +64,7 @@ void *MALLOC(size_t size)
/* Warning, memory leak checker must be posix_memalign/memalign aware, otherwise *
* reports may look strange. Aligned memory is required if the buffer is *
* used for read/write operation with a file opened with O_DIRECT */
-#if defined(HAVE_POSIX_MEMALIGN) && !defined(__FRAMAC__)
+#if defined(HAVE_POSIX_MEMALIGN)
if(size>=512)
{
if(posix_memalign(&res,4096,size)==0)
@@ -70,7 +73,7 @@ void *MALLOC(size_t size)
return res;
}
}
-#elif defined(HAVE_MEMALIGN) && !defined(__FRAMAC__)
+#elif defined(HAVE_MEMALIGN)
if(size>=512)
{
if((res=memalign(4096, size))!=NULL)
@@ -167,21 +170,16 @@ char * strcasestr (const char *haystack, const char *needle)
}
#endif
-#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__)
+#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__) && !defined(__FRAMAC__)
struct tm *localtime_r(const time_t *timep, struct tm *result)
{
return localtime(timep);
}
#endif
-unsigned int up2power(const unsigned int number)
-{
- /* log_trace("up2power(%u)=>%u\n",number, (1<<up2power_aux(number-1))); */
- if(number==0)
- return 1;
- return (1<<up2power_aux(number-1));
-}
-
+/*@
+ @ assigns \nothing;
+ @*/
static unsigned int up2power_aux(const unsigned int number)
{
if(number==0)
@@ -190,6 +188,13 @@ static unsigned int up2power_aux(const unsigned int number)
return(1+up2power_aux(number/2));
}
+unsigned int up2power(const unsigned int number)
+{
+ if(number==0)
+ return 1;
+ return (1<<up2power_aux(number-1));
+}
+
void set_part_name(partition_t *partition, const char *src, const unsigned int max_size)
{
unsigned int i;
@@ -212,9 +217,15 @@ char* strip_dup(char* str)
{
unsigned int i;
char *end;
+ /*@
+ @ loop assigns str;
+ @*/
while(isspace(*str))
str++;
end=str;
+ /*@
+ @ loop assigns i, end;
+ @*/
for (i = 0; str[i] != 0; i++)
if (!isspace (str[i]))
end=&str[i];
@@ -225,22 +236,67 @@ char* strip_dup(char* str)
}
/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
+/*
+ * The epoch of FAT timestamp is 1980.
+ * : bits : value
+ * date: 0 - 4: day (1 - 31)
+ * date: 5 - 8: month (1 - 12)
+ * date: 9 - 15: year (0 - 127) from 1980
+ * time: 0 - 4: sec (0 - 29) 2sec counts
+ * time: 5 - 10: min (0 - 59)
+ * time: 11 - 15: hour (0 - 23)
+ */
+#define SECS_PER_MIN 60
+#define SECS_PER_HOUR (60 * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+/* days between 1.1.70 and 1.1.80 (2 leap days) */
+#define DAYS_DELTA (365 * 10 + 2)
+/* 120 (2100 - 1980) isn't leap year */
+#define YEAR_2100 120
+#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100)
time_t date_dos2unix(const unsigned short f_time, const unsigned short f_date)
{
- static const unsigned int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
+ static const unsigned int days_in_year[] = { 0, 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0 };
/* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
- unsigned int month,year,secs;
+ unsigned long int day,leap_day,month,year,days;
+ unsigned long int secs;
+ year = f_date >> 9;
+ /*@ assert 0 <= year <= 127; */
+ month = td_max(1, (f_date >> 5) & 0xf);
+ /*@ assert 1 <= month <= 15; */
+ day = td_max(1, f_date & 0x1f) - 1;
+ /*@ assert 0 <= day <= 30; */
+
+ leap_day = (year + 3) / 4;
+ /*@ assert 0 <= leap_day <= 32; */
+ if (year > YEAR_2100) /* 2100 isn't leap year */
+ {
+ /*@ assert year > YEAR_2100; */
+ leap_day = (year + 3) / 4;
+ /*@ assert (YEAR_2100 + 3)/4 < leap_day <= 32; */
+ leap_day--;
+ /*@ assert (YEAR_2100 + 3)/4 <= leap_day < 32; */
+ }
+ else
+ {
+ /*@ assert year <= YEAR_2100; */
+ /*@ assert 0 <= leap_day <= (YEAR_2100 + 3)/4; */
+ }
+ /*@ assert 0 <= leap_day < 32; */
+ if (IS_LEAP_YEAR(year) && month > 2)
+ leap_day++;
+ /*@ assert 0 <= leap_day <= 32; */
+ days = days_in_year[month];
+ /*@ assert days <= 334; */
+ days += year * 365 + leap_day + day + DAYS_DELTA;
+
+ secs = (f_time & 0x1f)<<1;
+ secs += ((f_time >> 5) & 0x3f) * SECS_PER_MIN;
+ secs += (f_time >> 11)* SECS_PER_HOUR;
+ secs += days * SECS_PER_DAY;
- /* first subtract and mask after that... Otherwise, if
- f_date == 0, bad things happen */
- month = ((f_date >> 5) - 1) & 15;
- year = f_date >> 9;
- secs = (f_time & 31)*2+60*((f_time >> 5) & 63)+(f_time >> 11)*3600+86400*
- ((f_date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
- month < 2 ? 1 : 0)+3653);
- /* days since 1.1.70 plus 80's leap day */
return secs+secwest;
}
@@ -287,23 +343,39 @@ time_t td_ntfs2utc (int64_t ntfstime)
return (ntfstime - (NTFS_TIME_OFFSET)) / 10000000;
}
-int check_command(char **current_cmd, const char *cmd, size_t n)
+int check_command(char **current_cmd, const char *cmd, const size_t n)
{
const int res=strncmp(*current_cmd, cmd, n);
if(res==0)
+ {
(*current_cmd)+=n;
+ /*@ assert valid_read_string(*current_cmd); */
+ return 0;
+ }
+ /*@ assert valid_read_string(*current_cmd); */
return res;
}
void skip_comma_in_command(char **current_cmd)
{
+ /*@
+ loop invariant valid_read_string(*current_cmd);
+ loop assigns *current_cmd;
+ */
while(*current_cmd[0]==',')
+ {
(*current_cmd)++;
+ }
+ /*@ assert valid_read_string(*current_cmd); */
}
uint64_t get_int_from_command(char **current_cmd)
{
uint64_t tmp=0;
+ /*@
+ loop invariant valid_read_string(*current_cmd);
+ loop assigns *current_cmd, tmp;
+ */
while(*current_cmd[0] >='0' && *current_cmd[0] <= '9')
{
tmp = tmp * 10 + *current_cmd[0] - '0';
diff --git a/src/common.h b/src/common.h
index 8a5e5ea..886d4dd 100644
--- a/src/common.h
+++ b/src/common.h
@@ -24,6 +24,12 @@
#ifdef __cplusplus
extern "C" {
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_NCURSES
+#endif
+#if defined(__FRAMAC__) && defined(HAVE_STRING_H)
+#include <string.h>
+#endif
typedef struct efi_guid_s efi_guid_t;
struct efi_guid_s
@@ -105,6 +111,7 @@ struct efi_guid_s
#define PMAC_FWDRIVER 5
#define PMAC_SWAP 0x82
#define PMAC_LINUX 0x83
+#define PMAC_BEOS 0xEB
#define PMAC_HFS 0xAF
#define PMAC_MAP 6
#define PMAC_PATCHES 7
@@ -146,62 +153,66 @@ struct efi_guid_s
((const efi_guid_t){le32(0x516e7cb8),le16(0x6ecf),le16(0x11d6),0x8f,0xf8,{0x00,0x02,0x2d,0x09,0x71,0x2b}})
-#define GPT_ENT_TYPE_MS_RESERVED \
- ((const efi_guid_t){le32(0xe3c9e316),le16(0x0b5c),le16(0x4db8),0x81,0x7d,{0xf9,0x2d,0xf0,0x02,0x15,0xae}})
#define GPT_ENT_TYPE_MS_BASIC_DATA \
((const efi_guid_t){le32(0xebd0a0a2),le16(0xb9e5),le16(0x4433),0x87,0xc0,{0x68,0xb6,0xb7,0x26,0x99,0xc7}})
-#define GPT_ENT_TYPE_MS_LDM_METADATA \
- ((const efi_guid_t){le32(0x5808c8aa),le16(0x7e8f),le16(0x42e0),0x85,0xd2,{0xe1,0xe9,0x04,0x34,0xcf,0xb3}})
#define GPT_ENT_TYPE_MS_LDM_DATA \
((const efi_guid_t){le32(0xaf9b60a0),le16(0x1431),le16(0x4f62),0xbc,0x68,{0x33,0x11,0x71,0x4a,0x69,0xad}})
+#define GPT_ENT_TYPE_MS_LDM_METADATA \
+ ((const efi_guid_t){le32(0x5808c8aa),le16(0x7e8f),le16(0x42e0),0x85,0xd2,{0xe1,0xe9,0x04,0x34,0xcf,0xb3}})
#define GPT_ENT_TYPE_MS_RECOVERY \
((const efi_guid_t){le32(0xde94bba4),le16(0x06d1),le16(0x4d40),0xa1,0x6a,{0xbf,0xd5,0x01,0x79,0xd6,0xac}})
+#define GPT_ENT_TYPE_MS_RESERVED \
+ ((const efi_guid_t){le32(0xe3c9e316),le16(0x0b5c),le16(0x4db8),0x81,0x7d,{0xf9,0x2d,0xf0,0x02,0x15,0xae}})
+#define GPT_ENT_TYPE_MS_SPACES \
+ ((const efi_guid_t){le32(0xe75caf8f),le16(0xf680),le16(0x4cee),0xaf,0xa3,{0xb0,0x01,0xe5,0x6e,0xfc,0x2d}})
-#define GPT_ENT_TYPE_LINUX_RAID \
- ((const efi_guid_t){le32(0xa19d880f),le16(0x05fc),le16(0x4d3b),0xa0,0x06,{0x74,0x3f,0x0f,0x84,0x91,0x1e}})
-#define GPT_ENT_TYPE_LINUX_SWAP \
- ((const efi_guid_t){le32(0x0657fd6d),le16(0xa4ab),le16(0x43c4),0x84,0xe5,{0x09,0x33,0xc8,0x4b,0x4f,0x4f}})
-#define GPT_ENT_TYPE_LINUX_LVM \
- ((const efi_guid_t){le32(0xe6d6d379),le16(0xf507),le16(0x44c2),0xa2,0x3c,{0x23,0x8f,0x2a,0x3d,0xf9,0x28}})
-#define GPT_ENT_TYPE_LINUX_RESERVED \
- ((const efi_guid_t){le32(0x8da63339),le16(0x0007),le16(0x60c0),0xc4,0x36,{0x08,0x3a,0xc8,0x23,0x09,0x08}})
#define GPT_ENT_TYPE_LINUX_DATA \
((const efi_guid_t){le32(0x0fc63daf),le16(0x8483),le16(0x4772),0x8e,0x79,{0x3d,0x69,0xd8,0x47,0x7d,0xe4}})
#define GPT_ENT_TYPE_LINUX_HOME \
((const efi_guid_t){le32(0x933ac7e1),le16(0x2eb4),le16(0x4f13),0xb8,0x44,{0x0e,0x14,0xe2,0xae,0xf9,0x15}})
+#define GPT_ENT_TYPE_LINUX_LVM \
+ ((const efi_guid_t){le32(0xe6d6d379),le16(0xf507),le16(0x44c2),0xa2,0x3c,{0x23,0x8f,0x2a,0x3d,0xf9,0x28}})
+#define GPT_ENT_TYPE_LINUX_RAID \
+ ((const efi_guid_t){le32(0xa19d880f),le16(0x05fc),le16(0x4d3b),0xa0,0x06,{0x74,0x3f,0x0f,0x84,0x91,0x1e}})
+#define GPT_ENT_TYPE_LINUX_RESERVED \
+ ((const efi_guid_t){le32(0x8da63339),le16(0x0007),le16(0x60c0),0xc4,0x36,{0x08,0x3a,0xc8,0x23,0x09,0x08}})
#define GPT_ENT_TYPE_LINUX_SRV \
((const efi_guid_t){le32(0x3b8f8425),le16(0x20e0),le16(0x4f3b),0x90,0x7f,{0x1a,0x25,0xa7,0x6f,0x98,0xe8}})
+#define GPT_ENT_TYPE_LINUX_SWAP \
+ ((const efi_guid_t){le32(0x0657fd6d),le16(0xa4ab),le16(0x43c4),0x84,0xe5,{0x09,0x33,0xc8,0x4b,0x4f,0x4f}})
#define GPT_ENT_TYPE_HPUX_DATA \
((const efi_guid_t){le32(0x75894c1e),le16(0x3aeb),le16(0x11d3),0xb7,0xc1,{0x7b,0x03,0xa0,0x00,0x00,0x00}})
#define GPT_ENT_TYPE_HPUX_SERVICE \
((const efi_guid_t){le32(0xe2a1e728),le16(0x32e3),le16(0x11d6),0xa6,0x82,{0x7b,0x03,0xa0,0x00,0x00,0x00}})
-#define GPT_ENT_TYPE_MAC_AFS \
+#define GPT_ENT_TYPE_APPLE_CORE_STORAGE \
+ ((const efi_guid_t){le32(0x53746F72),le16(0x6167),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_APFS \
((const efi_guid_t){le32(0x7c3457ef),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_BOOT \
+ ((const efi_guid_t){le32(0x426f6f74),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_HFS \
((const efi_guid_t){le32(0x48465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_UFS \
- ((const efi_guid_t){le32(0x55465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_LABEL \
+ ((const efi_guid_t){le32(0x4c616265),le16(0x6c00),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_RAID \
((const efi_guid_t){le32(0x52414944),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_RAID_OFFLINE \
((const efi_guid_t){le32(0x52414944),le16(0x5f4f),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_BOOT \
- ((const efi_guid_t){le32(0x426f6f74),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
-#define GPT_ENT_TYPE_MAC_LABEL \
- ((const efi_guid_t){le32(0x4c616265),le16(0x6c00),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
#define GPT_ENT_TYPE_MAC_TV_RECOVERY \
((const efi_guid_t){le32(0x5265636f),le16(0x7665),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_MAC_UFS \
+ ((const efi_guid_t){le32(0x55465300),le16(0x0000),le16(0x11aa),0xaa,0x11,{0x00,0x30,0x65,0x43,0xec,0xac}})
+#define GPT_ENT_TYPE_SOLARIS_BACKUP \
+ ((const efi_guid_t){le32(0x6a8b642b),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_BOOT \
((const efi_guid_t){le32(0x6a82cb45),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_ROOT \
((const efi_guid_t){le32(0x6a85cf4d),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_SWAP \
((const efi_guid_t){le32(0x6a87c46f),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
-#define GPT_ENT_TYPE_SOLARIS_BACKUP \
- ((const efi_guid_t){le32(0x6a8b642b),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_SOLARIS_USR \
((const efi_guid_t){le32(0x6a898cc3),le16(0x1dd2),le16(0x11b2),0x99,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
#define GPT_ENT_TYPE_MAC_ZFS GPT_ENT_TYPE_SOLARIS_USR
@@ -222,6 +233,9 @@ struct efi_guid_s
#define GPT_ENT_TYPE_SOLARIS_RESERVED5 \
((const efi_guid_t){le32(0x6a8d2ac7),le16(0x1dd2),le16(0x11b2),0x96,0xa6,{0x08,0x00,0x20,0x73,0x66,0x31}})
+#define GPT_ENT_TYPE_BEOS_BFS \
+ ((const efi_guid_t){le32(0x42465331),le16(0x3ba3),le16(0x10f1),0x80,0x2a,{0x48,0x61,0x69,0x6b,0x75,0x21}})
+
#define TESTDISK_O_RDONLY 00
#define TESTDISK_O_RDWR 02
#define TESTDISK_O_DIRECT 040000
@@ -353,7 +367,7 @@ struct arch_fnct_struct
int (*write_MBR_code)(disk_t *disk);
void (*set_prev_status)(const disk_t *disk, partition_t *partition);
void (*set_next_status)(const disk_t *disk, partition_t *partition);
- int (*test_structure)(list_part_t *list_part);
+ int (*test_structure)(const list_part_t *list_part);
unsigned int (*get_part_type)(const partition_t *partition);
int (*set_part_type)(partition_t *partition, unsigned int part_type);
void (*init_structure)(const disk_t *disk,list_part_t *list_part, const int verbose);
@@ -445,12 +459,35 @@ struct my_data_struct
@*/
void *MALLOC(size_t size);
+/*@
+ @ assigns \nothing;
+ @*/
unsigned int up2power(const unsigned int number);
+
+/*@
+ @ requires \valid(partition);
+ @ requires \valid_read(src + (0 .. max_size-1));
+ @*/
void set_part_name(partition_t *partition, const char *src, const unsigned int max_size);
+
+/*@
+ @ requires \valid(partition);
+ @ requires \valid_read(src + (0 .. max_size-1));
+ @*/
void set_part_name_chomp(partition_t *partition, const unsigned char *src, const unsigned int max_size);
+
+/*@
+ @ requires valid_read_string(str);
+ @ ensures \result == \null || valid_read_string(\result);
+ @*/
char* strip_dup(char* str);
+
+/*@ assigns \nothing; */
time_t date_dos2unix(const unsigned short f_time,const unsigned short f_date);
+
void set_secwest(void);
+
+/*@ assigns \nothing; */
time_t td_ntfs2utc (int64_t ntfstime);
#ifndef BSD_MAXPARTITIONS
#define BSD_MAXPARTITIONS 8
@@ -514,7 +551,11 @@ int strncasecmp(const char * s1, const char * s2, size_t len);
#ifndef HAVE_STRCASESTR
char * strcasestr (const char *haystack, const char *needle);
#endif
-#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__)
+#if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__) && !defined(__FRAMAC__)
+/*@
+ @ requires valid_timer: \valid_read(timep);
+ @ requires \valid(result);
+ @*/
struct tm *localtime_r(const time_t *timep, struct tm *result);
#endif
/*
@@ -535,8 +576,34 @@ struct tm *localtime_r(const time_t *timep, struct tm *result);
(void) (&_x == &_y); \
_x > _y ? _x : _y; })
-int check_command(char **current_cmd, const char *cmd, size_t n);
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ requires valid_read_string(cmd);
+ @ requires \separated(cmd+(..), current_cmd);
+ @ requires strlen(cmd) == n;
+ @ assigns *current_cmd;
+ @ assigns \result \from indirect:(*current_cmd)[0 .. n-1], indirect:cmd[0 ..n-1], indirect:n;
+ @ ensures valid_read_string(*current_cmd);
+ @ ensures \result == 0 ==> *current_cmd == \old(*current_cmd) + n;
+ @ ensures \result != 0 ==> *current_cmd == \old(*current_cmd);
+ @*/
+int check_command(char **current_cmd, const char *cmd, const size_t n);
+
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ assigns *current_cmd;
+ @ ensures valid_read_string(*current_cmd);
+ @*/
void skip_comma_in_command(char **current_cmd);
+
+/*@
+ @ requires \valid(current_cmd);
+ @ requires valid_read_string(*current_cmd);
+ @ assigns *current_cmd;
+ @ ensures valid_read_string(*current_cmd);
+ @*/
uint64_t get_int_from_command(char **current_cmd);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/cramfs.c b/src/cramfs.c
index c547fb5..e5afeb0 100644
--- a/src/cramfs.c
+++ b/src/cramfs.c
@@ -76,7 +76,7 @@ static int test_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, co
return 0;
}
-int recover_cramfs(disk_t *disk_car, const struct cramfs_super *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_cramfs(disk_car, sb, partition, verbose)!=0)
return 1;
diff --git a/src/cramfs.h b/src/cramfs.h
index c525234..4b9b57f 100644
--- a/src/cramfs.h
+++ b/src/cramfs.h
@@ -83,7 +83,7 @@ struct cramfs_super {
int check_cramfs(disk_t *disk_car,partition_t *partition,const int verbose);
-int recover_cramfs(disk_t *disk_car, const struct cramfs_super *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_cramfs(const disk_t *disk_car, const struct cramfs_super *sb, partition_t *partition, const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/crc.c b/src/crc.c
index 0d1b268..10dd8bd 100644
--- a/src/crc.c
+++ b/src/crc.c
@@ -91,6 +91,7 @@ unsigned int get_crc32(const void*buf, const unsigned int len, const uint32_t se
register uint32_t crc32val;
const unsigned char *s=(const unsigned char *)buf;
crc32val = seed;
+ /*@ loop assigns i, crc32val; */
for (i = 0; i < len; i ++)
{
crc32val = crc32_tab[(crc32val ^ s[i]) & 0xff] ^ (crc32val >> 8);
diff --git a/src/crc.h b/src/crc.h
index 50b6667..846fa14 100644
--- a/src/crc.h
+++ b/src/crc.h
@@ -28,6 +28,11 @@ extern "C" {
uint32_t* make_crc32_table(uint32_t poly);
unsigned int get_crc32_gen(const unsigned char *s, const unsigned int len, const uint32_t seed, const uint32_t *crctab);
#endif
+/*@
+ @ requires \valid_read((const char *)s + (0 .. len-1));
+ @ requires \initialized((const char *)s + (0 .. len-1));
+ @ assigns \nothing;
+ @*/
unsigned int get_crc32(const void *s, const unsigned int len, const uint32_t seed);
#ifdef __cplusplus
diff --git a/src/dfxml.c b/src/dfxml.c
index c9da693..4f02702 100644
--- a/src/dfxml.c
+++ b/src/dfxml.c
@@ -24,6 +24,11 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__)
+#undef HAVE_LIBEWF
+#undef HAVE_SYS_UTSNAME_H
+#endif
+
#ifdef ENABLE_DFXML
#include <stdio.h>
#ifdef HAVE_STDLIB_H
@@ -200,11 +205,13 @@ void xml_add_DFXML_creator(const char *package, const char *version)
#ifdef RECORD_COMPILATION_DATE
xml_out2s("compilation_date", get_compilation_date());
#endif
+#ifndef MAIN_photorec
xml_printf("<library name='libext2fs' version='%s'/>\n", td_ext2fs_version());
xml_printf("<library name='libewf' version='%s'/>\n", td_ewf_version());
xml_printf("<library name='libjpeg' version='%s'/>\n", td_jpeg_version());
xml_printf("<library name='libntfs' version='%s'/>\n", td_ntfs_version());
xml_printf("<library name='zlib' version='%s'/>\n", td_zlib_version());
+#endif
xml_pop("build_environment");
xml_push("execution_environment","");
#if defined(__CYGWIN__) || defined(__MINGW32__)
@@ -238,34 +245,29 @@ void xml_add_DFXML_creator(const char *package, const char *version)
#endif
#ifdef HAVE_GETEUID
xml_out2i("uid", geteuid());
-#if 0
-#ifdef HAVE_GETPWUID
- {
- struct passwd *tmp=getpwuid(getuid());
- if(tmp != NULL)
- {
- xml_out2s("username", tmp->pw_name);
- }
- }
-#endif
-#endif
#endif
+#if !defined(__FRAMAC__)
{
char outstr[200];
const time_t t = time(NULL);
+#if defined(__MINGW32__) || defined(__FRAMAC__)
+ const struct tm *tmp = localtime(&t);
+#else
struct tm tm_tmp;
const struct tm *tmp = localtime_r(&t,&tm_tmp);
+#endif
if (tmp != NULL &&
strftime(outstr, sizeof(outstr), "%Y-%m-%dT%H:%M:%S%z", tmp) != 0)
{
xml_out2s("start_time", outstr);
}
}
+#endif
xml_pop("execution_environment");
xml_pop("creator");
}
-void xml_setup(disk_t *disk, const partition_t *partition)
+void xml_setup(const disk_t *disk, const partition_t *partition)
{
if(xml_handle==NULL)
return;
@@ -319,7 +321,7 @@ static const char *relative_name(const char *fname)
/* See filegen.h for the definition of file_recovery_struct */
void xml_log_file_recovered(const file_recovery_t *file_recovery)
{
- struct td_list_head *tmp;
+ const struct td_list_head *tmp;
uint64_t file_size=0;
if(xml_handle==NULL)
return;
diff --git a/src/dfxml.h b/src/dfxml.h
index 9f0b16c..c6cd34b 100644
--- a/src/dfxml.h
+++ b/src/dfxml.h
@@ -35,7 +35,7 @@ void xml_push(const char *tag, const char *attribute);
void xml_pop(const char *tag);
void xml_out2s(const char *tag, const char *value);
void xml_out2i(const char *tag, const uint64_t value);
-void xml_setup(disk_t *disk, const partition_t *partition);
+void xml_setup(const disk_t *disk, const partition_t *partition);
void xml_set_command_line(const int argc, char **argv);
void xml_clear_command_line(void);
void xml_add_DFXML_creator(const char *package, const char *version);
diff --git a/src/dimage.c b/src/dimage.c
index d1f3483..6e65118 100644
--- a/src/dimage.c
+++ b/src/dimage.c
@@ -41,6 +41,9 @@
#include <assert.h>
#include <string.h>
#include <errno.h>
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
#include "types.h"
#include "common.h"
#include "intrf.h"
@@ -123,6 +126,7 @@ int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd)
free(buffer);
return -1;
}
+#if !defined(__FRAMAC__)
if(fstat(disk_dst, &stat_buf)==0)
{
int res=1;
@@ -136,6 +140,7 @@ int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd)
src_offset+=dst_offset;
}
}
+#endif
src_offset_old=src_offset;
#ifdef HAVE_NCURSES
window=newwin(LINES, COLS, 0, 0); /* full screen */
diff --git a/src/dir.c b/src/dir.c
index f1f0fdf..7501627 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -22,6 +22,10 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#ifdef __FRAMAC__
+#undef HAVE_CHMOD
+#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
@@ -164,7 +168,7 @@ int set_datestr(char *datestr, size_t n, const time_t timev)
strncpy(datestr, " ", n);
return 0;
}
-#if defined(__MINGW32__)
+#if defined(__MINGW32__) || defined(__FRAMAC__)
tm_p=localtime(&timev);
#else
tm_p=localtime_r(&timev, &tmp);
diff --git a/src/dir.h b/src/dir.h
index b2d4f7a..ca67255 100644
--- a/src/dir.h
+++ b/src/dir.h
@@ -24,59 +24,19 @@
#ifdef __cplusplus
extern "C" {
#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#include "list.h"
-#define DIR_NAME_LEN 1024
-#define FLAG_LIST_DELETED 1
-#define FLAG_LIST_MASK12 2
-#define FLAG_LIST_MASK16 4
-#define FLAG_LIST_PATHNAME 8
-#define FLAG_LIST_ADS 16
-#define FLAG_LIST_SYSTEM 32
-/* capabilities */
-#define CAPA_LIST_DELETED 1
-#define CAPA_LIST_ADS 2
-
-typedef enum { DIR_PART_ENOIMP=-3, DIR_PART_ENOSYS=-2, DIR_PART_EIO=-1, DIR_PART_OK=0} dir_partition_t;
-typedef struct dir_data dir_data_t;
-typedef struct
-{
- struct td_list_head list;
- char *name;
- uint32_t st_ino;
- uint32_t st_mode;
- uint32_t st_uid;
- uint32_t st_gid;
- uint64_t st_size;
- time_t td_atime; /* time of last access */
- time_t td_mtime; /* time of last modification */
- time_t td_ctime; /* time of last status change */
- unsigned int status;
-} file_info_t;
-
-struct dir_data
-{
- void *display;
- char current_directory[DIR_NAME_LEN];
- unsigned long int current_inode;
- int verbose;
- unsigned int param;
- unsigned int capabilities;
- int(*get_dir)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_inode, file_info_t*list);
- int (*copy_file)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
- void (*close)(dir_data_t *dir_data);
- char *local_dir;
- void *private_dir_data;
-};
-
-#define FILE_STATUS_DELETED 1
-#define FILE_STATUS_MARKED 2
-#define FILE_STATUS_ADS 4
+#include "dir_common.h"
+/*@
+ @ requires \valid(datestr);
+ @*/
int set_datestr(char *datestr, size_t n, const time_t timev);
+
+/*@
+ @ requires \valid_read(dir_data);
+ @ requires \valid_read(dir_list);
+ @*/
int dir_aff_log(const dir_data_t *dir_data, const file_info_t*dir_list);
+
void log_list_file(const disk_t *disk_car, const partition_t *partition, const dir_data_t *dir_data, const file_info_t*list);
unsigned int delete_list_file(file_info_t *list);
int dir_whole_partition_log(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int inode);
@@ -87,49 +47,6 @@ FILE *fopen_local(char **localfilename, const char *localroot, const char *filen
char *gen_local_filename(const char *filename);
char *mkdir_local(const char *localroot, const char *pathname);
void mkdir_local_for_file(const char *filename);
-
-#define LINUX_S_IFMT 00170000
-#define LINUX_S_IFSOCK 0140000
-#define LINUX_S_IFLNK 0120000
-#define LINUX_S_IFREG 0100000
-#define LINUX_S_IFBLK 0060000
-#define LINUX_S_IFDIR 0040000
-#define LINUX_S_IFCHR 0020000
-#define LINUX_S_IFIFO 0010000
-#define LINUX_S_ISUID 0004000
-#define LINUX_S_ISGID 0002000
-#define LINUX_S_ISVTX 0001000
-
-
-#define LINUX_S_IRWXU 00700
-#define LINUX_S_IRUSR 00400
-#define LINUX_S_IWUSR 00200
-#define LINUX_S_IXUSR 00100
-
-#define LINUX_S_IRWXG 00070
-#define LINUX_S_IRGRP 00040
-#define LINUX_S_IWGRP 00020
-#define LINUX_S_IXGRP 00010
-
-#define LINUX_S_IRWXO 00007
-#define LINUX_S_IROTH 00004
-#define LINUX_S_IWOTH 00002
-#define LINUX_S_IXOTH 00001
-
-#define LINUX_S_IRWXUGO (LINUX_S_IRWXU|LINUX_S_IRWXG|LINUX_S_IRWXO)
-#define LINUX_S_IALLUGO (LINUX_S_ISUID|LINUX_S_ISGID|LINUX_S_ISVTX|LINUX_S_IRWXUGO)
-#define LINUX_S_IRUGO (LINUX_S_IRUSR|LINUX_S_IRGRP|LINUX_S_IROTH)
-#define LINUX_S_IWUGO (LINUX_S_IWUSR|LINUX_S_IWGRP|LINUX_S_IWOTH)
-#define LINUX_S_IXUGO (LINUX_S_IXUSR|LINUX_S_IXGRP|LINUX_S_IXOTH)
-
-#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
-#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
-#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
-#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
-#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
-#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
-#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
-
int filesort(const struct td_list_head *a, const struct td_list_head *b);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/dir_common.h b/src/dir_common.h
new file mode 100644
index 0000000..8463d67
--- /dev/null
+++ b/src/dir_common.h
@@ -0,0 +1,123 @@
+/*
+
+ File: dir_common.h
+
+ Copyright (C) 2020 Christophe GRENIER <grenier@cgsecurity.org>
+
+ This software is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ */
+#ifndef _DIR_COMMON_H
+#define _DIR_COMMON_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#include "list.h"
+#define DIR_NAME_LEN 1024
+#define FLAG_LIST_DELETED 1
+#define FLAG_LIST_MASK12 2
+#define FLAG_LIST_MASK16 4
+#define FLAG_LIST_PATHNAME 8
+#define FLAG_LIST_ADS 16
+#define FLAG_LIST_SYSTEM 32
+/* capabilities */
+#define CAPA_LIST_DELETED 1
+#define CAPA_LIST_ADS 2
+
+typedef enum { DIR_PART_ENOIMP=-3, DIR_PART_ENOSYS=-2, DIR_PART_EIO=-1, DIR_PART_OK=0} dir_partition_t;
+typedef struct dir_data dir_data_t;
+typedef struct
+{
+ struct td_list_head list;
+ char *name;
+ uint32_t st_ino;
+ uint32_t st_mode;
+ uint32_t st_uid;
+ uint32_t st_gid;
+ uint64_t st_size;
+ time_t td_atime; /* time of last access */
+ time_t td_mtime; /* time of last modification */
+ time_t td_ctime; /* time of last status change */
+ unsigned int status;
+} file_info_t;
+
+struct dir_data
+{
+ void *display;
+ char current_directory[DIR_NAME_LEN];
+ unsigned long int current_inode;
+ int verbose;
+ unsigned int param;
+ unsigned int capabilities;
+ int(*get_dir)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_inode, file_info_t*list);
+ int (*copy_file)(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
+ void (*close)(dir_data_t *dir_data);
+ char *local_dir;
+ void *private_dir_data;
+};
+
+#define FILE_STATUS_DELETED 1
+#define FILE_STATUS_MARKED 2
+#define FILE_STATUS_ADS 4
+
+#define LINUX_S_IFMT 00170000
+#define LINUX_S_IFSOCK 0140000
+#define LINUX_S_IFLNK 0120000
+#define LINUX_S_IFREG 0100000
+#define LINUX_S_IFBLK 0060000
+#define LINUX_S_IFDIR 0040000
+#define LINUX_S_IFCHR 0020000
+#define LINUX_S_IFIFO 0010000
+#define LINUX_S_ISUID 0004000
+#define LINUX_S_ISGID 0002000
+#define LINUX_S_ISVTX 0001000
+
+
+#define LINUX_S_IRWXU 00700
+#define LINUX_S_IRUSR 00400
+#define LINUX_S_IWUSR 00200
+#define LINUX_S_IXUSR 00100
+
+#define LINUX_S_IRWXG 00070
+#define LINUX_S_IRGRP 00040
+#define LINUX_S_IWGRP 00020
+#define LINUX_S_IXGRP 00010
+
+#define LINUX_S_IRWXO 00007
+#define LINUX_S_IROTH 00004
+#define LINUX_S_IWOTH 00002
+#define LINUX_S_IXOTH 00001
+
+#define LINUX_S_IRWXUGO (LINUX_S_IRWXU|LINUX_S_IRWXG|LINUX_S_IRWXO)
+#define LINUX_S_IALLUGO (LINUX_S_ISUID|LINUX_S_ISGID|LINUX_S_ISVTX|LINUX_S_IRWXUGO)
+#define LINUX_S_IRUGO (LINUX_S_IRUSR|LINUX_S_IRGRP|LINUX_S_IROTH)
+#define LINUX_S_IWUGO (LINUX_S_IWUSR|LINUX_S_IWGRP|LINUX_S_IWOTH)
+#define LINUX_S_IXUGO (LINUX_S_IXUSR|LINUX_S_IXGRP|LINUX_S_IXOTH)
+
+#define LINUX_S_ISLNK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFLNK)
+#define LINUX_S_ISREG(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFREG)
+#define LINUX_S_ISDIR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFDIR)
+#define LINUX_S_ISCHR(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFCHR)
+#define LINUX_S_ISBLK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFBLK)
+#define LINUX_S_ISFIFO(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFIFO)
+#define LINUX_S_ISSOCK(m) (((m) & LINUX_S_IFMT) == LINUX_S_IFSOCK)
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif
+#endif
diff --git a/src/dirn.c b/src/dirn.c
index ab18db9..050129f 100644
--- a/src/dirn.c
+++ b/src/dirn.c
@@ -202,7 +202,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"h");
+ waddstr(window,"'h'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((dir_data->param&FLAG_LIST_DELETED)==0)
@@ -215,7 +215,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"h");
+ waddstr(window,"'h'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((dir_data->param&FLAG_LIST_ADS)==0)
@@ -226,7 +226,7 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
wmove(window,LINES-2,4);
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"q");
+ waddstr(window,"'q'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to quit");
@@ -235,13 +235,13 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window,", ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,":");
+ waddstr(window,"':'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to select the current file, ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"a");
+ waddstr(window,"'a'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
if((status&FILE_STATUS_MARKED)==FILE_STATUS_MARKED)
@@ -250,13 +250,13 @@ static long int dir_aff_ncurses(disk_t *disk, const partition_t *partition, dir_
waddstr(window," to deselect all files");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- mvwaddstr(window,LINES-1,4,"C");
+ mvwaddstr(window,LINES-1,4,"'C'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to copy the selected files, ");
if(has_colors())
wbkgdset(window,' ' | A_BOLD | COLOR_PAIR(0));
- waddstr(window,"c");
+ waddstr(window,"'c'");
if(has_colors())
wbkgdset(window,' ' | COLOR_PAIR(0));
waddstr(window," to copy the current file");
diff --git a/src/ewf.c b/src/ewf.c
index 7bf502c..e7c6391 100644
--- a/src/ewf.c
+++ b/src/ewf.c
@@ -23,6 +23,10 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEWF
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -96,34 +100,30 @@ struct info_fewf_struct
unsigned int buffer_size;
};
+#if defined( HAVE_LIBEWF_V2_API )
disk_t *fewf_init(const char *device, const int mode)
{
unsigned int num_files=0;
char **filenames= NULL;
disk_t *disk=NULL;
struct info_fewf_struct *data;
-#if !defined( HAVE_LIBEWF_V2_API ) && defined( HAVE_GLOB_H )
- glob_t globbuf;
-#endif
-#if defined( HAVE_LIBEWF_V2_API )
libewf_error_t *ewf_error = NULL;
-#endif
data=(struct info_fewf_struct *)MALLOC(sizeof(struct info_fewf_struct));
- memset(data, 0, sizeof(struct info_fewf_struct));
+ memset(data, 0, sizeof(struct info_fewf_struct));
data->file_name = strdup(device);
+ if(data->file_name==NULL)
+ {
+ free(data);
+ return NULL;
+ }
data->handle=NULL;
data->mode = mode;
#ifdef DEBUG_EWF
-#if defined( HAVE_LIBEWF_V2_API )
libewf_notify_set_stream( stderr, NULL );
libewf_notify_set_verbose( 1 );
-#else
- libewf_set_notify_values( stderr, 1 );
-#endif
#endif
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_glob(
data->file_name,
strlen(data->file_name),
@@ -140,36 +140,9 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
-#elif defined( HAVE_GLOB_H )
- {
- globbuf.gl_offs = 0;
- glob(data->file_name, GLOB_DOOFFS, NULL, &globbuf);
- if(globbuf.gl_pathc>0)
- {
- filenames=(char **)MALLOC(globbuf.gl_pathc * sizeof(*filenames));
- for (num_files=0; num_files<globbuf.gl_pathc; num_files++) {
- filenames[num_files]=globbuf.gl_pathv[num_files];
- }
- }
- }
- if(filenames==NULL)
- {
- globfree(&globbuf);
- free(data->file_name);
- free(data);
- return NULL;
- }
-#else
- {
- filenames=(char **)MALLOC(1*sizeof(*filenames));
- filenames[num_files] = data->file_name;
- num_files++;
- }
-#endif
if((mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR)
{
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_handle_initialize(
&( data->handle ),
&ewf_error) != 1 )
@@ -209,18 +182,10 @@ disk_t *fewf_init(const char *device, const int mode)
NULL );
data->handle=NULL;
}
-#else
- data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ_WRITE);
- if(data->handle==NULL)
- {
- log_error("libewf_open(%s) in RW mode failed\n", device);
- }
-#endif /* defined( HAVE_LIBEWF_V2_API ) */
}
if(data->handle==NULL)
{
data->mode&=~TESTDISK_O_RDWR;
-#if defined( HAVE_LIBEWF_V2_API )
if( libewf_handle_initialize(
&( data->handle ),
&ewf_error) != 1 )
@@ -261,7 +226,140 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
+ }
+ if( libewf_handle_set_header_values_date_format(
+ data->handle,
+ LIBEWF_DATE_FORMAT_DAYMONTH,
+ NULL ) != 1 )
+ {
+ log_error("%s Unable to set header values date format\n", device);
+ }
+ disk=(disk_t *)MALLOC(sizeof(*disk));
+ init_disk(disk);
+ disk->arch=&arch_none;
+ disk->device=strdup(device);
+ if(disk->device==NULL)
+ {
+ free(disk);
+ libewf_glob_free(
+ filenames,
+ num_files,
+ NULL );
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
+ disk->data=data;
+ disk->description=&fewf_description;
+ disk->description_short=&fewf_description_short;
+ disk->pread=&fewf_pread;
+ disk->pwrite=((data->mode&TESTDISK_O_RDWR)?&fewf_pwrite:&fewf_nopwrite);
+ disk->sync=&fewf_sync;
+ disk->access_mode=(data->mode&TESTDISK_O_RDWR);
+ disk->clean=&fewf_clean;
+ {
+ uint32_t bytes_per_sector = 0;
+ if( libewf_handle_get_bytes_per_sector(
+ data->handle,
+ &bytes_per_sector,
+ NULL ) != 1 )
+ {
+ disk->sector_size=DEFAULT_SECTOR_SIZE;
+ }
+ else
+ {
+ disk->sector_size=bytes_per_sector;
+ }
+ }
+// printf("libewf_get_bytes_per_sector %u\n",disk->sector_size);
+ if(disk->sector_size==0)
+ disk->sector_size=DEFAULT_SECTOR_SIZE;
+ /* Set geometry */
+ disk->geom.cylinders=0;
+ disk->geom.heads_per_cylinder=1;
+ disk->geom.sectors_per_head=1;
+ disk->geom.bytes_per_sector=disk->sector_size;
+ {
+ size64_t media_size = 0;
+ if( libewf_handle_get_media_size(
+ data->handle,
+ &media_size,
+ NULL ) != 1 )
+ {
+ disk->disk_real_size=0;
+ }
+ disk->disk_real_size=media_size;
+ }
+ update_disk_car_fields(disk);
+ libewf_glob_free(
+ filenames,
+ num_files,
+ NULL );
+ return disk;
+}
+#else
+disk_t *fewf_init(const char *device, const int mode)
+{
+ unsigned int num_files=0;
+ char **filenames= NULL;
+ disk_t *disk=NULL;
+ struct info_fewf_struct *data;
+#if defined( HAVE_GLOB_H )
+ glob_t globbuf;
+#endif
+ data=(struct info_fewf_struct *)MALLOC(sizeof(struct info_fewf_struct));
+ memset(data, 0, sizeof(struct info_fewf_struct));
+ data->file_name = strdup(device);
+ if(data->file_name==NULL)
+ {
+ free(data);
+ return NULL;
+ }
+ data->handle=NULL;
+ data->mode = mode;
+
+#ifdef DEBUG_EWF
+ libewf_set_notify_values( stderr, 1 );
+#endif
+
+#if defined( HAVE_GLOB_H )
+ {
+ globbuf.gl_offs = 0;
+ glob(data->file_name, GLOB_DOOFFS, NULL, &globbuf);
+ if(globbuf.gl_pathc>0)
+ {
+ filenames=(char **)MALLOC(globbuf.gl_pathc * sizeof(*filenames));
+ for (num_files=0; num_files<globbuf.gl_pathc; num_files++) {
+ filenames[num_files]=globbuf.gl_pathv[num_files];
+ }
+ }
+ }
+ if(filenames==NULL)
+ {
+ globfree(&globbuf);
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
#else
+ {
+ filenames=(char **)MALLOC(1*sizeof(*filenames));
+ filenames[num_files] = data->file_name;
+ num_files++;
+ }
+#endif
+
+ if((mode&TESTDISK_O_RDWR)==TESTDISK_O_RDWR)
+ {
+ data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ_WRITE);
+ if(data->handle==NULL)
+ {
+ log_error("libewf_open(%s) in RW mode failed\n", device);
+ }
+ }
+ if(data->handle==NULL)
+ {
+ data->mode&=~TESTDISK_O_RDWR;
data->handle=libewf_open(filenames, num_files, LIBEWF_OPEN_READ);
if(data->handle==NULL)
{
@@ -274,27 +372,27 @@ disk_t *fewf_init(const char *device, const int mode)
free(data);
return NULL;
}
-#endif /* defined( HAVE_LIBEWF_V2_API ) */
}
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_set_header_values_date_format(
- data->handle,
- LIBEWF_DATE_FORMAT_DAYMONTH,
- NULL ) != 1 )
- {
- log_error("%s Unable to set header values date format\n", device);
- }
-#else
if( libewf_parse_header_values( data->handle, LIBEWF_DATE_FORMAT_DAYMONTH) != 1 )
{
log_error("%s Unable to parse EWF header values\n", device);
}
-#endif
disk=(disk_t *)MALLOC(sizeof(*disk));
init_disk(disk);
disk->arch=&arch_none;
disk->device=strdup(device);
+ if(disk->device==NULL)
+ {
+ free(disk);
+#if defined( HAVE_GLOB_H )
+ globfree(&globbuf);
+#endif
+ free(filenames);
+ free(data->file_name);
+ free(data);
+ return NULL;
+ }
disk->data=data;
disk->description=&fewf_description;
disk->description_short=&fewf_description_short;
@@ -303,18 +401,10 @@ disk_t *fewf_init(const char *device, const int mode)
disk->sync=&fewf_sync;
disk->access_mode=(data->mode&TESTDISK_O_RDWR);
disk->clean=&fewf_clean;
-#if defined( HAVE_LIBEWF_V2_API ) || defined( LIBEWF_GET_BYTES_PER_SECTOR_HAVE_TWO_ARGUMENTS )
+#if defined( LIBEWF_GET_BYTES_PER_SECTOR_HAVE_TWO_ARGUMENTS )
{
uint32_t bytes_per_sector = 0;
-
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_get_bytes_per_sector(
- data->handle,
- &bytes_per_sector,
- NULL ) != 1 )
-#else
if( libewf_get_bytes_per_sector(data->handle, &bytes_per_sector)<0)
-#endif
{
disk->sector_size=DEFAULT_SECTOR_SIZE;
}
@@ -326,7 +416,6 @@ disk_t *fewf_init(const char *device, const int mode)
#else
disk->sector_size=libewf_get_bytes_per_sector(data->handle);
#endif
-
// printf("libewf_get_bytes_per_sector %u\n",disk->sector_size);
if(disk->sector_size==0)
disk->sector_size=DEFAULT_SECTOR_SIZE;
@@ -335,19 +424,10 @@ disk_t *fewf_init(const char *device, const int mode)
disk->geom.heads_per_cylinder=1;
disk->geom.sectors_per_head=1;
disk->geom.bytes_per_sector=disk->sector_size;
- /* Get disk_real_size */
-#if defined( HAVE_LIBEWF_V2_API ) || defined( LIBEWF_GET_MEDIA_SIZE_HAVE_TWO_ARGUMENTS )
+#if defined( LIBEWF_GET_MEDIA_SIZE_HAVE_TWO_ARGUMENTS )
{
size64_t media_size = 0;
-
-#if defined( HAVE_LIBEWF_V2_API )
- if( libewf_handle_get_media_size(
- data->handle,
- &media_size,
- NULL ) != 1 )
-#else
if(libewf_get_media_size(data->handle, &media_size)<0)
-#endif
{
disk->disk_real_size=0;
}
@@ -360,19 +440,13 @@ disk_t *fewf_init(const char *device, const int mode)
disk->disk_real_size=libewf_get_media_size(data->handle);
#endif
update_disk_car_fields(disk);
-#if defined( HAVE_LIBEWF_V2_API )
- libewf_glob_free(
- filenames,
- num_files,
- NULL );
-#else
#if defined( HAVE_GLOB_H )
globfree(&globbuf);
#endif
free(filenames);
-#endif
return disk;
}
+#endif
static const char *fewf_description(disk_t *disk)
{
@@ -529,4 +603,3 @@ const char*td_ewf_version(void)
return "none";
}
#endif /* defined(HAVE_LIBEWF_H) && defined(HAVE_LIBEWF) */
-
diff --git a/src/ewf.h b/src/ewf.h
index 2bcf4cc..16d2bad 100644
--- a/src/ewf.h
+++ b/src/ewf.h
@@ -23,6 +23,10 @@
extern "C" {
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEWF
+#endif
+
#if defined(HAVE_LIBEWF_H) && defined(HAVE_LIBEWF)
disk_t *fewf_init(const char *device, const int testdisk_mode);
#endif
diff --git a/src/ext2.c b/src/ext2.c
index 2cd6a07..cb81316 100644
--- a/src/ext2.c
+++ b/src/ext2.c
@@ -109,7 +109,7 @@ static void set_EXT2_info(const struct ext2_super_block *sb, partition_t *partit
Primary superblock is at 1024 (SUPERBLOCK_OFFSET)
Group 0 begin at s_first_data_block
*/
-int recover_EXT2(disk_t *disk, const struct ext2_super_block *sb,partition_t *partition,const int verbose, const int dump_ind)
+int recover_EXT2(const disk_t *disk, const struct ext2_super_block *sb, partition_t *partition, const int verbose, const int dump_ind)
{
if(test_EXT2(sb, partition)!=0)
return 1;
diff --git a/src/ext2.h b/src/ext2.h
index 68bffea..47ef0a7 100644
--- a/src/ext2.h
+++ b/src/ext2.h
@@ -202,7 +202,7 @@ struct ext2_super_block {
uint32_t s_checksum; /* crc32c(superblock) */
};
int check_EXT2(disk_t *disk_car,partition_t *partition,const int verbose);
-int recover_EXT2(disk_t *disk_car, const struct ext2_super_block *sb,partition_t *partition,const int verbose, const int dump_ind);
+int recover_EXT2(const disk_t *disk_car, const struct ext2_super_block *sb, partition_t *partition, const int verbose, const int dump_ind);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2_dir.c b/src/ext2_dir.c
index f3dc4a2..efc19a3 100644
--- a/src/ext2_dir.c
+++ b/src/ext2_dir.c
@@ -23,6 +23,10 @@
#include <config.h>
#endif
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
@@ -31,12 +35,14 @@
#include <errno.h>
#endif
+#if defined(HAVE_LIBEXT2FS)
#ifdef HAVE_EXT2FS_EXT2_FS_H
#include "ext2fs/ext2_fs.h"
#endif
#ifdef HAVE_EXT2FS_EXT2FS_H
#include "ext2fs/ext2fs.h"
#endif
+#endif
#include "types.h"
#include "common.h"
@@ -67,7 +73,6 @@ static errcode_t my_flush(io_channel channel);
static errcode_t my_read_blk64(io_channel channel, unsigned long long block, int count, void *buf);
static errcode_t my_write_blk64(io_channel channel, unsigned long long block, int count, const void *buf);
-static io_channel alloc_io_channel(disk_t *disk_car,my_data_t *my_data);
static void dir_partition_ext2_close(dir_data_t *dir_data);
static int ext2_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
@@ -91,7 +96,6 @@ static struct struct_io_manager my_struct_manager = {
.write_blk64=&my_write_blk64,
#endif
};
-static int ext2_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int cluster, file_info_t *dir_list);
static io_channel shared_ioch=NULL;
/*
@@ -105,7 +109,7 @@ static io_channel shared_ioch=NULL;
/*
* Allocate libext2fs structures associated with I/O manager
*/
-static io_channel alloc_io_channel(disk_t *disk_car,my_data_t *my_data)
+static io_channel alloc_io_channel(const disk_t *disk_car,my_data_t *my_data)
{
io_channel ioch;
#ifdef DEBUG_EXT2
diff --git a/src/ext2_inc.h b/src/ext2_inc.h
index ca2421b..e3cf9f5 100644
--- a/src/ext2_inc.h
+++ b/src/ext2_inc.h
@@ -19,6 +19,10 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
#if defined(HAVE_LIBEXT2FS)
struct ext2_dir_struct {
file_info_t *dir_list;
diff --git a/src/ext2_sb.c b/src/ext2_sb.c
index 8a72ed3..e0e9763 100644
--- a/src/ext2_sb.c
+++ b/src/ext2_sb.c
@@ -38,7 +38,7 @@
#include "guid_cmp.h"
#include "ext2_sb.h"
-int interface_superblock(disk_t *disk_car,list_part_t *list_part, char**current_cmd)
+int interface_superblock(disk_t *disk_car, const list_part_t *list_part, char**current_cmd)
{
const list_part_t *parts;
const partition_t *old_part=NULL;
diff --git a/src/ext2_sb.h b/src/ext2_sb.h
index fae7c31..b527b8e 100644
--- a/src/ext2_sb.h
+++ b/src/ext2_sb.h
@@ -23,7 +23,7 @@
extern "C" {
#endif
-int interface_superblock(disk_t *disk_car,list_part_t *list_part,char**current_cmd);
+int interface_superblock(disk_t *disk_car, const list_part_t *list_part, char**current_cmd);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2grp.c b/src/ext2grp.c
index c48ec2b..96db73f 100644
--- a/src/ext2grp.c
+++ b/src/ext2grp.c
@@ -36,7 +36,7 @@
#include "log.h"
#include "photorec.h"
-unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition)
+unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition)
{
struct td_list_head *search_walker = NULL;
unsigned char *buffer;
@@ -73,7 +73,7 @@ unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, parti
return blocksize;
}
-unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition)
+unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition)
{
struct td_list_head *search_walker = NULL;
unsigned char *buffer;
diff --git a/src/ext2grp.h b/src/ext2grp.h
index ad854fe..ed5e9db 100644
--- a/src/ext2grp.h
+++ b/src/ext2grp.h
@@ -23,8 +23,8 @@
extern "C" {
#endif
-unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition);
-unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, partition_t *partition);
+unsigned int ext2_fix_group(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition);
+unsigned int ext2_fix_inode(alloc_data_t *list_search_space, disk_t *disk, const partition_t *partition);
#ifdef __cplusplus
} /* closing brace for extern "C" */
diff --git a/src/ext2p.c b/src/ext2p.c
index 6cbb0f7..2e57e43 100644
--- a/src/ext2p.c
+++ b/src/ext2p.c
@@ -22,6 +22,12 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(__FRAMAC__) || defined(MAIN_photorec)
+#undef HAVE_LIBEXT2FS
+#endif
+
+#if defined(HAVE_LIBEXT2FS)
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -48,7 +54,6 @@
#include "log.h"
#include "log_part.h"
-#ifdef HAVE_LIBEXT2FS
unsigned int ext2_remove_used_space(disk_t *disk, const partition_t *partition, alloc_data_t *list_search_space)
{
dir_data_t dir_data;
diff --git a/src/fat.c b/src/fat.c
index f1f3a65..667c778 100644
--- a/src/fat.c
+++ b/src/fat.c
@@ -43,21 +43,123 @@
#include "intrf.h"
#include "log.h"
#include "log_part.h"
-#include "fat_common.h"
#include "dir.h"
#include "fat_dir.h"
extern const arch_fnct_t arch_i386;
extern const arch_fnct_t arch_mac;
-static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition);
-static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header);
static int log_fat_info(const struct fat_boot_sector*fh1, const upart_type_t upart_type, const unsigned int sector_size);
static int test_OS2MB(const disk_t *disk, const struct fat_boot_sector *fat_header, const partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat12(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat16(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
static int is_fat32(const partition_t *partition);
+static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header)
+{
+ partition->fsname[0]='\0';
+ if((fat_header->sectors_per_cluster>0)&&(fat_header->sectors_per_cluster<=128))
+ {
+ const unsigned int cluster_size=fat_header->sectors_per_cluster*disk_car->sector_size;
+ unsigned char *buffer=(unsigned char*)MALLOC(cluster_size);
+ if((unsigned)disk_car->pread(disk_car, buffer, cluster_size,
+ partition->part_offset + (le16(fat_header->reserved) + fat_header->fats * le32(fat_header->fat32_length) + (uint64_t)(le32(fat_header->root_cluster) - 2) * fat_header->sectors_per_cluster) * disk_car->sector_size) != cluster_size)
+ {
+ log_error("fat32_set_part_name() cannot read FAT32 root cluster.\n");
+ }
+ else
+ {
+ int i;
+ int stop=0;
+ for(i=0;(i<16*fat_header->sectors_per_cluster)&&(stop==0);i++)
+ { /* Test attribut volume name and check if the volume name is erased or not */
+ if(((buffer[i*0x20+0xB] & ATTR_EXT) !=ATTR_EXT) && ((buffer[i*0x20+0xB] & ATTR_VOLUME) !=0) && (buffer[i*0x20]!=0xE5))
+ {
+ set_part_name_chomp(partition,&buffer[i*0x20],11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ if(buffer[i*0x20]==0)
+ {
+ stop=1;
+ }
+ }
+ }
+ free(buffer);
+ }
+ if(partition->fsname[0]=='\0')
+ {
+ log_info("set_FAT_info: name from BS used\n");
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT32_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ return 0;
+}
+
+static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition)
+{
+ uint64_t start_fat1;
+ uint64_t start_data;
+ uint64_t part_size;
+ unsigned long int no_of_cluster;
+ unsigned long int fat_length;
+ const char *buffer=(const char*)fat_header;
+ partition->fsname[0]='\0';
+ partition->blocksize=fat_sector_size(fat_header)* fat_header->sectors_per_cluster;
+ fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
+ part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
+ start_fat1=le16(fat_header->reserved);
+ start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header);
+ no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
+ if(no_of_cluster<4085)
+ {
+ partition->upart_type=UP_FAT12;
+ snprintf(partition->info, sizeof(partition->info), "FAT12, blocksize=%u", partition->blocksize);
+ if(buffer[38]==0x29) /* BS_BootSig */
+ {
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ }
+ else if(no_of_cluster<65525)
+ {
+ partition->upart_type=UP_FAT16;
+ snprintf(partition->info, sizeof(partition->info), "FAT16, blocksize=%u", partition->blocksize);
+ if(buffer[38]==0x29) /* BS_BootSig */
+ {
+ set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
+ if(check_VFAT_volume_name(partition->fsname, 11))
+ partition->fsname[0]='\0';
+ }
+ }
+ else
+ {
+ partition->upart_type=UP_FAT32;
+ if(partition->sb_offset==0)
+ snprintf(partition->info, sizeof(partition->info), "FAT32, blocksize=%u", partition->blocksize);
+ else
+ snprintf(partition->info, sizeof(partition->info), "FAT32 found using backup sector, blocksize=%u", partition->blocksize);
+ fat32_set_part_name(disk_car,partition,fat_header);
+ }
+}
+
static int log_fat_info(const struct fat_boot_sector*fh1, const upart_type_t upart_type, const unsigned int sector_size)
{
log_info("sector_size %u\n", fat_sector_size(fh1));
@@ -150,7 +252,7 @@ int log_fat2_info(const struct fat_boot_sector*fh1, const struct fat_boot_sector
return 0;
}
-int check_FAT(disk_t *disk_car,partition_t *partition,const int verbose)
+int check_FAT(disk_t *disk_car, partition_t *partition, const int verbose)
{
unsigned char *buffer;
buffer=(unsigned char *)MALLOC(3*disk_car->sector_size);
@@ -178,54 +280,6 @@ int check_FAT(disk_t *disk_car,partition_t *partition,const int verbose)
return 0;
}
-static void set_FAT_info(disk_t *disk_car, const struct fat_boot_sector *fat_header, partition_t *partition)
-{
- uint64_t start_fat1;
- uint64_t start_data;
- uint64_t part_size;
- unsigned long int no_of_cluster;
- unsigned long int fat_length;
- const char *buffer=(const char*)fat_header;
- partition->fsname[0]='\0';
- partition->blocksize=fat_sector_size(fat_header)* fat_header->sectors_per_cluster;
- fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
- part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
- start_fat1=le16(fat_header->reserved);
- start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header);
- no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
- if(no_of_cluster<4085)
- {
- partition->upart_type=UP_FAT12;
- snprintf(partition->info, sizeof(partition->info), "FAT12, blocksize=%u", partition->blocksize);
- if(buffer[38]==0x29) /* BS_BootSig */
- {
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- }
- else if(no_of_cluster<65525)
- {
- partition->upart_type=UP_FAT16;
- snprintf(partition->info, sizeof(partition->info), "FAT16, blocksize=%u", partition->blocksize);
- if(buffer[38]==0x29) /* BS_BootSig */
- {
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT1X_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- }
- else
- {
- partition->upart_type=UP_FAT32;
- if(partition->sb_offset==0)
- snprintf(partition->info, sizeof(partition->info), "FAT32, blocksize=%u", partition->blocksize);
- else
- snprintf(partition->info, sizeof(partition->info), "FAT32 found using backup sector, blocksize=%u", partition->blocksize);
- fat32_set_part_name(disk_car,partition,fat_header);
- }
-}
-
static unsigned int get_next_cluster_fat12(disk_t *disk, const partition_t *partition, const int offset, const unsigned int cluster)
{
unsigned int next_cluster;
@@ -764,7 +818,7 @@ unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const uns
return le32(fsinfo->nextfree);
}
-static int fat_has_EFI_entry(disk_t *disk, partition_t *partition, const int verbose)
+static int fat_has_EFI_entry(disk_t *disk, const partition_t *partition, const int verbose)
{
dir_data_t dir_data;
struct td_list_head *file_walker = NULL;
@@ -866,48 +920,6 @@ int recover_FAT(disk_t *disk_car, const struct fat_boot_sector*fat_header, parti
return 0;
}
-static int fat32_set_part_name(disk_t *disk_car, partition_t *partition, const struct fat_boot_sector*fat_header)
-{
- partition->fsname[0]='\0';
- if((fat_header->sectors_per_cluster>0)&&(fat_header->sectors_per_cluster<=128))
- {
- const unsigned int cluster_size=fat_header->sectors_per_cluster*disk_car->sector_size;
- unsigned char *buffer=(unsigned char*)MALLOC(cluster_size);
- if((unsigned)disk_car->pread(disk_car, buffer, cluster_size,
- partition->part_offset + (le16(fat_header->reserved) + fat_header->fats * le32(fat_header->fat32_length) + (uint64_t)(le32(fat_header->root_cluster) - 2) * fat_header->sectors_per_cluster) * disk_car->sector_size) != cluster_size)
- {
- log_error("fat32_set_part_name() cannot read FAT32 root cluster.\n");
- }
- else
- {
- int i;
- int stop=0;
- for(i=0;(i<16*fat_header->sectors_per_cluster)&&(stop==0);i++)
- { /* Test attribut volume name and check if the volume name is erased or not */
- if(((buffer[i*0x20+0xB] & ATTR_EXT) !=ATTR_EXT) && ((buffer[i*0x20+0xB] & ATTR_VOLUME) !=0) && (buffer[i*0x20]!=0xE5))
- {
- set_part_name_chomp(partition,&buffer[i*0x20],11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- if(buffer[i*0x20]==0)
- {
- stop=1;
- }
- }
- }
- free(buffer);
- }
- if(partition->fsname[0]=='\0')
- {
- log_info("set_FAT_info: name from BS used\n");
- set_part_name_chomp(partition,((const unsigned char*)fat_header)+FAT32_PART_NAME,11);
- if(check_VFAT_volume_name(partition->fsname, 11))
- partition->fsname[0]='\0';
- }
- return 0;
-}
-
int check_OS2MB(disk_t *disk, partition_t *partition, const int verbose)
{
unsigned char *buffer=(unsigned char *)MALLOC(disk->sector_size);
diff --git a/src/fat.h b/src/fat.h
index 11d0871..ea63cd7 100644
--- a/src/fat.h
+++ b/src/fat.h
@@ -26,139 +26,135 @@
extern "C" {
#endif
-#define FAT1X_PART_NAME 0x2B
-#define FAT32_PART_NAME 0x47
-#define FAT_NAME1 0x36
-#define FAT_NAME2 0x52 /* FAT32 only */
-#define NTFS_NAME 0x03
-#define OS2_NAME 0x03
-
-/*
- * FAT partition boot sector information, taken from the Linux
- * kernel sources.
- */
-
-struct fat_boot_sector {
- uint8_t ignored[3]; /* 0x00 Boot strap short or near jump */
- int8_t system_id[8]; /* 0x03 Name - can be used to special case
- partition manager volumes */
- uint8_t sector_size[2]; /* 0x0B bytes per logical sector */
- uint8_t sectors_per_cluster; /* 0x0D sectors/cluster */
- uint16_t reserved; /* 0x0E reserved sectors */
- uint8_t fats; /* 0x10 number of FATs */
- uint8_t dir_entries[2]; /* 0x11 root directory entries */
- uint8_t sectors[2]; /* 0x13 number of sectors */
- uint8_t media; /* 0x15 media code (unused) */
- uint16_t fat_length; /* 0x16 sectors/FAT */
- uint16_t secs_track; /* 0x18 sectors per track */
- uint16_t heads; /* 0x1A number of heads */
- uint32_t hidden; /* 0x1C hidden sectors (unused) */
- uint32_t total_sect; /* 0x20 number of sectors (if sectors == 0) */
-
- /* The following fields are only used by FAT32 */
- uint32_t fat32_length; /* 0x24=36 sectors/FAT */
- uint16_t flags; /* 0x28 bit 8: fat mirroring, low 4: active fat */
- uint8_t version[2]; /* 0x2A major, minor filesystem version */
- uint32_t root_cluster; /* 0x2C first cluster in root directory */
- uint16_t info_sector; /* 0x30 filesystem info sector */
- uint16_t backup_boot; /* 0x32 backup boot sector */
- uint8_t BPB_Reserved[12]; /* 0x34 Unused */
- uint8_t BS_DrvNum; /* 0x40 */
- uint8_t BS_Reserved1; /* 0x41 */
- uint8_t BS_BootSig; /* 0x42 */
- uint8_t BS_VolID[4]; /* 0x43 */
- uint8_t BS_VolLab[11]; /* 0x47 */
- uint8_t BS_FilSysType[8]; /* 0x52=82*/
-
- /* */
- uint8_t nothing[420]; /* 0x5A */
- uint16_t marker;
-} __attribute__ ((gcc_struct, __packed__));
-
-struct fat_fsinfo {
- uint32_t leadsig; /* 0x41615252 */
- uint8_t reserved1[480];
- uint32_t strucsig; /* 0x61417272 */
- uint32_t freecnt; /* free clusters 0xfffffffff if unknown */
- uint32_t nextfree; /* next free cluster */
- uint8_t reserved3[12];
- uint32_t magic3; /* 0xAA550000 */
-} __attribute__ ((gcc_struct, __packed__));
-
-struct msdos_dir_entry {
- int8_t name[8]; /* 00 name and extension */
- int8_t ext[3];
- uint8_t attr; /* 0B attribute bits */
- uint8_t lcase; /* 0C Case for base and extension */
- uint8_t ctime_ms; /* 0D Creation time, milliseconds */
- uint16_t ctime; /* 0E Creation time */
- uint16_t cdate; /* 10 Creation date */
- uint16_t adate; /* 12 Last access date */
- uint16_t starthi; /* 14 High 16 bits of cluster in FAT32 */
- uint16_t time; /* 16 time, date and first cluster */
- uint16_t date; /* 18 */
- uint16_t start; /* 1A */
- uint32_t size; /* 1C file size (in bytes) */
-} __attribute__ ((gcc_struct, __packed__));
-
-/* Up to 13 characters of the name */
-struct msdos_dir_slot {
- uint8_t id; /* 00 sequence number for slot */
- uint8_t name0_4[10]; /* 01 first 5 characters in name */
- uint8_t attr; /* 0B attribute byte */
- uint8_t reserved; /* 0C always 0 */
- uint8_t alias_checksum; /* 0D checksum for 8.3 alias */
- uint8_t name5_10[12]; /* 0E 6 more characters in name */
- uint16_t start; /* 1A starting cluster number, 0 in long slots */
- uint8_t name11_12[4]; /* 1C last 2 characters in name */
-};
-
-
-int comp_FAT(disk_t *disk,const partition_t *partition, const unsigned long int fat_size, const unsigned long int sect_res);
+#include "fat_common.h"
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+int comp_FAT(disk_t *disk, const partition_t *partition, const unsigned long int fat_size, const unsigned long int sect_res);
+
+/*@
+ @ requires \valid_read(fh1);
+ @ requires \valid_read(fh2);
+ @*/
int log_fat2_info(const struct fat_boot_sector*fh1, const struct fat_boot_sector*fh2, const upart_type_t upart_type, const unsigned int sector_size);
-unsigned int get_next_cluster(disk_t *disk,const partition_t *partition, const upart_type_t upart_type,const int offset, const unsigned int cluster);
-int set_next_cluster(disk_t *disk,const partition_t *partition, const upart_type_t upart_type,const int offset, const unsigned int cluster, const unsigned int next_cluster);
-
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+unsigned int get_next_cluster(disk_t *disk, const partition_t *partition, const upart_type_t upart_type, const int offset, const unsigned int cluster);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+int set_next_cluster(disk_t *disk, const partition_t *partition, const upart_type_t upart_type, const int offset, const unsigned int cluster, const unsigned int next_cluster);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_fat(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat12(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat16(const partition_t *partition);
+
+/*@
+ @ requires \valid_read(partition);
+ @ assigns \nothing;
+ @*/
int is_part_fat32(const partition_t *partition);
-unsigned int fat32_get_prev_cluster(disk_t *disk,const partition_t *partition, const unsigned int fat_offset, const unsigned int cluster, const unsigned int no_of_cluster);
-int fat32_free_info(disk_t *disk,const partition_t *partition, const unsigned int fat_offset, const unsigned int no_of_cluster, unsigned int *next_free, unsigned int*free_count);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
+unsigned int fat32_get_prev_cluster(disk_t *disk, const partition_t *partition, const unsigned int fat_offset, const unsigned int cluster, const unsigned int no_of_cluster);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(partition);
+ @ requires separation: \separated(disk, partition);
+ @ requires \valid(next_free);
+ @ requires \valid(free_count);
+ @*/
+int fat32_free_info(disk_t *disk, const partition_t *partition, const unsigned int fat_offset, const unsigned int no_of_cluster, unsigned int *next_free, unsigned int *free_count);
+
+/*@
+ @ requires \valid_read(boot_fat32 + (0 .. sector_size-1));
+ @ assigns \nothing;
+ @*/
unsigned long int fat32_get_free_count(const unsigned char *boot_fat32, const unsigned int sector_size);
-unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const unsigned int sector_size);
-#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
-#define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG)
-#define ATTR_RO 1 /* read-only */
-#define ATTR_HIDDEN 2 /* hidden */
-#define ATTR_SYS 4 /* system */
-#define ATTR_VOLUME 8 /* volume label */
-#define ATTR_DIR 16 /* directory */
-#define ATTR_ARCH 32 /* archived */
-
-#define ATTR_NONE 0 /* no attribute bits */
-#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
- /* attribute bits that are copied "as is" */
-#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
-#define ATTR_EXT_MASK (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME | ATTR_DIR | ATTR_ARCH)
- /* bits that are used by the Windows 95/Windows NT extended FAT */
-#define FAT12_BAD 0x0FF7
-#define FAT12_EOC 0x0FF8
-#define FAT16_BAD 0xFFF7
-#define FAT16_EOC 0xFFF8
-#define FAT32_BAD 0x0FFFFFF7
-#define FAT32_EOC 0x0FFFFFF8
-#define FAT1x_BOOT_SECTOR_SIZE 0x200
+/*@
+ @ requires \valid_read(boot_fat32 + (0 .. sector_size-1));
+ @ assigns \nothing;
+ @*/
+unsigned long int fat32_get_next_free(const unsigned char *boot_fat32, const unsigned int sector_size);
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int recover_FAT(disk_t *disk, const struct fat_boot_sector*fat_header, partition_t *partition, const int verbose, const int dump_ind, const int backup);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
int check_FAT(disk_t *disk, partition_t *partition, const int verbose);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int test_FAT(disk_t *disk, const struct fat_boot_sector *fat_header, const partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid_read(fat_header);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition, fat_header);
+ @*/
int recover_OS2MB(const disk_t *disk, const struct fat_boot_sector*fat_header, partition_t *partition, const int verbose, const int dump_ind);
+
+/*@
+ @ requires \valid(disk);
+ @ requires \valid(partition);
+ @ requires separation: \separated(disk, partition);
+ @*/
int check_OS2MB(disk_t *disk, partition_t *partition, const int verbose);
+
+/*@
+ @ requires \valid_read(name);
+ @*/
int check_VFAT_volume_name(const char *name, const unsigned int max_size);
+
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
diff --git a/src/fat1x.c b/src/fat1x.c
index 90ab49b..43d8950 100644
--- a/src/fat1x.c
+++ b/src/fat1x.c
@@ -43,7 +43,7 @@
#include "fat1x.h"
#ifdef HAVE_NCURSES
-static void dump_fat1x_ncurses(disk_t *disk_car, partition_t *partition, const unsigned char *buffer_bs)
+static void dump_fat1x_ncurses(disk_t *disk_car, const partition_t *partition, const unsigned char *buffer_bs)
{
WINDOW *window=newwin(LINES, COLS, 0, 0); /* full screen */
keypad(window, TRUE); /* Need it to get arrow key */
@@ -62,7 +62,7 @@ static void dump_fat1x_ncurses(disk_t *disk_car, partition_t *partition, const u
}
#endif
-static void dump_fat1x(disk_t *disk_car, partition_t *partition, const unsigned char *buffer_bs, char **current_cmd)
+static void dump_fat1x(disk_t *disk_car, const partition_t *partition, const unsigned char *buffer_bs, char **current_cmd)
{
log_info("Boot sector\n");
dump_log(buffer_bs, FAT1x_BOOT_SECTOR_SIZE);
diff --git a/src/fat_adv.c b/src/fat_adv.c
index 5fcfe77..c6f6790 100644
--- a/src/fat_adv.c
+++ b/src/fat_adv.c
@@ -173,7 +173,7 @@ static unsigned long int get_subdirectory(disk_t *disk_car,const uint64_t hd_off
#ifdef HAVE_NCURSES
#define INTER_DIR 16
-static int ask_root_directory(disk_t *disk_car, const partition_t *partition, const file_info_t*dir_list, const unsigned long int cluster)
+static int ask_root_directory(const disk_t *disk_car, const partition_t *partition, const file_info_t*dir_list, const unsigned long int cluster)
{
/* Return value
* -1: quit
diff --git a/src/fat_cluster.c b/src/fat_cluster.c
index 1384202..a009e7f 100644
--- a/src/fat_cluster.c
+++ b/src/fat_cluster.c
@@ -42,7 +42,7 @@
/* Using a couple of inodes of "." directory entries, get the cluster size and where the first cluster begins.
* */
-int find_sectors_per_cluster(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset_org, const upart_type_t upart_type)
+int find_sectors_per_cluster(disk_t *disk_car, const partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset_org, const upart_type_t upart_type)
{
unsigned int nbr_subdir=0;
sector_cluster_t sector_cluster[10];
diff --git a/src/fat_cluster.h b/src/fat_cluster.h
index a5b3d2f..9bc53fe 100644
--- a/src/fat_cluster.h
+++ b/src/fat_cluster.h
@@ -42,7 +42,7 @@ struct cluster_offset_struct
unsigned int first_sol;
};
-int find_sectors_per_cluster(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset, const upart_type_t upart_type);
+int find_sectors_per_cluster(disk_t *disk_car, const partition_t *partition, const int verbose, const int dump_ind, unsigned int *sectors_per_cluster, uint64_t *offset, const upart_type_t upart_type);
upart_type_t no_of_cluster2part_type(const unsigned long int no_of_cluster);
int find_sectors_per_cluster_aux(const sector_cluster_t *sector_cluster, const unsigned int nbr_sector_cluster,unsigned int *sectors_per_cluster, uint64_t *offset, const int verbose, const unsigned long int part_size_in_sectors, const upart_type_t upart_type);
diff --git a/src/fat_common.c b/src/fat_common.c
index ab1f181..2546026 100644
--- a/src/fat_common.c
+++ b/src/fat_common.c
@@ -28,7 +28,6 @@
#endif
#include "types.h"
#include "common.h"
-#include "fat.h"
#include "fat_common.h"
unsigned int fat_sector_size(const struct fat_boot_sector *fat_header)
diff --git a/src/fat_common.h b/src/fat_common.h
index 471c4e8..67fcc6b 100644
--- a/src/fat_common.h
+++ b/src/fat_common.h
@@ -24,10 +24,144 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+#define FAT1X_PART_NAME 0x2B
+#define FAT32_PART_NAME 0x47
+#define FAT_NAME1 0x36
+#define FAT_NAME2 0x52 /* FAT32 only */
+
+#define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */
+#define IS_FREE(n) (!*(n) || *(const unsigned char *) (n) == DELETED_FLAG)
+#define ATTR_RO 1 /* read-only */
+#define ATTR_HIDDEN 2 /* hidden */
+#define ATTR_SYS 4 /* system */
+#define ATTR_VOLUME 8 /* volume label */
+#define ATTR_DIR 16 /* directory */
+#define ATTR_ARCH 32 /* archived */
+
+#define ATTR_NONE 0 /* no attribute bits */
+#define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN)
+ /* attribute bits that are copied "as is" */
+#define ATTR_EXT (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME)
+#define ATTR_EXT_MASK (ATTR_RO | ATTR_HIDDEN | ATTR_SYS | ATTR_VOLUME | ATTR_DIR | ATTR_ARCH)
+ /* bits that are used by the Windows 95/Windows NT extended FAT */
+#define FAT12_BAD 0x0FF7
+#define FAT12_EOC 0x0FF8
+#define FAT16_BAD 0xFFF7
+#define FAT16_EOC 0xFFF8
+#define FAT32_BAD 0x0FFFFFF7
+#define FAT32_EOC 0x0FFFFFF8
+#define FAT1x_BOOT_SECTOR_SIZE 0x200
+
+/*
+ * FAT partition boot sector information, taken from the Linux
+ * kernel sources.
+ */
+
+struct fat_boot_sector {
+ uint8_t ignored[3]; /* 0x00 Boot strap short or near jump */
+ int8_t system_id[8]; /* 0x03 Name - can be used to special case
+ partition manager volumes */
+ uint8_t sector_size[2]; /* 0x0B bytes per logical sector */
+ uint8_t sectors_per_cluster; /* 0x0D sectors/cluster */
+ uint16_t reserved; /* 0x0E reserved sectors */
+ uint8_t fats; /* 0x10 number of FATs */
+ uint8_t dir_entries[2]; /* 0x11 root directory entries */
+ uint8_t sectors[2]; /* 0x13 number of sectors */
+ uint8_t media; /* 0x15 media code (unused) */
+ uint16_t fat_length; /* 0x16 sectors/FAT */
+ uint16_t secs_track; /* 0x18 sectors per track */
+ uint16_t heads; /* 0x1A number of heads */
+ uint32_t hidden; /* 0x1C hidden sectors (unused) */
+ uint32_t total_sect; /* 0x20 number of sectors (if sectors == 0) */
+
+ /* The following fields are only used by FAT32 */
+ uint32_t fat32_length; /* 0x24=36 sectors/FAT */
+ uint16_t flags; /* 0x28 bit 8: fat mirroring, low 4: active fat */
+ uint8_t version[2]; /* 0x2A major, minor filesystem version */
+ uint32_t root_cluster; /* 0x2C first cluster in root directory */
+ uint16_t info_sector; /* 0x30 filesystem info sector */
+ uint16_t backup_boot; /* 0x32 backup boot sector */
+ uint8_t BPB_Reserved[12]; /* 0x34 Unused */
+ uint8_t BS_DrvNum; /* 0x40 */
+ uint8_t BS_Reserved1; /* 0x41 */
+ uint8_t BS_BootSig; /* 0x42 */
+ uint8_t BS_VolID[4]; /* 0x43 */
+ uint8_t BS_VolLab[11]; /* 0x47 */
+ uint8_t BS_FilSysType[8]; /* 0x52=82*/
+
+ /* */
+ uint8_t nothing[420]; /* 0x5A */
+ uint16_t marker;
+} __attribute__ ((gcc_struct, __packed__));
+
+struct fat_fsinfo {
+ uint32_t leadsig; /* 0x41615252 */
+ uint8_t reserved1[480];
+ uint32_t strucsig; /* 0x61417272 */
+ uint32_t freecnt; /* free clusters 0xfffffffff if unknown */
+ uint32_t nextfree; /* next free cluster */
+ uint8_t reserved3[12];
+ uint32_t magic3; /* 0xAA550000 */
+} __attribute__ ((gcc_struct, __packed__));
+
+struct msdos_dir_entry {
+ int8_t name[8]; /* 00 name and extension */
+ int8_t ext[3];
+ uint8_t attr; /* 0B attribute bits */
+ uint8_t lcase; /* 0C Case for base and extension */
+ uint8_t ctime_ms; /* 0D Creation time, milliseconds */
+ uint16_t ctime; /* 0E Creation time */
+ uint16_t cdate; /* 10 Creation date */
+ uint16_t adate; /* 12 Last access date */
+ uint16_t starthi; /* 14 High 16 bits of cluster in FAT32 */
+ uint16_t time; /* 16 time, date and first cluster */
+ uint16_t date; /* 18 */
+ uint16_t start; /* 1A */
+ uint32_t size; /* 1C file size (in bytes) */
+} __attribute__ ((gcc_struct, __packed__));
+
+/* Up to 13 characters of the name */
+struct msdos_dir_slot {
+ uint8_t id; /* 00 sequence number for slot */
+ uint8_t name0_4[10]; /* 01 first 5 characters in name */
+ uint8_t attr; /* 0B attribute byte */
+ uint8_t reserved; /* 0C always 0 */
+ uint8_t alias_checksum; /* 0D checksum for 8.3 alias */
+ uint8_t name5_10[12]; /* 0E 6 more characters in name */
+ uint16_t start; /* 1A starting cluster number, 0 in long slots */
+ uint8_t name11_12[4]; /* 1C last 2 characters in name */
+};
+
+
+/*@
+ @ requires \valid_read(entry);
+ @ assigns \nothing;
+ @ */
unsigned int fat_get_cluster_from_entry(const struct msdos_dir_entry *entry);
+
+/*@
+ @ requires \valid_read(buffer + (0 .. 0x40-1));
+ @ assigns \nothing;
+ @ */
int is_fat_directory(const unsigned char *buffer);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int get_dir_entries(const struct fat_boot_sector *fat_header);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int fat_sector_size(const struct fat_boot_sector *fat_header);
+
+/*@
+ @ requires \valid_read(fat_header);
+ @ assigns \nothing;
+ @ */
unsigned int fat_sectors(const struct fat_boot_sector *fat_header);
#ifdef __cplusplus
diff --git a/src/fat_dir.c b/src/fat_dir.c
index 3c9c171..02a327b 100644
--- a/src/fat_dir.c
+++ b/src/fat_dir.c
@@ -57,7 +57,6 @@ struct fat_dir_struct
static int fat1x_rootdir(disk_t *disk_car, const partition_t *partition, const dir_data_t *dir_data, const struct fat_boot_sector*fat_header, file_info_t *dir_list);
-static int fat_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int first_cluster, file_info_t *dir_list);
static inline void fat16_towchar(wchar_t *dst, const uint8_t *src, size_t len);
static int fat_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file);
static void dir_partition_fat_close(dir_data_t *dir_data);
diff --git a/src/fat_dir.h b/src/fat_dir.h
index 4988260..c6cd24b 100644
--- a/src/fat_dir.h
+++ b/src/fat_dir.h
@@ -22,6 +22,7 @@
#ifdef __cplusplus
extern "C" {
#endif
+#include "dir_common.h"
int dir_fat_aux(const unsigned char*buffer, const unsigned int size, const unsigned int param, file_info_t *dir_list);
dir_partition_t dir_partition_fat_init(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const int verbose);
diff --git a/src/fat_unformat.c b/src/fat_unformat.c
index 4cf6a83..885ecda 100644
--- a/src/fat_unformat.c
+++ b/src/fat_unformat.c
@@ -55,8 +55,10 @@
#include "fat_common.h"
#include <assert.h>
+extern int need_to_stop;
+
#define READ_SIZE 4*1024*1024
-static int pfind_sectors_per_cluster(disk_t *disk, partition_t *partition, const int verbose, unsigned int *sectors_per_cluster, uint64_t *offset_org, alloc_data_t *list_search_space)
+static int pfind_sectors_per_cluster(disk_t *disk, const partition_t *partition, const int verbose, unsigned int *sectors_per_cluster, uint64_t *offset_org, alloc_data_t *list_search_space)
{
uint64_t offset=0;
uint64_t next_offset=0;
@@ -386,6 +388,13 @@ static pstatus_t fat_unformat_aux(struct ph_param *params, const struct ph_optio
}
}
#endif
+ if(need_to_stop!=0)
+ {
+ log_info("PhotoRec has been stopped\n");
+ params->offset=offset;
+ offset = offset_end;
+ ind_stop=PSTATUS_STOP;
+ }
}
}
free(buffer_start);
diff --git a/src/fatn.c b/src/fatn.c
index f86a704..c1ccf4f 100644
--- a/src/fatn.c
+++ b/src/fatn.c
@@ -32,7 +32,6 @@
#include "intrfn.h"
#include "fat.h"
#include "fatn.h"
-#include "fat_common.h"
int dump_fat_info_ncurses(const struct fat_boot_sector*fh1, const upart_type_t upart_type, const unsigned int sector_size)
{
diff --git a/src/fidentify.c b/src/fidentify.c
index 310bb42..e345273 100644
--- a/src/fidentify.c
+++ b/src/fidentify.c
@@ -24,6 +24,11 @@
#include <config.h>
#endif
+#ifdef __FRAMAC__
+#undef HAVE_FTELLO
+#undef HAVE_DUP2
+#endif
+
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
@@ -52,13 +57,21 @@
#include "misc.h"
#include "file_jpg.h"
#include "file_gz.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
-extern file_enable_t list_file_enable[];
+extern file_enable_t array_file_enable[];
extern file_check_list_t file_check_list;
#define READ_SIZE 1024*512
+#define OPT_CHECK 1
+#define OPT_TIME 2
-static int file_identify(const char *filename, const unsigned int check)
+/*@
+ @ requires valid_read_string(filename);
+ @*/
+static int file_identify(const char *filename, const unsigned int options)
{
const unsigned int blocksize=65536;
const unsigned int buffer_size=blocksize + READ_SIZE;
@@ -79,21 +92,31 @@ static int file_identify(const char *filename, const unsigned int check)
}
if(fread(buffer, 1, READ_SIZE, file) >0)
{
- struct td_list_head *tmpl;
+ const struct td_list_head *tmpl;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, READ_SIZE);
+#endif
reset_file_recovery(&file_recovery);
+ reset_file_recovery(&file_recovery_new);
file_recovery.blocksize=blocksize;
file_recovery_new.blocksize=blocksize;
- file_recovery_new.file_stat=NULL;
+ /*@ assert file_recovery_new.file_stat==NULL; */
td_list_for_each(tmpl, &file_check_list.list)
{
- struct td_list_head *tmp;
+ const struct td_list_head *tmp;
const file_check_list_t *pos=td_list_entry_const(tmpl, const file_check_list_t, list);
- td_list_for_each(tmp, &pos->file_checks[buffer[pos->offset]].list)
+ const struct td_list_head *tmp_list=&pos->file_checks[buffer[pos->offset]].list;
+ td_list_for_each(tmp, tmp_list)
{
+ /*TODO assert tmp!=tmp_list; */
const file_check_t *file_check=td_list_entry_const(tmp, const file_check_t, list);
- if((file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) &&
+ if(
+#ifdef __FRAMAC__
+ file_check->header_check!=NULL &&
+#endif
+ (file_check->length==0 || memcmp(buffer + file_check->offset, file_check->value, file_check->length)==0) &&
file_check->header_check(buffer, blocksize, 0, &file_recovery, &file_recovery_new)!=0)
{
file_recovery_new.file_stat=file_check->file_stat;
@@ -103,16 +126,25 @@ static int file_identify(const char *filename, const unsigned int check)
if(file_recovery_new.file_stat!=NULL)
break;
}
- if(file_recovery_new.file_stat!=NULL && file_recovery_new.file_stat->file_hint!=NULL &&
- check > 0 && file_recovery_new.file_check!=NULL)
+ if(file_recovery_new.file_stat!=NULL &&
+ file_recovery_new.file_stat->file_hint!=NULL &&
+ file_recovery_new.file_check!=NULL &&
+#ifdef __FRAMAC__
+ file_recovery_new.extension != NULL &&
+#endif
+ ((options&OPT_CHECK)!=0 || ((options&OPT_TIME)!=0 && file_recovery_new.time==0))
+ )
{
+ off_t file_size;
+ /*@ assert valid_read_string(file_recovery_new.extension); */
file_recovery_new.handle=file;
my_fseek(file_recovery_new.handle, 0, SEEK_END);
-#ifdef HAVE_FTELLO
- file_recovery_new.file_size=ftello(file_recovery_new.handle);
+#if defined(HAVE_FTELLO)
+ file_size=ftello(file_recovery_new.handle);
#else
- file_recovery_new.file_size=ftell(file_recovery_new.handle);
+ file_size=ftell(file_recovery_new.handle);
#endif
+ file_recovery_new.file_size=(file_size==-1?0:file_size);
file_recovery_new.calculated_file_size=file_recovery_new.file_size;
(file_recovery_new.file_check)(&file_recovery_new);
if(file_recovery_new.file_size < file_recovery_new.min_filesize)
@@ -125,8 +157,27 @@ static int file_identify(const char *filename, const unsigned int check)
printf("%s: %s", filename,
((file_recovery_new.extension!=NULL && file_recovery_new.extension[0]!='\0')?
file_recovery_new.extension:file_recovery_new.file_stat->file_hint->description));
- if(check > 0 && file_recovery_new.file_check!=NULL)
+ if((options&OPT_CHECK)!=0 && file_recovery_new.file_check!=NULL)
printf(" file_size=%llu", (long long unsigned)file_recovery_new.file_size);
+ if((options&OPT_TIME)!=0 && file_recovery_new.time!=0 && file_recovery_new.time!=(time_t)-1)
+#ifdef __FRAMAC__
+ {
+ printf(" time=%lld", (long long)file_recovery_new.time);
+ }
+#else
+ {
+ char outstr[200];
+#if defined(__MINGW32__) || defined(__FRAMAC__)
+ const struct tm *tmp = localtime(&file_recovery_new.time);
+#else
+ struct tm tm_tmp;
+ const struct tm *tmp = localtime_r(&file_recovery_new.time,&tm_tmp);
+#endif
+ if(tmp != NULL &&
+ strftime(outstr, sizeof(outstr), "%Y-%m-%dT%H:%M:%S%z", tmp) != 0)
+ printf(" time=%s", &outstr[0]);
+ }
+#endif
printf("\n");
}
else
@@ -140,8 +191,8 @@ static int file_identify(const char *filename, const unsigned int check)
return 0;
}
-#ifndef __AFL_COMPILER
-static void file_identify_dir(const char *current_dir, const unsigned int check)
+#if !defined(__AFL_COMPILER) && !defined(MAIN_fidentify)
+static void file_identify_dir(const char *current_dir, const unsigned int options)
{
DIR *dir;
struct dirent *entry;
@@ -164,9 +215,9 @@ static void file_identify_dir(const char *current_dir, const unsigned int check)
#endif
{
if(S_ISDIR(buf_stat.st_mode))
- file_identify_dir(current_file, check);
+ file_identify_dir(current_file, options);
else if(S_ISREG(buf_stat.st_mode))
- file_identify(current_file, check);
+ file_identify(current_file, options);
}
free(current_file);
}
@@ -193,25 +244,36 @@ static void display_version(void)
#ifdef RECORD_COMPILATION_DATE
printf("Compilation date: %s\n", get_compilation_date());
#endif
+#ifndef MAIN_fidentify
printf("libjpeg: %s, zlib: %s\n", td_jpeg_version(), td_zlib_version());
printf("OS: %s\n" , get_os());
+#endif
}
int main(int argc, char **argv)
{
int i;
- unsigned int check=0;
+#ifdef MAIN_fidentify
+ unsigned int options=OPT_CHECK|OPT_TIME;
+#else
+ unsigned int options=0;
+#endif
FILE *log_handle=NULL;
int log_errno=0;
int enable_all_formats=1;
int scan_dir=1;
file_stat_t *file_stats;
log_set_levels(LOG_LEVEL_DEBUG|LOG_LEVEL_TRACE|LOG_LEVEL_QUIET|LOG_LEVEL_INFO|LOG_LEVEL_VERBOSE|LOG_LEVEL_PROGRESS|LOG_LEVEL_WARNING|LOG_LEVEL_ERROR|LOG_LEVEL_PERROR|LOG_LEVEL_CRITICAL);
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
if( strcmp(argv[i], "/check")==0 || strcmp(argv[i], "-check")==0 || strcmp(argv[i], "--check")==0)
{
- check++;
+ options|=OPT_CHECK;
+ }
+ if( strcmp(argv[i], "/time")==0 || strcmp(argv[i], "-time")==0 || strcmp(argv[i], "--time")==0)
+ {
+ options|=OPT_TIME;
}
else if(strcmp(argv[i],"/help")==0 || strcmp(argv[i],"-help")==0 || strcmp(argv[i],"--help")==0 ||
strcmp(argv[i],"/h")==0 || strcmp(argv[i],"-h")==0 ||
@@ -227,28 +289,32 @@ int main(int argc, char **argv)
return 0;
}
}
+#endif
#ifndef __AFL_COMPILER
log_handle=log_open("fidentify.log", TD_LOG_CREATE, &log_errno);
if(log_handle!=NULL)
{
time_t my_time;
-#ifdef HAVE_DUP2
+#if defined(HAVE_DUP2)
dup2(fileno(log_handle),2);
#endif
my_time=time(NULL);
log_info("\n\n%s",ctime(&my_time));
log_info("Command line: fidentify");
+#ifndef MAIN_fidentify
for(i=1;i<argc;i++)
log_info(" %s", argv[i]);
+#endif
log_info("\n\n");
log_flush();
}
log_info("fidentify %s, Data Recovery Utility, %s\nChristophe GRENIER <grenier@cgsecurity.org>\nhttps://www.cgsecurity.org\n", VERSION, TESTDISKDATE);
#endif
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
file_enable_t *file_enable;
- for(file_enable=list_file_enable;file_enable->file_hint!=NULL;file_enable++)
+ for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++)
if(argv[i][0]=='+' &&
file_enable->file_hint->extension!=NULL &&
strcmp(file_enable->file_hint->extension,&argv[i][1])==0)
@@ -257,17 +323,20 @@ int main(int argc, char **argv)
enable_all_formats=0;
}
}
+#endif
if(enable_all_formats)
{
/* Enable all file formats */
file_enable_t *file_enable;
- for(file_enable=list_file_enable;file_enable->file_hint!=NULL;file_enable++)
+ for(file_enable=array_file_enable;file_enable->file_hint!=NULL;file_enable++)
file_enable->enable=1;
}
- file_stats=init_file_stats(list_file_enable);
+ file_stats=init_file_stats(array_file_enable);
+#ifndef MAIN_fidentify
for(i=1; i<argc; i++)
{
if(strcmp(argv[i], "/check")==0 || strcmp(argv[i], "-check")==0 || strcmp(argv[i], "--check")==0 ||
+ strcmp(argv[i], "/time")==0 || strcmp(argv[i], "-time")==0 || strcmp(argv[i], "--time")==0 ||
argv[i][0]=='+')
{
}
@@ -282,17 +351,20 @@ int main(int argc, char **argv)
#endif
{
if(S_ISREG(buf_stat.st_mode))
- file_identify(argv[i], check);
+ file_identify(argv[i], options);
#ifndef __AFL_COMPILER
else if(S_ISDIR(buf_stat.st_mode))
- file_identify_dir(argv[i], check);
+ file_identify_dir(argv[i], options);
#endif
}
}
}
#ifndef __AFL_COMPILER
if(scan_dir)
- file_identify_dir(".", check);
+ file_identify_dir(".", options);
+#endif
+#else
+ file_identify("demo", options);
#endif
free_header_check();
free(file_stats);
diff --git a/src/file_1cd.c b/src/file_1cd.c
index 24a5487..af153d8 100644
--- a/src/file_1cd.c
+++ b/src/file_1cd.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_1cd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,7 +57,7 @@ static int header_check_1cd(const unsigned char *buffer, const unsigned int buff
return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_1cd.extension;
- file_recovery_new->calculated_file_size=le32(hdr->size)<<12;
+ file_recovery_new->calculated_file_size=((uint64_t)le32(hdr->size))<<12;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
return 1;
@@ -67,3 +68,4 @@ static void register_header_check_1cd(file_stat_t *file_stat)
static const unsigned char header_1cd[9]= { '1', 'C', 'D', 'B', 'M', 'S', 'V', '8', 0x08 };
register_header_check(0, header_1cd, sizeof(header_1cd), &header_check_1cd, file_stat);
}
+#endif
diff --git a/src/file_3dm.c b/src/file_3dm.c
index dc1241e..1c9957b 100644
--- a/src/file_3dm.c
+++ b/src/file_3dm.c
@@ -3,23 +3,24 @@
File: file_3dm.c
Copyright (C) 2013 Christophe GRENIER <grenier@cgsecurity.org>
-
+
This software is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License along
with this program; if not, write the Free Software Foundation, Inc., 51
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_3dm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,3 +59,4 @@ static void register_header_check_3dm(file_stat_t *file_stat)
{
register_header_check(0, "3D Geometry File Format ", 24, &header_check_3dm, file_stat);
}
+#endif
diff --git a/src/file_3ds.c b/src/file_3ds.c
new file mode 100644
index 0000000..ee23943
--- /dev/null
+++ b/src/file_3ds.c
@@ -0,0 +1,76 @@
+/*
+
+ File: file_3ds.c
+
+ Copyright (C) 2019 Christophe GRENIER <grenier@cgsecurity.org>
+
+ This software is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ */
+
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_3ds)
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <stdio.h>
+#include "types.h"
+#include "filegen.h"
+#include "common.h"
+
+static void register_header_check_3ds(file_stat_t *file_stat);
+
+const file_hint_t file_hint_3ds= {
+ .extension="3ds",
+ .description="3d Studio",
+ .max_filesize=PHOTOREC_MAX_FILE_SIZE,
+ .recover=1,
+ .enable_by_default=1,
+ .register_header_check=&register_header_check_3ds
+};
+
+struct chunk_3ds
+{
+ uint16_t chunk_id;
+ uint32_t next_chunk;
+} __attribute__ ((gcc_struct, __packed__));
+
+static int header_check_3ds(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+{
+ uint64_t fs;
+ const struct chunk_3ds *hdr=(const struct chunk_3ds *)buffer;
+ if(buffer_size < 0x12)
+ return 0;
+ if(buffer[0]!=0x4d || buffer[1]!=0x4d || buffer[0x10]!=0x3d || buffer[0x11]!=0x3d)
+ return 0;
+ fs=le32(hdr->next_chunk);
+ if(fs <= 0x12)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_3ds.extension;
+ file_recovery_new->calculated_file_size=fs;
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ return 1;
+}
+
+static void register_header_check_3ds(file_stat_t *file_stat)
+{
+ static const unsigned char header_3ds[4]= { 0x02, 0x00, 0x0a, 0x00 };
+ register_header_check(6, header_3ds, sizeof(header_3ds), &header_check_3ds, file_stat);
+}
+#endif
diff --git a/src/file_7z.c b/src/file_7z.c
index bb9675d..583586d 100644
--- a/src/file_7z.c
+++ b/src/file_7z.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_7z)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,6 +59,9 @@ static int header_check_7z(const unsigned char *buffer, const unsigned int buffe
if(buffer_7z->majorversion!=0 ||
le64(buffer_7z->nextHeaderSize)==0)
return 0;
+ if( le64(buffer_7z->nextHeaderOffset) > 0x7000000000000000 ||
+ le64(buffer_7z->nextHeaderSize) > 0x7000000000000000)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_7z.extension;
file_recovery_new->min_filesize=31;
@@ -74,3 +78,4 @@ static void register_header_check_7z(file_stat_t *file_stat)
static const unsigned char header_7z[6] = {'7','z', 0xbc, 0xaf, 0x27, 0x1c};
register_header_check(0, header_7z, sizeof(header_7z), &header_check_7z, file_stat);
}
+#endif
diff --git a/src/file_DB.c b/src/file_DB.c
index c9a7a42..46d6bca 100644
--- a/src/file_DB.c
+++ b/src/file_DB.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_DB)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_DB(file_stat_t *file_stat)
};
register_header_check(0, DB_header,sizeof(DB_header), &header_check_DB, file_stat);
}
+#endif
diff --git a/src/file_a.c b/src/file_a.c
index 47a606c..f0cac6e 100644
--- a/src/file_a.c
+++ b/src/file_a.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_a)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -73,3 +74,4 @@ static void register_header_check_a(file_stat_t *file_stat)
static const unsigned char a_header[8] = { '!','<','a','r','c','h','>','\n'};
register_header_check(0, a_header,sizeof(a_header), &header_check_a, file_stat);
}
+#endif
diff --git a/src/file_ab.c b/src/file_ab.c
index e6e7381..011e675 100644
--- a/src/file_ab.c
+++ b/src/file_ab.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_addressbook)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -46,8 +47,21 @@ struct ab_header
uint32_t size;
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_ab;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_addressbook(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
@@ -92,3 +106,4 @@ static void register_header_check_ab(file_stat_t *file_stat)
static const unsigned char ab_header[2]={ 'L', 'J' };
register_header_check(0, ab_header,sizeof(ab_header), &header_check_addressbook, file_stat);
}
+#endif
diff --git a/src/file_abr.c b/src/file_abr.c
index 5d07f92..6d243ac 100644
--- a/src/file_abr.c
+++ b/src/file_abr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_abr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -49,8 +50,21 @@ const file_hint_t file_hint_abr= {
.register_header_check=&register_header_check_abr
};
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_abr;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_abr(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 12 < file_recovery->file_size + buffer_size/2)
{
@@ -94,3 +108,4 @@ static void register_header_check_abr(file_stat_t *file_stat)
};
register_header_check(2, abr_header, sizeof(abr_header), &header_check_abr, file_stat);
}
+#endif
diff --git a/src/file_acb.c b/src/file_acb.c
index f791fe5..0a0d4a9 100644
--- a/src/file_acb.c
+++ b/src/file_acb.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_acb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,3 +60,4 @@ static void register_header_check_acb(file_stat_t *file_stat)
};
register_header_check(0, acb_header, sizeof(acb_header), &header_check_acb, file_stat);
}
+#endif
diff --git a/src/file_ace.c b/src/file_ace.c
index 582e6ca..075dfde 100644
--- a/src/file_ace.c
+++ b/src/file_ace.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ace)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -32,9 +33,15 @@
#include "common.h"
#include "log.h"
#include "crc.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
/* #define DEBUG_ACE */
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_ace(file_stat_t *file_stat);
const file_hint_t file_hint_ace= {
@@ -61,34 +68,62 @@ struct header_ace {
typedef struct header_ace ace_header_t;
#define BUF_SIZE 4096
+/*@
+ @ requires \valid(handle);
+ @ requires \separated(handle, &errno, &Frama_C_entropy_source);
+ @ assigns *handle, errno;
+ @ assigns Frama_C_entropy_source;
+ @*/
static int check_ace_crc(FILE *handle, const unsigned int len, const unsigned int crc32_low)
{
- unsigned char buffer[BUF_SIZE];
+ char buffer[BUF_SIZE];
uint32_t crc32=0xFFFFFFFF;
unsigned int remaining=len;
+ /*@
+ @ loop assigns *handle, errno;
+ @ loop assigns Frama_C_entropy_source;
+ @ loop assigns buffer[0 .. BUF_SIZE-1], crc32, remaining;
+ @*/
while (remaining>0)
{
const unsigned int count = ((remaining>BUF_SIZE) ? BUF_SIZE : remaining);
if(fread(buffer, 1, count, handle) != count)
{
#ifdef DEBUG_ACE
- log_trace("file_ace: truncated file\n");
+ log_info("file_ace: truncated file\n");
#endif
return 1;
}
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&buffer, sizeof(buffer));
+#endif
crc32=get_crc32(buffer, count, crc32);
remaining -= count;
}
if (crc32_low != (crc32&0xFFFF))
{
#ifdef DEBUG_ACE
- log_trace("file_ace: bad CRC: %04X vs %04X\n", crc32_low, crc32&0xFFFF);
+ log_info("file_ace: bad CRC: %04X vs %04X\n", crc32_low, crc32&0xFFFF);
#endif
return 1;
}
return 0;
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires \valid_read(&file_recovery->extension);
+ @ requires valid_read_string(file_recovery->extension);
+ @ requires \separated(file_recovery, file_recovery->handle, file_recovery->extension, &errno, &Frama_C_entropy_source);
+ @ requires \initialized(&file_recovery->time);
+ @
+ @ requires file_recovery->file_check == &file_check_ace;
+ @ assigns *file_recovery->handle, errno, file_recovery->file_size, file_recovery->offset_error, file_recovery->offset_ok;
+ @ assigns Frama_C_entropy_source;
+ @
+ @ ensures \valid(file_recovery->handle);
+ @*/
static void file_check_ace(file_recovery_t *file_recovery)
{
file_recovery->offset_error = 0;
@@ -96,58 +131,52 @@ static void file_check_ace(file_recovery_t *file_recovery)
file_recovery->file_size = 0;
if(my_fseek(file_recovery->handle, 0, SEEK_SET)<0)
return ;
-#ifdef DEBUG_ACE
- log_trace("file_check_ace\n");
-#endif
+ /*@
+ @ loop assigns *file_recovery->handle, errno, file_recovery->file_size, file_recovery->offset_error;
+ @ loop assigns Frama_C_entropy_source;
+ @*/
while (!feof(file_recovery->handle))
{
- ace_header_t h;
- size_t res;
- memset(&h, 0, sizeof(h));
- res=fread(&h, 1, sizeof(h), file_recovery->handle);
- if(res==0)
- return ;
- if(res != sizeof(h))
+ char buffer[sizeof(ace_header_t)];
+ const ace_header_t *h=(const ace_header_t *)&buffer;
+ if(fread(&buffer, sizeof(buffer), 1, file_recovery->handle)!= 1)
{
- file_recovery->offset_error=file_recovery->file_size;
- file_recovery->file_size=0;
return ;
}
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&buffer, sizeof(buffer));
+#endif
#ifdef DEBUG_ACE
- log_trace("file_ace: Block header at 0x%08lx: CRC16=0x%04X size=%u type=%u"
+ log_info("file_ace: Block header at 0x%08lx: CRC16=0x%04X size=%u type=%u"
" flags=0x%04X addsize=%u\n",
(long unsigned) file_recovery->file_size,
- le16(h.crc16), le16(h.size), h.type, le16(h.flags),
- (le16(h.flags)&1) ? le32(h.addsize):0);
+ le16(h->crc16), le16(h->size), h->type, le16(h->flags),
+ (le16(h->flags)&1) ? le32(h->addsize):0);
#endif
/* Type 0=Archive header, 1=File block, 2=Recovery Record, 5 new_recovery ? */
- if (h.type==0 && le16(h.size)==0)
+ if (h->type==0 && le16(h->size)==0)
{
return ;
}
- if (h.type!=0 && h.type!=1 && h.type!=2 && h.type!=5)
+ if (h->type!=0 && h->type!=1 && h->type!=2 && h->type!=5)
{
#ifdef DEBUG_ACE
- log_trace("file_ace: Invalid block type %u\n", h.type);
+ log_info("file_ace: Invalid block type %u\n", h->type);
#endif
- file_recovery->offset_error=file_recovery->file_size;
- file_recovery->file_size=0;
return ;
}
/* Minimal size is type+flags */
- if (le16(h.size) < 1U + 2U)
+ if (le16(h->size) < 1U + 2U)
{
#ifdef DEBUG_ACE
- log_trace("file_ace: Invalid block size %u\n", le16(h.size));
+ log_info("file_ace: Invalid block size %u\n", le16(h->size));
#endif
- file_recovery->offset_error=file_recovery->file_size;
- file_recovery->file_size=0;
return ;
}
- if(my_fseek(file_recovery->handle, -sizeof(h)+4, SEEK_CUR)<0 ||
- check_ace_crc(file_recovery->handle, le16(h.size), le16(h.crc16)) != 0)
+ if(my_fseek(file_recovery->handle, -(off_t)sizeof(ace_header_t)+(off_t)4, SEEK_CUR)<0 ||
+ check_ace_crc(file_recovery->handle, le16(h->size), le16(h->crc16)) != 0)
{
file_recovery->offset_error=file_recovery->file_size;
file_recovery->file_size=0;
@@ -155,11 +184,17 @@ static void file_check_ace(file_recovery_t *file_recovery)
}
/* Add its header size */
- file_recovery->file_size += (uint64_t)4 + le16(h.size); /* +2: CRC16, +2: size */
+ file_recovery->file_size += (uint64_t)4 + le16(h->size); /* +2: CRC16, +2: size */
+
+ if(file_recovery->file_size >= 0x8000000000000000-0x100000000)
+ {
+ file_recovery->file_size=0;
+ return ;
+ }
/* If addsize flag, add complementary size */
- if (le16(h.flags)&1)
+ if (le16(h->flags)&1)
{
- file_recovery->file_size += le32(h.addsize);
+ file_recovery->file_size += le32(h->addsize);
if(my_fseek(file_recovery->handle, file_recovery->file_size, SEEK_SET)<0)
{
file_recovery->offset_error=file_recovery->file_size;
@@ -170,6 +205,36 @@ static void file_check_ace(file_recovery_t *file_recovery)
}
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= sizeof(ace_header_t);
+ @ requires separation: \separated(&file_hint_ace, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_ace.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_ace);
+ @*/
static int header_check_ace(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const ace_header_t *h=(const ace_header_t *)buffer;
@@ -193,3 +258,4 @@ static void register_header_check_ace(file_stat_t *file_stat)
static const unsigned char ace_header[7] = { '*','*','A','C','E','*','*'};
register_header_check(7, ace_header,sizeof(ace_header), &header_check_ace, file_stat);
}
+#endif
diff --git a/src/file_ado.c b/src/file_ado.c
index 74c9632..6739505 100644
--- a/src/file_ado.c
+++ b/src/file_ado.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ado)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_ado(file_stat_t *file_stat)
{
register_header_check(0x2c, "\5Black\0\0", 8, &header_check_ado, file_stat);
}
+#endif
diff --git a/src/file_afdesign.c b/src/file_afdesign.c
index af93b7c..c13d6b5 100644
--- a/src/file_afdesign.c
+++ b/src/file_afdesign.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_afdesign)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -76,3 +77,4 @@ static void register_header_check_afdesign(file_stat_t *file_stat)
static const unsigned char afdesign_header[4]= { 0x00, 0xff, 'K' , 'A' };
register_header_check(0, afdesign_header, sizeof(afdesign_header), &header_check_afdesign, file_stat);
}
+#endif
diff --git a/src/file_ahn.c b/src/file_ahn.c
index 8112322..f490ee5 100644
--- a/src/file_ahn.c
+++ b/src/file_ahn.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ahn)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_ahn(file_stat_t *file_stat)
static const unsigned char ahn_magic[10] = {'A','H','N','E','N','B','L','A','T','T'};
register_header_check(8, ahn_magic, sizeof(ahn_magic), &header_check_ahn, file_stat);
}
+#endif
diff --git a/src/file_aif.c b/src/file_aif.c
index 5504f22..69a06d4 100644
--- a/src/file_aif.c
+++ b/src/file_aif.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_aif)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -79,3 +80,4 @@ static void register_header_check_aif(file_stat_t *file_stat)
{
register_header_check(0, "FORM", 4, &header_check_aif, file_stat);
}
+#endif
diff --git a/src/file_all.c b/src/file_all.c
index de7b0ac..9972f25 100644
--- a/src/file_all.c
+++ b/src/file_all.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_all)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_all(file_stat_t *file_stat)
static const unsigned char all_header[8]= { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x06, 0x04};
register_header_check(0, all_header,sizeof(all_header), &header_check_all, file_stat);
}
+#endif
diff --git a/src/file_als.c b/src/file_als.c
index 5082331..c915341 100644
--- a/src/file_als.c
+++ b/src/file_als.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_als)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -76,3 +77,4 @@ static void register_header_check_als(file_stat_t *file_stat)
};
register_header_check(0, als_header,sizeof(als_header), &header_check_als, file_stat);
}
+#endif
diff --git a/src/file_amd.c b/src/file_amd.c
index 53f6885..cf7d203 100644
--- a/src/file_amd.c
+++ b/src/file_amd.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_amd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -84,3 +85,4 @@ static void register_header_check_amd(file_stat_t *file_stat)
register_header_check(0, amd_header,sizeof(amd_header), &header_check_amd, file_stat);
register_header_check(0, amt_header,sizeof(amt_header), &header_check_amt, file_stat);
}
+#endif
diff --git a/src/file_amr.c b/src/file_amr.c
index a5ec01c..ac1c132 100644
--- a/src/file_amr.c
+++ b/src/file_amr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_amr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -43,8 +44,21 @@ const file_hint_t file_hint_amr= {
.register_header_check=&register_header_check_amr
};
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_amr;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_amr(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 4 < file_recovery->file_size + buffer_size/2)
{
@@ -94,3 +108,4 @@ static void register_header_check_amr(file_stat_t *file_stat)
static const unsigned char amr_header[6]= {'#','!','A','M','R','\n'};
register_header_check(0, amr_header,sizeof(amr_header), &header_check_amr, file_stat);
}
+#endif
diff --git a/src/file_apa.c b/src/file_apa.c
index fc47582..88648fb 100644
--- a/src/file_apa.c
+++ b/src/file_apa.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_apa)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -62,3 +63,4 @@ static int header_check_apa(const unsigned char *buffer, const unsigned int buff
}
return 0;
}
+#endif
diff --git a/src/file_ape.c b/src/file_ape.c
index c013880..b30c52a 100644
--- a/src/file_ape.c
+++ b/src/file_ape.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ape)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -139,3 +140,4 @@ static void register_header_check_ape(file_stat_t *file_stat)
static const unsigned char ape_header[4]= { 'M', 'A', 'C', ' '};
register_header_check(0, ape_header,sizeof(ape_header), &header_check_ape, file_stat);
}
+#endif
diff --git a/src/file_apple.c b/src/file_apple.c
index de63f33..1612ebc 100644
--- a/src/file_apple.c
+++ b/src/file_apple.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_apple)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_apple(file_stat_t *file_stat)
};
register_header_check(0, apple_header,sizeof(apple_header), &header_check_apple, file_stat);
}
+#endif
diff --git a/src/file_ari.c b/src/file_ari.c
index fbe99b6..cc17ef1 100644
--- a/src/file_ari.c
+++ b/src/file_ari.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ari)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -74,3 +75,4 @@ static void register_header_check_ari(file_stat_t *file_stat)
0x00, 0x10, 0x00, 0x00};
register_header_check(0, ari_header, sizeof(ari_header), &header_check_ari, file_stat);
}
+#endif
diff --git a/src/file_arj.c b/src/file_arj.c
index 9bf2c1e..62bf5d0 100644
--- a/src/file_arj.c
+++ b/src/file_arj.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_arj)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -162,3 +163,4 @@ static void register_header_check_arj(file_stat_t *file_stat)
static const unsigned char arj_header[2]={0x60, 0xEA};
register_header_check(0, arj_header,sizeof(arj_header), &header_check_arj, file_stat);
}
+#endif
diff --git a/src/file_asf.c b/src/file_asf.c
index 8f96d2a..0598f1e 100644
--- a/src/file_asf.c
+++ b/src/file_asf.c
@@ -32,6 +32,7 @@
#include "common.h"
#include "log.h"
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asf)
static void register_header_check_asf(file_stat_t *file_stat);
static int header_check_asf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
@@ -66,24 +67,29 @@ struct asf_stream_prop_s {
unsigned char stream_type[16];
} __attribute__ ((gcc_struct, __packed__));
+static const char *extension_wma="wma";
+static const char *extension_wmv="wmv";
+
static int header_check_asf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct asf_header_obj_s *hdr=(const struct asf_header_obj_s*)buffer;
- unsigned int i;
- const struct asf_file_prop_s *prop=(const struct asf_file_prop_s*)(hdr+1);
+ const char *extension=file_hint_asf.extension;
+ const unsigned int nbr_header_obj=le32(hdr->nbr_header_obj);
uint64_t size=0;
time_t time=0;
- const char *extension=file_hint_asf.extension;
+ unsigned int i;
+ uint64_t offset_prop=sizeof(struct asf_header_obj_s);
/* Header + File Properties + Stream Properties + Header Extension */
if(le64(hdr->object_size)<30 ||
le64(hdr->object_size)>buffer_size ||
- le32(hdr->nbr_header_obj)<4)
+ nbr_header_obj<4)
return 0;
for(i=0;
- i<le32(hdr->nbr_header_obj) &&
- (const unsigned char *)prop+0x28 < buffer + buffer_size;
- i++, prop=(const struct asf_file_prop_s *)((const char *)prop + le64(prop->object_size)))
+ i < nbr_header_obj && offset_prop + 0x28 < buffer_size;
+ i++)
{
+ const struct asf_file_prop_s *prop=(const struct asf_file_prop_s*)&buffer[offset_prop];
+ const uint64_t object_size=le64(prop->object_size);
// ASF_File_Properties_Object // 8CABDCA1-A947-11CF-8EE4-00C00C205365
// ASF_Stream_Properties_Object // B7DC0791-A9B7-11CF-8EE6-00C00C205365
static const unsigned char asf_file_prop_id[16]= {
@@ -94,18 +100,20 @@ static int header_check_asf(const unsigned char *buffer, const unsigned int buff
0x91, 0x07, 0xdc, 0xb7, 0xb7, 0xa9, 0xcf, 0x11,
0x8e, 0xe6, 0x00, 0xc0, 0x0c, 0x20, 0x53, 0x65
};
- if(le64(prop->object_size) < 0x18)
+ if(object_size < 0x18)
{
- log_info("header_check_asf object_size too small %llu\n", (long long unsigned)le64(prop->object_size));
+ log_info("header_check_asf object_size too small %llu\n", (long long unsigned)object_size);
return 0;
}
+ if(object_size > 0x8000000000000000)
+ return 0;
if(memcmp(prop->object_id, asf_file_prop_id, sizeof(asf_file_prop_id))==0)
{
- if(le64(prop->object_size) < 0x28)
- return 0;
- if(le64(prop->file_size) < sizeof(struct asf_header_obj_s) + sizeof(struct asf_file_prop_s))
+ if(object_size < 0x28)
return 0;
size=le64(prop->file_size);
+ if(size < sizeof(struct asf_header_obj_s) + sizeof(struct asf_file_prop_s))
+ return 0;
time=td_ntfs2utc(le64(prop->file_date));
}
else if(memcmp(prop->object_id, asf_stream_prop_s, sizeof(asf_stream_prop_s))==0)
@@ -117,25 +125,27 @@ static int header_check_asf(const unsigned char *buffer, const unsigned int buff
const char wmv[16]={
0xc0, 0xef, 0x19, 0xbc, 0x4d, 0x5b, 0xcf, 0x11, 0xa8, 0xfd, 0x00, 0x80, 0x5f, 0x5c, 0x44, 0x2b
};
- if(le64(prop->object_size) < 0x28)
+ if(object_size < 0x28)
return 0;
if(memcmp(stream->stream_type, wma, sizeof(wma))==0)
- extension="wma";
+ extension=extension_wma;
else if(memcmp(stream->stream_type, wmv, sizeof(wmv))==0)
- extension="wmv";
+ extension=extension_wmv;
}
- if(le64(prop->object_size) > buffer_size)
- break;
+ offset_prop+=object_size;
}
+ if(size > 0 && size < offset_prop)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=extension;
+ file_recovery_new->min_filesize=offset_prop;
+ file_recovery_new->time=time;
if(size > 0)
{
- file_recovery_new->calculated_file_size=le64(size);
+ file_recovery_new->calculated_file_size=size;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
}
- file_recovery_new->time=time;
return 1;
}
@@ -147,3 +157,4 @@ static void register_header_check_asf(file_stat_t *file_stat)
};
register_header_check(0, asf_header,sizeof(asf_header), &header_check_asf, file_stat);
}
+#endif
diff --git a/src/file_asl.c b/src/file_asl.c
index 7c541c2..c70b26d 100644
--- a/src/file_asl.c
+++ b/src/file_asl.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asl)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_asl(file_stat_t *file_stat)
};
register_header_check(0, asl_header, sizeof(asl_header), &header_check_asl, file_stat);
}
+#endif
diff --git a/src/file_asm.c b/src/file_asm.c
index 6026c74..71ef2f8 100644
--- a/src/file_asm.c
+++ b/src/file_asm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,10 +32,7 @@
#include "types.h"
#include "filegen.h"
-
static void register_header_check_asm(file_stat_t *file_stat);
-static int header_check_asm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
-static void file_check_asm(file_recovery_t *file_recovery);
const file_hint_t file_hint_asm= {
.extension="asm",
@@ -49,9 +47,12 @@ static const unsigned char asm_header[16]= {
'#', 'U', 'G', 'C', ':', '2', ' ', 'A',
'S', 'S', 'E', 'M', 'B', 'L', 'Y', ' '};
-static void register_header_check_asm(file_stat_t *file_stat)
+static void file_check_asm(file_recovery_t *file_recovery)
{
- register_header_check(0, asm_header,sizeof(asm_header), &header_check_asm, file_stat);
+ const unsigned char asm_footer[11]= {
+ '#', 'E', 'N', 'D', '_', 'O', 'F', '_',
+ 'U', 'G', 'C'};
+ file_search_footer(file_recovery, asm_footer, sizeof(asm_footer), 1);
}
static int header_check_asm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
@@ -64,10 +65,8 @@ static int header_check_asm(const unsigned char *buffer, const unsigned int buff
return 1;
}
-static void file_check_asm(file_recovery_t *file_recovery)
+static void register_header_check_asm(file_stat_t *file_stat)
{
- const unsigned char asm_footer[11]= {
- '#', 'E', 'N', 'D', '_', 'O', 'F', '_',
- 'U', 'G', 'C'};
- file_search_footer(file_recovery, asm_footer, sizeof(asm_footer), 1);
+ register_header_check(0, asm_header,sizeof(asm_header), &header_check_asm, file_stat);
}
+#endif
diff --git a/src/file_atd.c b/src/file_atd.c
index 5478354..409ecb3 100644
--- a/src/file_atd.c
+++ b/src/file_atd.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_atd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_atd(file_stat_t *file_stat)
'D' ,'A' ,'T' ,'A' ,'B' ,'A' ,'S' ,'E' };
register_header_check(0, atd_header,sizeof(atd_header), &header_check_atd, file_stat);
}
+#endif
diff --git a/src/file_au.c b/src/file_au.c
index bab248b..9d51a78 100644
--- a/src/file_au.c
+++ b/src/file_au.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_au)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -85,3 +86,4 @@ static void register_header_check_au(file_stat_t *file_stat)
static const unsigned char au_header[4]= {'.','s','n','d'};
register_header_check(0, au_header,sizeof(au_header), &header_check_au, file_stat);
}
+#endif
diff --git a/src/file_axp.c b/src/file_axp.c
index 349dc5a..3a8d290 100644
--- a/src/file_axp.c
+++ b/src/file_axp.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_axp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -41,6 +42,16 @@ const file_hint_t file_hint_axp= {
.register_header_check=&register_header_check_axp
};
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_axp;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_axp(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
const unsigned char axp_footer[34]= {
@@ -51,6 +62,9 @@ static data_check_t data_check_axp(const unsigned char *buffer, const unsigned i
0x0a, 0
};
unsigned int j;
+ /*@
+ @ loop assigns j;
+ @*/
for(j=(buffer_size/2>sizeof(axp_footer)?buffer_size/2-sizeof(axp_footer):0);
j+sizeof(axp_footer) < buffer_size;
j++)
@@ -94,3 +108,4 @@ static void register_header_check_axp(file_stat_t *file_stat)
};
register_header_check(0, axp_header, sizeof(axp_header), &header_check_axp, file_stat);
}
+#endif
diff --git a/src/file_axx.c b/src/file_axx.c
index bc6bc4a..a1d2a1b 100644
--- a/src/file_axx.c
+++ b/src/file_axx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_axx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,7 +53,7 @@ struct SHeader
static void file_check_axx(file_recovery_t *fr)
{
uint64_t offset=0x10;
- while(1)
+ while(offset < 0x8000000000000000)
{
struct SHeader header;
unsigned int len;
@@ -60,6 +61,9 @@ static void file_check_axx(file_recovery_t *fr)
return ;
if (fread(&header, sizeof(header), 1, fr->handle)!=1)
return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown(&header, sizeof(header));
+#endif
len=le32(header.aoLength);
#ifdef DEBUG_AAX
log_info("axx 0x%llx 0x%x 0x%x/%d\n", (long long int)offset, len, header.oType, header.oType);
@@ -67,6 +71,8 @@ static void file_check_axx(file_recovery_t *fr)
if(len<5)
return ;
offset+=len;
+ if(offset >= 0x8000000000000000)
+ break;
if(header.oType==63) // eData
{
uint64_t fsize;
@@ -74,12 +80,18 @@ static void file_check_axx(file_recovery_t *fr)
return ;
if (fread(&fsize, sizeof(fsize), 1, fr->handle)!=1)
return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown(&fsize, sizeof(fsize));
+#endif
fsize=le64(fsize);
+ if(fsize >= 0x8000000000000000)
+ break;
offset+=fsize;
fr->file_size=(fr->file_size < offset ? 0 : offset);
return ;
}
}
+ fr->file_size=0;
}
static int header_check_axx(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
@@ -90,7 +102,7 @@ static int header_check_axx(const unsigned char *buffer, const unsigned int buff
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_axx.extension;
file_recovery_new->file_check=&file_check_axx;
- file_recovery_new->min_filesize=0x25+le32(header->aoLength);
+ file_recovery_new->min_filesize=(uint64_t)0x25+le32(header->aoLength);
return 1;
}
@@ -104,3 +116,4 @@ static void register_header_check_axx(file_stat_t *file_stat)
};
register_header_check(0, axx_header, sizeof(axx_header), &header_check_axx, file_stat);
}
+#endif
diff --git a/src/file_bac.c b/src/file_bac.c
index e9aada3..c4514f2 100644
--- a/src/file_bac.c
+++ b/src/file_bac.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bac)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -33,6 +34,9 @@
#include "log.h"
#include "memmem.h"
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_bac(file_stat_t *file_stat);
const file_hint_t file_hint_bac= {
@@ -54,6 +58,16 @@ struct block_header
uint32_t VolSessionTime; /* Session Time for Job */
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires buffer_size >= 2*0x18;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_bac;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_bac(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
if(buffer_size < 2*0x18)
@@ -62,6 +76,9 @@ static data_check_t data_check_bac(const unsigned char *buffer, const unsigned i
file_recovery->file_check=NULL;
return DC_CONTINUE;
}
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 0x18 < file_recovery->file_size + buffer_size/2)
{
@@ -76,8 +93,10 @@ static data_check_t data_check_bac(const unsigned char *buffer, const unsigned i
#endif
if(memcmp(hdr->ID, "BB02", 4)!=0 || block_size<0x18)
{
+#ifndef __FRAMAC__
log_error("file_bac.c: invalid block at %llu\n",
(long long unsigned)file_recovery->calculated_file_size);
+#endif
return DC_STOP;
}
file_recovery->calculated_file_size+=(uint64_t)block_size;
@@ -89,6 +108,24 @@ static data_check_t data_check_bac(const unsigned char *buffer, const unsigned i
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size >= sizeof(struct block_header);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_bac, buffer, file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || file_recovery_new->data_check == &data_check_bac);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_bac.extension);
+ @*/
static int header_check_bac(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct block_header *hdr=(const struct block_header *)buffer;
@@ -111,3 +148,4 @@ static void register_header_check_bac(file_stat_t *file_stat)
static const unsigned char bac_header[8]={ 0, 0, 0, 0, 'B', 'B', '0', '2' };
register_header_check(8, bac_header, sizeof(bac_header), &header_check_bac, file_stat);
}
+#endif
diff --git a/src/file_bdm.c b/src/file_bdm.c
index 84512e8..cd5066d 100644
--- a/src/file_bdm.c
+++ b/src/file_bdm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bdm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_bdm(file_stat_t *file_stat)
register_header_check(0, "INDX0100", 8, &header_check_bdm, file_stat);
register_header_check(0, "MOBJ0100", 8, &header_check_bdm, file_stat);
}
+#endif
diff --git a/src/file_berkeley.c b/src/file_berkeley.c
index 3f5452a..67dbd1f 100644
--- a/src/file_berkeley.c
+++ b/src/file_berkeley.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_berkeley)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -72,3 +73,4 @@ static void register_header_check_berkeley_le(file_stat_t *file_stat)
register_header_check(0xC, berkeley_db_btree_8, 8, &header_check_berkeley_le, file_stat);
register_header_check(0xC, berkeley_db_btree_9, 8, &header_check_berkeley_le, file_stat);
}
+#endif
diff --git a/src/file_bfa.c b/src/file_bfa.c
new file mode 100644
index 0000000..573b9ec
--- /dev/null
+++ b/src/file_bfa.c
@@ -0,0 +1,78 @@
+/*
+
+ File: file_bfa.c
+
+ Copyright (C) 2019 Christophe GRENIER <grenier@cgsecurity.org>
+
+ This software is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ */
+
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bfa)
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <stdio.h>
+#include "types.h"
+#include "filegen.h"
+#include "common.h"
+
+static void register_header_check_bfa(file_stat_t *file_stat);
+
+const file_hint_t file_hint_bfa= {
+ .extension="bfa",
+ .description="Blowfish Advanced CS",
+ .max_filesize=PHOTOREC_MAX_FILE_SIZE,
+ .recover=1,
+ .enable_by_default=1,
+ .register_header_check=&register_header_check_bfa
+};
+
+struct bfa_header
+{
+ uint32_t lMagic;
+ uint16_t wSizeOfHeader;
+ uint16_t wVersion;
+ uint64_t lLength;
+ uint16_t wCipherInitDataSize;
+ uint16_t wCipherBlockSize;
+ uint8_t salt[11];
+ uint32_t lKeyHash;
+} __attribute__ ((gcc_struct, __packed__));
+
+static int header_check_bfa(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+{
+ const struct bfa_header *header=(const struct bfa_header*)buffer;
+ uint64_t size=le64(header->lLength);
+ if(size > PHOTOREC_MAX_FILE_SIZE)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_bfa.extension;
+ file_recovery_new->calculated_file_size=size + le16(header->wSizeOfHeader);
+ file_recovery_new->file_check=&file_check_size_min;
+ return 1;
+}
+
+static void register_header_check_bfa(file_stat_t *file_stat)
+{
+ static const unsigned char bfa_header[8]= {
+ 0x24, 0x08, 0x19, 0x92, 0x23, 0x00, 0x15, 0x01
+ };
+ register_header_check(0, bfa_header, sizeof(bfa_header), &header_check_bfa, file_stat);
+}
+#endif
diff --git a/src/file_bim.c b/src/file_bim.c
index 7fbc9b3..10ebb23 100644
--- a/src/file_bim.c
+++ b/src/file_bim.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bim)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,3 +59,4 @@ static void register_header_check_bim(file_stat_t *file_stat)
};
register_header_check(0, bim_header, sizeof(bim_header), &header_check_bim, file_stat);
}
+#endif
diff --git a/src/file_bin.c b/src/file_bin.c
index 5dabdb2..7be6a4c 100644
--- a/src/file_bin.c
+++ b/src/file_bin.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bin)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -72,3 +73,4 @@ static void register_header_check_bin(file_stat_t *file_stat)
'i' , 'c' , 'k' , 'e' , 't' , 's' };
register_header_check(6, bin_header, sizeof(bin_header), &header_check_bin, file_stat);
}
+#endif
diff --git a/src/file_binvox.c b/src/file_binvox.c
index b4ac7d8..4d6886c 100644
--- a/src/file_binvox.c
+++ b/src/file_binvox.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_binvox)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_binvox(file_stat_t *file_stat)
{
register_header_check(0, "#binvox 1\ndim ", 14, &header_check_binvox, file_stat);
}
+#endif
diff --git a/src/file_bkf.c b/src/file_bkf.c
index bebc131..5aac25c 100644
--- a/src/file_bkf.c
+++ b/src/file_bkf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bkf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -32,12 +33,15 @@
#include "common.h"
#include "log.h"
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_bkf(file_stat_t *file_stat);
const file_hint_t file_hint_bkf= {
.extension="bkf",
.description="MS Backup file",
- .max_filesize=-1,
+ .max_filesize=PHOTOREC_MAX_FILE_SIZE,
.recover=1,
.enable_by_default=1,
.register_header_check=&register_header_check_bkf
@@ -62,12 +66,57 @@ struct mtf_db_hdr
uint16_t check; /* header checksum */
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires \valid_read(&file_recovery->extension);
+ @ requires valid_read_string(file_recovery->extension);
+ @ requires \separated(file_recovery, file_recovery->handle, file_recovery->extension, &errno, &Frama_C_entropy_source);
+ @ requires \initialized(&file_recovery->time);
+ @
+ @ requires file_recovery->file_check == &file_check_bkf;
+ @ assigns *file_recovery->handle, errno, file_recovery->file_size;
+ @ assigns Frama_C_entropy_source;
+ @
+ @ ensures \valid(file_recovery->handle);
+ @*/
static void file_check_bkf(file_recovery_t *file_recovery)
{
const unsigned char bkf_footer[4]= { 'S', 'F', 'M', 'B'};
file_search_footer(file_recovery, bkf_footer, sizeof(bkf_footer), 0x400-4);
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= sizeof(struct mtf_db_hdr);
+ @ requires separation: \separated(&file_hint_bkf, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 52);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_bkf.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_bkf);
+ @*/
static int header_check_bkf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct mtf_db_hdr *hdr=(const struct mtf_db_hdr *)buffer;
@@ -94,3 +143,4 @@ static void register_header_check_bkf(file_stat_t *file_stat)
static const unsigned char bkf_header[4]= { 'T','A','P','E'};
register_header_check(0, bkf_header,sizeof(bkf_header), &header_check_bkf, file_stat);
}
+#endif
diff --git a/src/file_bld.c b/src/file_bld.c
index 3fc5b26..5653189 100644
--- a/src/file_bld.c
+++ b/src/file_bld.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_blend)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,6 +32,9 @@
#include "filegen.h"
#include "log.h"
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_blend(file_stat_t *file_stat);
const file_hint_t file_hint_blend= {
@@ -44,8 +48,19 @@ const file_hint_t file_hint_blend= {
static const unsigned char blend_header_footer[4] = { 'E', 'N', 'D', 'B'};
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_blend4le;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_blend4le(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@ loop assigns file_recovery->calculated_file_size; */
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 0x14 < file_recovery->file_size + buffer_size/2)
{
@@ -68,8 +83,19 @@ static data_check_t data_check_blend4le(const unsigned char *buffer, const unsig
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_blend8le;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_blend8le(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@ loop assigns file_recovery->calculated_file_size; */
while(file_recovery->calculated_file_size + 0x18 < file_recovery->file_size + buffer_size/2)
{
const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
@@ -91,8 +117,19 @@ static data_check_t data_check_blend8le(const unsigned char *buffer, const unsig
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_blend4be;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_blend4be(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@ loop assigns file_recovery->calculated_file_size; */
while(file_recovery->calculated_file_size + 0x14 < file_recovery->file_size + buffer_size/2)
{
const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
@@ -114,8 +151,19 @@ static data_check_t data_check_blend4be(const unsigned char *buffer, const unsig
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_blend8be;
+ @ requires \separated(buffer, file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_blend8be(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@ loop assigns file_recovery->calculated_file_size; */
while(file_recovery->calculated_file_size + 0x18 < file_recovery->file_size + buffer_size/2)
{
const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
@@ -137,6 +185,42 @@ static data_check_t data_check_blend8be(const unsigned char *buffer, const unsig
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= 8;
+ @ requires separation: \separated(&file_hint_blend, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 12);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_blend.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_blend4be ||
+ file_recovery_new->data_check == &data_check_blend4le ||
+ file_recovery_new->data_check == &data_check_blend8be ||
+ file_recovery_new->data_check == &data_check_blend8le
+ );
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @*/
static int header_check_blend(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
if(buffer[7]!='_' && buffer[7]!='-')
@@ -169,3 +253,4 @@ static void register_header_check_blend(file_stat_t *file_stat)
static const unsigned char blend_header[7] = { 'B', 'L', 'E', 'N', 'D', 'E', 'R'};
register_header_check(0, blend_header,sizeof(blend_header), &header_check_blend, file_stat);
}
+#endif
diff --git a/src/file_bmp.c b/src/file_bmp.c
index 42209d2..b2d56b0 100644
--- a/src/file_bmp.c
+++ b/src/file_bmp.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bmp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -63,15 +64,45 @@ struct bmp_header
@ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_bmp, buffer+(..), file_recovery, file_recovery_new);
+ @ assigns file_recovery_new->filename[0];
+ @ assigns file_recovery_new->time;
+ @ assigns file_recovery_new->file_stat;
+ @ assigns file_recovery_new->handle;
+ @ assigns file_recovery_new->file_size;
+ @ assigns file_recovery_new->location.list.prev;
+ @ assigns file_recovery_new->location.list.next;
+ @ assigns file_recovery_new->location.end;
+ @ assigns file_recovery_new->location.data;
+ @ assigns file_recovery_new->extension;
+ @ assigns file_recovery_new->min_filesize;
+ @ assigns file_recovery_new->calculated_file_size;
+ @ assigns file_recovery_new->data_check;
+ @ assigns file_recovery_new->file_check;
+ @ assigns file_recovery_new->file_rename;
+ @ assigns file_recovery_new->offset_error;
+ @ assigns file_recovery_new->offset_ok;
+ @ assigns file_recovery_new->checkpoint_status;
+ @ assigns file_recovery_new->checkpoint_offset;
+ @ assigns file_recovery_new->flags;
+ @ assigns file_recovery_new->extra;
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_bmp.extension);
@ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= 65);
@ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
@ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 65);
@ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
@ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @ ensures *buffer==\old(*buffer);
@*/
+ /* TODO ensures *file_recovery==\old(*file_recovery); */
static int header_check_bmp(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct bmp_header *bm=(const struct bmp_header *)buffer;
@@ -100,6 +131,8 @@ static int header_check_bmp(const unsigned char *buffer, const unsigned int buff
/*@ assert file_recovery_new->min_filesize == 65; */
/*@ assert file_recovery_new->data_check == &data_check_size; */
/*@ assert file_recovery_new->file_check == &file_check_size; */
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ /*@ assert \initialized(&file_recovery_new->time); */
return 1;
}
return 0;
@@ -112,14 +145,14 @@ static void register_header_check_bmp(file_stat_t *file_stat)
{
register_header_check(0, bmp_header,sizeof(bmp_header), &header_check_bmp, file_stat);
}
+#endif
#if defined(MAIN_bmp)
#define BLOCKSIZE 65536u
-int main()
+int main(void)
{
const char fn[] = "recup_dir.1/f0000000.bmp";
unsigned char buffer[BLOCKSIZE];
- int res;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
file_stat_t file_stats;
diff --git a/src/file_bpg.c b/src/file_bpg.c
index bc16eb5..e6dbaa1 100644
--- a/src/file_bpg.c
+++ b/src/file_bpg.c
@@ -6,7 +6,7 @@
Copyright (C) 2016 Dmitry Brant <me@dmitrybrant.com>
BPG specification can be found at:
- http://bellard.org/bpg/bpg_spec.txt
+ https://bellard.org/bpg/bpg_spec.txt
This software is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bpg)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -47,10 +48,22 @@ const file_hint_t file_hint_bpg= {
.register_header_check=&register_header_check_bpg
};
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(buf_ptr);
+ @ requires \separated(buffer+(..), buf_ptr);
+ @*/
static unsigned int getue32(const unsigned char *buffer, const unsigned int buffer_size, unsigned int *buf_ptr)
{
- unsigned int value = 0;
+ uint64_t value = 0;
int bitsRead = 0;
+ /*@
+ @ loop invariant bitsRead <= 35;
+ @ loop invariant value < (bitsRead == 0 ? 1: (0x80 << (bitsRead-7)));
+ @ loop assigns value, bitsRead, *buf_ptr;
+ @ loop variant 35 - bitsRead;
+ @ */
while (*buf_ptr < buffer_size)
{
const unsigned int b = buffer[*buf_ptr];
@@ -63,9 +76,39 @@ static unsigned int getue32(const unsigned char *buffer, const unsigned int buff
if (bitsRead >= 32)
break;
}
- return value;
+ return value&0xffffffff;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= 6+3*5;
+ @ requires separation: \separated(&file_hint_bpg, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_bpg.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check== &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @*/
static int header_check_bpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
unsigned int buf_ptr = 6;
@@ -73,7 +116,7 @@ static int header_check_bpg(const unsigned char *buffer, const unsigned int buff
const unsigned int picture_width = getue32(buffer, buffer_size, &buf_ptr);
// get image height
const unsigned int picture_height = getue32(buffer, buffer_size, &buf_ptr);
- unsigned int size = getue32(buffer, buffer_size, &buf_ptr);
+ uint64_t size = getue32(buffer, buffer_size, &buf_ptr);
if(picture_width==0 || picture_height==0)
return 0;
if (size == 0) {
@@ -94,3 +137,4 @@ static void register_header_check_bpg(file_stat_t *file_stat)
static const unsigned char bpg_header[4]= {'B','P','G',0xFB};
register_header_check(0, bpg_header,sizeof(bpg_header), &header_check_bpg, file_stat);
}
+#endif
diff --git a/src/file_bvr.c b/src/file_bvr.c
index 1b4a43d..ca02620 100644
--- a/src/file_bvr.c
+++ b/src/file_bvr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bvr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -43,6 +44,9 @@ const file_hint_t file_hint_bvr= {
static data_check_t data_check_bvr(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 16 < file_recovery->file_size + buffer_size/2)
{
@@ -77,3 +81,4 @@ static void register_header_check_bvr(file_stat_t *file_stat)
static const unsigned char bvrheader[8]= { 'B', 'L', 'U', 'E', 0x20, 0x00, 0x10, 0x00};
register_header_check(0, bvrheader, sizeof(bvrheader), &header_check_bvr, file_stat);
}
+#endif
diff --git a/src/file_bz2.c b/src/file_bz2.c
index 05914f2..7aba0e9 100644
--- a/src/file_bz2.c
+++ b/src/file_bz2.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bz2)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -51,7 +52,7 @@ static void register_header_check_bz2(file_stat_t *file_stat)
static int header_check_bz2(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
- if(buffer[0]=='B' && buffer[1]=='Z' && buffer[2]=='h' && buffer[3]>='0' && buffer[4]=='1' && buffer[5]=='A' && buffer[6]=='Y' && buffer[7]=='&' && buffer[8]=='S' && buffer[9]=='Y')
+ if(buffer[0]=='B' && buffer[1]=='Z' && buffer[2]=='h' && buffer[3]>='0' && buffer[3]<='9' && buffer[4]=='1' && buffer[5]=='A' && buffer[6]=='Y' && buffer[7]=='&' && buffer[8]=='S' && buffer[9]=='Y')
{
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_bz2.extension;
@@ -59,3 +60,4 @@ static int header_check_bz2(const unsigned char *buffer, const unsigned int buff
}
return 0;
}
+#endif
diff --git a/src/file_c4d.c b/src/file_c4d.c
index aafaded..48681ca 100644
--- a/src/file_c4d.c
+++ b/src/file_c4d.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_c4d)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_c4d(file_stat_t *file_stat)
{
register_header_check(0, "QC4DC4D6", 8, &header_check_c4d, file_stat);
}
+#endif
diff --git a/src/file_cab.c b/src/file_cab.c
index 16db328..0e9bda4 100644
--- a/src/file_cab.c
+++ b/src/file_cab.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cab)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -77,3 +78,4 @@ static void register_header_check_cab(file_stat_t *file_stat)
static const unsigned char cab_header[4] = { 'M','S','C','F'};
register_header_check(0, cab_header,sizeof(cab_header), &header_check_cab, file_stat);
}
+#endif
diff --git a/src/file_caf.c b/src/file_caf.c
index 521a0b9..fbde9e3 100644
--- a/src/file_caf.c
+++ b/src/file_caf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_caf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -46,7 +47,7 @@ const file_hint_t file_hint_caf= {
.register_header_check=&register_header_check_caf
};
-/* http://developer.apple.com/library/mac/documentation/MusicAudio/Reference/CAFSpec/CAF_spec/CAF_spec.html */
+/* https://developer.apple.com/library/archive/documentation/MusicAudio/Reference/CAFSpec/CAF_spec/CAF_spec.html */
struct chunk_struct
{
@@ -56,6 +57,9 @@ struct chunk_struct
static data_check_t data_check_caf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 12 < file_recovery->file_size + buffer_size/2)
{
@@ -97,7 +101,7 @@ static data_check_t data_check_caf(const unsigned char *buffer, const unsigned i
static int header_check_caf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct chunk_struct *chunk=(const struct chunk_struct*)&buffer[8];
- const int64_t chunk_size=be64(chunk->size);
+ const int64_t chunk_size=(int64_t)be64(chunk->size);
if(chunk_size < 0)
return 0;
reset_file_recovery(file_recovery_new);
@@ -120,3 +124,4 @@ static void register_header_check_caf(file_stat_t *file_stat)
};
register_header_check(0, caf_header, sizeof(caf_header), &header_check_caf, file_stat);
}
+#endif
diff --git a/src/file_cam.c b/src/file_cam.c
index b62431d..ad6f804 100644
--- a/src/file_cam.c
+++ b/src/file_cam.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cam)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_cam(file_stat_t *file_stat)
static const unsigned char cam_header[4]= {0x07, 0x20, 'M', 'M'};
register_header_check(0, cam_header,sizeof(cam_header), &header_check_cam, file_stat);
}
+#endif
diff --git a/src/file_catdrawing.c b/src/file_catdrawing.c
index a76b775..3748397 100644
--- a/src/file_catdrawing.c
+++ b/src/file_catdrawing.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_catdrawing)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_catdrawing(file_stat_t *file_stat)
};
register_header_check(0, catdrawing_header, sizeof(catdrawing_header), &header_check_catdrawing, file_stat);
}
+#endif
diff --git a/src/file_cdt.c b/src/file_cdt.c
index 3a90db5..1a2c7b8 100644
--- a/src/file_cdt.c
+++ b/src/file_cdt.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cdt)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -62,3 +63,4 @@ static void register_header_check_cdt(file_stat_t *file_stat)
};
register_header_check(12, cdt_header, sizeof(cdt_header), &header_check_cdt, file_stat);
}
+#endif
diff --git a/src/file_che.c b/src/file_che.c
index 17a2641..b290e5d 100644
--- a/src/file_che.c
+++ b/src/file_che.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_che)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -97,3 +98,4 @@ static void register_header_check_che(file_stat_t *file_stat)
{
register_header_check(0, "Compucon EOS Design File", 24, &header_check_che, file_stat);
}
+#endif
diff --git a/src/file_chm.c b/src/file_chm.c
index cc4b65a..597ffe9 100644
--- a/src/file_chm.c
+++ b/src/file_chm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_chm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -60,3 +61,4 @@ static void register_header_check_chm(file_stat_t *file_stat)
0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
register_header_check(0, chm_header,sizeof(chm_header), &header_check_chm, file_stat);
}
+#endif
diff --git a/src/file_class.c b/src/file_class.c
index 91f446e..38e23e4 100644
--- a/src/file_class.c
+++ b/src/file_class.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_class)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -71,3 +72,4 @@ static int header_check_class(const unsigned char *buffer, const unsigned int bu
}
return 0;
}
+#endif
diff --git a/src/file_cm.c b/src/file_cm.c
index 0f25a05..c8a6b26 100644
--- a/src/file_cm.c
+++ b/src/file_cm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_cm(file_stat_t *file_stat)
static const unsigned char cm_header[8] = { 'f','L','m','C','0','0','0','1'};
register_header_check(0x0, cm_header,sizeof(cm_header), &header_check_cm, file_stat);
}
+#endif
diff --git a/src/file_compress.c b/src/file_compress.c
index 7722128..fcdf338 100644
--- a/src/file_compress.c
+++ b/src/file_compress.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_compress)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_compress(file_stat_t *file_stat)
static const unsigned char compress_header[9] = {'S', 'Z', 'D', 'D', 0x88, 0xf0, 0x27, 0x33, 'A'};
register_header_check(0, compress_header, sizeof(compress_header), &header_check_compress, file_stat);
}
+#endif
diff --git a/src/file_cow.c b/src/file_cow.c
index b0de7cb..b1f5b72 100644
--- a/src/file_cow.c
+++ b/src/file_cow.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cow)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -127,3 +128,4 @@ static void register_header_check_cow(file_stat_t *file_stat)
register_header_check(0, cow_header2,sizeof(cow_header2), &header_check_qcow2, file_stat);
register_header_check(0, cow_header3,sizeof(cow_header3), &header_check_qcow2, file_stat);
}
+#endif
diff --git a/src/file_cpi.c b/src/file_cpi.c
index 8d7ad5c..54f8a76 100644
--- a/src/file_cpi.c
+++ b/src/file_cpi.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cpi)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_cpi(file_stat_t *file_stat)
{
register_header_check(0, "HDMV0100", 8, &header_check_cpi, file_stat);
}
+#endif
diff --git a/src/file_crw.c b/src/file_crw.c
index 6db052d..7fc5c97 100644
--- a/src/file_crw.c
+++ b/src/file_crw.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_crw)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -71,3 +72,4 @@ static void file_check_crw(file_recovery_t *file_recovery)
const unsigned char crw_footer[2]= { 0x0A, 0x30};
file_search_footer(file_recovery, crw_footer, sizeof(crw_footer), 12);
}
+#endif
diff --git a/src/file_csh.c b/src/file_csh.c
index 50c20a7..73fc76c 100644
--- a/src/file_csh.c
+++ b/src/file_csh.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_csh)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_csh(file_stat_t *file_stat)
};
register_header_check(0, csh_header, sizeof(csh_header), &header_check_csh, file_stat);
}
+#endif
diff --git a/src/file_ctg.c b/src/file_ctg.c
index 991c31b..d661aaf 100644
--- a/src/file_ctg.c
+++ b/src/file_ctg.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ctg)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_ctg(file_stat_t *file_stat)
static const unsigned char ctg_header[7]= {':','\\','D','C','I','M','\\'};
register_header_check(1, ctg_header,sizeof(ctg_header), &header_check_ctg, file_stat);
}
+#endif
diff --git a/src/file_cwk.c b/src/file_cwk.c
index cba78e6..6b9f1b2 100644
--- a/src/file_cwk.c
+++ b/src/file_cwk.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cwk)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -86,3 +87,4 @@ static void register_header_check_cwk(file_stat_t *file_stat)
static const unsigned char cwk_header[4]= {'B','O','B','O'};
register_header_check(4, cwk_header,sizeof(cwk_header), &header_check_cwk, file_stat);
}
+#endif
diff --git a/src/file_d2s.c b/src/file_d2s.c
index 9a3779a..3aa8954 100644
--- a/src/file_d2s.c
+++ b/src/file_d2s.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_d2s)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -46,7 +47,7 @@ struct d2s_header {
uint32_t size;
uint32_t unk1;
uint32_t unk2;
- char name[0];
+// char name[0];
} __attribute__ ((gcc_struct, __packed__));
static void file_rename_d2s(file_recovery_t *file_recovery)
@@ -82,3 +83,4 @@ static void register_header_check_d2s(file_stat_t *file_stat)
};
register_header_check(0, d2s_header,sizeof(d2s_header), &header_check_d2s, file_stat);
}
+#endif
diff --git a/src/file_dad.c b/src/file_dad.c
index f4e5794..b99bf43 100644
--- a/src/file_dad.c
+++ b/src/file_dad.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dad)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,6 +54,9 @@ struct dad_header
static data_check_t data_check_dad(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 16 <= file_recovery->file_size + buffer_size/2)
{
@@ -98,3 +102,4 @@ static void register_header_check_dad(file_stat_t *file_stat)
{
register_header_check(0, "DHAV", 4, &header_check_dad, file_stat);
}
+#endif
diff --git a/src/file_dar.c b/src/file_dar.c
index f642493..52ce361 100644
--- a/src/file_dar.c
+++ b/src/file_dar.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dar)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -61,3 +62,4 @@ static void register_header_check_dar(file_stat_t *file_stat)
};
register_header_check(0, dar_header, sizeof(dar_header), &header_check_dar, file_stat);
}
+#endif
diff --git a/src/file_dat.c b/src/file_dat.c
index 3618323..370fbed 100644
--- a/src/file_dat.c
+++ b/src/file_dat.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dat)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -93,3 +94,4 @@ static void register_header_check_dat(file_stat_t *file_stat)
register_header_check(4, dat_history, sizeof(dat_history), &header_check_dat_history4, file_stat);
register_header_check(10, dat_history, sizeof(dat_history), &header_check_dat_history10, file_stat);
}
+#endif
diff --git a/src/file_dbf.c b/src/file_dbf.c
index 19b30b6..085dc20 100644
--- a/src/file_dbf.c
+++ b/src/file_dbf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dbf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -66,3 +67,4 @@ static int header_check_dbf(const unsigned char *buffer, const unsigned int buff
}
return 0;
}
+#endif
diff --git a/src/file_dbn.c b/src/file_dbn.c
index 44a8575..e857051 100644
--- a/src/file_dbn.c
+++ b/src/file_dbn.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dbn)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,3 +60,4 @@ static void register_header_check_dbn(file_stat_t *file_stat)
};
register_header_check(0, dbn_header, sizeof(dbn_header), &header_check_dbn, file_stat);
}
+#endif
diff --git a/src/file_dcm.c b/src/file_dcm.c
index 81a62a7..f0eb886 100644
--- a/src/file_dcm.c
+++ b/src/file_dcm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dcm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_dcm(file_stat_t *file_stat)
'U' , 'L' };
register_header_check(0x80, dcm_header, sizeof(dcm_header), &header_check_dcm, file_stat);
}
+#endif
diff --git a/src/file_ddf.c b/src/file_ddf.c
index 805c95c..401d97d 100644
--- a/src/file_ddf.c
+++ b/src/file_ddf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ddf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -138,3 +139,4 @@ static void register_header_check_ddf(file_stat_t *file_stat)
register_header_check(0, ddf4_header, sizeof(ddf4_header), &header_check_ddf4, file_stat);
register_header_check(0, ddf5_header, sizeof(ddf5_header), &header_check_ddf5, file_stat);
}
+#endif
diff --git a/src/file_dex.c b/src/file_dex.c
index a79e864..3c1b229 100644
--- a/src/file_dex.c
+++ b/src/file_dex.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dex)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -93,3 +94,4 @@ static void register_header_check_dex(file_stat_t *file_stat)
static const unsigned char dex_header[4]= {'d','e','x','\n'};
register_header_check(0, dex_header,sizeof(dex_header), &header_check_dex, file_stat);
}
+#endif
diff --git a/src/file_dim.c b/src/file_dim.c
index 02a3731..dae7824 100644
--- a/src/file_dim.c
+++ b/src/file_dim.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dim)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_dim(file_stat_t *file_stat)
static const unsigned char dim_header[4]= { 'S', 'P','C','I'};
register_header_check(0x0c, dim_header,sizeof(dim_header), &header_check_dim, file_stat);
}
+#endif
diff --git a/src/file_dir.c b/src/file_dir.c
index 09a5b96..9d445e8 100644
--- a/src/file_dir.c
+++ b/src/file_dir.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dir)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -33,10 +34,8 @@
#include "types.h"
#include "filegen.h"
#include "common.h"
-#include "fat.h"
-#include "dir.h"
-#include "fat_dir.h"
#include "fat_common.h"
+#include "fat_dir.h"
static void register_header_check_dir(file_stat_t *file_stat);
static int header_check_dir(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
@@ -50,6 +49,11 @@ const file_hint_t file_hint_dir= {
.register_header_check=&register_header_check_dir
};
+/*@
+ @ requires \valid(file_recovery);
+ @ requires valid_read_string((char*)&file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_fatdir;
+ @*/
static void file_rename_fatdir(file_recovery_t *file_recovery)
{
unsigned char buffer[512];
@@ -68,6 +72,15 @@ static void file_rename_fatdir(file_recovery_t *file_recovery)
file_rename(file_recovery, buffer_cluster, strlen(buffer_cluster), 0, NULL, 1);
}
+/*@
+ @ requires buffer_size >= 2;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read((char *)buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check == &data_check_fatdir;
+ @ ensures \result == DC_STOP;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_fatdir(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
/* Save only one cluster */
@@ -75,6 +88,15 @@ static data_check_t data_check_fatdir(const unsigned char *buffer, const unsigne
return DC_STOP;
}
+/*@
+ @ requires buffer_size >= sizeof(struct msdos_dir_entry);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_dir, buffer+(..), file_recovery, file_recovery_new);
+ @*/
static int header_check_dir(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct msdos_dir_entry *de=(const struct msdos_dir_entry*)buffer;
@@ -89,7 +111,11 @@ static int header_check_dir(const unsigned char *buffer, const unsigned int buff
return 1;
}
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_dir(file_stat_t *file_stat)
{
register_header_check(0, ". ", 8+3, &header_check_dir, file_stat);
}
+#endif
diff --git a/src/file_djv.c b/src/file_djv.c
index 3e4300d..2d3731b 100644
--- a/src/file_djv.c
+++ b/src/file_djv.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_djv)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -68,3 +69,4 @@ static void register_header_check_djv(file_stat_t *file_stat)
static const unsigned char djv_header[8]= { 'A','T','&','T','F','O','R','M'};
register_header_check(0, djv_header,sizeof(djv_header), &header_check_djv, file_stat);
}
+#endif
diff --git a/src/file_dmp.c b/src/file_dmp.c
index 95aa021..f53e615 100644
--- a/src/file_dmp.c
+++ b/src/file_dmp.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dmp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,4 +59,4 @@ static void register_header_check_dmp(file_stat_t *file_stat)
};
register_header_check(0, dmp_header, sizeof(dmp_header), &header_check_dmp, file_stat);
}
-
+#endif
diff --git a/src/file_doc.c b/src/file_doc.c
index de28d49..33c471a 100644
--- a/src/file_doc.c
+++ b/src/file_doc.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_doc)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -43,11 +44,10 @@
#include "__fc_builtin.h"
#endif
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_doc(file_stat_t *file_stat);
-static void file_check_doc(file_recovery_t *file_recovery);
-static void file_rename_doc(file_recovery_t *file_recovery);
-static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header, const uint64_t offset);
-static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const uint32_t *fat, const unsigned int fat_entries, const uint64_t offset);
const file_hint_t file_hint_doc= {
.extension="doc",
@@ -58,6 +58,45 @@ const file_hint_t file_hint_doc= {
.register_header_check=&register_header_check_doc
};
+static const char *extension_albm="albm";
+static const char *extension_amb="amb";
+static const char *extension_apr="apr";
+static const char *extension_camrec="camrec";
+static const char *extension_db="db";
+static const char *extension_dgn="dgn";
+static const char *extension_emb="emb";
+static const char *extension_et="et";
+static const char *extension_fla="fla";
+static const char *extension_ipt="ipt";
+static const char *extension_jnb="jnb";
+static const char *extension_max="max";
+static const char *extension_mdb="mdb";
+static const char *extension_mws="mws";
+static const char *extension_msg="msg";
+static const char *extension_p65="p65";
+static const char *extension_ppt="ppt";
+static const char *extension_psmodel="psmodel";
+static const char *extension_pub="pub";
+static const char *extension_qbb="qbb";
+static const char *extension_qdf_backup="qdf-backup";
+static const char *extension_qpw="qpw";
+static const char *extension_rvt="rvt";
+static const char *extension_sda="sda";
+static const char *extension_sdc="sdc";
+static const char *extension_sdd="sdd";
+static const char *extension_sdw="sdw";
+#ifdef DJGPP
+static const char *extension_sldprt="sld";
+#else
+static const char *extension_sldprt="sldprt";
+#endif
+static const char *extension_snt="snt";
+static const char *extension_tcw="tcw";
+static const char *extension_vsd="vsd";
+static const char *extension_wps="wps";
+static const char *extension_xlr="xlr";
+static const char *extension_xls="xls";
+static const char *extension_wdb="wdb";
const char WilcomDesignInformationDDD[56]=
{
@@ -74,60 +113,158 @@ const char WilcomDesignInformationDDD[56]=
@ requires \valid(IN);
@ requires (9 == uSectorShift) || (12 == uSectorShift);
@ requires \valid( buf + (0 .. (1<<uSectorShift)-1));
+ @ requires separation: \separated(buf+(..), IN, &errno, &Frama_C_entropy_source);
+ @ assigns \result, *IN, errno;
+ @ assigns *((char *)buf + (0 .. (1 << uSectorShift) - 1));
+ @ assigns Frama_C_entropy_source;
@ ensures \result == -1 || \result == 0;
@*/
-static int OLE_read_block(FILE *IN, unsigned char *buf, const unsigned int uSectorShift, const unsigned int block, const uint64_t offset)
+/* TODO: ensures \result == 0 ==> \initialized(buf + (0 .. (1<<uSectorShift)-1)); */
+static int OLE_read_block(FILE *IN, char *buf, const unsigned int uSectorShift, const unsigned int block, const uint64_t offset)
{
+ const size_t size=1<<uSectorShift;
if(block==0xFFFFFFFF || block==0xFFFFFFFE)
return -1;
if(my_fseek(IN, offset + ((uint64_t)(1+block)<<uSectorShift), SEEK_SET) < 0)
{
return -1;
}
- if(fread(buf, 1<<uSectorShift, 1, IN)!=1)
+ if(fread(buf, size, 1, IN)!=1)
{
return -1;
}
#if defined(__FRAMAC__)
- Frama_C_make_unknown((char *)buf, 1<<uSectorShift);
+ Frama_C_make_unknown(buf, size);
#endif
+ /* TODO: assert \initialized(buf + (0 .. size-1)); */
return 0;
}
/*@
+ @ requires \valid_read(dir_entry);
+ @ requires \initialized(dir_entry);
+ @ assigns \nothing;
+ @ ensures \result == \null || valid_read_string(\result);
+ @*/
+static const char *entry2ext(const struct OLE_DIR *dir_entry)
+{
+ switch(le16(dir_entry->namsiz))
+ {
+ case 10:
+ if(memcmp(dir_entry->name, ".\0Q\0D\0F\0\0\0",10)==0)
+ return extension_qdf_backup;
+ break;
+ case 12:
+ /* 3ds max */
+ if(memcmp(dir_entry->name, "S\0c\0e\0n\0e\0\0\0",12)==0)
+ return extension_max;
+ /* Licom AlphaCAM */
+ else if(memcmp(dir_entry->name,"L\0i\0c\0o\0m\0\0\0",12)==0)
+ return extension_amb;
+ break;
+ case 18:
+ /* Microsoft Works .wps */
+ if(memcmp(dir_entry->name,"C\0O\0N\0T\0E\0N\0T\0S\0\0\0",18)==0)
+ return extension_wps;
+ break;
+ case 20:
+ /* Page Maker */
+ if(memcmp(&dir_entry->name, "P\0a\0g\0e\0M\0a\0k\0e\0r\0\0\0", 20)==0)
+ return extension_p65;
+ break;
+ case 22:
+ /* SigmaPlot .jnb */
+ if(memcmp(dir_entry->name, "J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0\0\0", 22)==0)
+ return extension_jnb;
+ /* Autodesk Inventor part ipt or iam file */
+ if(memcmp(dir_entry->name, "R\0S\0e\0S\0t\0o\0r\0a\0g\0e\0\0\0", 22)==0)
+ return extension_ipt;
+ break;
+ case 24:
+ /* HP Photosmart Photo Printing Album */
+ if(memcmp(dir_entry->name,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0\0\0",24)==0)
+ return extension_albm;
+ /* Lotus Approch */
+ if(memcmp(dir_entry->name,"A\0p\0p\0r\0o\0a\0c\0h\0D\0o\0c\0\0\0",24)==0)
+ return extension_apr;
+ break;
+ case 28:
+ /* Microsoft Works Spreadsheet or Chart */
+ if(memcmp(dir_entry->name,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0\0\0",28)==0)
+ return extension_xlr;
+ /* Visio */
+ else if(memcmp(dir_entry->name,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",28)==0)
+ return extension_vsd;
+ /* SolidWorks */
+ else if(memcmp(&dir_entry->name,"s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0\0\0",28)==0)
+ return extension_sldprt;
+ break;
+ case 32:
+ if(memcmp(dir_entry->name, "m\0a\0n\0i\0f\0e\0s\0t\0.\0c\0a\0m\0x\0m\0l\0\0\0",32)==0)
+ return extension_camrec;
+ /* Revit */
+ if(memcmp(dir_entry->name, "R\0e\0v\0i\0t\0P\0r\0e\0v\0i\0e\0w\0004\0.\0000\0\0", 32)==0)
+ return extension_rvt;
+ break;
+ case 34:
+ if(memcmp(dir_entry->name, "S\0t\0a\0r\0C\0a\0l\0c\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",34)==0)
+ return extension_sdc;
+ break;
+ case 36:
+ if(memcmp(dir_entry->name, "f\0i\0l\0e\0_\0C\0O\0M\0P\0A\0N\0Y\0_\0F\0I\0L\0E\0\0\0", 36)==0)
+ return extension_qbb;
+ break;
+ case 38:
+ /* Quattro Pro spreadsheet */
+ if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0\0\0", 38)==0)
+ return extension_qpw;
+ else if(memcmp(dir_entry->name, "S\0t\0a\0r\0W\0r\0i\0t\0e\0r\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 38)==0)
+ return extension_sdw;
+ break;
+ case 40:
+ if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0)
+ return extension_ppt;
+ /* Outlook */
+ else if(memcmp(dir_entry->name,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0\0\0",40)==0)
+ return extension_msg;
+ break;
+ case 46:
+ if(memcmp(dir_entry->name,
+ "I\0S\0o\0l\0i\0d\0W\0o\0r\0k\0s\0I\0n\0f\0o\0r\0m\0a\0t\0i\0o\0n\0\0\0", 46)==0)
+ {
+ return extension_sldprt;
+ }
+ break;
+ case 56:
+ /* Wilcom ES Software */
+ if(memcmp(dir_entry->name, WilcomDesignInformationDDD, 56)==0)
+ return extension_emb;
+ break;
+ }
+ return NULL;
+}
+
+/*@
@ requires buffer_size >= sizeof(struct OLE_HDR);
- @ requires \valid_read(buffer + (0 .. buffer_size-1));
+ @ requires \valid_read((char *)header + (0 .. buffer_size-1));
+ @ requires 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift);
+ @ requires le32(header->num_FAT_blocks)>0;
+ @ requires 0 <= le32(header->num_extra_FAT_blocks) <= 50;
+ @ ensures \result == \null || valid_read_string(\result);
@*/
-static const char *ole_get_file_extension(const unsigned char *buffer, const unsigned int buffer_size)
+static const char *ole_get_file_extension(const struct OLE_HDR *header, const unsigned int buffer_size)
{
- const struct OLE_HDR *header=(const struct OLE_HDR *)buffer;
- const uint32_t *fat;
+ const unsigned char *buffer=(const unsigned char *)header;
unsigned int fat_entries;
unsigned int block;
unsigned int i;
- /*@ assert 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift); */
- /*@ assert le32(header->num_FAT_blocks)>0; */
const unsigned int uSectorShift=le16(header->uSectorShift);
+ unsigned int fat_size;
if(buffer_size<512)
return NULL;
/*@ assert buffer_size >= 512; */
- {
- const uint32_t *fati=(const uint32_t *)(header+1);
- const uint64_t fat_offset=((uint64_t)1+le32(fati[0])) << uSectorShift;
- unsigned int fat_size;
- if(fat_offset > buffer_size)
- return NULL;
- /*@ assert 0 < fat_offset <= buffer_size; */
- fat=(const uint32_t *)&buffer[fat_offset];
- fat_size=(le32(header->num_FAT_blocks) << uSectorShift);
- if(fat_offset + fat_size > buffer_size)
- {
- /*@ assert fat_offset + fat_size <= buffer_size; */
- fat_size=buffer_size - fat_offset;
- }
- fat_entries=fat_size>>2;
- /*@ assert \valid_read(fat + (0 .. fat_entries-1)); */
- }
+ fat_size=(le32(header->num_FAT_blocks) << uSectorShift);
+ fat_entries=fat_size/4;
/* FFFFFFFE = ENDOFCHAIN
* Use a loop count i to avoid endless loop */
#ifdef DEBUG_OLE
@@ -135,7 +272,7 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
#endif
for(block=le32(header->root_start_block), i=0;
block<fat_entries && block!=0xFFFFFFFE && i<fat_entries;
- block=le32(fat[block]), i++)
+ i++)
{
const uint64_t offset_root_dir=((uint64_t)1+block)<<uSectorShift;
#ifdef DEBUG_OLE
@@ -151,6 +288,10 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
/*@ assert \valid_read(dir_entries + (0 .. 512/sizeof(struct OLE_DIR)-1)); */
const char *ext=NULL;
int is_db=0;
+ /*@
+ @ loop invariant ext == \null || ext == extension_xls || ext == extension_psmodel || ext == extension_snt;
+ @ loop assigns ext, is_db, sid;
+ @*/
for(sid=0;
sid<512/sizeof(struct OLE_DIR);
sid++)
@@ -174,124 +315,67 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
(unsigned int)le32(dir_entry->size));
}
#endif
- if(sid==1 && memcmp(&dir_entry->name, "1\0\0\0", 4)==0)
- is_db=1;
- else if(is_db==1 && sid==2 && (memcmp(&dir_entry->name, "2\0\0\0", 4)==0 ||
- memcmp(&dir_entry->name, "C\0a\0t\0a\0l\0o\0g\0", 14)==0))
- is_db=2;
+ {
+ const char *tmp=entry2ext(dir_entry);
+ /*@ assert tmp == \null || valid_read_string(tmp); */
+ if(tmp!=NULL)
+ return tmp;
+ }
switch(le16(dir_entry->namsiz))
{
- case 10:
- if(memcmp(dir_entry->name, ".\0Q\0D\0F\0\0\0",10)==0)
- return "qdf-backup";
+ case 4:
+ if(sid==1 && memcmp(&dir_entry->name, "1\0\0\0", 4)==0)
+ is_db=1;
+ else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "2\0\0\0", 4)==0)
+ is_db=2;
break;
- case 12:
- /* 3ds max */
- if(memcmp(dir_entry->name, "S\0c\0e\0n\0e\0\0\0",12)==0)
- return "max";
- /* Licom AlphaCAM */
- else if(memcmp(dir_entry->name,"L\0i\0c\0o\0m\0\0\0",12)==0)
- return "amb";
+ case 16:
+ if(sid==1 && memcmp(dir_entry->name, "d\0o\0c\0.\0d\0e\0t\0\0\0", 16)==0)
+ ext=extension_psmodel;
+ /* Windows Sticky Notes */
+ else if(sid==1 && memcmp(dir_entry->name, "V\0e\0r\0s\0i\0o\0n\0\0\0", 16)==0)
+ ext=extension_snt;
+ else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "C\0a\0t\0a\0l\0o\0g\0\0\0", 16)==0)
+ is_db=2;
break;
case 18:
/* MS Excel
* Note: Microsoft Works Spreadsheet contains the same signature */
if(memcmp(dir_entry->name, "W\0o\0r\0k\0b\0o\0o\0k\0\0\0",18)==0)
- ext="xls";
- /* Microsoft Works .wps */
- else if(memcmp(dir_entry->name,"C\0O\0N\0T\0E\0N\0T\0S\0\0\0",18)==0)
- return "wps";
- break;
- case 20:
- /* Page Maker */
- if(memcmp(&dir_entry->name, "P\0a\0g\0e\0M\0a\0k\0e\0r\0\0\0", 20)==0)
- return "p65";
- break;
- case 22:
- /* SigmaPlot .jnb */
- if(memcmp(dir_entry->name, "J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0\0\0", 22)==0)
- return "jnb";
- /* Autodesk Inventor part ipt or iam file */
- if(memcmp(dir_entry->name, "R\0S\0e\0S\0t\0o\0r\0a\0g\0e\0\0\0", 22)==0)
- return "ipt";
- break;
- case 24:
- /* HP Photosmart Photo Printing Album */
- if(memcmp(dir_entry->name,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0\0\0",24)==0)
- return "albm";
- /* Lotus Approch */
- if(memcmp(dir_entry->name,"A\0p\0p\0r\0o\0a\0c\0h\0D\0o\0c\0\0\0",24)==0)
- return "apr";
- break;
- case 28:
- /* Microsoft Works Spreadsheet or Chart */
- if(memcmp(dir_entry->name,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0\0\0",28)==0)
- return "xlr";
- /* Visio */
- else if(memcmp(dir_entry->name,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",28)==0)
- return "vsd";
- /* SolidWorks */
- else if(memcmp(&dir_entry->name,"s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0\0\0",28)==0)
- {
-#ifdef DJGPP
- return "sld";
-#else
- return "sldprt";
-#endif
- }
- break;
- case 32:
- /* Revit */
- if(memcmp(dir_entry->name, "R\0e\0v\0i\0t\0P\0r\0e\0v\0i\0e\0w\0004\0.\0000\0\0", 32)==0)
- return "rvt";
- break;
- case 34:
- if(memcmp(dir_entry->name, "S\0t\0a\0r\0C\0a\0l\0c\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",34)==0)
- return "sdc";
+ ext=extension_xls;
break;
case 36:
+ /* sda=StarDraw, sdd=StarImpress */
if(memcmp(dir_entry->name, "S\0t\0a\0r\0D\0r\0a\0w\0D\0o\0c\0u\0m\0e\0n\0t\0003\0\0\0", 36)==0)
- return "sda";
- break;
- case 38:
- /* Quattro Pro spreadsheet */
- if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0\0\0", 38)==0)
- return "qpw";
- else if(memcmp(dir_entry->name, "S\0t\0a\0r\0W\0r\0i\0t\0e\0r\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 38)==0)
- return "sdw";
- break;
- case 40:
- if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0)
- return "ppt";
- /* Outlook */
- else if(memcmp(dir_entry->name,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0\0\0",40)==0)
- return "msg";
- break;
- case 46:
- if(memcmp(dir_entry->name,
- "I\0S\0o\0l\0i\0d\0W\0o\0r\0k\0s\0I\0n\0f\0o\0r\0m\0a\0t\0i\0o\0n\0\0\0", 46)==0)
- {
-#ifdef DJGPP
- return "sld";
-#else
- return "sldprt";
-#endif
- }
- break;
- case 56:
- /* Wilcom ES Software */
- if(memcmp(dir_entry->name, WilcomDesignInformationDDD, 56)==0)
- return "emb";
+ return extension_sda;
break;
}
if(sid==1 && memcmp(&dir_entry->name, "D\0g\0n", 6)==0)
- return "dgn";
+ return extension_dgn;
}
if(ext!=NULL)
+ {
+ /*@ assert ext == extension_xls || ext == extension_psmodel || ext == extension_snt; */
return ext;
+ }
/* Thumbs.db */
if(is_db==2)
- return "db";
+ return extension_db;
+ }
+ {
+ const uint32_t *fati=(const uint32_t *)(header+1);
+ const uint64_t fat_offset=((uint64_t)1+le32(fati[0])) << uSectorShift;
+ unsigned int fat_test_size;
+ const uint32_t *val32_ptr;
+ if(fat_offset >= buffer_size)
+ return NULL;
+ /*@ assert 0 < fat_offset < buffer_size; */
+ fat_test_size=fat_offset+block*4;
+ if(fat_test_size + 4 > buffer_size)
+ return NULL;
+ /*@ assert fat_test_size + 4 <= buffer_size; */
+ val32_ptr=(const uint32_t *)&buffer[fat_test_size];
+ block=le32(*val32_ptr);
}
}
#ifdef DEBUG_OLE
@@ -301,8 +385,77 @@ static const char *ole_get_file_extension(const unsigned char *buffer, const uns
}
/*@
+ @ requires \valid(IN);
+ @ requires \valid_read(header);
+ @ requires le32(header->num_FAT_blocks) > 0;
+ @ requires 0 <= le32(header->num_extra_FAT_blocks)<= 50;
+ @ requires 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift);
+ @ requires le32(header->num_FAT_blocks) <= 109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))/4-1);
+ @ requires \separated(IN, header);
+ @ ensures \result==\null || \valid_read((const char *)\result + ( 0 .. (le32(header->num_FAT_blocks)<<le16(header->uSectorShift))-1));
+ @*/
+static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header, const uint64_t offset)
+{
+ uint32_t *fat;
+ uint32_t *dif;
+ const unsigned int uSectorShift=le16(header->uSectorShift);
+ const unsigned int num_FAT_blocks=le32(header->num_FAT_blocks);
+ const unsigned int num_extra_FAT_blocks=le32(header->num_extra_FAT_blocks);
+ /*@ assert uSectorShift == le16(header->uSectorShift); */
+ /*@ assert num_FAT_blocks==le32(header->num_FAT_blocks); */
+ /*@ assert num_FAT_blocks <= 109+le32(header->num_extra_FAT_blocks)*((1<<uSectorShift)/4-1); */
+ const unsigned int dif_size=109*4+(le32(header->num_extra_FAT_blocks)<<uSectorShift);
+ /*@ assert 109*4 <= dif_size <= 109*4+(50<<12); */
+#ifdef __FRAMAC__
+ dif=(uint32_t*)MALLOC(109*4+(50<<12));
+#else
+ dif=(uint32_t*)MALLOC(dif_size);
+#endif
+ /*@ assert \valid((char *)dif+(0..dif_size-1)); */
+ memcpy(dif,(header+1),109*4);
+ if(num_extra_FAT_blocks > 0)
+ { /* Load DIF*/
+ unsigned long int i;
+ for(i=0; i<le32(header->num_extra_FAT_blocks); i++)
+ {
+ const unsigned int block=(i==0 ? le32(header->FAT_next_block) : le32(dif[109+i*(((1<<uSectorShift)/4)-1)]));
+ unsigned char *data=(unsigned char*)&dif[109]+i*((1<<uSectorShift)-4);
+ if(OLE_read_block(IN, data, uSectorShift, block, offset) < 0)
+ {
+ free(dif);
+ return NULL;
+ }
+ }
+ }
+#ifdef __FRAMAC__
+ /*@ assert (109+50*((1<<12)/4-1))<<12 >= num_FAT_blocks<<uSectorShift; */
+ fat=(uint32_t*)MALLOC((109+50*((1<<12)/4-1))<<12);
+#else
+ fat=(uint32_t*)MALLOC(num_FAT_blocks<<uSectorShift);
+#endif
+ /*@ assert \valid((char *)fat + (0 .. (num_FAT_blocks<<uSectorShift)-1)); */
+ { /* Load FAT */
+ unsigned int j;
+ for(j=0; j<num_FAT_blocks; j++)
+ {
+ if(OLE_read_block(IN, (char*)fat + (j<<uSectorShift), uSectorShift, le32(dif[j]), offset)<0)
+ {
+ free(dif);
+ free(fat);
+ return NULL;
+ }
+ }
+ }
+ free(dif);
+ return fat;
+}
+
+
+/*@
@ requires \valid(file_recovery);
@ requires \valid(file_recovery->handle);
+ @ requires \separated(file_recovery, file_recovery->handle);
+ @ ensures \valid(file_recovery->handle);
@*/
void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset)
{
@@ -416,7 +569,7 @@ void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset)
#else
dir_entries=(struct OLE_DIR *)MALLOC(1<<uSectorShift);
#endif
- if(OLE_read_block(file_recovery->handle, (unsigned char *)dir_entries, uSectorShift, block, offset)<0)
+ if(OLE_read_block(file_recovery->handle, (char *)dir_entries, uSectorShift, block, offset)<0)
{
#ifdef DEBUG_OLE
log_info("OLE_read_block failed\n");
@@ -459,6 +612,9 @@ void file_check_doc_aux(file_recovery_t *file_recovery, const uint64_t offset)
/*@
@ requires \valid(file_recovery);
@ requires \valid(file_recovery->handle);
+ @ requires \separated(file_recovery, file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_doc;
+ @ ensures \valid(file_recovery->handle);
@*/
static void file_check_doc(file_recovery_t *file_recovery)
{
@@ -466,200 +622,11 @@ static void file_check_doc(file_recovery_t *file_recovery)
}
/*@
- @ requires buffer_size >= sizeof(struct OLE_HDR);
- @ requires \valid_read(buffer+(0..buffer_size-1));
- @ requires \valid_read(file_recovery);
- @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
- @ requires \valid(file_recovery_new);
- @ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
- @ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_doc);
- @ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_doc);
- @ ensures (\result == 1) ==> valid_read_string(file_recovery_new->extension);
- @*/
-static int header_check_doc(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
-{
- /*@ assert file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename); */
- const struct OLE_HDR *header=(const struct OLE_HDR *)buffer;
- /* Check for Little Endian */
- if(le16(header->uByteOrder)!=0xFFFE)
- return 0;
- if(le16(header->uDllVersion)!=3 && le16(header->uDllVersion)!=4)
- return 0;
- if(le16(header->reserved)!=0 || le32(header->reserved1)!=0)
- return 0;
- if(le16(header->uMiniSectorShift)!=6)
- return 0;
- if(le16(header->uDllVersion)==3 && le16(header->uSectorShift)!=9)
- return 0;
- /* max and qbb file have uSectorShift=12 */
- if(le16(header->uDllVersion)==4 && le16(header->uSectorShift)!=12)
- return 0;
- if(le16(header->uDllVersion)==3 && le32(header->csectDir)!=0)
- return 0;
- /* max file have csectDir=1
- * qbb file have csectDir=4 */
- if(le16(header->uDllVersion)==4 && le32(header->csectDir)==0)
- return 0;
- /*
- num_FAT_blocks=109+num_extra_FAT_blocks*(512-1);
- maximum file size is 512+(num_FAT_blocks*128)*512, about 1.6GB
- */
- if(le32(header->num_FAT_blocks)==0 ||
- le32(header->num_extra_FAT_blocks)>50 ||
- le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))/4-1))
- return 0;
- /*@ assert file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename); */
- reset_file_recovery(file_recovery_new);
- file_recovery_new->file_check=&file_check_doc;
- file_recovery_new->file_rename=&file_rename_doc;
- file_recovery_new->extension=ole_get_file_extension(buffer, buffer_size);
- if(file_recovery_new->extension!=NULL)
- {
- if(strcmp(file_recovery_new->extension,"sda")==0)
- {
- if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL)
- file_recovery_new->extension="sdd";
- }
- else if(strcmp(file_recovery_new->extension,"wps")==0)
- {
- /* Distinguish between MS Works .wps and MS Publisher .pub */
- if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL)
- file_recovery_new->extension="pub";
- }
- return 1;
- }
- if(td_memmem(buffer,buffer_size,"WordDocument",12)!=NULL)
- {
- file_recovery_new->extension="doc";
- }
- else if(td_memmem(buffer,buffer_size,"StarDraw",8)!=NULL)
- {
- file_recovery_new->extension="sda";
- }
- else if(td_memmem(buffer,buffer_size,"StarCalc",8)!=NULL)
- {
- file_recovery_new->extension="sdc";
- }
- else if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL)
- {
- file_recovery_new->extension="sdd";
- }
- else if(td_memmem(buffer,buffer_size,"Worksheet",9)!=NULL ||
- td_memmem(buffer,buffer_size,"Book",4)!=NULL ||
- td_memmem(buffer,buffer_size,"Workbook",8)!=NULL ||
- td_memmem(buffer,buffer_size,"Calc",4)!=NULL)
- {
- file_recovery_new->extension="xls";
- }
- else if(td_memmem(buffer,buffer_size,"Power",5)!=NULL)
- {
- file_recovery_new->extension="ppt";
- }
- else if(td_memmem(buffer,buffer_size,"AccessObjSiteData",17)!=NULL)
- {
- file_recovery_new->extension="mdb";
- }
- else if(td_memmem(buffer,buffer_size,"Visio",5)!=NULL)
- {
- file_recovery_new->extension="vsd";
- }
- else if(td_memmem(buffer,buffer_size,"SfxDocument",11)!=NULL)
- {
- file_recovery_new->extension="sdw";
- }
- else if(td_memmem(buffer,buffer_size,"CPicPage",8)!=NULL)
- { /* Flash Project File */
- file_recovery_new->extension="fla";
- }
- else if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL)
- { /* Publisher */
- file_recovery_new->extension="pub";
- }
- else if(td_memmem(buffer, buffer_size, "Microsoft Works Database", 24)!=NULL
- || td_memmem( buffer, buffer_size, "MSWorksDBDoc", 12)!=NULL)
- { /* Microsoft Works .wdb */
- file_recovery_new->extension="wdb";
- }
- else if(td_memmem(buffer,buffer_size,"MetaStock",9)!=NULL)
- { /* MetaStock */
- file_recovery_new->extension="mws";
- }
- else
- file_recovery_new->extension=file_hint_doc.extension;
- return 1;
-}
-
-/*@
- @ requires \valid(IN);
- @ requires \valid_read(header);
- @ requires le32(header->num_FAT_blocks) > 0;
- @ requires 0 <= le32(header->num_extra_FAT_blocks)<= 50;
- @ requires 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift);
- @ requires le32(header->num_FAT_blocks) <= 109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))/4-1);
- @ ensures \result==\null || \valid_read((const char *)\result + ( 0 .. (le32(header->num_FAT_blocks)<<le16(header->uSectorShift))-1));
- @*/
-static uint32_t *OLE_load_FAT(FILE *IN, const struct OLE_HDR *header, const uint64_t offset)
-{
- uint32_t *fat;
- uint32_t *dif;
- const unsigned int uSectorShift=le16(header->uSectorShift);
- const unsigned int num_FAT_blocks=le32(header->num_FAT_blocks);
- /*@ assert uSectorShift == le16(header->uSectorShift); */
- /*@ assert num_FAT_blocks==le32(header->num_FAT_blocks); */
- /*@ assert num_FAT_blocks <= 109+le32(header->num_extra_FAT_blocks)*((1<<uSectorShift)/4-1); */
- const unsigned int dif_size=109*4+(le32(header->num_extra_FAT_blocks)<<uSectorShift);
- /*@ assert 109*4 <= dif_size <= 109*4+(50<<12); */
-#ifdef __FRAMAC__
- dif=(uint32_t*)MALLOC(109*4+(50<<12));
-#else
- dif=(uint32_t*)MALLOC(dif_size);
-#endif
- /*@ assert \valid((char *)dif+(0..dif_size-1)); */
- memcpy(dif,(header+1),109*4);
- if(le32(header->num_extra_FAT_blocks)>0)
- { /* Load DIF*/
- unsigned long int i;
- for(i=0; i<le32(header->num_extra_FAT_blocks); i++)
- {
- const unsigned int block=(i==0 ? le32(header->FAT_next_block) : le32(dif[109+i*(((1<<uSectorShift)/4)-1)]));
- unsigned char *data=(unsigned char*)&dif[109]+i*((1<<uSectorShift)-4);
- if(OLE_read_block(IN, data, uSectorShift, block, offset) < 0)
- {
- free(dif);
- return NULL;
- }
- }
- }
-#ifdef __FRAMAC__
- /*@ assert (109+50*((1<<12)/4-1))<<12 >= num_FAT_blocks<<uSectorShift; */
- fat=(uint32_t*)MALLOC((109+50*((1<<12)/4-1))<<12);
-#else
- fat=(uint32_t*)MALLOC(num_FAT_blocks<<uSectorShift);
-#endif
- /*@ assert \valid((char *)fat + (0 .. (num_FAT_blocks<<uSectorShift)-1)); */
- { /* Load FAT */
- unsigned int j;
- for(j=0; j<num_FAT_blocks; j++)
- {
- if(OLE_read_block(IN, (unsigned char*)fat + (j<<uSectorShift), uSectorShift, le32(dif[j]), offset)<0)
- {
- free(dif);
- free(fat);
- return NULL;
- }
- }
- }
- free(dif);
- return fat;
-}
-
-/*@
@ requires \valid(IN);
@ requires \valid_read(fat + (0 .. fat_entries-1));
@ requires 9 == uSectorShift || 12 == uSectorShift;
@ requires 0 < len <= 1024*1024;
+ @ requires \separated(IN, fat + (..), &errno, &Frama_C_entropy_source);
@ ensures \result!=\null ==> \valid((char *)\result + (0 .. len - 1));
@*/
static void *OLE_read_stream(FILE *IN,
@@ -667,14 +634,14 @@ static void *OLE_read_stream(FILE *IN,
const unsigned int block_start, const unsigned int len, const uint64_t offset)
{
//@ split uSectorShift;
- unsigned char *dataPt;
+ char *dataPt;
unsigned int block;
unsigned int i;
const unsigned int i_max=((len+(1<<uSectorShift)-1) >> uSectorShift);
#ifdef __FRAMAC__
- dataPt=(unsigned char *)MALLOC(((1024*1024+(1<<uSectorShift)-1) >> uSectorShift) << uSectorShift);
+ dataPt=(char *)MALLOC(((1024*1024+(1<<uSectorShift)-1) >> uSectorShift) << uSectorShift);
#else
- dataPt=(unsigned char *)MALLOC(i_max << uSectorShift);
+ dataPt=(char *)MALLOC(i_max << uSectorShift);
#endif
/*@ assert \valid(dataPt + ( 0 .. len-1)); */
for(i=0, block=block_start;
@@ -692,6 +659,7 @@ static void *OLE_read_stream(FILE *IN,
return NULL;
}
}
+ /*@ assert \valid(dataPt + (0 .. len - 1)); */
return dataPt;
}
@@ -709,24 +677,27 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const
unsigned int block;
unsigned int i;
const unsigned int uSectorShift=le16(header->uSectorShift);
- if(le32(header->csectMiniFat)==0)
+ /*@ assert uSectorShift==9 || uSectorShift==12; */
+ const unsigned int csectMiniFat=le32(header->csectMiniFat);
+ if(csectMiniFat==0)
return NULL;
- /*@ assert le32(header->csectMiniFat)!=0; */
+ /*@ assert 0 < csectMiniFat; */
+ /*@ assert 0 < csectMiniFat <= 2048; */
#ifdef __FRAMAC__
minifat=(uint32_t*)MALLOC(2048 << 12);
#else
- minifat=(uint32_t*)MALLOC(le32(header->csectMiniFat) << uSectorShift);
+ minifat=(uint32_t*)MALLOC(csectMiniFat << uSectorShift);
#endif
block=le32(header->MiniFat_block);
- for(i=0; i < le32(header->csectMiniFat); i++)
+ for(i=0; i < csectMiniFat; i++)
{
- unsigned char*minifat_pos=(unsigned char*)minifat + (i << uSectorShift);
+ char *minifat_pos=(char*)minifat + (i << uSectorShift);
if(block >= fat_entries)
{
free(minifat);
return NULL;
}
- if(OLE_read_block(IN, (unsigned char *)minifat_pos, uSectorShift, block, offset)<0)
+ if(OLE_read_block(IN, minifat_pos, uSectorShift, block, offset)<0)
{
free(minifat);
return NULL;
@@ -738,15 +709,24 @@ static uint32_t *OLE_load_MiniFAT(FILE *IN, const struct OLE_HDR *header, const
/*@
@ requires \valid_read((char *)buffer + (offset .. offset + 4 - 1));
+ @ requires \initialized((char *)buffer + (offset .. offset + 4 - 1));
+ @ assigns \nothing;
@*/
static uint32_t get32u(const void *buffer, const unsigned int offset)
{
- const uint32_t *val=(const uint32_t *)((const unsigned char *)buffer+offset);
+ /*@ assert \valid_read((char *)buffer + offset + (0 .. 4-1)); */
+ /*@ assert \initialized((char *)buffer + offset + (0 .. 4-1)); */
+ const char *ptr=(const char *)buffer+offset;
+ /*@ assert \valid_read(ptr + (0 .. 4-1)); */
+ /*@ assert \initialized(ptr + (0 .. 4-1)); */
+ const uint32_t *val=(const uint32_t *)ptr;
return le32(*val);
}
/*@
@ requires \valid_read((char *)buffer + (offset .. offset + 8 - 1));
+ @ requires \initialized((char *)buffer + (offset .. offset + 8 - 1));
+ @ assigns \nothing;
@*/
static uint64_t get64u(const void *buffer, const unsigned int offset)
{
@@ -760,59 +740,115 @@ static uint64_t get64u(const void *buffer, const unsigned int offset)
@ requires count > 0;
@ requires \valid_read(software + (0 .. count-1));
@ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
@*/
-static void software2ext(const char **ext, const unsigned int count, const unsigned char *software)
+static void software2ext(const char **ext, const char *software, const unsigned int count)
{
- if(count>=12 && memcmp(software, "MicroStation", 12)==0)
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ if(count>=12)
{
- *ext="dgn";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "MicroStation", 12)==0)
+ {
+ *ext=extension_dgn;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=14 && memcmp(software, "Microsoft Word", 14)==0)
+ if(count>=14)
{
- *ext="doc";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Word", 14)==0)
+ {
+ *ext=file_hint_doc.extension;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=15 && memcmp(software, "Microsoft Excel", 15)==0)
+ if(count>=15)
{
- if(*ext==NULL || strcmp(*ext,"sldprt")!=0)
- *ext="xls";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Excel", 15)==0)
+ {
+ if(*ext==NULL || strcmp(*ext,"sldprt")!=0)
+ {
+ *ext=extension_xls;
+ /*@ assert valid_read_string(*ext); */
+ }
+ return;
+ }
}
- if(count>=20 && memcmp(software, "Microsoft PowerPoint", 20)==0)
+ if(count>=20)
{
- *ext="ppt";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft PowerPoint", 20)==0)
+ {
+ *ext=extension_ppt;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count>=21 && memcmp(software, "Microsoft Office Word", 21)==0)
+ if(count>=21)
{
- *ext="doc";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "Microsoft Office Word", 21)==0)
+ {
+ *ext=file_hint_doc.extension;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count==21 && memcmp(software, "TurboCAD for Windows", 21)==0)
+ if(count==21)
{
- *ext="tcw";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "TurboCAD for Windows", 21)==0)
+ {
+ *ext=extension_tcw;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
- if(count==22 && memcmp(software, "TurboCAD pour Windows", 22)==0)
+ if(count==22)
{
- *ext="tcw";
- return;
+ /*@ assert \valid_read(software + (0 .. count-1)); */
+ if(memcmp(software, "TurboCAD pour Windows", 22)==0)
+ {
+ *ext=extension_tcw;
+ /*@ assert valid_read_string(*ext); */
+ return;
+ }
}
+ /*@ assert *ext == \null || valid_read_string(*ext); */
return ;
}
/*@
@ requires count > 0;
@ requires \valid_read(software + (0 .. 2*count-1));
+ @ ensures \result == \null || \result == extension_et || \result == extension_psmodel;
@ ensures \result == \null || valid_read_string(\result);
+ @ assigns \nothing;
@*/
-static const char *software_uni2ext(const unsigned int count, const unsigned char *software)
+static const char *software_uni2ext(const char *software, const unsigned int count)
{
- if(count>=15 && memcmp(software, "M\0i\0c\0r\0o\0s\0o\0f\0t\0 \0E\0x\0c\0e\0l\0", 30)==0)
- return "et";
- if(count>=17 && memcmp(software, "D\0e\0l\0c\0a\0m\0 \0P\0o\0w\0e\0r\0S\0H\0A\0P\0E\0", 34)==0)
- return "psmodel";
+ if(count>=15)
+ {
+ /*@ assert \valid_read(software + (0 .. 2*count-1)); */
+ if(memcmp(software, "M\0i\0c\0r\0o\0s\0o\0f\0t\0 \0E\0x\0c\0e\0l\0", 30)==0)
+ {
+ /*@ assert valid_read_string(extension_et); */
+ return extension_et;
+ }
+ }
+ if(count>=17)
+ {
+ /*@ assert \valid_read(software + (0 .. 2*count-1)); */
+ if(memcmp(software, "D\0e\0l\0c\0a\0m\0 \0P\0o\0w\0e\0r\0S\0H\0A\0P\0E\0", 34)==0)
+ {
+ /*@ assert valid_read_string(extension_psmodel); */
+ return extension_psmodel;
+ }
+ }
return NULL;
}
@@ -825,15 +861,309 @@ struct summary_entry
/*@
@ requires 8 <= size <= 1024*1024;
@ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \initialized(buffer+ (0 .. size-1));
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires *ext == \null || valid_read_string(*ext);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
+ @*/
+static void OLE_parse_software_entry(const char *buffer, const unsigned int size, const unsigned int offset, const char **ext)
+{
+ if(offset >= size - 8)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert offset < size - 8; */
+ {
+ const unsigned int count=get32u(buffer, offset + 4);
+ const unsigned int offset_soft=offset + 8;
+ /*@ assert offset_soft == offset + 8; */
+ if(count == 0 || count > size)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert 0 < count <= size; */
+ if(offset_soft + count > size)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert offset_soft + count <= size; */
+ /*@ assert \valid_read(buffer + (0 .. size-1)); */
+ /*@ assert \forall int j; (0 <= j < size ) ==> \valid_read(buffer + j + (0 .. size-1-j)); */
+ /*@ assert 0 <= offset_soft < size; */
+ /*@ assert \valid_read(buffer + offset_soft + (0 .. size - offset_soft -1)); */
+ /*@ assert 0 < count <= size - offset_soft; */
+ /*@ assert \valid_read(buffer + offset_soft + (0 .. count -1)); */
+
+ /*@ assert offset_soft + count <= size; */
+ /*@ assert count <= size - offset_soft; */
+ /*@ assert \valid_read(buffer + (0 .. size-1)); */
+ /*@ assert \valid_read(buffer + (0 .. offset_soft + count -1)); */
+#ifdef DEBUG_OLE
+ {
+ unsigned int j;
+ log_info("Software ");
+ for(j=0; j<count; j++)
+ {
+ /*@ assert 0 <= j < count; */
+ /*@ assert offset_soft + count <= size; */
+ const unsigned int tmp=offset_soft+j;
+ /*@ assert tmp < size; */
+ log_info("%c", buffer[tmp]);
+ }
+ log_info("\n");
+ }
+#endif
+ software2ext(ext, &buffer[offset_soft], count);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \initialized(buffer+ (0 .. size-1));
+ @ requires \valid(ext);
+ @ requires *ext == \null || valid_read_string(*ext);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ assigns *ext;
+ @*/
+static void OLE_parse_uni_software_entry(const char *buffer, const unsigned int size, const unsigned int offset, const char **ext)
+{
+ if(offset >= size - 8)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert offset < size - 8; */
+ {
+ const unsigned int offset_soft=offset + 8;
+ /*@ assert offset_soft < size; */
+ const unsigned int count=get32u(buffer, offset + 4);
+ unsigned int count2;
+ if(count == 0 || count > size/2)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert 0 < count <= size/2; */
+ count2=2*count;
+ /*@ assert 0 < count2 <= size; */
+ if(count2 > size - offset_soft)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ return ;
+ }
+ /*@ assert count2 <= size - offset_soft; */
+ /*@ assert offset_soft + count2 <= size; */
+ /*@ assert \valid_read(buffer + (0 .. size - 1)) && \initialized(buffer + (0 .. size - 1)); */
+ /*@ assert \valid_read(buffer + (0 .. offset_soft + count2 - 1)); */
+#ifdef DEBUG_OLE
+ {
+ unsigned int j;
+ log_info("Software ");
+ for(j=0; j < count2; j+=2)
+ {
+ /*@ assert 0 <= j < count2; */
+ /*@ assert offset_soft + count2 <= size; */
+ const unsigned int tmp=offset_soft + j;
+ /*@ assert tmp < size; */
+ log_info("%c", buffer[tmp]);
+ }
+ log_info("\n");
+ }
+#endif
+ *ext=software_uni2ext(&buffer[offset_soft], count);
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \valid(title + (0 .. 1024-1));
+ @ requires valid_string(title);
+ @ requires \initialized(buffer+ (0 .. size-1));
+ @ ensures valid_string(title);
+ @ assigns *(title + (0 .. 1023));
+ @*/
+static void OLE_parse_title_entry(const char *buffer, const unsigned int size, const unsigned int offset, char *title)
+{
+ if(offset + 8 > size)
+ {
+ return;
+ }
+ /*@ assert offset + 8 <= size; */
+ {
+ /*@ assert \valid_read(buffer + (0 .. size - 1)); */
+ const unsigned int count=get32u(buffer, offset + 4);
+ const unsigned int offset_tmp=offset + 8;
+ const char *src=(const char *)buffer;
+ if(count <= 1 || count > size)
+ {
+ return;
+ }
+ /*@ assert 1 < count <= size; */
+ /*@ assert 1 < count <= 1024*1024; */
+ if(offset_tmp + count > size)
+ {
+ return;
+ }
+ /*@ assert offset_tmp + count <= size; */
+ /*@ assert \valid_read(src + (0 .. size - 1)); */
+ /*@ assert offset_tmp + count <= size; */
+ /*@ assert \valid_read(src + (0 .. offset_tmp + count - 1)); */
+ /*@ assert \valid_read((src + offset_tmp) + (0 .. count - 1)); */
+ /*@ assert \valid_read((src + offset_tmp) + (1 .. count - 1)); */
+ /*@ assert \valid_read((char*)src + (0 .. offset_tmp + count - 1)); */
+ /*@ assert \valid_read(((char*)(src+offset_tmp))+(0..count-1)); */
+ /*@ assert \valid_read(((char*)(src+offset_tmp))+(1..count-1)); */
+ /*@ assert \valid_read((char*)(src + offset_tmp)); */
+ /*@ assert \valid_read((char*)(src + offset_tmp)) && \valid_read(((char*)(src+offset_tmp))+(1..count-1)); */
+ /*@ assert valid_read_or_empty((void const *)(src + offset_tmp), count); */
+ /*@ assert valid_read_or_empty((void const *)(src + offset_tmp), count); */
+#ifndef __FRAMAC__
+ if(count < 1024)
+ {
+ memcpy(title, &src[offset_tmp], count);
+ title[count]='\0';
+ /*@ assert valid_string(title); */
+ }
+ else
+ {
+ memcpy(title, &src[offset_tmp], 1023);
+ title[1023]='\0';
+ /*@ assert valid_string(title); */
+ }
+#endif
+#ifdef DEBUG_OLE
+ log_info("Title %s\n", title);
+#endif
+ }
+ /*@ assert valid_string(title); */
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \initialized(buffer+ (0 .. size-1));
+ @ requires \valid(file_time);
+ @ assigns *file_time;
+ @*/
+static void OLE_parse_filetime_entry(const char *buffer, const unsigned int size, const unsigned int offset, time_t *file_time)
+{
+ uint64_t tmp;
+ if(offset + 12 > size)
+ {
+ return ;
+ }
+ /*@ assert offset + 12 <= size; */
+ tmp=get64u(buffer, offset + 4);
+ tmp/=10000000;
+ if(tmp > (uint64_t)134774 * 24 * 3600)
+ {
+ tmp -= (uint64_t)134774 * 24 * 3600;
+ *file_time=tmp;
+ }
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \initialized(buffer+ (0 .. size-1));
+ @ requires \valid(ext);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires \valid_read(entry);
@ requires *ext == \null || valid_read_string(*ext);
- @ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ requires valid_string(title);
+ @ requires separation: \separated(buffer+(..), ext, title + ( 0 .. 1023), file_time);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ ensures valid_string(title);
+ @ assigns *ext, *(title + (0..1023)), *file_time;
@*/
-static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned int size, const char **ext, char **title, time_t *file_time)
+static void OLE_parse_PropertySet_entry(const char *buffer, const unsigned int size, const struct summary_entry *entry, const char **ext, char *title, time_t *file_time)
+{
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_read_string(title); */
+ const unsigned int tag=le32(entry->tag);
+ const unsigned int offset=le32(entry->offset);
+ unsigned int type;
+ if(offset >= size - 4)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /*@ assert offset < size - 4; */
+ /*@ assert \valid_read(buffer + (0 .. offset + 4 - 1)); */
+ type=get32u(buffer, offset);
+#ifdef DEBUG_OLE
+ log_info("entry 0x%x, tag 0x%x, offset 0x%x, offset + 4 0x%x, type 0x%x\n",
+ entry_offset, tag, offset, offset + 4, type);
+#endif
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ /* tag: Software, type: VT_LPSTR */
+ if(tag==0x12 && type==30)
+ {
+ /*@ assert valid_string(title); */
+ OLE_parse_software_entry(buffer, size, offset, ext);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /* tag: Software, type: VT_LPWSTR */
+ if(tag==0x12 && type==31)
+ {
+ /*@ assert valid_string(title); */
+ OLE_parse_uni_software_entry(buffer, size, offset, ext);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /* tag: title, type: VT_LPSTR */
+ if(tag==0x02 && type==30 && title[0]=='\0')
+ {
+ OLE_parse_title_entry(buffer, size, offset, title);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return ;
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ /* ModifyDate, type=VT_FILETIME */
+ if(tag==0x0d && type==64)
+ {
+ OLE_parse_filetime_entry(buffer, size, offset, file_time);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return;
+}
+
+/*@
+ @ requires 8 <= size <= 1024*1024;
+ @ requires \valid_read(buffer+ (0 .. size-1));
+ @ requires \initialized(buffer+ (0 .. size-1));
+ @ requires \valid(ext);
+ @ requires \valid(title + (0 .. 1024-1));
+ @ requires \valid(file_time);
+ @ requires valid_string(title);
+ @ requires *ext == \null || valid_read_string(*ext);
+ @ requires separation: \separated(buffer+(..), ext, title + (0 .. 1023), file_time);
+ @ ensures *ext == \null || valid_read_string(*ext);
+ @ ensures valid_string(title);
+ @ assigns *ext, *(title + (0..1023)), *file_time;
+ @*/
+static void OLE_parse_PropertySet(const char *buffer, const unsigned int size, const char **ext, char *title, time_t *file_time)
{
const struct summary_entry *entries=(const struct summary_entry *)&buffer[8];
const unsigned int numEntries=get32u(buffer, 4);
@@ -841,197 +1171,131 @@ static void OLE_parse_PropertySet(const unsigned char *buffer, const unsigned in
#ifdef DEBUG_OLE
log_info("Property Info %u entries - %u bytes\n", numEntries, size);
#endif
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
if(numEntries == 0 || numEntries > 1024*1024)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
/*@ assert 0 < numEntries <= 1024*1024; */
if(8 + numEntries * 8 > size)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
/*@ assert 8 + numEntries * 8 <= size; */
/*@ assert numEntries * 8 <= size - 8; */
/*@ assert numEntries < size/8; */
- if((const unsigned char *)&entries[numEntries] > &buffer[size])
+ if((const char *)&entries[numEntries] > &buffer[size])
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
- /*TODO assert (const unsigned char *)&entries[numEntries] <= &buffer[size]; */
+ }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
/*@ assert \valid_read(buffer + (0 .. size - 1)); */
/*@ assert \valid_read((buffer+8) + (8 .. size - 8 - 1)); */
- /*TODO assert \valid_read((char *)entries + (0 .. size - 8 - 1)); */
- /*TODO assert \valid_read(entries + (0 .. numEntries-1)); */
/*@
+ @ loop invariant *ext == \null || valid_read_string(*ext);
+ @ loop invariant valid_string(title);
@ loop invariant 0 <= i <= numEntries;
+ @ loop assigns i, *ext, *(title + (0..1023)), *file_time;
@ loop variant numEntries-i;
@*/
for(i=0; i<numEntries; i++)
{
- // const struct summary_entry *entry=&entries[i];
+ const struct summary_entry *entry;
const unsigned int entry_offset=8+8*i;
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
if(entry_offset + 8 > size)
- return ;
- /*@ assert entry_offset + 8 <= size; */
{
- const struct summary_entry *entry=(const struct summary_entry *)&buffer[entry_offset];
- const unsigned int tag=le32(entry->tag);
- const unsigned int offset=le32(entry->offset);
- unsigned int type;
- if(offset >= size - 4)
- return ;
- /*@ assert offset < size - 4; */
- /*@ assert \valid_read(buffer + (0 .. offset + 4 - 1)); */
- type=get32u(buffer, offset);
-#ifdef DEBUG_OLE
- log_info("entry 0x%x, tag 0x%x, offset 0x%x, offset + 4 0x%x, type 0x%x\n",
- entry, tag, offset, offset + 4, type);
-#endif
- /* tag: Software, type: VT_LPSTR */
- if(tag==0x12 && type==30)
- {
- if(offset >= size - 8)
- return ;
- /*@ assert offset < size - 8; */
- {
- const unsigned int count=get32u(buffer, offset + 4);
- const unsigned int offset_soft=offset + 8;
- /*@ assert offset_soft == offset + 8; */
- if(count > size)
- return ;
- /*@ assert count <= size; */
- if(offset_soft + count > size)
- return ;
- /*@ assert offset_soft + count <= size; */
- if(count > 0)
- {
- /*@ assert count > 0; */
-#ifdef DEBUG_OLE
- unsigned int j;
- log_info("Software ");
- for(j=0; j<count; j++)
- {
- log_info("%c", buffer[offset_soft + j]);
- }
- log_info("\n");
-#endif
- software2ext(ext, count, &buffer[offset_soft]);
- }
- }
- }
- /* tag: Software, type: VT_LPWSTR */
- if(tag==0x12 && type==31)
- {
- if(offset >= size - 8)
- return ;
- /*@ assert offset < size - 8; */
- {
- const unsigned int count=get32u(buffer, offset + 4);
- if(count > size)
- return ;
- /*@ assert count <= size; */
- if(offset + 8 + 2 * count > size)
- return ;
- /*@ assert offset + 8 + 2 * count <= size; */
- if(count > 0)
- {
- /*@ assert count > 0; */
-#ifdef DEBUG_OLE
- unsigned int j;
- log_info("Software ");
- for(j=0; j < 2 * count; j+=2)
- {
- log_info("%c", buffer[offset + 8 + j]);
- }
- log_info("\n");
-#endif
- *ext=software_uni2ext(count, &buffer[offset + 8]);
- }
- }
- }
- /* tag: title, type: VT_LPSTR */
- if(tag==0x02 && type==30 && *title==NULL)
- {
- if(offset + 8 > size)
- return ;
- /*@ assert offset + 8 <= size; */
- {
- /*@ assert \valid_read(buffer + (0 .. size - 1)); */
- const unsigned int count=get32u(buffer, offset + 4);
- const unsigned int offset_tmp=offset + 8;
- if(count > size)
- return ;
- /*@ assert count <= size; */
- if(offset_tmp + count > size)
- return ;
- /*@ assert offset_tmp + count <= size; */
- if(count > 0)
- {
- /*@ assert count > 0; */
- char *tmp;
- /*@ assert \valid_read(buffer + (0 .. size - 1)); */
- /*@ assert \valid_read(buffer + (0 .. offset_tmp + count - 1)); */
- tmp=(char*)MALLOC(count+1);
- memcpy(tmp, &buffer[offset_tmp], count);
- tmp[count]='\0';
-#ifdef DEBUG_OLE
- log_info("Title %s\n", tmp);
-#endif
- *title=tmp;
- }
- }
- }
- /* ModifyDate, type=VT_FILETIME */
- if(tag==0x0d && type==64)
- {
- uint64_t tmp;
- if(offset + 12 > size)
- return ;
- /*@ assert offset + 12 <= size; */
- tmp=get64u(buffer, offset + 4);
- tmp/=10000000;
- if(tmp > (uint64_t)134774 * 24 * 3600)
- {
- tmp -= (uint64_t)134774 * 24 * 3600;
- *file_time=tmp;
- }
- }
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ return ;
}
+ /*@ assert entry_offset + 8 <= size; */
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
+ entry=(const struct summary_entry *)&buffer[entry_offset];
+ OLE_parse_PropertySet_entry(buffer, size, entry, ext, title, file_time);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
}
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
}
/*@
@ requires 48 <= dirLen <= 1024*1024;
@ requires \valid_read(dataPt + (0 .. dirLen-1));
+ @ requires \initialized(dataPt + (0 .. dirLen-1));
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires valid_string(title);
@ requires *ext == \null || valid_read_string(*ext);
+ @ requires separation: \separated(dataPt+(..), ext, title + (0 .. 1023), file_time);
@ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
@*/
-static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned int dirLen, const char **ext, char **title, time_t *file_time)
+/*X TODO assigns *ext, *(title + (0..1023)), *file_time; */
+static void OLE_parse_summary_aux(const char *dataPt, const unsigned int dirLen, const char **ext, char *title, time_t *file_time)
{
unsigned int pos;
+ const unsigned char *udataPt=(const unsigned char *)dataPt;
assert(dirLen >= 48 && dirLen<=1024*1024);
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
#ifdef DEBUG_OLE
dump_log(dataPt, dirLen);
#endif
-#ifndef __FRAMAC__
- if(dataPt[0]!=0xfe || dataPt[1]!=0xff)
+ if(udataPt[0]!=0xfe || udataPt[1]!=0xff)
return ;
-#endif
pos=get32u(dataPt, 44);
if(pos > dirLen - 8)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
- /*@ assert pos <= dirLen - 8; */
+ }
+ /*@ assert 0 <= pos <= dirLen - 8; */
{
/* PropertySet */
const unsigned int size=get32u(dataPt, pos);
if(size <= 8 || size > dirLen || pos + size > dirLen)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
- /*@ assert 8 < size <= dirLen <=1024*1024; */
+ }
+ /*@ assert size > 8 && size <= dirLen && pos + size <= dirLen; */
+
+ /*@ assert 0 < dirLen <=1024*1024; */
/*@ assert \valid_read(dataPt + (0 .. dirLen-1)); */
/*@ assert pos + size <= dirLen; */
/*@ assert \valid_read(dataPt + (0 .. pos+size-1)); */
- /*TODO assert \valid_read(&dataPt[pos] + (0 .. 1024*1024-1-pos)); */
+ /*@ assert \valid_read(dataPt + pos + (0 .. size-1)); */
+
+ /*@ assert 0 < dirLen <=1024*1024; */
+ /*@ assert \initialized(dataPt + (0 .. dirLen-1)); */
+ /*@ assert pos + size <= dirLen; */
+ /*@ ghost int small_dirLen = pos + size; */
+ /*@ assert small_dirLen <= dirLen; */
+ /*@ assert \initialized(dataPt + (0 .. small_dirLen-1)); */
+
+#ifndef __FRAMAC__
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
OLE_parse_PropertySet(&dataPt[pos], size, ext, title, file_time);
+#endif
}
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
}
/*@
@@ -1041,7 +1305,7 @@ static void OLE_parse_summary_aux(const unsigned char *dataPt, const unsigned in
@ requires 48 <= len <= 1024*1024;
@ ensures \result!=\null ==> \valid((char *)\result + (0 .. len-1));
@*/
-static void *OLE_read_ministream(unsigned char *ministream,
+static void *OLE_read_ministream(const unsigned char *ministream,
const uint32_t *minifat, const unsigned int minifat_entries, const unsigned int uMiniSectorShift,
const unsigned int miniblock_start, const unsigned int len, const unsigned int ministream_size)
{
@@ -1055,20 +1319,25 @@ static void *OLE_read_ministream(unsigned char *ministream,
#endif
for(mblock=miniblock_start, size_read=0;
size_read < len;
- mblock=le32(minifat[mblock]), size_read+=(1<<uMiniSectorShift))
+ size_read+=(1<<uMiniSectorShift))
{
if(mblock >= minifat_entries)
{
free(dataPt);
return NULL;
}
+ /* TODO assert mblock < minifat_entries; */
if((mblock+1)> ministream_size>>uMiniSectorShift)
{
free(dataPt);
return NULL;
}
- /*TODO assert \valid_read(ministream + (0 .. (mblock<<uMiniSectorShift) + (1<<uMiniSectorShift) -1)); */
memcpy(&dataPt[size_read], &ministream[mblock<<uMiniSectorShift], (1<<uMiniSectorShift));
+#ifdef __FRAMAC__
+ mblock=Frama_C_interval(0, minifat_entries);
+#else
+ mblock=le32(minifat[mblock]);
+#endif
}
return dataPt;
}
@@ -1080,42 +1349,61 @@ static void *OLE_read_ministream(unsigned char *ministream,
@ requires 9 == le16(header->uSectorShift) || 12 == le16(header->uSectorShift);
@ requires 6 == le16(header->uMiniSectorShift);
@ requires \valid(ext);
- @ requires \valid(title);
+ @ requires \valid(title + (0 .. 1024-1));
@ requires \valid(file_time);
@ requires *ext == \null || valid_read_string(*ext);
- @ requires *title == \null || valid_read_string(*title);
+ @ requires valid_string(title);
+ @ requires separation: \separated(file,fat+(..), header, ext, title + (0 .. 1023), file_time);
@ ensures *ext == \null || valid_read_string(*ext);
- @ ensures *title == \null || valid_read_string(*title);
+ @ ensures valid_string(title);
@*/
static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned int fat_entries,
const struct OLE_HDR *header, const unsigned int ministream_block, const unsigned int ministream_size,
- const unsigned int block, const unsigned int len, const char **ext, char **title, time_t *file_time,
+ const unsigned int block, const unsigned int len, const char **ext, char *title, time_t *file_time,
const uint64_t offset)
{
const unsigned int uSectorShift=le16(header->uSectorShift);
- unsigned char *summary=NULL;
+ char *summary=NULL;
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
if(len < 48 || len>1024*1024)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
/*@ assert 48 <= len <= 1024*1024; */
if(len < le32(header->miniSectorCutoff))
{
if(le32(header->csectMiniFat)==0 || ministream_size == 0)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
if(ministream_size > 1024*1024 || le32(header->csectMiniFat) > 2048)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
/*@ assert 0 < le32(header->csectMiniFat) <= 2048; */
{
const unsigned int mini_fat_entries=(le32(header->csectMiniFat) << uSectorShift) / 4;
uint32_t *minifat;
unsigned char *ministream;
if((minifat=OLE_load_MiniFAT(file, header, fat, fat_entries, offset))==NULL)
+ {
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
return ;
+ }
ministream=(unsigned char *)OLE_read_stream(file,
fat, fat_entries, uSectorShift,
ministream_block, ministream_size, offset);
if(ministream != NULL)
{
- summary=(unsigned char*)OLE_read_ministream(ministream,
+ summary=(char*)OLE_read_ministream(ministream,
minifat, mini_fat_entries, le16(header->uMiniSectorShift),
block, len, ministream_size);
free(ministream);
@@ -1124,24 +1412,40 @@ static void OLE_parse_summary(FILE *file, const uint32_t *fat, const unsigned in
}
}
else
- summary=(unsigned char *)OLE_read_stream(file,
+ summary=(char *)OLE_read_stream(file,
fat, fat_entries, uSectorShift,
block, len, offset);
+#if defined(__FRAMAC__)
+ {
+ free(summary);
+ summary=MALLOC(4096);
+ Frama_C_make_unknown((char *)summary, 4096);
+ /*@ assert \initialized((char *)summary + (0 .. 4096 - 1)); */
+ OLE_parse_PropertySet(summary, 4096, ext, title, file_time);
+ OLE_parse_summary_aux(summary, 4096, ext, title, file_time);
+ /*@ assert valid_string(title); */
+ free(summary);
+ }
+#else
if(summary!=NULL)
{
OLE_parse_summary_aux(summary, len, ext, title, file_time);
free(summary);
}
+#endif
+ /*@ assert *ext == \null || valid_read_string(*ext); */
+ /*@ assert valid_string(title); */
}
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_doc;
@*/
static void file_rename_doc(file_recovery_t *file_recovery)
{
const char *ext=NULL;
- char *title=NULL;
+ char title[1024];
FILE *file;
unsigned char buffer_header[512];
uint32_t *fat;
@@ -1150,8 +1454,10 @@ static void file_rename_doc(file_recovery_t *file_recovery)
unsigned int fat_entries;
unsigned int uSectorShift;
unsigned int num_FAT_blocks;
+ title[0]='\0';
+ /*@ assert valid_string(&title[0]); */
if(strstr(file_recovery->filename, ".sdd")!=NULL)
- ext="sdd";
+ ext=extension_sdd;
if((file=fopen(file_recovery->filename, "rb"))==NULL)
return;
#ifdef DEBUG_OLE
@@ -1211,27 +1517,32 @@ static void file_rename_doc(file_recovery_t *file_recovery)
#ifdef DEBUG_OLE
log_info("file_rename_doc root_start_block=%u, fat_entries=%u\n", le32(header->root_start_block), fat_entries);
#endif
+#ifndef __FRAMAC__
for(block=le32(header->root_start_block), i=0;
block<fat_entries && block!=0xFFFFFFFE && i<fat_entries;
block=le32(fat[block]), i++)
+#else
+ block=le32(header->root_start_block), i=0;
+#endif
{
+ /*@ assert valid_string(&title[0]); */
struct OLE_DIR *dir_entries;
#ifdef __FRAMAC__
dir_entries=(struct OLE_DIR *)MALLOC(1<<12);
#else
dir_entries=(struct OLE_DIR *)MALLOC(1<<uSectorShift);
#endif
- if(OLE_read_block(file, (unsigned char *)dir_entries, uSectorShift, block, 0)<0)
+ if(OLE_read_block(file, (char *)dir_entries, uSectorShift, block, 0)<0)
{
free(fat);
free(dir_entries);
fclose(file);
- free(title);
return ;
}
#ifdef DEBUG_OLE
log_info("Root Directory block=%u (0x%x)\n", block, block);
#endif
+ /*@ assert valid_string(&title[0]); */
{
unsigned int sid;
int is_db=0;
@@ -1241,10 +1552,12 @@ static void file_rename_doc(file_recovery_t *file_recovery)
ministream_block=le32(dir_entry->start_block);
ministream_size=le32(dir_entry->size);
}
+ /*@ assert valid_string(&title[0]); */
for(sid=0;
sid<(1<<uSectorShift)/sizeof(struct OLE_DIR);
sid++)
{
+ /*@ assert valid_string(&title[0]); */
const struct OLE_DIR *dir_entry=&dir_entries[sid];
if(dir_entry->type!=NO_ENTRY)
{
@@ -1256,9 +1569,10 @@ static void file_rename_doc(file_recovery_t *file_recovery)
'r', '\0', 'm', '\0', 'a', '\0', 't', '\0',
'i', '\0', 'o', '\0', 'n', '\0', '\0', '\0'
};
+ const unsigned int namsiz=le16(dir_entry->namsiz);
#ifdef DEBUG_OLE
unsigned int j;
- for(j=0;j<64 && j<le16(dir_entry->namsiz) && dir_entry->name[j]!='\0';j+=2)
+ for(j=0;j<64 && j<namsiz && dir_entry->name[j]!='\0';j+=2)
{
log_info("%c",dir_entry->name[j]);
}
@@ -1268,153 +1582,83 @@ static void file_rename_doc(file_recovery_t *file_recovery)
(unsigned int)le32(dir_entry->start_block),
(unsigned int)le32(dir_entry->size));
#endif
- switch(le16(dir_entry->namsiz))
+ {
+ const char *tmp=entry2ext(dir_entry);
+ /*@ assert tmp == \null || valid_read_string(tmp); */
+ if(tmp!=NULL)
+ ext=tmp;
+ /*@ assert ext == \null || valid_read_string(ext); */
+ }
+ /*@ assert valid_string(&title[0]); */
+ switch(namsiz)
{
case 4:
if(sid==1 && memcmp(&dir_entry->name, "1\0\0\0", 4)==0)
is_db=1;
- if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "2\0\0\0", 4)==0)
+ else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "2\0\0\0", 4)==0)
is_db=2;
- break;
- case 10:
- if(memcmp(dir_entry->name, ".\0Q\0D\0F\0\0\0",10)==0)
- ext="qdf-backup";
- break;
- case 12:
- /* 3ds max */
- if(memcmp(dir_entry->name, "S\0c\0e\0n\0e\0\0\0",12)==0)
- ext="max";
- /* Licom AlphaCAM */
- else if(memcmp(dir_entry->name,"L\0i\0c\0o\0m\0\0\0",12)==0)
- ext="amb";
+ /*@ assert valid_string(&title[0]); */
break;
case 16:
if(sid==1 && memcmp(dir_entry->name, "d\0o\0c\0.\0d\0e\0t\0\0\0", 16)==0)
- ext="psmodel";
+ ext=extension_psmodel;
/* Windows Sticky Notes */
else if(sid==1 && memcmp(dir_entry->name, "V\0e\0r\0s\0i\0o\0n\0\0\0", 16)==0)
- ext="snt";
+ ext=extension_snt;
else if(is_db==1 && sid==2 && memcmp(&dir_entry->name, "C\0a\0t\0a\0l\0o\0g\0\0\0", 16)==0)
is_db=2;
+ /*@ assert valid_string(&title[0]); */
break;
case 18:
/* MS Excel
* Note: Microsoft Works Spreadsheet contains the same signature */
if(ext==NULL &&
memcmp(dir_entry->name, "W\0o\0r\0k\0b\0o\0o\0k\0\0\0",18)==0)
- ext="xls";
- /* Microsoft Works .wps */
- else if(memcmp(dir_entry->name,"C\0O\0N\0T\0E\0N\0T\0S\0\0\0",18)==0)
- ext="wps";
- break;
- case 20:
- /* Page Maker */
- if(memcmp(&dir_entry->name, "P\0a\0g\0e\0M\0a\0k\0e\0r\0\0\0", 20)==0)
- ext="p65";
- break;
- case 22:
- /* SigmaPlot .jnb */
- if(memcmp(dir_entry->name, "J\0N\0B\0V\0e\0r\0s\0i\0o\0n\0\0\0", 22)==0)
- ext="jnb";
- /* Autodesk Inventor part ipt or iam file */
- if(memcmp(dir_entry->name, "R\0S\0e\0S\0t\0o\0r\0a\0g\0e\0\0\0", 22)==0)
- ext="ipt";
- break;
- case 24:
- /* HP Photosmart Photo Printing Album */
- if(memcmp(dir_entry->name,"I\0m\0a\0g\0e\0s\0S\0t\0o\0r\0e\0\0\0",24)==0)
- ext="albm";
- /* Lotus Approach */
- else if(memcmp(dir_entry->name,"A\0p\0p\0r\0o\0a\0c\0h\0D\0o\0c\0\0\0",24)==0)
- ext="apr";
- break;
- case 28:
- /* Microsoft Works Spreadsheet or Chart */
- if(memcmp(dir_entry->name,"W\0k\0s\0S\0S\0W\0o\0r\0k\0B\0o\0o\0k\0\0\0",28)==0)
- ext="xlr";
- /* Visio */
- else if(memcmp(dir_entry->name,"V\0i\0s\0i\0o\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",28)==0)
- ext="vsd";
- /* SolidWorks */
- else if(memcmp(&dir_entry->name, "s\0w\0X\0m\0l\0C\0o\0n\0t\0e\0n\0t\0s\0\0\0", 28)==0)
- {
-#ifdef DJGPP
- ext="sld";
-#else
- ext="sldprt";
-#endif
- }
- break;
- case 32:
- if(memcmp(dir_entry->name, "m\0a\0n\0i\0f\0e\0s\0t\0.\0c\0a\0m\0x\0m\0l\0\0\0",32)==0)
- ext="camrec";
- /* Revit */
- else if(memcmp(dir_entry->name, "R\0e\0v\0i\0t\0P\0r\0e\0v\0i\0e\0w\0004\0.\0000\0\0", 32)==0)
- ext="rvt";
- break;
- case 34:
- if(memcmp(dir_entry->name, "S\0t\0a\0r\0C\0a\0l\0c\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0",34)==0)
- ext="sdc";
+ ext=extension_xls;
+ /*@ assert valid_string(&title[0]); */
break;
case 36:
/* sda=StarDraw, sdd=StarImpress */
- if((ext==NULL || strcmp(ext,"sdd")!=0) &&
+ if(ext!=extension_sdd &&
memcmp(dir_entry->name, "S\0t\0a\0r\0D\0r\0a\0w\0D\0o\0c\0u\0m\0e\0n\0t\0003\0\0\0", 36)==0)
- ext="sda";
- else if(memcmp(dir_entry->name, "f\0i\0l\0e\0_\0C\0O\0M\0P\0A\0N\0Y\0_\0F\0I\0L\0E\0\0\0", 36)==0)
- ext="qbb";
- break;
- case 38:
- /* Quattro Pro spreadsheet */
- if(memcmp(dir_entry->name, "N\0a\0t\0i\0v\0e\0C\0o\0n\0t\0e\0n\0t\0_\0M\0A\0I\0N\0\0\0", 38)==0)
- ext="qpw";
- else if(memcmp(dir_entry->name, "S\0t\0a\0r\0W\0r\0i\0t\0e\0r\0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 38)==0)
- ext="sdw";
+ ext=extension_sda;
+ /*@ assert valid_string(&title[0]); */
break;
case 40:
if(memcmp(dir_entry->name, SummaryInformation, 40)==0)
{
+ /*@ assert ext == \null || valid_read_string(ext); */
+ /*@ assert valid_string(&title[0]); */
OLE_parse_summary(file, fat, fat_entries, header,
ministream_block, ministream_size,
le32(dir_entry->start_block), le32(dir_entry->size),
- &ext, &title, &file_time, 0);
+ &ext, &title[0], &file_time, 0);
+ /*@ assert valid_string(&title[0]); */
+ /*@ assert ext == \null || valid_read_string(ext); */
}
- else if(memcmp(dir_entry->name,"P\0o\0w\0e\0r\0P\0o\0i\0n\0t\0 \0D\0o\0c\0u\0m\0e\0n\0t\0\0\0", 40)==0)
- ext="ppt";
- /* Outlook */
- else if(memcmp(dir_entry->name,"_\0_\0n\0a\0m\0e\0i\0d\0_\0v\0e\0r\0s\0i\0o\0n\0001\0.\0000\0\0\0",40)==0)
- ext="msg";
+ /*@ assert valid_string(&title[0]); */
break;
- case 46:
- if(memcmp(dir_entry->name,
- "I\0S\0o\0l\0i\0d\0W\0o\0r\0k\0s\0I\0n\0f\0o\0r\0m\0a\0t\0i\0o\0n\0\0\0", 46)==0)
- {
-#ifdef DJGPP
- ext="sld";
-#else
- ext="sldprt";
-#endif
- }
- break;
- case 56:
- /* Wilcom ES Software */
- if(memcmp(dir_entry->name, WilcomDesignInformationDDD, 56)==0)
- ext="emb";
+ default:
+ /*@ assert valid_string(&title[0]); */
break;
}
- if(sid==1 && le16(dir_entry->namsiz) >=6 &&
+ /*@ assert valid_string(&title[0]); */
+ if(sid==1 && namsiz >=6 &&
memcmp(dir_entry->name, "D\0g\0n", 6)==0)
- ext="dgn";
+ ext=extension_dgn;
#ifdef DEBUG_OLE
if(ext!=NULL)
- log_info("Found %s %u\n", ext, le16(dir_entry->namsiz));
+ log_info("Found %s %u\n", ext, namsiz);
#endif
+ /*@ assert valid_string(&title[0]); */
}
+ /*@ assert valid_string(&title[0]); */
}
if(ext==NULL && is_db==2)
- ext="db";
+ ext=extension_db;
}
free(dir_entries);
+ /*@ assert valid_string(&title[0]); */
}
}
free(fat);
@@ -1423,21 +1667,156 @@ static void file_rename_doc(file_recovery_t *file_recovery)
set_date(file_recovery->filename, file_time, file_time);
if(title!=NULL)
{
- file_rename(file_recovery, (const unsigned char*)title, strlen(title), 0, ext, 1);
- free(title);
+ file_rename(file_recovery, &title, strlen((const char *)title), 0, ext, 1);
}
else
file_rename(file_recovery, NULL, 0, 0, ext, 1);
}
/*@
- @ requires \valid(file_stat);
+ @ requires buffer_size >= sizeof(struct OLE_HDR);
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(&file_hint_doc, buffer, file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_doc);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == &file_rename_doc);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
+ // TODO ensures *buffer == \old(*buffer);
+ // TODO ensures *file_recovery == \old(*file_recovery);
+static int header_check_doc(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+{
+ /*@ assert file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename); */
+ const struct OLE_HDR *header=(const struct OLE_HDR *)buffer;
+ /* Check for Little Endian */
+ if(le16(header->uByteOrder)!=0xFFFE)
+ return 0;
+ if(le16(header->uDllVersion)!=3 && le16(header->uDllVersion)!=4)
+ return 0;
+ if(le16(header->reserved)!=0 || le32(header->reserved1)!=0)
+ return 0;
+ if(le16(header->uMiniSectorShift)!=6)
+ return 0;
+ if(le16(header->uDllVersion)==3 && le16(header->uSectorShift)!=9)
+ return 0;
+ /* max and qbb file have uSectorShift=12 */
+ if(le16(header->uDllVersion)==4 && le16(header->uSectorShift)!=12)
+ return 0;
+ if(le16(header->uDllVersion)==3 && le32(header->csectDir)!=0)
+ return 0;
+ /* max file have csectDir=1
+ * qbb file have csectDir=4 */
+ if(le16(header->uDllVersion)==4 && le32(header->csectDir)==0)
+ return 0;
+ /*
+ num_FAT_blocks=109+num_extra_FAT_blocks*(512-1);
+ maximum file size is 512+(num_FAT_blocks*128)*512, about 1.6GB
+ */
+ if(le32(header->num_FAT_blocks)==0 ||
+ le32(header->num_extra_FAT_blocks)>50 ||
+ le32(header->num_FAT_blocks)>109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))/4-1))
+ return 0;
+ /*@ assert file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename); */
+ /*@ assert le32(header->num_FAT_blocks) <= 109+le32(header->num_extra_FAT_blocks)*((1<<le16(header->uSectorShift))/4-1); */
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->file_check=&file_check_doc;
+ file_recovery_new->file_rename=&file_rename_doc;
+ file_recovery_new->extension=ole_get_file_extension(header, buffer_size);
+ if(file_recovery_new->extension!=NULL)
+ {
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ if(strcmp(file_recovery_new->extension,"sda")==0)
+ {
+ if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL)
+ file_recovery_new->extension=extension_sdd;
+ }
+ else if(strcmp(file_recovery_new->extension,"wps")==0)
+ {
+ /* Distinguish between MS Works .wps and MS Publisher .pub */
+ if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL)
+ file_recovery_new->extension=extension_pub;
+ }
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ return 1;
+ }
+ if(td_memmem(buffer,buffer_size,"WordDocument",12)!=NULL)
+ {
+ file_recovery_new->extension=file_hint_doc.extension;
+ }
+ else if(td_memmem(buffer,buffer_size,"StarDraw",8)!=NULL)
+ {
+ file_recovery_new->extension=extension_sda;
+ }
+ else if(td_memmem(buffer,buffer_size,"StarCalc",8)!=NULL)
+ {
+ file_recovery_new->extension=extension_sdc;
+ }
+ else if(td_memmem(buffer,buffer_size,"StarImpress",11)!=NULL)
+ {
+ file_recovery_new->extension=extension_sdd;
+ }
+ else if(td_memmem(buffer,buffer_size,"Worksheet",9)!=NULL ||
+ td_memmem(buffer,buffer_size,"Book",4)!=NULL ||
+ td_memmem(buffer,buffer_size,"Workbook",8)!=NULL ||
+ td_memmem(buffer,buffer_size,"Calc",4)!=NULL)
+ {
+ file_recovery_new->extension=extension_xls;
+ }
+ else if(td_memmem(buffer,buffer_size,"Power",5)!=NULL)
+ {
+ file_recovery_new->extension=extension_ppt;
+ }
+ else if(td_memmem(buffer,buffer_size,"AccessObjSiteData",17)!=NULL)
+ {
+ file_recovery_new->extension=extension_mdb;
+ }
+ else if(td_memmem(buffer,buffer_size,"Visio",5)!=NULL)
+ {
+ file_recovery_new->extension=extension_vsd;
+ }
+ else if(td_memmem(buffer,buffer_size,"SfxDocument",11)!=NULL)
+ {
+ file_recovery_new->extension=extension_sdw;
+ }
+ else if(td_memmem(buffer,buffer_size,"CPicPage",8)!=NULL)
+ { /* Flash Project File */
+ file_recovery_new->extension=extension_fla;
+ }
+ else if(td_memmem(buffer,buffer_size,"Microsoft Publisher",19)!=NULL)
+ { /* Publisher */
+ file_recovery_new->extension=extension_pub;
+ }
+ else if(td_memmem(buffer, buffer_size, "Microsoft Works Database", 24)!=NULL
+ || td_memmem( buffer, buffer_size, "MSWorksDBDoc", 12)!=NULL)
+ { /* Microsoft Works .wdb */
+ file_recovery_new->extension=extension_wdb;
+ }
+ else if(td_memmem(buffer,buffer_size,"MetaStock",9)!=NULL)
+ { /* MetaStock */
+ file_recovery_new->extension=extension_mws;
+ }
+ else
+ file_recovery_new->extension=file_hint_doc.extension;
+ /*@ assert valid_read_string(file_recovery_new->extension); */
+ return 1;
+}
+
static void register_header_check_doc(file_stat_t *file_stat)
{
static const unsigned char doc_header[]= { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
register_header_check(0, doc_header,sizeof(doc_header), &header_check_doc, file_stat);
}
+#endif
#if defined(MAIN_doc)
#define BLOCKSIZE 65536u
@@ -1474,6 +1853,8 @@ int main()
/*@ assert file_recovery_new.file_size == 0; */
/*@ assert file_recovery_new.file_check == &file_check_doc; */
/*@ assert file_recovery_new.file_rename == &file_rename_doc; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert \separated(&file_recovery_new, file_recovery_new.extension); */
#ifdef __FRAMAC__
file_recovery_new.file_size = 512*Frama_C_interval(1, 1000);
#endif
@@ -1481,6 +1862,7 @@ int main()
memcpy(file_recovery_new.filename, fn, sizeof(fn));
/*@ assert valid_read_string((char *)&file_recovery_new.filename); */
/*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*X TODO assert valid_read_string(file_recovery_new.extension); */
file_recovery_new.file_stat=&file_stats;
if(file_recovery_new.file_stat!=NULL)
{
diff --git a/src/file_dpx.c b/src/file_dpx.c
index b764efe..89368cc 100644
--- a/src/file_dpx.c
+++ b/src/file_dpx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dpx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -89,3 +90,4 @@ static void register_header_check_dpx(file_stat_t *file_stat)
register_header_check(0, "SDPX", 4, &header_check_dpx, file_stat);
register_header_check(0, "XPDS", 4, &header_check_dpx, file_stat);
}
+#endif
diff --git a/src/file_drw.c b/src/file_drw.c
index 05c9924..2c7cb95 100644
--- a/src/file_drw.c
+++ b/src/file_drw.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_drw)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -67,3 +68,4 @@ static void register_header_check_drw(file_stat_t *file_stat)
'R', 'A', 'W', 'I', 'N', 'G'};
register_header_check(0, drw_header,sizeof(drw_header), &header_check_drw, file_stat);
}
+#endif
diff --git a/src/file_ds2.c b/src/file_ds2.c
index 73b1116..754d8e7 100644
--- a/src/file_ds2.c
+++ b/src/file_ds2.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ds2)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -74,3 +75,4 @@ static void register_header_check_ds2(file_stat_t *file_stat)
static const unsigned char ds2_header[4]= { 0x03, 'd','s','2'};
register_header_check(0, ds2_header,sizeof(ds2_header), &header_check_ds2, file_stat);
}
+#endif
diff --git a/src/file_ds_store.c b/src/file_ds_store.c
index ba23b46..c4d4431 100644
--- a/src/file_ds_store.c
+++ b/src/file_ds_store.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ds_store)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -70,3 +71,4 @@ static void register_header_check_ds_store(file_stat_t *file_stat)
};
register_header_check(0, ds_store_header, sizeof(ds_store_header), &header_check_ds_store, file_stat);
}
+#endif
diff --git a/src/file_dsc.c b/src/file_dsc.c
index 398ae6e..002cd84 100644
--- a/src/file_dsc.c
+++ b/src/file_dsc.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dsc)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_dsc(file_stat_t *file_stat)
static const unsigned char dsc_header[3]= { 'M','L','T'};
register_header_check(588, dsc_header,sizeof(dsc_header), &header_check_dsc, file_stat);
}
+#endif
diff --git a/src/file_dss.c b/src/file_dss.c
index 8f6de2b..6e4db8e 100644
--- a/src/file_dss.c
+++ b/src/file_dss.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dss)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -78,3 +79,4 @@ static void register_header_check_dss(file_stat_t *file_stat)
static const unsigned char dss_header[4]= { 0x02, 'd','s','s'};
register_header_check(0, dss_header,sizeof(dss_header), &header_check_dss, file_stat);
}
+#endif
diff --git a/src/file_dst.c b/src/file_dst.c
index 38a2e5e..3267bae 100644
--- a/src/file_dst.c
+++ b/src/file_dst.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dst)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -62,3 +63,4 @@ static void register_header_check_dst(file_stat_t *file_stat)
{
register_header_check(0x13, "\rST:", 4, &header_check_dst, file_stat);
}
+#endif
diff --git a/src/file_dta.c b/src/file_dta.c
index ce52423..8fe774a 100644
--- a/src/file_dta.c
+++ b/src/file_dta.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dta)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -66,3 +67,4 @@ static void register_header_check_dta(file_stat_t *file_stat)
register_header_check(0, dta_header_71le,sizeof(dta_header_71le), &header_check_dta, file_stat);
register_header_check(0, dta_header_72le,sizeof(dta_header_72le), &header_check_dta, file_stat);
}
+#endif
diff --git a/src/file_dump.c b/src/file_dump.c
index 38c77f3..f21b9c6 100644
--- a/src/file_dump.c
+++ b/src/file_dump.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dump)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -145,3 +146,4 @@ static void register_header_check_dump(file_stat_t *file_stat)
register_header_check(0x18, dump_header_le_old_fs,sizeof(dump_header_le_old_fs), &header_check_dump, file_stat);
register_header_check(0x18, dump_header_le_new_fs,sizeof(dump_header_le_new_fs), &header_check_dump, file_stat);
}
+#endif
diff --git a/src/file_dv.c b/src/file_dv.c
index 6aabd81..bc45ce3 100644
--- a/src/file_dv.c
+++ b/src/file_dv.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dv)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -29,6 +30,9 @@
#include <stdio.h>
#include "types.h"
#include "filegen.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
static void register_header_check_dv(file_stat_t *file_stat);
@@ -43,6 +47,9 @@ const file_hint_t file_hint_dv= {
static data_check_t data_check_NTSC(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
@@ -64,6 +71,9 @@ static void file_check_dv_NTSC(file_recovery_t *fr)
if(my_fseek(fr->handle, 0, SEEK_SET) < 0 ||
fread(&buffer_header, sizeof(buffer_header), 1, fr->handle) != 1)
return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer_header, sizeof(buffer_header));
+#endif
if(fs > 0)
fs-=120000;
if(fs > 0)
@@ -73,6 +83,9 @@ static void file_check_dv_NTSC(file_recovery_t *fr)
fread(&buffer, sizeof(buffer), 1, fr->handle) == 1)
{
unsigned int i;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
+#endif
for(i=1; i<sizeof(buffer); i+=0x50)
if((buffer[i]&0x0f)!=(buffer_header[1]&0x0f))
{
@@ -86,6 +99,9 @@ static void file_check_dv_NTSC(file_recovery_t *fr)
static data_check_t data_check_PAL(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
@@ -107,6 +123,9 @@ static void file_check_dv_PAL(file_recovery_t *fr)
if(my_fseek(fr->handle, 0, SEEK_SET) < 0 ||
fread(&buffer_header, sizeof(buffer_header), 1, fr->handle) != 1)
return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer_header, sizeof(buffer_header));
+#endif
if(fs > 0)
fs-=144000;
if(fs > 0)
@@ -116,6 +135,9 @@ static void file_check_dv_PAL(file_recovery_t *fr)
fread(&buffer, sizeof(buffer), 1, fr->handle) == 1)
{
unsigned int i;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
+#endif
for(i=1; i<sizeof(buffer); i+=0x50)
if((buffer[i]&0x0f)!=(buffer_header[1]&0x0f))
{
@@ -159,3 +181,4 @@ static void register_header_check_dv(file_stat_t *file_stat)
static const unsigned char dv_header[3]= {0x1f, 0x07, 0x00};
register_header_check(0, dv_header,sizeof(dv_header), &header_check_dv, file_stat);
}
+#endif
diff --git a/src/file_dvi.c b/src/file_dvi.c
index 0458f67..48570ae 100644
--- a/src/file_dvi.c
+++ b/src/file_dvi.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dvi)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -65,3 +66,4 @@ static void register_header_check_dvi(file_stat_t *file_stat)
};
register_header_check(0, dvi_header, sizeof(dvi_header), &header_check_dvi, file_stat);
}
+#endif
diff --git a/src/file_dvr.c b/src/file_dvr.c
index 4adbbb7..3b9aa4b 100644
--- a/src/file_dvr.c
+++ b/src/file_dvr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dvr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -60,3 +61,4 @@ static void register_header_check_dvr(file_stat_t *file_stat)
{
register_header_check(0, "RT60", 4, &header_check_dvr, file_stat);
}
+#endif
diff --git a/src/file_dwg.c b/src/file_dwg.c
index 9eb30e3..09abae4 100644
--- a/src/file_dwg.c
+++ b/src/file_dwg.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dwg)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -69,3 +70,4 @@ static void register_header_check_dwg(file_stat_t *file_stat)
register_header_check(0, dwg_header_24,sizeof(dwg_header_24), &header_check_dwg, file_stat);
register_header_check(0, dwg_header_27,sizeof(dwg_header_27), &header_check_dwg, file_stat);
}
+#endif
diff --git a/src/file_dxf.c b/src/file_dxf.c
index fb0ed16..9308d3b 100644
--- a/src/file_dxf.c
+++ b/src/file_dxf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dxf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,6 +60,9 @@ static int header_check_dxf(const unsigned char *buffer, const unsigned int buff
static data_check_t data_check_dxf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
unsigned int i;
+ /*@
+ @ loop assigns i, file_recovery->calculated_file_size;
+ @*/
for(i=(buffer_size/2)-3;i+4<buffer_size;i++)
{
if(buffer[i]=='\n' && buffer[i+1]=='E' && buffer[i+2]=='O' && buffer[i+3]=='F')
@@ -94,3 +98,4 @@ static void register_header_check_dxf(file_stat_t *file_stat)
register_header_check(0, header_dxflib, sizeof(header_dxflib), &header_check_dxf, file_stat);
register_header_check(0, header_dxflib_dos, sizeof(header_dxflib_dos), &header_check_dxf, file_stat);
}
+#endif
diff --git a/src/file_e01.c b/src/file_e01.c
index ed219a3..2c746c7 100644
--- a/src/file_e01.c
+++ b/src/file_e01.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_e01)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -86,12 +87,29 @@ static void file_check_e01(file_recovery_t *file_recovery)
static int header_check_e01(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct ewf_file_header *ewf=(const struct ewf_file_header *)buffer;
- static char ext[4];
+ static char ext[10];
+ uint16_t fields_segment=le16(ewf->fields_segment);
reset_file_recovery(file_recovery_new);
- ext[0]='E'+le16(ewf->fields_segment)/100;
- ext[1]='0'+(le16(ewf->fields_segment)%100)/10;
- ext[2]='0'+(le16(ewf->fields_segment)%10);
- ext[3]='\0';
+ if(fields_segment > ('Z'-'E') * 100 + 99)
+ {
+ ext[0]='E';
+ ext[1]='0';
+ ext[2]='1';
+ ext[3]='_';
+ ext[4]='0'+(fields_segment/10000)%10;
+ ext[5]='0'+(fields_segment/1000)%10;
+ ext[6]='0'+(fields_segment/100)%10;
+ ext[7]='0'+(fields_segment/10)%10;
+ ext[8]='0'+fields_segment%10;
+ ext[9]='\0';
+ }
+ else
+ {
+ ext[0]='E'+fields_segment/100;
+ ext[1]='0'+(fields_segment/10)%10;
+ ext[2]='0'+(fields_segment%10);
+ ext[3]='\0';
+ }
file_recovery_new->extension=(const char*)&ext;
file_recovery_new->file_check=&file_check_e01;
return 1;
@@ -105,3 +123,4 @@ static void register_header_check_e01(file_stat_t *file_stat)
};
register_header_check(0, e01_header, sizeof(e01_header), &header_check_e01, file_stat);
}
+#endif
diff --git a/src/file_ecryptfs.c b/src/file_ecryptfs.c
index a43b9a4..5f5741b 100644
--- a/src/file_ecryptfs.c
+++ b/src/file_ecryptfs.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ecryptfs)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -87,3 +88,4 @@ static int header_check_ecryptfs(const unsigned char *buffer, const unsigned int
file_recovery_new->file_check=&file_check_ecryptfs;
return 1;
}
+#endif
diff --git a/src/file_edb.c b/src/file_edb.c
index e09d61b..ad07bda 100644
--- a/src/file_edb.c
+++ b/src/file_edb.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_edb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -65,3 +66,4 @@ static void register_header_check_edb(file_stat_t *file_stat)
};
register_header_check(4, edb_magic, sizeof(edb_magic), &header_check_edb, file_stat);
}
+#endif
diff --git a/src/file_elf.c b/src/file_elf.c
index f9ff9a0..2bdbcb2 100644
--- a/src/file_elf.c
+++ b/src/file_elf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_elf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -152,3 +153,4 @@ static void register_header_check_elf(file_stat_t *file_stat)
register_header_check(0, elf_header16, sizeof(elf_header16), &header_check_elf, file_stat);
register_header_check(0, elf_header32, sizeof(elf_header32), &header_check_elf, file_stat);
}
+#endif
diff --git a/src/file_emf.c b/src/file_emf.c
index db02070..39ff7ac 100644
--- a/src/file_emf.c
+++ b/src/file_emf.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_emf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -30,10 +31,11 @@
#include "filegen.h"
#include "log.h"
#include "common.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
static void register_header_check_emf(file_stat_t *file_stat);
-static int header_check_emf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
-static data_check_t data_check_emf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
const file_hint_t file_hint_emf= {
.extension="emf",
@@ -201,37 +203,30 @@ struct EMF_HDR
#define EMR_COLORMATCHTOTARGETW 121
#define EMR_CREATECOLORSPACEW 122
-static int header_check_emf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
-{
- static const unsigned char emf_header[4]= { 0x01, 0x00, 0x00, 0x00};
- const struct EMF_HDR *hdr=(const struct EMF_HDR *)buffer;
- const unsigned int atom_size=le32(hdr->emr.nSize);
- if(memcmp(buffer,emf_header,sizeof(emf_header))==0 &&
- le32(hdr->nBytes) >= 88 &&
- le16(hdr->sReserved)==0 &&
- atom_size>=0x34 && atom_size%4==0)
- {
- reset_file_recovery(file_recovery_new);
- file_recovery_new->extension=file_hint_emf.extension;
- if(file_recovery_new->blocksize >= 8)
- {
- file_recovery_new->data_check=&data_check_emf;
- file_recovery_new->file_check=&file_check_size;
- file_recovery_new->calculated_file_size=atom_size;
- }
- return 1;
- }
- return 0;
-}
-
+/*@
+ @ requires buffer_size >= 2;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->data_check==&data_check_emf;
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP || \result == DC_ERROR;
+ @ ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8);
+ @ ensures file_recovery->data_check==&data_check_emf;
+ @ assigns file_recovery->calculated_file_size;
+ @*/
static data_check_t data_check_emf(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
- const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
- const unsigned int itype=buffer[i]+(buffer[i+1]<<8)+(buffer[i+2]<<16)+(buffer[i+3]<<24);
- const unsigned int atom_size=buffer[i+4]+(buffer[i+5]<<8)+(buffer[i+6]<<16)+(buffer[i+7]<<24);
+ const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
+ /*@ assert 0 <= i < buffer_size - 8 ; */
+ const U_EMR *hdr=(const U_EMR *)&buffer[i];
+ const unsigned int itype=le32(hdr->iType);
+ const unsigned int atom_size=le32(hdr->nSize);
#ifdef DEBUG_EMF
log_trace("0x%llx ", (long long unsigned)file_recovery->calculated_file_size);
switch(itype)
@@ -362,15 +357,159 @@ static data_check_t data_check_emf(const unsigned char *buffer, const unsigned i
#endif
if(atom_size<8 || atom_size%4!=0 || atom_size>1024*1024)
return DC_ERROR;
+ /*@ assert 8 <= atom_size <= 1024*1024; */
file_recovery->calculated_file_size+=(uint64_t)atom_size;
if(itype==EMR_EOF)
return DC_STOP;
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size + buffer_size/2 - 8 + 1024*1024; */
}
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8; */
+ /*@ assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 8; */
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_emf.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size >= 0x34);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_emf);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename== \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @*/
+static int header_check_emf(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+{
+ static const unsigned char emf_header[4]= { 0x01, 0x00, 0x00, 0x00};
+ const struct EMF_HDR *hdr=(const struct EMF_HDR *)buffer;
+ const unsigned int atom_size=le32(hdr->emr.nSize);
+ if(buffer_size < sizeof(struct EMF_HDR))
+ return 0;
+ if(memcmp(buffer,emf_header,sizeof(emf_header))==0 &&
+ le32(hdr->nBytes) >= 88 &&
+ le16(hdr->sReserved)==0 &&
+ atom_size>=0x34 && atom_size%4==0)
+ {
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_emf.extension;
+ if(file_recovery_new->blocksize >= 8)
+ {
+ file_recovery_new->data_check=&data_check_emf;
+ file_recovery_new->file_check=&file_check_size;
+ file_recovery_new->calculated_file_size=atom_size;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_emf(file_stat_t *file_stat)
{
static const unsigned char emf_sign[4]= { ' ','E', 'M','F'};
register_header_check(0x28, emf_sign,sizeof(emf_sign), &header_check_emf, file_stat);
}
+#endif
+
+#if defined(MAIN_emf)
+#define BLOCKSIZE 65536u
+int main()
+{
+ const char fn[] = "recup_dir.1/f0000000.emf";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.location.start=0;
+
+ file_stats.file_hint=&file_hint_emf;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+ register_header_check_emf(&file_stats);
+ if(header_check_emf(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.calculated_file_size > 0; */
+ /*@ assert file_recovery_new.data_check == &data_check_emf; */
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
+ /*@ assert file_recovery_new.file_rename == \null; */
+ /*@ assert file_recovery_new.extension == file_hint_emf.extension; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert \separated(&file_recovery_new, file_recovery_new.extension); */
+ /*@ assert valid_read_string((char *)&fn); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ /*@ assert valid_read_string((char *)&file_recovery_new.filename); */
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ /*X TODO assert valid_read_string(file_recovery_new.extension); */
+ file_recovery_new.file_stat=&file_stats;
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_emf; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ /*@ assert file_recovery_new.file_size <= file_recovery_new.calculated_file_size; */;
+ res_data_check=data_check_emf(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ data_check_emf(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ }
+ }
+ {
+ file_recovery_t file_recovery_new2;
+ /* Test when another file of the same is detected in the next block */
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+ header_check_emf(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ }
+ /*@ assert valid_read_string((char *)file_recovery_new.filename); */
+ {
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_size(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ }
+ return 0;
+}
+#endif
diff --git a/src/file_ess.c b/src/file_ess.c
index 9ed99f2..dd316e8 100644
--- a/src/file_ess.c
+++ b/src/file_ess.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ess)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_ess(file_stat_t *file_stat)
{
register_header_check(0, "TESV_SAVEGAME", 13, &header_check_ess, file_stat);
}
+#endif
diff --git a/src/file_evt.c b/src/file_evt.c
index 6eb621f..a06f356 100644
--- a/src/file_evt.c
+++ b/src/file_evt.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_evt)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -34,7 +35,6 @@
static void register_header_check_evt(file_stat_t *file_stat);
static int header_check_evt(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
-static data_check_t data_check_evt(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
const file_hint_t file_hint_evt= {
.extension="evt",
@@ -52,6 +52,9 @@ struct evt_chunk {
static data_check_t data_check_evt(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
@@ -84,9 +87,10 @@ static data_check_t data_check_evt(const unsigned char *buffer, const unsigned i
static int header_check_evt(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct evt_chunk *chunk=(const struct evt_chunk *)buffer;
- const struct evt_chunk *chunk2=(const struct evt_chunk *)&buffer[le32(chunk->size)];
+ const struct evt_chunk *chunk2;
if(le32(chunk->size) != 0x30)
return 0;
+ chunk2=(const struct evt_chunk *)&buffer[le32(chunk->size)];
if(le32(chunk2->size) < 8)
return 0;
reset_file_recovery(file_recovery_new);
@@ -105,3 +109,4 @@ static void register_header_check_evt(file_stat_t *file_stat)
static const unsigned char evt_header[8]= {0x30, 0x00, 0x00, 0x00, 'L', 'f', 'L', 'e'};
register_header_check(0, evt_header,sizeof(evt_header), &header_check_evt, file_stat);
}
+#endif
diff --git a/src/file_evtx.c b/src/file_evtx.c
index 68f884f..6f19ad9 100644
--- a/src/file_evtx.c
+++ b/src/file_evtx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_evtx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -78,3 +79,4 @@ static void register_header_check_evtx(file_stat_t *file_stat)
{
register_header_check(0, "ElfFile", 8, &header_check_evtx, file_stat);
}
+#endif
diff --git a/src/file_exe.c b/src/file_exe.c
index ade58b0..8aa1a6f 100644
--- a/src/file_exe.c
+++ b/src/file_exe.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exe)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,11 +59,19 @@ static const unsigned char exe_header[2] = {'M','Z'};
@ requires buffer_size >= 2;
@ requires \valid_read(buffer+(0..buffer_size-1));
@ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
@ requires \valid(file_recovery_new);
@ requires file_recovery_new->blocksize > 0;
- @ requires separation: \separated(file_recovery, file_recovery_new);
+ @ requires separation: \separated(&file_hint_exe, buffer+(..), file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_exe.extension || file_recovery_new->extension == extension_dll);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || file_recovery_new->file_rename == &file_rename_pe_exe);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_exe(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
@@ -285,6 +294,7 @@ static char InternalName[24]={
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_String(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -300,12 +310,16 @@ static int parse_String(file_recovery_t *file_recovery, const char*buffer, const
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
type=le16(PE_index->type);
+#ifdef DEBUG_EXE
log_info("parse_String len=%u val_len=%u type=%u\n", len, val_len, type);
+#endif
if(len > end)
return -1;
if(6 + 2 * val_len > len)
return -1;
+#ifdef DEBUG_EXE
dump_log(buffer, len);
+#endif
// type=1 => text
if(6+needle_len < end && type==1 && memcmp(&buffer[6], needle, needle_len)==0)
{
@@ -322,11 +336,14 @@ static int parse_String(file_recovery_t *file_recovery, const char*buffer, const
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringArray(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
unsigned int pos=0;
+#ifdef DEBUG_EXE
log_info("parse_StringArray end=%u\n", end);
+#endif
/*@
@ loop variant end - pos;
@*/
@@ -350,6 +367,7 @@ static int parse_StringArray(file_recovery_t *file_recovery, const char*buffer,
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -365,7 +383,9 @@ static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer,
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_StringTable len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len > end)
return -1;
/* szKey: language identifier + code page */
@@ -385,6 +405,7 @@ static int parse_StringTable(file_recovery_t *file_recovery, const char*buffer,
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(file_recovery, buffer+(..), needle+(..));
@*/
static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -401,7 +422,9 @@ static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffe
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_StringFileInfo len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len > end)
return -1;
if(6 + sizeof(StringFileInfo) > end)
@@ -427,6 +450,8 @@ static int parse_StringFileInfo(file_recovery_t *file_recovery, const char*buffe
@ requires needle_len > 0;
@ requires \valid_read(buffer+(0..end-1));
@ requires \valid_read(needle+(0..needle_len-1));
+ @ requires \separated(vs_version_info+(..), file_recovery, buffer+(..), needle+(..));
+ @ behavior types: requires \separated(vs_version_info+(..), \union(file_recovery, buffer+(..), needle+(..)));
@*/
static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffer, const unsigned int end, const char *needle, const unsigned int needle_len, const int force_ext)
{
@@ -444,7 +469,9 @@ static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffe
/*@ assert \valid_read(PE_index); */
len=le16(PE_index->len);
val_len=le16(PE_index->val_len);
+#ifdef DEBUG_EXE
log_info("parse_VS_VERSIONINFO len=%u val_len=%u type=%u\n", len, val_len, le16(PE_index->type));
+#endif
if(len==0 && val_len==0)
{
return -1;
@@ -488,7 +515,9 @@ static int parse_VS_VERSIONINFO(file_recovery_t *file_recovery, const char*buffe
static void PEVersion(FILE *file, const unsigned int offset, const unsigned int length, file_recovery_t *file_recovery)
{
char buffer[1024*1024];
+#ifdef DEBUG_EXE
log_info("PEVersion(file, %u, %u, file_recovery)\n", offset, length);
+#endif
if(length==0 || length > 1024*1024)
return;
if(fseek(file, offset, SEEK_SET)<0)
@@ -586,7 +615,9 @@ static void pe_resource_language(FILE *file, const unsigned int base, const unsi
idEntries = buffer[14]+(buffer[15]<<8);
count = nameEntries + idEntries;
}
+#ifdef DEBUG_EXE
log_info("pe_resource_language count=%u\n", count);
+#endif
if(count==0 || count > 1024)
return ;
/*@ assert 0 < count <= 1024; */
@@ -765,6 +796,7 @@ static void pe_resource_type(FILE *file, const unsigned int base, const unsigned
/*@
@ requires \valid(file_recovery);
@ requires valid_read_string((char*)&file_recovery->filename);
+ @ requires file_recovery->file_rename==&file_rename_pe_exe;
@*/
static void file_rename_pe_exe(file_recovery_t *file_recovery)
{
@@ -882,6 +914,7 @@ static void register_header_check_exe(file_stat_t *file_stat)
{
register_header_check(0, exe_header,sizeof(exe_header), &header_check_exe, file_stat);
}
+#endif
#if defined(MAIN_exe)
#define BLOCKSIZE 65536u
@@ -954,17 +987,19 @@ int main()
}
if(file_recovery_new.file_check!=NULL)
{
+ /*@ assert file_recovery_new.file_check == &file_check_size; */
file_recovery_new.handle=fopen(fn, "rb");
if(file_recovery_new.handle!=NULL)
{
- (file_recovery_new.file_check)(&file_recovery_new);
+ file_check_size(&file_recovery_new);
fclose(file_recovery_new.handle);
}
}
if(file_recovery_new.file_rename!=NULL)
{
/*@ assert valid_read_string((char *)&file_recovery_new.filename); */
- (file_recovery_new.file_rename)(&file_recovery_new);
+ /*@ assert file_recovery_new.file_rename == &file_rename_pe_exe; */
+ file_rename_pe_exe(&file_recovery_new);
}
return 0;
}
diff --git a/src/file_exr.c b/src/file_exr.c
index f0df6ba..886fa6e 100644
--- a/src/file_exr.c
+++ b/src/file_exr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_exr(file_stat_t *file_stat)
static const unsigned char exr_header[5]= { 'v' , 0x2f, '1' , 0x01, 0x02 };
register_header_check(0, exr_header, sizeof(exr_header), &header_check_exr, file_stat);
}
+#endif
diff --git a/src/file_exs.c b/src/file_exs.c
index 921d596..26913ec 100644
--- a/src/file_exs.c
+++ b/src/file_exs.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exs)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -70,5 +71,4 @@ static void register_header_check_exs(file_stat_t *file_stat)
};
register_header_check(0, exs_header, sizeof(exs_header), &header_check_exs, file_stat);
}
-
-
+#endif
diff --git a/src/file_ext.c b/src/file_ext.c
index b131fc7..cf55797 100644
--- a/src/file_ext.c
+++ b/src/file_ext.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ext2_sb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -32,6 +33,7 @@
#include "ext2.h"
#include "ext2_common.h"
#include "filegen.h"
+#include "log.h"
static void register_header_check_ext2_sb(file_stat_t *file_stat);
@@ -121,3 +123,4 @@ static void register_header_check_ext2_sb(file_stat_t *file_stat)
register_header_check(0x38, ext2_sb_header, sizeof(ext2_sb_header), &header_check_ext2_sb, file_stat);
register_header_check(0x4, ext2_ll_dir1, sizeof(ext2_ll_dir1), &header_check_ext2_dir, file_stat);
}
+#endif
diff --git a/src/file_ext2.c b/src/file_ext2.c
index 7bc31a9..cc672fe 100644
--- a/src/file_ext2.c
+++ b/src/file_ext2.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ext2_fs)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -37,7 +38,7 @@ static void register_header_check_ext2_fs(file_stat_t *file_stat);
static int header_check_ext2_fs(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
const file_hint_t file_hint_ext2_fs= {
- .extension="ext",
+ .extension="ext2",
.description="ext2/ext3/ext4 Filesystem",
.max_filesize=0,
.recover=1,
@@ -73,3 +74,4 @@ static int header_check_ext2_fs(const unsigned char *buffer, const unsigned int
file_recovery_new->file_check=&file_check_size;
return 1;
}
+#endif
diff --git a/src/file_fat.c b/src/file_fat.c
index 2904129..bd27eab 100644
--- a/src/file_fat.c
+++ b/src/file_fat.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fat)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -35,7 +36,6 @@
#include "filegen.h"
#include "log.h"
#include "memmem.h"
-#include "fat.h"
#include "fat_common.h"
static void register_header_check_fat(file_stat_t *file_stat);
@@ -62,13 +62,14 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
const struct fat_boot_sector *fat_header=(const struct fat_boot_sector *)buffer;
uint64_t start_fat1,start_data,part_size;
unsigned long int no_of_cluster,fat_length,fat_length_calc;
+ const unsigned int sector_size=fat_sector_size(fat_header);
if(!(le16(fat_header->marker)==0xAA55
&& (fat_header->ignored[0]==0xeb || fat_header->ignored[0]==0xe9)
&& (fat_header->fats==1 || fat_header->fats==2)))
return 0; /* Obviously not a FAT */
if(!((fat_header->ignored[0]==0xeb && fat_header->ignored[2]==0x90)||fat_header->ignored[0]==0xe9))
return 0;
- if(fat_sector_size(fat_header)==0 || fat_sector_size(fat_header)%512!=0)
+ if(sector_size==0 || sector_size%512!=0)
return 0;
switch(fat_header->sectors_per_cluster)
{
@@ -91,7 +92,7 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
fat_length=le16(fat_header->fat_length)>0?le16(fat_header->fat_length):le32(fat_header->fat32_length);
part_size=(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect));
start_fat1=le16(fat_header->reserved);
- start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+fat_sector_size(fat_header)-1)/fat_sector_size(fat_header);
+ start_data=start_fat1+fat_header->fats*fat_length+(get_dir_entries(fat_header)*32+sector_size-1)/sector_size;
if(part_size < start_data)
return 0;
no_of_cluster=(part_size-start_data)/fat_header->sectors_per_cluster;
@@ -102,7 +103,7 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
return 0;
if((le16(fat_header->fat_length)>256)||(le16(fat_header->fat_length)==0))
return 0;
- fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)*2/3-1)*3/2/fat_sector_size(fat_header));
+ fat_length_calc=((no_of_cluster+2+sector_size*2/3-1)*3/2/sector_size);
}
else if(no_of_cluster<65525)
{
@@ -111,7 +112,7 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
return 0;
if((get_dir_entries(fat_header)==0)||(get_dir_entries(fat_header)%16!=0))
return 0;
- fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)/2-1)*2/fat_sector_size(fat_header));
+ fat_length_calc=((no_of_cluster+2+sector_size/2-1)*2/sector_size);
}
else
{
@@ -122,7 +123,7 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
return 0;
if((le32(fat_header->root_cluster)<2) ||(le32(fat_header->root_cluster)>=2+no_of_cluster))
return 0;
- fat_length_calc=((no_of_cluster+2+fat_sector_size(fat_header)/4-1)*4/fat_sector_size(fat_header));
+ fat_length_calc=((no_of_cluster+2+sector_size/4-1)*4/sector_size);
}
if(fat_length<fat_length_calc)
return 0;
@@ -130,8 +131,9 @@ static int header_check_fat(const unsigned char *buffer, const unsigned int buff
file_recovery_new->extension=file_hint_fat.extension;
file_recovery_new->calculated_file_size=(uint64_t)
(fat_sectors(fat_header)>0?fat_sectors(fat_header):le32(fat_header->total_sect)) *
- fat_sector_size(fat_header);
+ sector_size;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
return 1;
}
+#endif
diff --git a/src/file_fbf.c b/src/file_fbf.c
index 31c5747..addf7af 100644
--- a/src/file_fbf.c
+++ b/src/file_fbf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fbf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -57,3 +58,4 @@ static void register_header_check_fbf(file_stat_t *file_stat)
};
register_header_check(0, fbf_header, sizeof(fbf_header), &header_check_fbf, file_stat);
}
+#endif
diff --git a/src/file_fbk.c b/src/file_fbk.c
index 6efd490..c88994b 100644
--- a/src/file_fbk.c
+++ b/src/file_fbk.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fbk)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_fbk(file_stat_t *file_stat)
static const unsigned char fbk_header[10] = {'T','a','b','l','e','D','a','t','a',' '};
register_header_check(0, fbk_header, sizeof(fbk_header), &header_check_fbk, file_stat);
}
+#endif
diff --git a/src/file_fcp.c b/src/file_fcp.c
index 8d71e89..a5390a0 100644
--- a/src/file_fcp.c
+++ b/src/file_fcp.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fcp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,3 +59,4 @@ static void register_header_check_fcp(file_stat_t *file_stat)
static const unsigned char fcp_header[5]= { 0xA2, 'K','e','y','G'};
register_header_check(0, fcp_header,sizeof(fcp_header), &header_check_fcp, file_stat);
}
+#endif
diff --git a/src/file_fcs.c b/src/file_fcs.c
index 05ce8ca..58c5a26 100644
--- a/src/file_fcs.c
+++ b/src/file_fcs.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fcs)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -31,8 +32,10 @@
#include "filegen.h"
#include "log.h"
+/*@
+ @ requires \valid(file_stat);
+ @*/
static void register_header_check_fcs(file_stat_t *file_stat);
-static int header_check_fcs(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
const file_hint_t file_hint_fcs= {
.extension="fcs",
@@ -43,13 +46,6 @@ const file_hint_t file_hint_fcs= {
.register_header_check=&register_header_check_fcs
};
-static const unsigned char fcs_signature[6]= {'F','C','S','3','.','0'};
-
-static void register_header_check_fcs(file_stat_t *file_stat)
-{
- register_header_check(0, fcs_signature, sizeof(fcs_signature), &header_check_fcs, file_stat);
-}
-
struct fcs_header
{
unsigned char magic[6];
@@ -62,36 +58,95 @@ struct fcs_header
unsigned char analysis_end[8]; /* 50 */
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires \valid_read(string + (0 .. max_length-1));
+ @ assigns \nothing;
+ @*/
static uint64_t ascii2int(const unsigned char *string, const unsigned int max_length)
{
uint64_t res=0;
unsigned int i;
+ /*@
+ @ loop invariant res <= 0x1999999999999998;
+ @ loop assigns res,i;
+ @*/
for(i=0;i<max_length;i++)
{
if(string[i]>='0' && string[i]<='9')
+ {
res=res*10+(string[i]-'0');
+ if(res > 0x1999999999999998)
+ return 0xffffffffffffffff;
+ }
else if(!(string[i]==' ' && res==0))
return 0;
}
return res;
}
+/*@
+ @ requires \valid_read(string + (0 .. max_length-1));
+ @ assigns \nothing;
+ @*/
static uint64_t ascii2int2(const unsigned char *string, const unsigned int max_length, const unsigned int delimiter)
{
uint64_t res=0;
unsigned int i;
+ /*@
+ @ loop invariant res <= 0x1999999999999998;
+ @ loop assigns res,i;
+ @*/
for(i=0;i<max_length;i++)
+ {
if(string[i]>='0' && string[i]<='9')
+ {
res=res*10+(string[i]-'0');
+ if(res > 0x1999999999999998)
+ return res;
+ }
else if(string[i]==delimiter)
return res;
else if(string[i]==' ' && res>0)
return res;
else if(string[i]!=' ')
return 0;
+ }
return res;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= sizeof(struct fcs_header);
+ @ requires separation: \separated(&file_hint_fcs, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 58);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size > 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_fcs.extension);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == &data_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_size);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @*/
static int header_check_fcs(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct fcs_header *fcs=(const struct fcs_header*)buffer;
@@ -113,8 +168,11 @@ static int header_check_fcs(const unsigned char *buffer, const unsigned int buff
if((data_end==0 || analysis_end==0) && text_start < buffer_size)
{ /* Explore TEXT segment */
unsigned int i;
- const char delimiter=buffer[text_start];
+ const unsigned char delimiter=buffer[text_start];
const unsigned int smallest=(buffer_size < text_end ? buffer_size : text_end);
+ /*@
+ @ loop assigns i, data_end, stext_end, analysis_end;
+ @*/
for(i=0; i<smallest; i++)
{
if(buffer[i]==delimiter)
@@ -136,6 +194,10 @@ static int header_check_fcs(const unsigned char *buffer, const unsigned int buff
log_info("$ENDSTEXT %llu\n", (long long unsigned) stext_end);
log_info("$ENDANALYSIS %llu\n", (long long unsigned) analysis_end);
#endif
+ if( data_end >= 0x8000000000000000 - 9 ||
+ analysis_end >= 0x8000000000000000 - 9 ||
+ stext_end >= 0x8000000000000000 - 9)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_fcs.extension;
file_recovery_new->min_filesize=58;
@@ -148,3 +210,10 @@ static int header_check_fcs(const unsigned char *buffer, const unsigned int buff
file_recovery_new->file_check=&file_check_size;
return 1;
}
+
+static void register_header_check_fcs(file_stat_t *file_stat)
+{
+ static const unsigned char fcs_signature[6]= {'F','C','S','3','.','0'};
+ register_header_check(0, fcs_signature, sizeof(fcs_signature), &header_check_fcs, file_stat);
+}
+#endif
diff --git a/src/file_fdb.c b/src/file_fdb.c
index a827049..90bebda 100644
--- a/src/file_fdb.c
+++ b/src/file_fdb.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fdb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,3 +59,4 @@ static void register_header_check_fdb(file_stat_t *file_stat)
static const unsigned char fdb_header[7] = { 0x00, 0x00, 0x00, 0x5c, 0xa0, 0x83, 0x02};
register_header_check(5, fdb_header, sizeof(fdb_header), &header_check_fdb, file_stat);
}
+#endif
diff --git a/src/file_fds.c b/src/file_fds.c
index 0217fb6..2ec3c4b 100644
--- a/src/file_fds.c
+++ b/src/file_fds.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fds)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -67,3 +68,4 @@ static void register_header_check_fds(file_stat_t *file_stat)
static const unsigned char fds_header[4]= {'F','D','S',0x1A};
register_header_check(0, fds_header,sizeof(fds_header), &header_check_fds, file_stat);
}
+#endif
diff --git a/src/file_fh10.c b/src/file_fh10.c
index f742f68..d350d8e 100644
--- a/src/file_fh10.c
+++ b/src/file_fh10.c
@@ -22,6 +22,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fh10)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -64,3 +65,4 @@ static void register_header_check_fh10(file_stat_t *file_stat)
};
register_header_check(0, fh10_header,sizeof(fh10_header), &header_check_fh10, file_stat);
}
+#endif
diff --git a/src/file_fh5.c b/src/file_fh5.c
index 63a39f0..1d29412 100644
--- a/src/file_fh5.c
+++ b/src/file_fh5.c
@@ -21,6 +21,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fh5)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -77,3 +78,4 @@ static void register_header_check_fh5(file_stat_t *file_stat)
static const unsigned char fh5_header[8] = { 0x41, 0x47, 0x44, 0x31, 0xbe, 0xb8, 0xbb, 0xce };
register_header_check(0, fh5_header,sizeof(fh5_header), &header_check_fh5, file_stat);
}
+#endif
diff --git a/src/file_filevault.c b/src/file_filevault.c
index b4bb498..afe45ee 100644
--- a/src/file_filevault.c
+++ b/src/file_filevault.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_filevault)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -60,3 +61,4 @@ static void register_header_check_filevault(file_stat_t *file_stat)
};
register_header_check(0, filevault_header, sizeof(filevault_header), &header_check_filevault, file_stat);
}
+#endif
diff --git a/src/file_fit.c b/src/file_fit.c
index 323beb7..3a1d317 100644
--- a/src/file_fit.c
+++ b/src/file_fit.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fit )
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -73,3 +74,4 @@ static void register_header_check_fit(file_stat_t *file_stat)
static const unsigned char fits_header[4]= { '.', 'F', 'I', 'T' };
register_header_check(8, fits_header, sizeof(fits_header), &header_check_fit, file_stat);
}
+#endif
diff --git a/src/file_fits.c b/src/file_fits.c
index 12065ec..b40be59 100644
--- a/src/file_fits.c
+++ b/src/file_fits.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fits)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,25 +53,45 @@ const file_hint_t file_hint_fits= {
* Image metadata is store in an ASCII header
* Specification can be found at http://fits.gsfc.nasa.gov/ */
+/*@
+ @ requires \valid_read(str + (0 .. 80-1));
+ @ assigns \nothing;
+ @*/
static uint64_t fits_get_val(const unsigned char *str)
{
unsigned int i;
uint64_t val=0;
+ /*@ loop assigns i; */
for(i=0;i<80 && str[i]!='=';i++);
i++;
+ /*@ loop assigns i; */
for(;i<80 && str[i]==' ';i++);
if(i<80 && str[i]=='-')
i++;
+ /*@ loop assigns i,val; */
for(;i<80 && str[i]>='0' && str[i]<='9';i++)
val=val*10+str[i]-'0';
return val;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer + (0 .. buffer_size-1));
+ @ requires \valid(file_recovery);
+ @ requires \valid(i_pointer);
+ @ requires \separated(buffer+(..), file_recovery, i_pointer);
+ @*/
static uint64_t fits_info(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery, unsigned int *i_pointer)
{
uint64_t naxis_size=1;
unsigned int i=*i_pointer;
+ if( i+80 >= buffer_size)
+ return 1;
/* Header is composed of 80 character fixed-length strings */
+ /*@
+ @ loop invariant i < buffer_size + 80;
+ @ loop assigns i, naxis_size, file_recovery->time;
+ @*/
for(; i+80 < buffer_size &&
memcmp(&buffer[i], "END ", 4)!=0;
i+=80)
@@ -95,13 +116,14 @@ static uint64_t fits_info(const unsigned char *buffer, const unsigned int buffer
{
/* CREA_DAT= '2007-08-29T16:22:09' */
/* 0123456789012345678 */
- const char *date_asc;
unsigned int j;
- for(j=0,date_asc=(const char *)&buffer[i];j<80 && *date_asc!='\'';j++,date_asc++);
- if(j<60 && *date_asc=='\'')
+ /*@
+ @ loop assigns j;
+ @*/
+ for(j=0;j<80 && buffer[i+j]!='\'';j++);
+ if(j<60 && buffer[i+j]=='\'')
{
- date_asc++;
- file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS(date_asc);
+ file_recovery->time=get_time_from_YYYY_MM_DD_HH_MM_SS(&buffer[i+j+1]);
}
}
}
@@ -111,6 +133,9 @@ static uint64_t fits_info(const unsigned char *buffer, const unsigned int buffer
static data_check_t data_check_fits(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 8 < file_recovery->file_size + buffer_size/2)
{
@@ -171,3 +196,4 @@ static void register_header_check_fits(file_stat_t *file_stat)
{
register_header_check(0, "SIMPLE =", 9, &header_check_fits, file_stat);
}
+#endif
diff --git a/src/file_flac.c b/src/file_flac.c
index 2a3a863..f46bb6d 100644
--- a/src/file_flac.c
+++ b/src/file_flac.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flac)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -90,8 +91,11 @@ static int header_check_flac(const unsigned char *buffer, const unsigned int buf
#endif
file_recovery_new->min_filesize=4+size;
#if 0
- file_recovery_new->calculated_file_size=4;
- file_recovery_new->data_check=&data_check_flac_metadata;
+ if(file_recovery_new->blocksize >= 4)
+ {
+ file_recovery_new->calculated_file_size=4;
+ file_recovery_new->data_check=&data_check_flac_metadata;
+ }
#endif
return 1;
}
@@ -104,3 +108,4 @@ static void register_header_check_flac(file_stat_t *file_stat)
register_header_check(0, flac_header,sizeof(flac_header), &header_check_flac, file_stat);
register_header_check(0, flac_header2,sizeof(flac_header2), &header_check_flac, file_stat);
}
+#endif
diff --git a/src/file_flp.c b/src/file_flp.c
index affebe4..a6d23dd 100644
--- a/src/file_flp.c
+++ b/src/file_flp.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -76,3 +77,4 @@ static void register_header_check_flp(file_stat_t *file_stat)
static const unsigned char flp_header[8]= {'F', 'L', 'h', 'd', 0x06, 0x00, 0x00, 0x00};
register_header_check(0, flp_header,sizeof(flp_header), &header_check_flp, file_stat);
}
+#endif
diff --git a/src/file_flv.c b/src/file_flv.c
index 1adf12a..dd89350 100644
--- a/src/file_flv.c
+++ b/src/file_flv.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flv)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -64,6 +65,9 @@ struct flv_tag
static data_check_t data_check_flv(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
static uint32_t datasize=0;
+ /*@
+ @ loop assigns file_recovery->calculated_file_size, datasize;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 15 < file_recovery->file_size + buffer_size/2)
{
@@ -113,3 +117,4 @@ static void register_header_check_flv(file_stat_t *file_stat)
static const unsigned char flv_header[4]= {'F', 'L', 'V', 0x01};
register_header_check(0, flv_header,sizeof(flv_header), &header_check_flv, file_stat);
}
+#endif
diff --git a/src/file_fm.c b/src/file_fm.c
index 240e15d..d5800c2 100644
--- a/src/file_fm.c
+++ b/src/file_fm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -51,6 +52,8 @@ struct fm_header
static int header_check_fm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct fm_header *hdr=(const struct fm_header *)buffer;
+ if(le64(hdr->size) > PHOTOREC_MAX_FILE_SIZE)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_fm.extension;
file_recovery_new->calculated_file_size=(uint64_t)le64(hdr->size) + 12833;
@@ -67,3 +70,4 @@ static void register_header_check_fm(file_stat_t *file_stat)
};
register_header_check(0, fm_header, sizeof(fm_header), &header_check_fm, file_stat);
}
+#endif
diff --git a/src/file_fob.c b/src/file_fob.c
index c96f1bc..35b8362 100644
--- a/src/file_fob.c
+++ b/src/file_fob.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fob)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -72,3 +73,4 @@ static void register_header_check_fob(file_stat_t *file_stat)
register_header_check(0, "Table ", 6, &header_check_fob, file_stat);
register_header_check(0, "XMLport ", 8, &header_check_fob, file_stat);
}
+#endif
diff --git a/src/file_fos.c b/src/file_fos.c
index c2254a3..31be28f 100644
--- a/src/file_fos.c
+++ b/src/file_fos.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fos)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -53,3 +54,4 @@ static void register_header_check_fos(file_stat_t *file_stat)
{
register_header_check(0, "FO4_SAVEGAME", 11, &header_check_fos, file_stat);
}
+#endif
diff --git a/src/file_fp5.c b/src/file_fp5.c
index 5c762bc..a861201 100644
--- a/src/file_fp5.c
+++ b/src/file_fp5.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fp5)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_fp5(file_stat_t *file_stat)
};
register_header_check(0, fp5_header,sizeof(fp5_header), &header_check_fp5, file_stat);
}
+#endif
diff --git a/src/file_fp7.c b/src/file_fp7.c
index 8e54e54..0749ede 100644
--- a/src/file_fp7.c
+++ b/src/file_fp7.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fp7)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -69,3 +70,4 @@ static void register_header_check_fp7(file_stat_t *file_stat)
};
register_header_check(0, fp7_header,sizeof(fp7_header), &header_check_fp7, file_stat);
}
+#endif
diff --git a/src/file_freeway.c b/src/file_freeway.c
index bdbb419..8e07f46 100644
--- a/src/file_freeway.c
+++ b/src/file_freeway.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_freeway)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_freeway(file_stat_t *file_stat)
};
register_header_check(0x10, freeway_header, sizeof(freeway_header), &header_check_freeway, file_stat);
}
+#endif
diff --git a/src/file_frm.c b/src/file_frm.c
index 4b3f126..480c158 100644
--- a/src/file_frm.c
+++ b/src/file_frm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_frm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -70,3 +71,4 @@ static void register_header_check_frm(file_stat_t *file_stat)
'W', 'G', 'F', 'O', 'R', 'M'};
register_header_check(0, frm_header,sizeof(frm_header), &header_check_frm, file_stat);
}
+#endif
diff --git a/src/file_fs.c b/src/file_fs.c
index c8aa99f..dbd7e05 100644
--- a/src/file_fs.c
+++ b/src/file_fs.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fs)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -58,6 +59,9 @@ struct transaction_header
static data_check_t data_check_fs(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 0x11 < file_recovery->file_size + buffer_size/2)
{
@@ -102,3 +106,4 @@ static void register_header_check_fs(file_stat_t *file_stat)
static const unsigned char fs_header[4]={ 'F', 'S','2','1' };
register_header_check(0, fs_header,sizeof(fs_header), &header_check_fs, file_stat);
}
+#endif
diff --git a/src/file_fwd.c b/src/file_fwd.c
index 86c0ad8..195e2e7 100644
--- a/src/file_fwd.c
+++ b/src/file_fwd.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fwd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_fwd(file_stat_t *file_stat)
{
register_header_check(0, "FRWD0120", 8, &header_check_fwd, file_stat);
}
+#endif
diff --git a/src/file_gam.c b/src/file_gam.c
index 95b9491..28c0d39 100644
--- a/src/file_gam.c
+++ b/src/file_gam.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gam)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_gam(file_stat_t *file_stat)
};
register_header_check(0, gam_header, sizeof(gam_header), &header_check_gam, file_stat);
}
+#endif
diff --git a/src/file_gct.c b/src/file_gct.c
index fd76bb9..727fbd5 100644
--- a/src/file_gct.c
+++ b/src/file_gct.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gct)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,3 +60,4 @@ static void register_header_check_gct(file_stat_t *file_stat)
};
register_header_check(0, gct_header, sizeof(gct_header), &header_check_gct, file_stat);
}
+#endif
diff --git a/src/file_gho.c b/src/file_gho.c
index cdd0de3..8e405df 100644
--- a/src/file_gho.c
+++ b/src/file_gho.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gho)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -56,3 +57,4 @@ static void register_header_check_gho(file_stat_t *file_stat)
static const unsigned char gho_header[3]= { 0xfe, 0xef, 0x01 };
register_header_check(0, gho_header,sizeof(gho_header), &header_check_db, file_stat);
}
+#endif
diff --git a/src/file_gi.c b/src/file_gi.c
index bd36fc7..9784612 100644
--- a/src/file_gi.c
+++ b/src/file_gi.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gi)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -51,6 +52,8 @@ struct header_gi
static int header_check_gi(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
const struct header_gi *hdr=(const struct header_gi *)buffer;
+ if(le64(hdr->size) > PHOTOREC_MAX_FILE_SIZE)
+ return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_gi.extension;
file_recovery_new->calculated_file_size=le64(hdr->size)+20;
@@ -67,3 +70,4 @@ static void register_header_check_gi(file_stat_t *file_stat)
};
register_header_check(0, gi_header, sizeof(gi_header), &header_check_gi, file_stat);
}
+#endif
diff --git a/src/file_gif.c b/src/file_gif.c
index 6f093c5..75254be 100644
--- a/src/file_gif.c
+++ b/src/file_gif.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gif)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -32,8 +33,6 @@
#include "log.h"
static void register_header_check_gif(file_stat_t *file_stat);
-static int header_check_gif(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
-static void file_check_gif(file_recovery_t *file_recovery);
static data_check_t data_check_gif(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
static data_check_t data_check_gif2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
@@ -46,36 +45,36 @@ const file_hint_t file_hint_gif= {
.register_header_check=&register_header_check_gif
};
-static int header_check_gif(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires \valid_read(&file_recovery->extension);
+ @ requires valid_read_string(file_recovery->extension);
+ @ requires \separated(file_recovery, file_recovery->handle, file_recovery->extension, &errno, &Frama_C_entropy_source);
+ @ requires \initialized(&file_recovery->time);
+ @
+ @ requires file_recovery->file_check == &file_check_gif;
+ @ assigns *file_recovery->handle, errno, file_recovery->file_size;
+ @ assigns Frama_C_entropy_source;
+ @
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static void file_check_gif(file_recovery_t *file_recovery)
{
- uint64_t offset;
- offset=6; /* Header */
- offset+=7; /* Logical Screen Descriptor */
- if((buffer[10]>>7)&0x1)
+ const char gif_footer[2]= {0x00, 0x3b};
+ char buffer[2];
+ /* file_recovery->calculated_file_size is always >= */
+ if(file_recovery->calculated_file_size < 2 ||
+ my_fseek(file_recovery->handle, file_recovery->calculated_file_size-2, SEEK_SET)<0 ||
+ fread(buffer, 2, 1, file_recovery->handle)!=1)
{
- /* Global Color Table */
- offset+=3<<((buffer[10]&7)+1);
+ file_recovery->file_size=0;
+ return;
}
- if(offset < buffer_size && buffer[offset]!=0x21 && buffer[offset]!=0x2c)
- return 0;
- reset_file_recovery(file_recovery_new);
- file_recovery_new->extension=file_hint_gif.extension;
- file_recovery_new->min_filesize=42;
- if(file_recovery_new->blocksize < 2)
- return 1;
- file_recovery_new->file_check=&file_check_gif;
- file_recovery_new->calculated_file_size=offset;
- file_recovery_new->data_check=&data_check_gif;
- return 1;
-}
-
-static void file_check_gif(file_recovery_t *file_recovery)
-{
- const unsigned char gif_footer[2]= {0x00, 0x3b};
- unsigned char buffer[2];
- if(my_fseek(file_recovery->handle, file_recovery->calculated_file_size-2, SEEK_SET)<0 ||
- fread(buffer, 2, 1, file_recovery->handle)!=1 ||
- memcmp(buffer, gif_footer, sizeof(gif_footer))!=0)
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&buffer, sizeof(buffer));
+#endif
+ if(memcmp(buffer, gif_footer, sizeof(gif_footer))!=0)
{
file_recovery->file_size=0;
return;
@@ -153,6 +152,59 @@ static data_check_t data_check_gif2(const unsigned char *buffer, const unsigned
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= 6+7+(3<<8)+1;
+ @ requires separation: \separated(&file_hint_gif, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures (\result == 1) ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result != 0) ==> file_recovery_new->extension != \null;
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1 && file_recovery_new->blocksize>=2) ==> (file_recovery_new->calculated_file_size >= 6+7);
+ @ ensures (\result == 1 && file_recovery_new->blocksize>=2) ==> (file_recovery_new->extension == file_hint_gif.extension);
+ @ ensures (\result == 1 && file_recovery_new->blocksize>=2) ==> (file_recovery_new->file_check == &file_check_gif);
+ @*/
+static int header_check_gif(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
+{
+ uint64_t offset;
+ offset=6; /* Header */
+ offset+=7; /* Logical Screen Descriptor */
+ if((buffer[10]>>7)&0x1)
+ {
+ /* Global Color Table */
+ offset+=3<<((buffer[10]&7)+1);
+ }
+ if(offset < buffer_size && buffer[offset]!=0x21 && buffer[offset]!=0x2c)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->extension=file_hint_gif.extension;
+ file_recovery_new->min_filesize=42;
+ if(file_recovery_new->blocksize < 2)
+ return 1;
+ file_recovery_new->calculated_file_size=offset;
+ file_recovery_new->file_check=&file_check_gif;
+ file_recovery_new->data_check=&data_check_gif;
+ return 1;
+}
+
static void register_header_check_gif(file_stat_t *file_stat)
{
static const unsigned char gif_header[6]= { 'G','I','F','8','7','a'};
@@ -160,3 +212,4 @@ static void register_header_check_gif(file_stat_t *file_stat)
register_header_check(0, gif_header,sizeof(gif_header), &header_check_gif, file_stat);
register_header_check(0, gif_header2,sizeof(gif_header2), &header_check_gif, file_stat);
}
+#endif
diff --git a/src/file_gm6.c b/src/file_gm6.c
index 536eeca..4445a6c 100644
--- a/src/file_gm6.c
+++ b/src/file_gm6.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gm6)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -140,3 +141,4 @@ static void register_header_check_gm6(file_stat_t *file_stat)
register_header_check(0, gm50_header, sizeof(gm50_header), &header_check_gmd, file_stat);
register_header_check(0, gm43_header, sizeof(gm43_header), &header_check_gmd, file_stat);
}
+#endif
diff --git a/src/file_gp2.c b/src/file_gp2.c
index a96e80d..407a4c5 100644
--- a/src/file_gp2.c
+++ b/src/file_gp2.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gp2)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -66,3 +67,4 @@ static void register_header_check_gp2(file_stat_t *file_stat)
};
register_header_check(0, gp2_header, sizeof(gp2_header), &header_check_gp2, file_stat);
}
+#endif
diff --git a/src/file_gp5.c b/src/file_gp5.c
index 4d9d156..fcd66d0 100644
--- a/src/file_gp5.c
+++ b/src/file_gp5.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gp5)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -77,3 +78,4 @@ static void register_header_check_gp5(file_stat_t *file_stat)
};
register_header_check(0, gp5_header, sizeof(gp5_header), &header_check_gp5, file_stat);
}
+#endif
diff --git a/src/file_gpg.c b/src/file_gpg.c
index 84a5587..225eaf0 100644
--- a/src/file_gpg.c
+++ b/src/file_gpg.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gpg)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -87,6 +88,7 @@ static const unsigned char pgp_header[5]= {0xa8, 0x03, 'P', 'G', 'P'};
/*@
@ ensures 0 <= \result <= 0x3f;
+ @ assigns \nothing;
@*/
static unsigned int openpgp_packet_tag(const unsigned char buf)
{
@@ -100,6 +102,7 @@ static unsigned int openpgp_packet_tag(const unsigned char buf)
@ requires \valid(length_type);
@ requires \valid(indeterminate_length);
@ ensures (*length_type == 1) || (*length_type == 2) || (*length_type==3)|| (*length_type==5);
+ @ assigns *length_type, *indeterminate_length;
*/
static unsigned int old_format_packet_length(const unsigned char *buf, unsigned int *length_type, int *indeterminate_length)
{
@@ -128,50 +131,60 @@ static unsigned int old_format_packet_length(const unsigned char *buf, unsigned
/*@ requires \valid_read(buf+(0..5));
@ requires \valid(length_type);
@ requires \valid(partial_body_length);
+ @ requires separation: \separated(buf+(0..5), length_type, partial_body_length);
@ ensures (*length_type == 1) || (*length_type == 2) || (*length_type==5);
@ ensures (*partial_body_length==0) || (*partial_body_length==1);
+ @ assigns *length_type, *partial_body_length;
*/
static unsigned int new_format_packet_length(const unsigned char *buf, unsigned int *length_type, int *partial_body_length)
{
+ const unsigned char buf0=buf[0];
*partial_body_length=0;
/* One-Octet Body Length */
- if(buf[0]<=191)
+ if(buf0<=191)
{
*length_type=1;
- /*@ assert 0 <= buf[0] <= 191; */
- return buf[0];
+ /*@ assert buf0 <= 191; */
+ return buf0;
}
/* Two-Octet Body Length */
- if(buf[0]<=223)
+ if(buf0<=223)
{
- /*@ assert 192 <= buf[0] <= 223; */
- unsigned int tmp=buf[0];
+ /*@ assert 192 <= buf0 <= 223; */
+ unsigned int tmp=buf0;
/*@ assert 192 <= tmp <= 223; */
tmp = ((tmp-192) << 8) + buf[1] + 192;
- /*@ assert 192 <= tmp <= ((223-192) << 8) + 255 + 192; */
*length_type=2;
+ /*@ assert 192 <= tmp <= ((223-192) << 8) + 255 + 192; */
return tmp;
}
+ /*@ assert 224 <= buf0; */
/* Five-Octet Body Length */
- if(buf[0]==255)
+ if(buf0==255)
{
const uint32_t *tmp32=(const uint32_t *)&buf[1];
const unsigned int tmp=be32(*tmp32);
*length_type=5;
+ /*@ assert tmp <= 0xffffffff; */
return tmp;
}
+ /*@ assert buf0 != 255; */
+ /*@ assert 224 <= buf0 <= 254; */
{
- /*@ assert 224 <= buf[0] <= 254; */
- const unsigned int tmp=buf[0]&0x1fu;
+ const unsigned int tmp=buf0&0x1fu;
+ /*@ assert tmp <= 30; */
+ const unsigned int tmp2=1u << tmp;
/* Partial Body Lengths */
*length_type=1;
*partial_body_length=1;
- return 1u << tmp;
+ /*@ assert tmp2 <= (1<<30); */
+ return tmp2;
}
}
/*@
@ ensures \result == -1 || 0 <= \result <= 2048;
+ @ assigns \nothing;
@*/
static int is_valid_mpi(const uint16_t size)
{
@@ -183,6 +196,7 @@ static int is_valid_mpi(const uint16_t size)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_pubkey_algo(const int algo)
{
@@ -213,6 +227,7 @@ static int is_valid_pubkey_algo(const int algo)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_sym_algo(const int algo)
{
@@ -249,6 +264,7 @@ static int is_valid_sym_algo(const int algo)
/*@
@ ensures \result == 0 || \result == 1;
+ @ assigns \nothing;
@*/
static int is_valid_S2K(const unsigned int algo)
{
@@ -264,8 +280,36 @@ static int is_valid_S2K(const unsigned int algo)
}
/*@
+ @ requires \valid(handle);
+ @ requires offset + tmp2 < 0x8000000000000000;
+ @ assigns *handle, errno;
+ @ assigns Frama_C_entropy_source;
+ @*/
+static unsigned int file_check_gpg_pubkey(FILE *handle, const uint64_t offset, const uint64_t tmp2)
+{
+ int len2;
+ char buffer[2];
+ const uint16_t *mpi2_ptr=(uint16_t *)&buffer;
+ if(my_fseek(handle, offset+tmp2, SEEK_SET) < 0 ||
+ fread(buffer, sizeof(buffer), 1, handle) != 1)
+ return 0;
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&buffer, sizeof(buffer));
+#endif
+ len2=is_valid_mpi(*mpi2_ptr);
+#ifdef DEBUG_GPG
+ log_info(" data: [ %u bits]\n", be16(*mpi2_ptr));
+#endif
+ if(len2 < 0)
+ return 0;
+ return len2;
+}
+
+/*@
@ requires \valid(file_recovery);
@ requires \valid(file_recovery->handle);
+ @ requires \separated(file_recovery, file_recovery->handle);
+ @ requires file_recovery->file_check == &file_check_gpg;
@*/
static void file_check_gpg(file_recovery_t *file_recovery)
{
@@ -283,12 +327,16 @@ static void file_check_gpg(file_recovery_t *file_recovery)
unsigned int length_type=0;
unsigned int length;
const int old_partial_body_length=partial_body_length;
- if(nbr >=0xffffffff || offset + 6 >= 0x8000000000000000)
+ if(nbr >=0xffffffff || offset >= 0x7000000000000000)
return;
- /*@ assert offset < 0x8000000000000000 - 6; */
+ /*@ assert offset < 0x7000000000000000; */
if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0 ||
fread(&buffer, sizeof(buffer), 1, file_recovery->handle) != 1)
+ {
+ if(nbr>=2 && offset <= org_file_size)
+ file_recovery->file_size=org_file_size;
return;
+ }
#ifdef __FRAMAC__
Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
#endif
@@ -330,49 +378,44 @@ static void file_check_gpg(file_recovery_t *file_recovery)
i+=length_type;
/*@ assert 0 < i <= 6; */
offset+=length_type;
- /*@ assert offset < 0x8000000000000000; */
- if(offset + length >= 0x8000000000000000)
+ if(offset >= 0x7000000000000000 || offset + length >= 0x7000000000000000)
return ;
+ /*@ assert offset < 0x7000000000000000; */
+ /*@ assert offset + length < 0x7000000000000000; */
if(old_partial_body_length==0)
{
if(tag==OPENPGP_TAG_PUBKEY_ENC_SESSION_KEY)
{
const uint16_t *mpi_ptr=(const uint16_t *)&buffer[i+1+8+1];
const int len=is_valid_mpi(*mpi_ptr);
+ const int pubkey_algo=buffer[i+1+8];
/* uint8_t version must be 3
* uint64_t pub_key_id
* uint8_t pub_key_algo
* encrypted_session_key */
- if(buffer[i]==3 && is_valid_pubkey_algo(buffer[i+1+8]) &&
+ if(buffer[i]==3 && is_valid_pubkey_algo(pubkey_algo) &&
len>0)
{
+ /* assert 0 < len <=2048; */
+ const unsigned int tmp2=1+8+1+2+len;
+ /* assert 12 < tmp2 <=12+2048; */
#ifdef DEBUG_GPG
log_info("GPG :pubkey enc packet: version %u, algo %u, keyid %02X%02X%02X%02X%02X%02X%02X%02X\n",
- buffer[i], buffer[i+1+8],
+ buffer[i], pubkey_algo,
buffer[i+1], buffer[i+2], buffer[i+3], buffer[i+4],
buffer[i+5], buffer[i+6], buffer[i+7], buffer[i+8]);
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
- if((unsigned)(1+8+1+2+len) > length)
+ if(tmp2 > length)
return ;
- if(buffer[i+1+8]==16 || buffer[i+1+8]==20)
+ /*@ assert tmp2 <= length; */
+ if(pubkey_algo==16 || pubkey_algo==20)
{
- int len2;
- uint16_t mpi2;
- if(my_fseek(file_recovery->handle, offset+1+8+1+2+len, SEEK_SET) < 0 ||
- fread(&mpi2, sizeof(mpi2), 1, file_recovery->handle) != 1)
- return;
-#ifdef __FRAMAC__
- Frama_C_make_unknown((char *)&mpi2, sizeof(mpi2));
-#endif
- len2=is_valid_mpi(mpi2);
-#ifdef DEBUG_GPG
- log_info(" data: [ %u bits]\n", be16(*mpi2));
-#endif
+ const int len2=file_check_gpg_pubkey(file_recovery->handle, offset, tmp2);
if(len2 <= 0)
- return ;
+ return;
if((unsigned)(1+8+1+2+len+2+len2) > length)
- return ;
+ return;
}
}
else
@@ -466,8 +509,18 @@ static void file_check_gpg(file_recovery_t *file_recovery)
@ requires file_recovery_new->blocksize > 0;
@ requires separation: \separated(file_recovery, file_recovery_new);
@ ensures \result == 0 || \result == 1;
- @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_gpg);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
@ ensures (\result == 1) ==> (file_recovery_new->extension == file_hint_gpg.extension || file_recovery_new->extension == extension_pgp);
+ @ ensures (\result == 1) ==> (file_recovery_new->time == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->calculated_file_size == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->min_filesize == 0);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == &file_check_gpg);
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null);
+ @ ensures (\result == 1) ==> (valid_read_string(file_recovery_new->extension));
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
@*/
static int header_check_gpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
@@ -512,7 +565,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
/*@ assert 0 <= length_type <= 6; */
tag=packet_tag[nbr];
#ifdef DEBUG_GPG
- log_info("GPG 0x%04x: %02u tag=%2u, size=%u + %u)\n",
+ log_info("GPG 0x%04lx: %02u tag=%2u, size=%u + %u)\n",
i, nbr, tag, length_type, length);
#endif
#if 0
@@ -543,7 +596,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
buffer[i], buffer[i+1+8],
buffer[i+1], buffer[i+2], buffer[i+3], buffer[i+4],
buffer[i+5], buffer[i+6], buffer[i+7], buffer[i+8]);
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
if(offset_mpi +2 > length)
return 0;
@@ -555,7 +608,7 @@ static int header_check_gpg(const unsigned char *buffer, const unsigned int buff
mpi_ptr=(const uint16_t *)&buffer[offset_mpi];
len2=is_valid_mpi(*mpi_ptr);
#ifdef DEBUG_GPG
- log_info(" data: [ %u bits]\n", be16(*mpi));
+ log_info(" data: [ %u bits]\n", be16(*mpi_ptr));
#endif
if(len2 <= 0)
return 0;
@@ -730,6 +783,7 @@ static void register_header_check_gpg(file_stat_t *file_stat)
register_header_check(0, pgp_header, sizeof(pgp_header), &header_check_gpg, file_stat);
register_header_check(0, gpg_header_pkey, sizeof(gpg_header_pkey), &header_check_gpg, file_stat);
}
+#endif
#if defined(MAIN_gpg)
#define BLOCKSIZE 65536u
@@ -737,7 +791,6 @@ int main()
{
const char fn[] = "recup_dir.1/f0000000.gpg";
unsigned char buffer[BLOCKSIZE];
- int res;
file_recovery_t file_recovery_new;
file_recovery_t file_recovery;
file_stat_t file_stats;
diff --git a/src/file_gpx.c b/src/file_gpx.c
index a1b91e7..7d7c5c9 100644
--- a/src/file_gpx.c
+++ b/src/file_gpx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gpx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_gpx(file_stat_t *file_stat)
{
register_header_check(0, "BCFZ", 4, &header_check_gpx, file_stat);
}
+#endif
diff --git a/src/file_gsm.c b/src/file_gsm.c
index 7955344..affa471 100644
--- a/src/file_gsm.c
+++ b/src/file_gsm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gsm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,6 +53,9 @@ struct block_header
static data_check_t data_check_gsm(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + sizeof(struct block_header) < file_recovery->file_size + buffer_size/2)
{
@@ -64,14 +68,26 @@ static data_check_t data_check_gsm(const unsigned char *buffer, const unsigned i
return DC_CONTINUE;
}
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires file_recovery_new->blocksize <= buffer_size;
+ @ requires separation: \separated(&file_hint_gsm, buffer+(..), file_recovery, file_recovery_new);
+ @*/
static int header_check_gsm(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
- const struct block_header *hdr;
unsigned int i=0;
- for(i=0, hdr=(const struct block_header *)buffer;
- i * sizeof(struct block_header) < file_recovery_new->blocksize;
- i++, hdr++)
+ /*@ loop assigns i; */
+ for(i=0;
+ (i+1) * sizeof(struct block_header) <= file_recovery_new->blocksize;
+ i++)
{
+ const struct block_header *hdr=(const struct block_header *)&buffer[i*sizeof(struct block_header)];
if(hdr->marker < 0xd0 || hdr->marker > 0xdf)
return 0;
}
@@ -128,3 +144,4 @@ static void register_header_check_gsm(file_stat_t *file_stat)
register_header_check(0, gsm_header15, sizeof(gsm_header15), &header_check_gsm, file_stat);
register_header_check(0, gsm_header16, sizeof(gsm_header16), &header_check_gsm, file_stat);
}
+#endif
diff --git a/src/file_gz.c b/src/file_gz.c
index 0ef52e0..d75cfa9 100644
--- a/src/file_gz.c
+++ b/src/file_gz.c
@@ -20,9 +20,16 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gz)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(MAIN_fidentify) || defined(MAIN_photorec) || defined(__FRAMAC__)
+#undef HAVE_LIBZ
+#undef HAVE_ZLIB_H
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -37,7 +44,9 @@
static void register_header_check_gz(file_stat_t *file_stat);
static void file_rename_gz(file_recovery_t *file_recovery);
+#ifndef SINGLE_FORMAT
extern const file_hint_t file_hint_doc;
+#endif
const file_hint_t file_hint_gz= {
.extension="gz",
@@ -157,26 +166,20 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
}
if(off >= 512 || off >= buffer_size)
return 0;
- if(file_recovery->file_stat!=NULL &&
- file_recovery->file_stat->file_hint==&file_hint_doc)
- {
- if(header_ignored_adv(file_recovery, file_recovery_new)==0)
- return 0;
- }
- if(file_recovery->file_check==&file_check_bgzf)
- {
- header_ignored(file_recovery_new);
- return 0;
- }
+ /*@ assert off < 512; */
+ /*@ assert off < buffer_size ; */
#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ)
{
static const unsigned char schematic_header[12]={ 0x0a, 0x00, 0x09,
'S', 'c', 'h', 'e', 'm', 'a', 't', 'i', 'c'};
static const unsigned char tar_header_posix[8] = { 'u','s','t','a','r',' ',' ',0x00};
const unsigned char *buffer_compr=buffer+off;
- unsigned char buffer_uncompr[512];
- const unsigned int comprLen=(buffer_size<512?buffer_size:512)-off;
- const unsigned int uncomprLen=512-1;
+ unsigned char buffer_uncompr[4096];
+ const unsigned int uncomprLen=sizeof(buffer_uncompr)-1;
+ const unsigned int bs=td_max(512,file_recovery_new->blocksize);
+ /*@ assert bs >=512; */
+ const unsigned int comprLen=td_min(buffer_size,bs)-off;
+ /*@ assert comprLen > 0; */
int err;
z_stream d_stream; /* decompression stream */
d_stream.zalloc = (alloc_func)0;
@@ -207,6 +210,19 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
/* Probably too small to be a file */
if(d_stream.total_out < 16)
return 0;
+#ifndef SINGLE_FORMAT
+ if(file_recovery->file_stat!=NULL &&
+ file_recovery->file_stat->file_hint==&file_hint_doc)
+ {
+ if(header_ignored_adv(file_recovery, file_recovery_new)==0)
+ return 0;
+ }
+#endif
+ if(file_recovery->file_check==&file_check_bgzf)
+ {
+ header_ignored(file_recovery_new);
+ return 0;
+ }
buffer_uncompr[d_stream.total_out]='\0';
if(bgzf!=0)
{
@@ -216,6 +232,15 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
file_recovery_new->min_filesize=22;
file_recovery_new->time=le32(gz->mtime);
file_recovery_new->file_rename=&file_rename_gz;
+ if(d_stream.avail_in==0 && d_stream.total_in < comprLen && d_stream.total_out < uncomprLen)
+ {
+ /* an 8-byte footer, containing a CRC-32 checksum and
+ * the length of the original uncompressed data, modulo 2^32
+ */
+ file_recovery_new->calculated_file_size=off+d_stream.total_in+8;
+ file_recovery_new->data_check=&data_check_size;
+ file_recovery_new->file_check=&file_check_size;
+ }
if(memcmp(buffer_uncompr, "PVP ", 4)==0)
{
/* php Video Pro */
@@ -297,6 +322,19 @@ static int header_check_gz(const unsigned char *buffer, const unsigned int buffe
}
}
#else
+#ifndef SINGLE_FORMAT
+ if(file_recovery->file_stat!=NULL &&
+ file_recovery->file_stat->file_hint==&file_hint_doc)
+ {
+ if(header_ignored_adv(file_recovery, file_recovery_new)==0)
+ return 0;
+ }
+#endif
+ if(file_recovery->file_check==&file_check_bgzf)
+ {
+ header_ignored(file_recovery_new);
+ return 0;
+ }
reset_file_recovery(file_recovery_new);
file_recovery_new->min_filesize=22;
file_recovery_new->time=le32(gz->mtime);
@@ -334,6 +372,13 @@ static void file_rename_gz(file_recovery_t *file_recovery)
}
}
+static void register_header_check_gz(file_stat_t *file_stat)
+{
+ static const unsigned char gz_header_magic[3]= {0x1F, 0x8B, 0x08};
+ register_header_check(0, gz_header_magic,sizeof(gz_header_magic), &header_check_gz, file_stat);
+}
+#endif
+
const char*td_zlib_version(void)
{
#if defined(HAVE_ZLIB_H) && defined(HAVE_LIBZ)
@@ -342,9 +387,3 @@ const char*td_zlib_version(void)
return "none";
#endif
}
-
-static void register_header_check_gz(file_stat_t *file_stat)
-{
- static const unsigned char gz_header_magic[3]= {0x1F, 0x8B, 0x08};
- register_header_check(0, gz_header_magic,sizeof(gz_header_magic), &header_check_gz, file_stat);
-}
diff --git a/src/file_hdf.c b/src/file_hdf.c
index 378855c..a3014d7 100644
--- a/src/file_hdf.c
+++ b/src/file_hdf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hdf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -71,33 +72,49 @@ static void file_check_hdf(file_recovery_t *file_recovery)
do
{
struct ddh_struct ddh;
- const struct dd_struct *p;
unsigned int i;
unsigned int size;
if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0 ||
- fread(&ddh, sizeof(ddh), 1, file_recovery->handle) !=1 ||
- be16(ddh.size)==0 ||
- fread(dd, sizeof(struct dd_struct)*be16(ddh.size), 1, file_recovery->handle) !=1)
+ fread(&ddh, sizeof(ddh), 1, file_recovery->handle) !=1)
{
free(dd);
file_recovery->file_size=0;
return ;
}
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&ddh, sizeof(ddh));
+#endif
size=be16(ddh.size);
+ if(size==0 ||
+ fread(dd, sizeof(struct dd_struct)*size, 1, file_recovery->handle) !=1)
+ {
+ free(dd);
+ file_recovery->file_size=0;
+ return ;
+ }
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(dd, sizeof(struct dd_struct)*size);
+#endif
if(file_size < offset + sizeof(struct dd_struct) * size)
file_size = offset + sizeof(struct dd_struct) * size;
#ifdef DEBUG_HDF
log_info("size=%u next=%lu\n", size, be32(ddh.next));
#endif
- for(i=0, p=dd; i < size; i++,p++)
+ /*@
+ @ loop assigns i, file_size;
+ @*/
+ for(i=0; i < size; i++)
{
+ const struct dd_struct *p=&dd[i];
+ const unsigned int p_offset=be32(p->offset);
+ const unsigned int p_length=be32(p->length);
#ifdef DEBUG_HDF
log_info("tag=0x%04x, ref=%u, offset=%lu, length=%lu\n",
- be16(p->tag), be16(p->ref), be32(p->offset), be32(p->length));
+ be16(p->tag), be16(p->ref), p_offset, p_length);
#endif
- if((unsigned)be32(p->offset)!=(unsigned)(-1) &&
- file_size < (uint64_t)be32(p->offset) + (uint64_t)be32(p->length))
- file_size = (uint64_t)be32(p->offset) + (uint64_t)be32(p->length);
+ if(p_offset!=0xffffffff &&
+ file_size < (uint64_t)p_offset + (uint64_t)p_length)
+ file_size = (uint64_t)p_offset + (uint64_t)p_length;
}
offset_old=offset;
offset=be32(ddh.next);
@@ -129,3 +146,4 @@ static void register_header_check_hdf(file_stat_t *file_stat)
static const unsigned char hdf_header[4]= { 0x0e, 0x03, 0x13, 0x01};
register_header_check(0, hdf_header, sizeof(hdf_header), &header_check_hdf, file_stat);
}
+#endif
diff --git a/src/file_hdr.c b/src/file_hdr.c
index 0e6e9e6..596d3bc 100644
--- a/src/file_hdr.c
+++ b/src/file_hdr.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hdr)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -79,3 +80,4 @@ static void register_header_check_hdr(file_stat_t *file_stat)
{
register_header_check(0, "ISc(", 4, &header_check_hdr, file_stat);
}
+#endif
diff --git a/src/file_hds.c b/src/file_hds.c
index 92664d2..4ada2f6 100644
--- a/src/file_hds.c
+++ b/src/file_hds.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hds)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -74,3 +75,4 @@ static void register_header_check_hds(file_stat_t *file_stat)
};
register_header_check(0, hds_header,sizeof(hds_header), &header_check_hds, file_stat);
}
+#endif
diff --git a/src/file_hfsp.c b/src/file_hfsp.c
index 8ed2504..0f7fc40 100644
--- a/src/file_hfsp.c
+++ b/src/file_hfsp.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hfsp)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,3 +60,4 @@ static void register_header_check_hfsp(file_stat_t *file_stat)
register_header_check(0, "HX\0\5", 4, &header_check_hfsp, file_stat);
}
+#endif
diff --git a/src/file_hm.c b/src/file_hm.c
index 2eaa559..ea2f07c 100644
--- a/src/file_hm.c
+++ b/src/file_hm.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hm)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -57,3 +58,4 @@ static void register_header_check_hm(file_stat_t *file_stat)
};
register_header_check(0, hm_header, sizeof(hm_header), &header_check_hm, file_stat);
}
+#endif
diff --git a/src/file_hr9.c b/src/file_hr9.c
index 3f5045f..ace2b02 100644
--- a/src/file_hr9.c
+++ b/src/file_hr9.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_hr9)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -63,3 +64,4 @@ static void register_header_check_hr9(file_stat_t *file_stat)
};
register_header_check(0, hr9_header,sizeof(hr9_header), &header_check_hr9, file_stat);
}
+#endif
diff --git a/src/file_http.c b/src/file_http.c
index 33e63fa..5baa99e 100644
--- a/src/file_http.c
+++ b/src/file_http.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_http)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,3 +53,4 @@ static void register_header_check_http(file_stat_t *file_stat)
{
register_header_check(0, "HTTP/1.1 200 OK\r\nDate:", 22, &header_check_http, file_stat);
}
+#endif
diff --git a/src/file_ibd.c b/src/file_ibd.c
index b26eb2b..0631e75 100644
--- a/src/file_ibd.c
+++ b/src/file_ibd.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ibd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -49,7 +50,7 @@ const file_hint_t file_hint_ibd= {
#define DICT_TF_BITS 6 /* number of flag bits */
#define DICT_TF_FORMAT_SHIFT 5 /* file format */
#define DICT_TF_FORMAT_MASK \
- ((~(~0 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
+ ((~(~0U << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
#define DICT_TF_FORMAT_ZIP 1 /* InnoDB plugin for 5.1: compressed tables */
@@ -104,3 +105,4 @@ static void register_header_check_ibd(file_stat_t *file_stat)
{
register_header_check(0xc063, "infimum", 7, &header_check_ibd, file_stat);
}
+#endif
diff --git a/src/file_icc.c b/src/file_icc.c
index 9d22646..f540091 100644
--- a/src/file_icc.c
+++ b/src/file_icc.c
@@ -19,6 +19,7 @@
Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_icc)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -65,3 +66,4 @@ static void register_header_check_icc(file_stat_t *file_stat)
static const unsigned char icc_header[4]= { 'a', 'c', 's', 'p' };
register_header_check(36, icc_header,sizeof(icc_header), &header_check_icc, file_stat);
}
+#endif
diff --git a/src/file_icns.c b/src/file_icns.c
index 20d5d12..2216369 100644
--- a/src/file_icns.c
+++ b/src/file_icns.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_icns)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -52,7 +53,7 @@ struct icon_data
{
char type[4];
uint32_t size;
- uint8_t data[0];
+// uint8_t data[0];
};
static int check_icon_type(const char *type)
@@ -100,17 +101,19 @@ static int header_check_icns(const unsigned char *buffer, const unsigned int buf
{
const struct icns_header *hdr=(const struct icns_header *)buffer;
const struct icon_data *icon=(const struct icon_data *)&buffer[8];
- if(be32(hdr->size) < sizeof(struct icns_header))
+ const unsigned int hdr_size=be32(hdr->size);
+ const unsigned int icon_size=be32(icon->size);
+ if(hdr_size < sizeof(struct icns_header))
return 0;
- if(be32(icon->size) < sizeof(struct icon_data))
+ if(icon_size < sizeof(struct icon_data))
return 0;
- if(8 + be32(icon->size) > be32(hdr->size))
+ if(icon_size > hdr_size - 8)
return 0;
if(!check_icon_type(icon->type))
return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->extension=file_hint_icns.extension;
- file_recovery_new->calculated_file_size=be32(hdr->size);
+ file_recovery_new->calculated_file_size=hdr_size;
file_recovery_new->data_check=&data_check_size;
file_recovery_new->file_check=&file_check_size;
return 1;
@@ -120,3 +123,4 @@ static void register_header_check_icns(file_stat_t *file_stat)
{
register_header_check(0, "icns", 4, &header_check_icns, file_stat);
}
+#endif
diff --git a/src/file_ico.c b/src/file_ico.c
index af2ae41..4d63a7a 100644
--- a/src/file_ico.c
+++ b/src/file_ico.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ico)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -155,3 +156,4 @@ static void register_header_check_ico(file_stat_t *file_stat)
register_header_check(0, header_ico8, sizeof(header_ico8), &header_check_ico, file_stat);
register_header_check(0, header_ico9, sizeof(header_ico9), &header_check_ico, file_stat);
}
+#endif
diff --git a/src/file_idx.c b/src/file_idx.c
index 66f9cee..83934f6 100644
--- a/src/file_idx.c
+++ b/src/file_idx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_idx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -71,3 +72,4 @@ static void register_header_check_idx(file_stat_t *file_stat)
{
register_header_check(0, "RT60", 4, &header_check_idx, file_stat);
}
+#endif
diff --git a/src/file_ifo.c b/src/file_ifo.c
index a55ec66..1577ec4 100644
--- a/src/file_ifo.c
+++ b/src/file_ifo.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ifo)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -67,3 +68,4 @@ static void register_header_check_ifo(file_stat_t *file_stat)
register_header_check(0, ifo_header_vmg, sizeof(ifo_header_vmg), &header_check_ifo, file_stat);
register_header_check(0, ifo_header_vts, sizeof(ifo_header_vts), &header_check_ifo, file_stat);
}
+#endif
diff --git a/src/file_imb.c b/src/file_imb.c
index d21be56..3d35bf6 100644
--- a/src/file_imb.c
+++ b/src/file_imb.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_imb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_imb(file_stat_t *file_stat)
static const unsigned char imb_header[15]= { 0x00, 0x00, 0x00, 'I','n','c','r','e','d','i','m','a','i','l',' '};
register_header_check(1, imb_header,sizeof(imb_header), &header_check_imb, file_stat);
}
+#endif
diff --git a/src/file_indd.c b/src/file_indd.c
index 5d16702..638a321 100644
--- a/src/file_indd.c
+++ b/src/file_indd.c
@@ -21,6 +21,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_indd)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -94,8 +95,17 @@ static void file_check_indd(file_recovery_t *file_recovery)
file_recovery->file_size=0;
return ;
}
- if(fread(&hdr, sizeof(hdr), 1, file_recovery->handle) != 1 ||
- memcmp(hdr.fGUID, kINDDContigObjHeaderGUID, sizeof(kINDDContigObjHeaderGUID))!=0)
+ if(fread(&hdr, sizeof(hdr), 1, file_recovery->handle) != 1)
+ {
+ file_recovery->file_size=(offset+4096-1)/4096*4096;
+ if(file_recovery->file_size>file_size_org)
+ file_recovery->file_size=0;
+ return ;
+ }
+#ifdef __FRAMAC__
+ Frama_C_make_unknown(&hdr, sizeof(hdr));
+#endif
+ if(memcmp(hdr.fGUID, kINDDContigObjHeaderGUID, sizeof(kINDDContigObjHeaderGUID))!=0)
{
file_recovery->file_size=(offset+4096-1)/4096*4096;
if(file_recovery->file_size>file_size_org)
@@ -150,3 +160,4 @@ static void register_header_check_indd(file_stat_t *file_stat)
0x44, 0x4f, 0x43, 0x55, 0x4d, 0x45, 0x4e, 0x54 };
register_header_check(0, indd_header,sizeof(indd_header), &header_check_indd, file_stat);
}
+#endif
diff --git a/src/file_info.c b/src/file_info.c
index 1b4d3e9..360394b 100644
--- a/src/file_info.c
+++ b/src/file_info.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_info)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -57,3 +58,4 @@ static void register_header_check_info(file_stat_t *file_stat)
};
register_header_check(0, info_header, sizeof(info_header), &header_check_info, file_stat);
}
+#endif
diff --git a/src/file_iso.c b/src/file_iso.c
index 0483809..49c5dbe 100644
--- a/src/file_iso.c
+++ b/src/file_iso.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_iso)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -28,6 +29,7 @@
#endif
#include <stdio.h>
#include "types.h"
+#include "common.h"
#include "filegen.h"
#include "iso9660.h"
@@ -49,13 +51,13 @@ static int header_check_db(const unsigned char *buffer, const unsigned int buffe
return 0;
{
const struct iso_primary_descriptor *iso1=(const struct iso_primary_descriptor*)&buffer[0x8000];
- const unsigned int volume_space_size=iso1->volume_space_size[0] | (iso1->volume_space_size[1]<<8) | (iso1->volume_space_size[2]<<16) | (iso1->volume_space_size[3]<<24);
- const unsigned int volume_space_size2=iso1->volume_space_size[7] | (iso1->volume_space_size[6]<<8) | (iso1->volume_space_size[5]<<16) | (iso1->volume_space_size[4]<<24);
- const unsigned int logical_block_size=iso1->logical_block_size[0] | (iso1->logical_block_size[1]<<8);
- const unsigned int logical_block_size2=iso1->logical_block_size[3] | (iso1->logical_block_size[2]<<8);
- if(volume_space_size==volume_space_size2 && logical_block_size==logical_block_size2)
+ const unsigned int volume_space_size_le=le32(iso1->volume_space_size_le);
+ const unsigned int volume_space_size_be=be32(iso1->volume_space_size_be);
+ const unsigned int logical_block_size_le=le16(iso1->logical_block_size_le);
+ const unsigned int logical_block_size_be=be16(iso1->logical_block_size_be);
+ if(volume_space_size_le==volume_space_size_be && logical_block_size_le==logical_block_size_be)
{ /* ISO 9660 */
- const uint64_t size=(uint64_t)volume_space_size * logical_block_size;
+ const uint64_t size=(uint64_t)volume_space_size_le * logical_block_size_le;
if(size < 0x8000+512)
return 0;
reset_file_recovery(file_recovery_new);
@@ -78,4 +80,4 @@ static void register_header_check_iso(file_stat_t *file_stat)
static const unsigned char iso_header[6]= { 0x01, 'C', 'D', '0', '0', '1'};
register_header_check(0x8000, iso_header,sizeof(iso_header), &header_check_db, file_stat);
}
-
+#endif
diff --git a/src/file_it.c b/src/file_it.c
index 3f8925f..4aa14ed 100644
--- a/src/file_it.c
+++ b/src/file_it.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_it)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -82,3 +83,4 @@ static void register_header_check_it(file_stat_t *file_stat)
{
register_header_check(0, "IMPM", 4, &header_check_it, file_stat);
}
+#endif
diff --git a/src/file_itu.c b/src/file_itu.c
index 6033e6a..1c00342 100644
--- a/src/file_itu.c
+++ b/src/file_itu.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_itunes)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -63,3 +64,4 @@ static void register_header_check_itunes(file_stat_t *file_stat)
static const unsigned char itunes_header[8]= {'m', 'h', 'b', 'd', 0x68, 0x00, 0x00, 0x00};
register_header_check(0, itunes_header,sizeof(itunes_header), &header_check_itunes, file_stat);
}
+#endif
diff --git a/src/file_jks.c b/src/file_jks.c
index 9539db1..3ca16b7 100644
--- a/src/file_jks.c
+++ b/src/file_jks.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jks)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -68,3 +69,4 @@ static void register_header_check_jks(file_stat_t *file_stat)
};
register_header_check(0, jks_header, sizeof(jks_header), &header_check_jks, file_stat);
}
+#endif
diff --git a/src/file_jpg.c b/src/file_jpg.c
index bf82acd..a807a48 100644
--- a/src/file_jpg.c
+++ b/src/file_jpg.c
@@ -20,9 +20,17 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jpg)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+
+#if defined(__FRAMAC__) || defined(SINGLE_FORMAT)
+#undef HAVE_LIBJPEG
+#undef DEBUG_JPEG
+#undef HAVE_JPEGLIB_H
+#endif
+
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@@ -49,18 +57,28 @@
#include "file_jpg.h"
#include "file_tiff.h"
#include "setdate.h"
+#if defined(__FRAMAC__)
+#include "__fc_builtin.h"
+#endif
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
extern const file_hint_t file_hint_doc;
extern const file_hint_t file_hint_indd;
extern const file_hint_t file_hint_mov;
extern const file_hint_t file_hint_riff;
extern const file_hint_t file_hint_rw2;
extern data_check_t data_check_avi_stream(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
+#endif
static void register_header_check_jpg(file_stat_t *file_stat);
-static int header_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new);
static void file_check_jpg(file_recovery_t *file_recovery);
-data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
+static data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery);
+
+/*@
+ @ requires i < buffer_size;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ assigns \nothing;
+ @*/
static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_size, const unsigned i, const unsigned int size);
const file_hint_t file_hint_jpg= {
@@ -72,12 +90,12 @@ const file_hint_t file_hint_jpg= {
.register_header_check=&register_header_check_jpg
};
-static void register_header_check_jpg(file_stat_t *file_stat)
-{
- static const unsigned char jpg_header[3]= { 0xff,0xd8,0xff};
- register_header_check(0, jpg_header, sizeof(jpg_header), &header_check_jpg, file_stat);
-}
-
+/*@
+ @ requires \valid_read(buffer + (0 .. buffer_size-1));
+ @ requires \valid(height);
+ @ requires \valid(width);
+ @ requires \separated(buffer, height, width);
+ @*/
static void jpg_get_size(const unsigned char *buffer, const unsigned int buffer_size, unsigned int *height, unsigned int *width)
{
unsigned int i=2;
@@ -108,7 +126,7 @@ struct MP_IFD_Field
uint16_t tag;
uint16_t type;
uint32_t count;
- char value[0];
+ char value[4];
} __attribute__ ((gcc_struct, __packed__));
struct MP_Entry
@@ -120,6 +138,11 @@ struct MP_Entry
uint16_t dep2;
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires size >= 8;
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
+ @*/
static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset, const unsigned int size)
{
const uint16_t *tmp16;
@@ -129,40 +152,55 @@ static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset
unsigned int nbr;
unsigned int NumberOfImages=0;
unsigned int MPEntry_offset=0;
- const struct MP_Entry* MPEntry;
uint64_t max_offset=0;
#ifdef DEBUG_JPEG
log_info("check_mpo_be\n");
#endif
- if(offset+2 >= size)
+ if(offset >= size - 2)
return 0;
+ /*@ assert offset < size - 2; */
tmp16=(const uint16_t*)(&mpo[offset]);
nbr=be16(*tmp16);
offset+=2;
+ /* @offset: MP Index Fields*/
+ if(offset + nbr * 12 > size)
+ return 0;
+ /*@ assert offset + nbr * 12 <= size; */
+ /*@
+ @ loop invariant 0 <= i <= nbr;
+ @ loop assigns i, NumberOfImages, MPEntry_offset;
+ @ loop variant nbr-i;
+ @*/
for(i=0; i< nbr; i++)
{
- const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)(&mpo[offset]);
- if(offset+12 > size)
- return 0;
+ /*@ assert 0 <= i < nbr; */
+ const unsigned char *field_ptr=&mpo[offset + i * 12];
+ /*@ assert \valid_read(field_ptr + ( 0 .. sizeof(struct MP_IFD_Field)-1)); */
+ const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)field_ptr;
+ const unsigned int count=be32(field->count);
+ const unsigned int type=be16(field->type);
switch(be16(field->tag))
{
case 0xb000:
/* MPFVersion, type must be undefined */
- if(be16(field->type)!=7 || be32(field->count)!=4)
+ if(type!=7 || count!=4)
return 0;
break;
case 0xb001:
/* NumberOfImages, type must be long */
- if(be16(field->type)!=4 || be32(field->count)!=1)
+ if(type!=4 || count!=1)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
NumberOfImages=be32(*tmp);
+ if(NumberOfImages >= 0x100000)
+ return 0;
+ /*@ assert NumberOfImages < 0x100000; */
}
break;
case 0xb002:
/* MPEntry, type must be undefined */
- if(be16(field->type)!=7 || be32(field->count)!=16*NumberOfImages)
+ if(type!=7 || count!=16*NumberOfImages)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
@@ -170,74 +208,105 @@ static uint64_t check_mpo_be(const unsigned char *mpo, const uint64_t mpo_offset
}
break;
}
- offset+=12;
}
#ifdef DEBUG_JPEG
log_info("MPEntry_offset=%u, NumberOfImages=%u\n", MPEntry_offset, NumberOfImages);
#endif
+ /*@ assert NumberOfImages < 0x100000; */
+ if(MPEntry_offset > size)
+ return 0;
if(MPEntry_offset + 16*NumberOfImages > size)
return 0;
- for(i=0, MPEntry=(const struct MP_Entry*)(&mpo[MPEntry_offset]);
- i<NumberOfImages;
- i++, MPEntry++)
+ /*@
+ @ loop invariant 0 <= i <= NumberOfImages;
+ @ loop assigns i, max_offset;
+ @ loop variant NumberOfImages-i;
+ @*/
+ for(i=0; i<NumberOfImages; i++)
{
- uint64_t tmp=be32(MPEntry->offset)+be32(MPEntry->size);
+ /*@ assert 0 <= i < NumberOfImages; */
+ const unsigned char *MPEntry_ptr=&mpo[MPEntry_offset + i * sizeof(struct MP_Entry)];
+ /*@ assert \valid_read(MPEntry_ptr+ ( 0 .. sizeof(struct MP_Entry)-1)); */
+ const struct MP_Entry *MPEntry=(const struct MP_Entry*)MPEntry_ptr;
+ uint64_t tmp=be32(MPEntry->size);
#ifdef DEBUG_JPEG
log_info("offset=%lu, size=%lu\n",
(long unsigned)be32(MPEntry->offset),
(long unsigned)be32(MPEntry->size));
#endif
if(be32(MPEntry->offset)>0)
- tmp+=mpo_offset;
+ tmp+=be32(MPEntry->offset)+mpo_offset;
if(max_offset < tmp)
max_offset = tmp;
}
return max_offset;
}
+/*@
+ @ requires size >= 8;
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
+ @*/
static uint64_t check_mpo_le(const unsigned char *mpo, const uint64_t mpo_offset, const unsigned int size)
{
const uint16_t *tmp16;
+ /* Offset to first IFD */
const uint32_t *tmp32=(const uint32_t *)(&mpo[4]);
unsigned int offset=le32(*tmp32);
unsigned int i;
unsigned int nbr;
unsigned int NumberOfImages=0;
unsigned int MPEntry_offset=0;
- const struct MP_Entry* MPEntry;
uint64_t max_offset=0;
#ifdef DEBUG_JPEG
log_info("check_mpo_le\n");
#endif
- if(offset+2 >= size)
+ if(offset >= size - 2)
return 0;
+ /*@ assert offset < size - 2; */
tmp16=(const uint16_t*)(&mpo[offset]);
nbr=le16(*tmp16);
offset+=2;
+ /* @offset: MP Index Fields*/
+ if(offset + nbr * 12 > size)
+ return 0;
+ /*@ assert offset + nbr * 12 <= size; */
+ /*@
+ @ loop invariant 0 <= i <= nbr;
+ @ loop assigns i, NumberOfImages, MPEntry_offset;
+ @ loop variant nbr-i;
+ @*/
for(i=0; i< nbr; i++)
{
- const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)(&mpo[offset]);
- if(offset+12 > size)
- return 0;
+ /*@ assert 0 <= i < nbr; */
+ const unsigned char *field_ptr=&mpo[offset + i * 12];
+ /*@ assert \valid_read(field_ptr + ( 0 .. sizeof(struct MP_IFD_Field)-1)); */
+ const struct MP_IFD_Field *field=(const struct MP_IFD_Field *)field_ptr;
+ /*@ assert \valid_read(field); */
+ const unsigned int count=le32(field->count);
+ const unsigned int type=le16(field->type);
switch(le16(field->tag))
{
case 0xb000:
/* MPFVersion, type must be undefined */
- if(le16(field->type)!=7 || le32(field->count)!=4)
+ if(type!=7 || count!=4)
return 0;
break;
case 0xb001:
/* NumberOfImages, type must be long */
- if(le16(field->type)!=4 || le32(field->count)!=1)
+ if(type!=4 || count!=1)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
NumberOfImages=le32(*tmp);
+ if(NumberOfImages >= 0x100000)
+ return 0;
+ /*@ assert NumberOfImages < 0x100000; */
}
break;
case 0xb002:
/* MPEntry, type must be undefined */
- if(le16(field->type)!=7 || le32(field->count)!=16*NumberOfImages)
+ if(type!=7 || count!=16*NumberOfImages)
return 0;
{
const uint32_t *tmp=(const uint32_t *)&field->value[0];
@@ -245,33 +314,51 @@ static uint64_t check_mpo_le(const unsigned char *mpo, const uint64_t mpo_offset
}
break;
}
- offset+=12;
}
#ifdef DEBUG_JPEG
log_info("MPEntry_offset=%u, NumberOfImages=%u\n", MPEntry_offset, NumberOfImages);
#endif
+ /*@ assert NumberOfImages < 0x100000; */
+ if(MPEntry_offset > size)
+ return 0;
if(MPEntry_offset + 16*NumberOfImages > size)
return 0;
- for(i=0, MPEntry=(const struct MP_Entry*)(&mpo[MPEntry_offset]);
- i<NumberOfImages;
- i++, MPEntry++)
+ /*@
+ @ loop invariant 0 <= i <= NumberOfImages;
+ @ loop assigns i, max_offset;
+ @ loop variant NumberOfImages-i;
+ @*/
+ for(i=0; i<NumberOfImages; i++)
{
- uint64_t tmp=le32(MPEntry->offset)+le32(MPEntry->size);
+ /*@ assert 0 <= i < NumberOfImages; */
+ const unsigned char *MPEntry_ptr=&mpo[MPEntry_offset + i * sizeof(struct MP_Entry)];
+ /*@ assert \valid_read(MPEntry_ptr+ ( 0 .. sizeof(struct MP_Entry)-1)); */
+ const struct MP_Entry *MPEntry=(const struct MP_Entry*)MPEntry_ptr;
+ uint64_t tmp=le32(MPEntry->size);
#ifdef DEBUG_JPEG
log_info("offset=%lu, size=%lu\n",
(long unsigned)le32(MPEntry->offset),
(long unsigned)le32(MPEntry->size));
#endif
if(le32(MPEntry->offset)>0)
- tmp+=mpo_offset;
+ tmp+=(uint64_t)le32(MPEntry->offset) + mpo_offset;
if(max_offset < tmp)
max_offset = tmp;
}
return max_offset;
}
+/*@
+ @ requires size >= 8;
+ @ requires \valid_read(mpo + ( 0 .. size-1));
+ @ assigns \nothing;
+ @*/
static uint64_t check_mpo(const unsigned char *mpo, const uint64_t offset, const unsigned int size)
{
+ /* MP header:
+ * - MP Endian (4Byte)
+ * - Offset to First IFD (4Byte)
+ */
if(mpo[0]=='I' && mpo[1]=='I' && mpo[2]=='*' && mpo[3]==0)
{
return check_mpo_le(mpo, offset, size);
@@ -283,6 +370,13 @@ static uint64_t check_mpo(const unsigned char *mpo, const uint64_t offset, const
return 0;
}
+/*@
+ @ requires \valid(fr);
+ @ requires \valid(fr->handle);
+ @ requires valid_read_string((char *)&fr->filename);
+ @ requires \initialized(&fr->time);
+ @ requires fr->file_check==&file_check_mpo;
+ @*/
static void file_check_mpo(file_recovery_t *fr)
{
unsigned char buffer[512];
@@ -300,12 +394,21 @@ static void file_check_mpo(file_recovery_t *fr)
do
{
offset+=(uint64_t)2+size;
+ if(offset >= 0x8000000000000000)
+ {
+ fr->file_size=0;
+ return ;
+ }
+ /*@ assert offset < 0x8000000000000000; */
if(my_fseek(fr->handle, offset, SEEK_SET) < 0)
{
fr->file_size=0;
return ;
}
nbytes=fread(&buffer, 1, sizeof(buffer), fr->handle);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
+#endif
// log_info("file_check_mpo offset=%llu => nbytes=%d, buffer=%02x %02x\n",
// (long long unsigned)offset, nbytes, buffer[0], buffer[1]);
/* 0xda SOS Start Of Scan */
@@ -314,19 +417,22 @@ static void file_check_mpo(file_recovery_t *fr)
fr->file_size=0;
return ;
}
+ /*@ assert nbytes >= 8; */
size=(buffer[2]<<8)+buffer[3];
} while(!(buffer[1]==0xe2 &&
buffer[4]=='M' && buffer[5]=='P' && buffer[6]=='F' && buffer[7]==0));
#ifdef DEBUG_JPEG
log_info("Found at %lu\n", (long unsigned)offset);
#endif
- if(2+size > nbytes)
- size=nbytes-2;
- if(size<12)
+ if(8+size > nbytes)
+ size=nbytes-8;
+ /*@ assert 8 + size <= nbytes; */
+ if(size<16)
{
fr->file_size=0;
return ;
}
+ /*@ assert 16 <= size <= 65535; */
{
const uint64_t max_offset=check_mpo(buffer+8, offset+8, size-8);
fr->file_size=(max_offset > fr->file_size ? 0 : max_offset);
@@ -337,7 +443,6 @@ static int is_marker_valid(const unsigned int marker)
{
switch(marker)
{
- case 0x02 ... 0xbf: /* Reserved */
case 0xc0: /* SOF0 Start of Frame */
case 0xc1: /* SOF1 Extended sequential */
case 0xc2: /* SOF2 Progressive */
@@ -354,28 +459,126 @@ static int is_marker_valid(const unsigned int marker)
case 0xcd: /* SOF13 Differential sequential, arithmetic coding */
case 0xce: /* SOF14 Differential progressive, arithmetic coding */
case 0xcf: /* SOF15 Differential lossless, arithmetic coding */
- case 0xd0 ... 0xd7: /* JPEG_RST0 .. JPEG_RST7 markers */
-// case 0xd8: /* SOI Start of Image */
-// case 0xd9: /* EOI End of Image */
-// case 0xda: /* SOS: Start Of Scan */
case 0xdb: /* DQT: Define Quantization Table */
- case 0xdc: /* DNL: Define Number of Lines */
case 0xdd: /* DRI: define restart interval */
- case 0xde: /* DHP: define hierarchical progression */
case 0xe0 ... 0xef: /* APP0 - APP15 */
- case 0xf0 ... 0xfd: /* Reserved for JPEG extensions */
case 0xfe: /* COM */
case 0xff:
return 1;
+#if 0
+ case 0x02 ... 0xbf: /* Reserved */
+ case 0xd0 ... 0xd7: /* JPEG_RST0 .. JPEG_RST7 markers */
+ case 0xd8: /* SOI Start of Image */
+ case 0xd9: /* EOI End of Image */
+ case 0xda: /* SOS: Start Of Scan */
+ case 0xdc: /* DNL: Define Number of Lines */
+ case 0xde: /* DHP: define hierarchical progression */
+ case 0xf0 ... 0xfd: /* Reserved for JPEG extensions */
+#endif
default:
return 0;
}
}
+/*@
+ @ requires \valid_read(buffer + (0 .. buffer_size-1));
+ @*/
+static time_t jpg_get_date(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int i, const unsigned int size)
+{ /* APP1 Exif information */
+ const unsigned int tiff_offset=i+2+8;
+ if(tiff_offset < buffer_size && size > 8)
+ {
+ /*@ assert tiff_offset < buffer_size; */
+ /*@ assert size > 8; */
+ unsigned int tiff_size=size-0x08;
+ if(buffer_size - tiff_offset < tiff_size)
+ {
+ tiff_size=buffer_size - tiff_offset;
+ /*@ assert tiff_offset + tiff_size == buffer_size; */
+ }
+ else
+ {
+ /*@ assert tiff_offset + tiff_size <= buffer_size; */
+ }
+ /*@ assert tiff_offset + tiff_size <= buffer_size; */
+ return get_date_from_tiff_header(&buffer[tiff_offset], tiff_size);
+ }
+ return 0;
+}
+
+
+/*@
+ @ requires buffer_size > 0;
+ @ requires \valid_read(buffer+(0..buffer_size-1));
+ @ requires \valid_read(file_recovery);
+ @ requires file_recovery->file_stat==\null || valid_read_string((char*)&file_recovery->filename);
+ @ requires \valid(file_recovery_new);
+ @ requires file_recovery_new->blocksize > 0;
+ @
+ @ requires buffer_size >= 10;
+ @ requires separation: \separated(&file_hint_jpg, buffer+(..), file_recovery, file_recovery_new);
+ @
+ @ ensures \result == 0 || \result == 1;
+ @ ensures (\result == 1) ==> (file_recovery_new->file_stat == \null);
+ @ ensures (\result == 1) ==> (file_recovery_new->handle == \null);
+ @ ensures \result == 1 ==> \initialized(&file_recovery_new->time);
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->calculated_file_size);
+ @ ensures \result == 1 ==> file_recovery_new->file_size == 0;
+ @ ensures (\result == 1) ==> \initialized(&file_recovery_new->min_filesize);
+ @ ensures (\result == 1) ==> (file_recovery_new->data_check == \null || \valid_function(file_recovery_new->data_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_check == \null || \valid_function(file_recovery_new->file_check));
+ @ ensures (\result == 1) ==> (file_recovery_new->file_rename == \null || \valid_function(file_recovery_new->file_rename));
+ @ ensures (\result == 1) ==> (file_recovery_new->extension != \null);
+ @ ensures (\result == 1) ==> valid_read_string(file_recovery_new->extension);
+ @ ensures (\result == 1) ==> \separated(file_recovery_new, file_recovery_new->extension);
+ @
+ @ ensures \result == 1 ==> file_recovery_new->calculated_file_size == 0;
+ @ ensures \result == 1 && buffer_size >= 4 ==> file_recovery_new->data_check == data_check_jpg;
+ @ ensures \result == 1 ==> file_recovery_new->file_check == file_check_jpg;
+ @ ensures \result == 1 ==> file_recovery_new->file_rename == \null;
+ @ ensures \result == 1 ==> file_recovery_new->extension == file_hint_jpg.extension;
+ @ ensures \result == 1 ==> file_recovery_new->min_filesize > 0;
+ @ ensures \result == 1 ==> file_recovery_new->offset_ok == 0;
+ @*/
static int header_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
{
unsigned int i=2;
time_t jpg_time=0;
+ while(i+4<buffer_size && buffer[i]==0xff && is_marker_valid(buffer[i+1]))
+ {
+ const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
+ if(buffer[i+1]==0xff)
+ i++;
+ else
+ {
+ if(buffer[i+1]==0xe1)
+ { /* APP1 Exif information */
+ jpg_time=jpg_get_date(buffer, buffer_size, i, size);
+ }
+ else if(buffer[i+1]==0xc4)
+ {
+ /* DHT */
+ if(jpg_check_dht(buffer, buffer_size, i, 2+(buffer[i+2]<<8)+buffer[i+3])!=0)
+ return 0;
+ }
+ i+=2+size;
+ }
+ }
+ if(i < file_recovery_new->blocksize && buffer[i]!=0xff)
+ return 0;
+ if(i+1 < file_recovery_new->blocksize && buffer[i+1]!=0xda)
+ return 0;
+ if(i < 512 && buffer[i]!=0xff)
+ return 0;
+ if(i+1 < 512 && buffer[i+1]!=0xda)
+ return 0;
+ if(file_recovery->file_stat==NULL)
+ {
+ if(i < buffer_size && buffer[i]!=0xff)
+ return 0;
+ if(i+1 < buffer_size && buffer[i+1]!=0xda)
+ return 0;
+ }
if(file_recovery->file_stat!=NULL)
{
static const unsigned char jpg_header_app0_avi[0x0c]= {
@@ -388,17 +591,19 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
unsigned int width=0;
unsigned int height=0;
jpg_get_size(buffer, buffer_size, &height, &width);
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
if(file_recovery->file_stat->file_hint==&file_hint_indd)
{
if(header_ignored_adv(file_recovery, file_recovery_new)==0)
return 0;
}
if(file_recovery->file_stat->file_hint==&file_hint_doc &&
- strstr(file_recovery->filename, ".albm")!=NULL)
+ strstr(file_recovery->filename, ".albm")!=NULL)
{
if(header_ignored_adv(file_recovery, file_recovery_new)==0)
return 0;
}
+#endif
if( file_recovery->file_stat->file_hint==&file_hint_jpg)
{
/* Don't recover the thumb instead of the jpg itself */
@@ -432,6 +637,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
return 0;
}
}
+#if !defined(MAIN_jpg) && !defined(MAIN_fidentify)
/* Don't extract jpg inside AVI */
if( file_recovery->file_stat->file_hint==&file_hint_riff &&
(memcmp(buffer, jpg_header_app0_avi, sizeof(jpg_header_app0_avi))==0 ||
@@ -454,61 +660,35 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
if(header_ignored_adv(file_recovery, file_recovery_new)==0)
return 0;
}
- if(buffer[3]==0xdb) /* DQT */
- {
- header_ignored(file_recovery_new);
- return 0;
- }
- if(buffer[3]==0xc4) /* DHT - needed to recover .cr2 */
- {
- header_ignored(file_recovery_new);
- return 0;
- }
- if(buffer[3]==0xe0 && (buffer[6]!='J' || buffer[7]!='F')) /* Should be JFIF/JFXX */
- {
- header_ignored(file_recovery_new);
- return 0;
- }
- if(buffer[3]==0xe1 && (buffer[6]!='E' || buffer[7]!='x' || buffer[8]!='i'|| buffer[9]!='f')) /* Should be EXIF */
- {
- header_ignored(file_recovery_new);
- return 0;
- }
- if(buffer[3]==0xfe && (!isprint(buffer[6]) || !isprint(buffer[7])))
- {
- header_ignored(file_recovery_new);
- return 0;
- }
- }
- while(i+4<buffer_size && buffer[i]==0xff && is_marker_valid(buffer[i+1]))
- {
- if(buffer[i+1]==0xff)
- i++;
- else
+#endif
+ switch(buffer[3])
{
- if(buffer[i+1]==0xe1)
- { /* APP1 Exif information */
- if(i+0x0A < buffer_size && 2+(buffer[i+2]<<8)+buffer[i+3] > 0x0A)
+ case 0xe0: /* APP0 */
+ if(buffer[6]!='J' || buffer[7]!='F') /* Should be JFIF/JFXX */
{
- unsigned int tiff_size=2+(buffer[i+2]<<8)+buffer[i+3]-0x0A;
- if(buffer_size - (i+0x0A) < tiff_size)
- tiff_size=buffer_size - (i+0x0A);
- jpg_time=get_date_from_tiff_header((const TIFFHeader*)&buffer[i+0x0A], tiff_size);
+ header_ignored(file_recovery_new);
+ return 0;
}
- }
- else if(buffer[i+1]==0xc4)
- {
- /* DHT */
- if(jpg_check_dht(buffer, buffer_size, i, 2+(buffer[i+2]<<8)+buffer[i+3])!=0)
+ break;
+ case 0xe1: /* APP1 */
+ if(buffer[6]!='E' || buffer[7]!='x' || buffer[8]!='i'|| buffer[9]!='f') /* Should be Exif */
+ {
+ header_ignored(file_recovery_new);
return 0;
- }
- i+=2+(buffer[i+2]<<8)+buffer[i+3];
+ }
+ break;
+ case 0xfe: /* COM */
+ if(!isprint(buffer[6]) || !isprint(buffer[7]))
+ {
+ header_ignored(file_recovery_new);
+ return 0;
+ }
+ break;
+ default:
+ header_ignored(file_recovery_new);
+ return 0;
}
}
- if(i+1 < file_recovery->blocksize && buffer[i+1]!=0xda)
- return 0;
- if(i+1 < 512 && buffer[i+1]!=0xda)
- return 0;
reset_file_recovery(file_recovery_new);
file_recovery_new->min_filesize=i;
file_recovery_new->calculated_file_size=0;
@@ -517,6 +697,7 @@ static int header_check_jpg(const unsigned char *buffer, const unsigned int buff
file_recovery_new->file_check=&file_check_jpg;
if(buffer_size >= 4)
file_recovery_new->data_check=&data_check_jpg;
+ /*@ assert valid_read_string(file_recovery_new->extension); */
return 1;
}
@@ -741,13 +922,25 @@ static void jpg_term_source (j_decompress_ptr cinfo)
}
+/* WARNING: This function must be listed in clang Control Flow Integrity (CFI) function blacklist, section cfi-icall */
+static void jpeg_testdisk_alloc_src (j_decompress_ptr cinfo, const unsigned int blocksize)
+{
+ my_source_mgr *src= (my_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(my_source_mgr));
+ cinfo->src = (struct jpeg_source_mgr *) src;
+ src->buffer = (JOCTET *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ blocksize * sizeof(JOCTET));
+}
+
/*
* Prepare for input from a stdio stream.
* The caller must have already opened the stream, and is responsible
* for closing it after finishing decompression.
*/
-static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, uint64_t offset, const unsigned int blocksize)
+static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, const uint64_t offset, const unsigned int blocksize)
{
my_source_mgr * src;
@@ -759,13 +952,7 @@ static void jpeg_testdisk_src (j_decompress_ptr cinfo, FILE * infile, uint64_t o
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof(my_source_mgr));
- src = (my_source_mgr *) cinfo->src;
- src->buffer = (JOCTET *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- blocksize * sizeof(JOCTET));
+ jpeg_testdisk_alloc_src(cinfo, blocksize);
}
src = (my_source_mgr *) cinfo->src;
@@ -1176,7 +1363,7 @@ static uint64_t jpg_check_thumb(FILE *infile, const uint64_t offset, const unsig
if(jpeg_session.frame!=NULL && jpeg_session.flags!=0)
{
const uint64_t tmp=jpg_find_error(&jpeg_session, &offsets[0], checkpoint_offset);
-// log_info("jpg_check_thumb jpeg corrupted near %llu\n", offset_error);
+// log_info("jpg_check_thumb jpeg corrupted near %llu\n", (long long unsigned)offset_error);
if(tmp !=0 && offset_error > tmp)
offset_error=tmp;
// log_info("jpg_check_thumb find_error estimation %llu\n", (long long unsigned)offset_error);
@@ -1250,7 +1437,6 @@ static void jpg_check_picture(file_recovery_t *file_recovery)
(long long unsigned)file_recovery->offset_ok,
(long long unsigned)file_recovery->offset_error);
#endif
-#if 1
if(jpeg_session.frame!=NULL && jpeg_session.flags!=0)
{
const uint64_t offset_error=jpg_find_error(&jpeg_session, &offsets[0], file_recovery->checkpoint_offset);
@@ -1262,7 +1448,6 @@ static void jpg_check_picture(file_recovery_t *file_recovery)
(long long unsigned)file_recovery->offset_error);
#endif
}
-#endif
jpeg_session_delete(&jpeg_session);
return;
}
@@ -1328,13 +1513,14 @@ static void jpg_check_picture(file_recovery_t *file_recovery)
}
#endif
-static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_size, const unsigned i, const unsigned int size)
+static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int i, const unsigned int size)
{
unsigned int j=i+4;
/* DHT must not be shorter than 18 bytes, 1+16+1 */
/* DHT should not be longer than 1088 bytes, 4*(1+16+255) */
if(size<18)
return 2;
+ /*@ loop assigns j; */
while(j < buffer_size && j < i+size)
{
const unsigned int tc=buffer[j]>>4;
@@ -1348,6 +1534,12 @@ static int jpg_check_dht(const unsigned char *buffer, const unsigned int buffer_
if(n > 3)
return 2;
j++;
+ /*@
+ @ loop invariant 0 <= l <= 16;
+ @ loop invariant sum <= l*255;
+ @ loop assigns l,sum;
+ @ loop variant 16-l;
+ @*/
for(l=0; l < 16; l++)
if(j+l < buffer_size)
sum+=buffer[j+l];
@@ -1369,299 +1561,469 @@ struct sof_header
uint16_t height; /* 0-65535 */
uint16_t width; /* 1-65535 */
unsigned char nbr; /* 1-255 */
+#if 0
unsigned char data[0];
+#endif
} __attribute__ ((gcc_struct, __packed__));
+/*@
+ @ requires \valid_read(buffer + (0..buffer_size-1));
+ @ assigns \nothing;
+ @*/
static int jpg_check_sof0(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int i)
{
- const struct sof_header *h=(const struct sof_header *)&buffer[i];
if(i+4 > buffer_size)
return 0;
- if(be16(h->length) < sizeof(struct sof_header)-2)
- return 1;
+ {
+ const struct sof_header *h=(const struct sof_header *)&buffer[i];
+ const unsigned int length=be16(h->length);
+ if(length < sizeof(struct sof_header)-2)
+ return 1;
+ }
if(i+2+8 > buffer_size)
return 0;
- if(h->precision!=8 || be16(h->width)==0 || h->nbr==0)
- return 1;
- if(be16(h->length) < 8+h->nbr*3)
- return 1;
+ {
+ const struct sof_header *h=(const struct sof_header *)&buffer[i];
+ const unsigned int length=be16(h->length);
+ if(h->precision!=8 || be16(h->width)==0 || h->nbr==0)
+ return 1;
+ if(length < 8+h->nbr*3)
+ return 1;
+ }
// if(i+2+be16(h->length) > buffer_size)
// return 0;
return 0;
}
+/*@
+ @ requires \valid_read(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires 0 < file_recovery->blocksize <= 1048576;
+ @ requires file_recovery->offset_error <= (1<<63) - 1;
+ @ requires separation: \separated(file_recovery, file_recovery->handle, &errno);
+ @ ensures \valid(file_recovery->handle);
+ @ assigns *file_recovery->handle, errno;
+ @ assigns Frama_C_entropy_source;
+ @ assigns file_recovery->extra;
+ @*/
static void jpg_search_marker(file_recovery_t *file_recovery)
{
FILE* infile=file_recovery->handle;
- unsigned char buffer[40*8192];
+ char sbuffer[40*8192];
size_t nbytes;
+ const uint64_t offset_error=file_recovery->offset_error;
+ uint64_t offset_test=offset_error;
uint64_t offset;
- unsigned int i;
+ /*@ assert offset_test == offset_error; */
if(file_recovery->blocksize==0)
return ;
- offset=file_recovery->offset_error / file_recovery->blocksize * file_recovery->blocksize;
- i=file_recovery->offset_error % file_recovery->blocksize;
+ offset=offset_test / file_recovery->blocksize * file_recovery->blocksize;
if(my_fseek(infile, offset, SEEK_SET) < 0)
return ;
- do
+ /*@ assert offset_test == offset_error; */
+ /*@
+ @ loop invariant offset_test >= offset_error;
+ @ loop assigns nbytes, sbuffer[ 0 .. sizeof(sbuffer)-1];
+ @ loop assigns *infile, errno;
+ @ loop assigns Frama_C_entropy_source;
+ @ loop assigns offset, offset_test;
+ @ loop assigns file_recovery->extra;
+ @*/
+ while((nbytes=fread(&sbuffer, 1, sizeof(sbuffer), infile))>0)
{
- while((nbytes=fread(&buffer, 1, sizeof(buffer), infile))>0)
+ unsigned int i;
+ const unsigned char *buffer=(const unsigned char *)sbuffer;
+ /*@ assert 0 < nbytes <= sizeof(sbuffer); */
+ if(offset_test > 0x80000000)
+ return ;
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown(&sbuffer, sizeof(sbuffer));
+#endif
+ /*@ assert offset_test >= offset_error; */
+ offset=offset_test / file_recovery->blocksize * file_recovery->blocksize;
+ i=offset_test % file_recovery->blocksize;
+ /*@ assert offset + i == offset_test; */
+ /*@ assert i == offset_test - offset; */
+ /*@ assert offset_test >= offset_error; */
+ /*@
+ @ loop invariant offset + i >= offset_test;
+ @ loop invariant offset_test >= offset_error;
+ @ loop invariant 0 <= i < nbytes + file_recovery->blocksize;
+ @ loop assigns i,file_recovery->extra;
+ @*/
+ while(i+1<nbytes)
{
- for(;i+1<nbytes; i+=file_recovery->blocksize)
+ const uint64_t tmp=offset + i;
+ /*@ assert tmp == offset + i; */
+ /*@ assert tmp >= offset_test; */
+ /*@ assert offset_test >= offset_error; */
+ if(buffer[i]==0xff &&
+ (buffer[i+1]==0xd8 || /* SOI */
+ buffer[i+1]==0xdb || /* DQT */
+ (buffer[i+1]>=0xc0 && buffer[i+1]<=0xcf) || /* SOF0 - SOF15, 0xc4=DHT */
+ buffer[i+1]==0xda || /* SOS: Start Of Scan */
+ buffer[i+1]==0xdd || /* DRI */
+ (buffer[i+1]>=0xe0 && buffer[i+1]<=0xef) || /* APP0 - APP15 */
+ buffer[i+1]==0xfe) /* COM */
+ )
{
- if(buffer[i]==0xff &&
- (buffer[i+1]==0xd8 || /* SOI */
- buffer[i+1]==0xdb || /* DQT */
- (buffer[i+1]>=0xc0 && buffer[i+1]<=0xcf) || /* SOF0 - SOF15, 0xc4=DHT */
- buffer[i+1]==0xda || /* SOS: Start Of Scan */
- buffer[i+1]==0xdd || /* DRI */
- (buffer[i+1]>=0xe0 && buffer[i+1]<=0xef) || /* APP0 - APP15 */
- buffer[i+1]==0xfe) /* COM */
- )
+ file_recovery->extra=tmp - offset_error;
+#ifndef __FRAMAC__
+ if(file_recovery->extra % file_recovery->blocksize != 0)
{
- file_recovery->extra=offset + i - file_recovery->offset_error;
- if(file_recovery->extra % file_recovery->blocksize != 0)
- {
- log_info("jpg_search_marker %s extra=%llu\n",
- file_recovery->filename,
- (long long unsigned)file_recovery->extra);
- }
- return ;
+ log_info("jpg_search_marker %s extra=%llu\n",
+ file_recovery->filename,
+ (long long unsigned)file_recovery->extra);
}
+#endif
+ return ;
}
+ i+=file_recovery->blocksize;
}
- offset +=nbytes;
- i=i % file_recovery->blocksize;
- } while(nbytes == sizeof(buffer));
+ offset_test += nbytes;
+ }
return ;
}
-static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsigned int extract_thumb)
+/*@
+ @ requires \valid_read(file_recovery);
+ @ requires \valid_read(buffer + (0 .. nbytes-1));
+ @ requires thumb_offset < nbytes;
+ @ requires thumb_size > 0;
+ @ requires thumb_offset + thumb_size <= nbytes;
+ @*/
+static void jpg_save_thumbnail(const file_recovery_t *file_recovery, const char *buffer, const uint64_t nbytes, const uint64_t thumb_offset, const unsigned int thumb_size)
{
- FILE* infile=file_recovery->handle;
- unsigned char buffer[40*8192];
- uint64_t thumb_offset=0;
- size_t nbytes;
- file_recovery->extra=0;
- if(my_fseek(infile, 0, SEEK_SET) < 0)
- return 0;
- if((nbytes=fread(&buffer, 1, sizeof(buffer), infile))>0)
+ char thumbname[2048];
+ char *sep;
+ /*@ assert sizeof(thumbname) == sizeof(file_recovery->filename); */
+ /*@ assert valid_read_string((char *)&file_recovery->filename); */
+ memcpy(thumbname,file_recovery->filename, sizeof(thumbname));
+ thumbname[sizeof(thumbname)-1]='\0';
+ /*@ assert valid_read_string(&thumbname[0]); */
+ sep=strrchr(thumbname,'/');
+ if(sep!=NULL
+#ifndef __FRAMAC__
+ && *(sep+1)=='f'
+#endif
+ )
{
- unsigned int offset;
- file_recovery->offset_error=0;
- for(offset=file_recovery->blocksize; offset + 30 < nbytes && file_recovery->offset_error==0; offset+=file_recovery->blocksize)
+ FILE *out;
+#ifndef __FRAMAC__
+ *(sep+1)='t';
+#endif
+ if((out=fopen(thumbname,"wb"))!=NULL)
{
- if(buffer[offset]==0xff && buffer[offset+1]==0xd8 && buffer[offset+2]==0xff &&
- ((buffer[offset+3]==0xe1 && memcmp(&buffer[offset+6], "http://ns.adobe.com/xap/", 24)!=0)
- || buffer[offset+3]==0xec))
+ /*@ assert \valid_read(buffer + (0 .. nbytes - 1)); */
+ /*@ assert 0 <= thumb_offset < nbytes; */
+ /*@ assert \valid_read(buffer + (thumb_offset .. nbytes - 1)); */
+ /*@ assert \valid_read(buffer + thumb_offset + (0 .. nbytes - 1 - thumb_offset)); */
+ /*@ ghost const char *thumb_char=&buffer[thumb_offset]; */
+ /*@ assert \valid_read(thumb_char + (0 .. nbytes - thumb_offset - 1)); */
+ /*@ assert 0 < thumb_size <= nbytes - thumb_offset; */
+ /*@ ghost uint64_t tmp_size=nbytes - thumb_offset; */
+ /*@ assert 0 < thumb_size <= tmp_size; */
+ /*@ assert \valid_read(thumb_char + (0 .. tmp_size - 1)); */
+ /*@ assert \valid_read(thumb_char + (0 .. thumb_size - 1)); */
+ if(fwrite(&buffer[thumb_offset], thumb_size, 1, out) < 1)
{
- file_recovery->offset_error=offset;
+ log_error("Can't write to %s: %s\n", thumbname, strerror(errno));
}
+ fclose(out);
+ if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
+ set_date(thumbname, file_recovery->time, file_recovery->time);
}
- offset=2;
- while(offset + 4 < nbytes && (file_recovery->offset_error==0 || offset < file_recovery->offset_error))
+ else
{
- const unsigned int i=offset;
- const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
- if(buffer[i]!=0xff)
+ log_error("fopen %s failed\n", thumbname);
+ }
+ }
+}
+
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires \valid(thumb_offset_ptr);
+ @ requires valid_read_string((char *)&file_recovery->filename);
+ @ requires file_recovery->blocksize > 0;
+ @ requires nbytes > 4;
+ @ requires \valid_read(buffer + (0 .. nbytes-1));
+ @ requires \initialized(&file_recovery->time);
+ @ requires separation: \separated(file_recovery, file_recovery->handle, buffer+(..), thumb_offset_ptr, &errno);
+ @ ensures \valid(file_recovery->handle);
+ @*/
+static int jpg_check_app1(file_recovery_t *file_recovery, const unsigned int extract_thumb, const unsigned char *buffer, const unsigned int i, const unsigned int offset, const unsigned int size, const uint64_t nbytes, uint64_t *thumb_offset_ptr)
+{ /* APP1 Exif information */
+ const unsigned int tiff_offset=i+2+8;
+ const unsigned char *potential_error=NULL;
+ const unsigned char *tiff;
+ unsigned int thumb_size=0;
+ unsigned int tiff_size;
+ uint64_t thumb_offset;
+ *thumb_offset_ptr=0;
+ if(tiff_offset >= nbytes || size <= 8)
+ return 1;
+ /*@ assert tiff_offset < nbytes; */
+ /*@ assert size > 8; */
+ tiff_size=size-0x08;
+ if(nbytes - tiff_offset < tiff_size)
+ {
+ tiff_size=nbytes - tiff_offset;
+ /*@ assert tiff_offset + tiff_size == nbytes; */
+ }
+ else
+ {
+ /*@ assert tiff_offset + tiff_size <= nbytes; */
+ }
+ /*@ assert tiff_offset + tiff_size <= nbytes; */
+ if(tiff_size<sizeof(TIFFHeader))
+ return 1;
+ /*@ assert tiff_size >= sizeof(TIFFHeader); */
+ /*@ assert \valid_read(buffer + (0 .. tiff_offset+tiff_size-1)); */
+ /*@ assert \valid_read((buffer + tiff_offset) + (0 .. tiff_size-1)); */
+ tiff=&buffer[tiff_offset];
+ /*@ assert \valid_read(tiff+ (0 .. tiff_size-1)); */
+ if(file_recovery->time==0)
+ {
+ /*@ assert \valid_read(tiff+ (0 .. tiff_size-1)); */
+ file_recovery->time=get_date_from_tiff_header(tiff, tiff_size);
+ }
+ thumb_offset=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFOFFSET, &potential_error);
+ if(potential_error!=NULL)
+ {
+ file_recovery->offset_error=potential_error-buffer;
+ return 0;
+ }
+ if(thumb_offset==0)
+ return 1;
+ /*@ assert 0 < thumb_offset; */
+ thumb_offset+=tiff_offset;
+ thumb_size=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFBYTECOUNT, &potential_error);
+ if(potential_error!=NULL)
+ {
+ file_recovery->offset_error=potential_error-buffer;
+ return 0;
+ }
+ if(thumb_size==0)
+ return 1;
+ /*@ assert 0 < thumb_size; */
+ *thumb_offset_ptr=thumb_offset;
+ if(file_recovery->offset_ok<i)
+ file_recovery->offset_ok=i;
+ if(thumb_offset + 6 >= nbytes)
+ return 1;
+ /*@ assert 0 < thumb_offset < nbytes - 6; */
+ /*@ assert thumb_offset < nbytes; */
+ {
+ unsigned int j=thumb_offset+2;
+ unsigned int thumb_sos_found=0;
+#ifdef DEBUG_JPEG
+ unsigned int j_old=j;
+#endif
+ if(buffer[thumb_offset]!=0xff)
+ {
+ file_recovery->offset_error=thumb_offset;
+ jpg_search_marker(file_recovery);
+ return 0;
+ }
+ if(buffer[thumb_offset+1]!=0xd8)
+ {
+ file_recovery->offset_error=thumb_offset+1;
+ return 0;
+ }
+ /*@ assert j == thumb_offset + 2; */
+ /*@ assert j < nbytes - 4; */
+ /*@
+ @ loop invariant 0 < thumb_size;
+ @ loop invariant 0 < thumb_offset < nbytes - 1;
+ @*/
+ /*X
+ X loop assigns j, thumb_sos_found;
+ X loop assigns errno, *file_recovery->handle,Frama_C_entropy_source;
+ X loop assigns file_recovery->offset_ok;
+ X loop assigns file_recovery->offset_error;
+ X loop assigns file_recovery->extra;
+ X*/
+ while(j+4<nbytes && thumb_sos_found==0)
+ {
+ /*@ assert j + 4 < nbytes; */
+ if(buffer[j]!=0xff)
{
+ file_recovery->offset_error=j;
#ifdef DEBUG_JPEG
- log_info("%s no marker at 0x%x\n", file_recovery->filename, i);
+ log_info("%s thumb no marker at 0x%x\n", file_recovery->filename, j);
+ log_error("%s Error between %u and %u\n", file_recovery->filename, j_old, j);
#endif
- file_recovery->offset_error=i;
jpg_search_marker(file_recovery);
- return thumb_offset;
+ return 0;
}
- if(buffer[i+1]==0xff)
+ if(buffer[j+1]==0xff)
{
/* See B.1.1.2 Markers in http://www.w3.org/Graphics/JPEG/itu-t81.pdf*/
- offset++;
+ j++;
continue;
}
#ifdef DEBUG_JPEG
- log_info("%s marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[i+1], i);
+ log_info("%s thumb marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[j+1], j);
#endif
- offset+=(uint64_t)2+size;
- if(buffer[i+1]==0xda) /* SOS: Start Of Scan */
+ if(buffer[j+1]==0xda) /* Thumb SOS: Start Of Scan */
{
- file_recovery->offset_ok=i+1;
- return thumb_offset;
+ thumb_sos_found=1;
}
- else if(buffer[i+1]==0xe1)
- { /* APP1 Exif information */
-#if 1
- if(i+0x0A < nbytes && 2+size > 0x0A)
+ else if(buffer[j+1]==0xc4) /* DHT */
+ {
+ if(jpg_check_dht(buffer, nbytes, j, 2+(buffer[j+2]<<8)+buffer[j+3])!=0)
{
- const char *potential_error=NULL;
- const TIFFHeader *tiff=(const TIFFHeader*)&buffer[i+0x0A];
- unsigned int tiff_size=2+size-0x0A;
- const char *thumb_data=NULL;
- const char *ifbytecount=NULL;
- if(nbytes - (i+0x0A) < tiff_size)
- tiff_size=nbytes - (i+0x0A);
- if(file_recovery->time==0)
- file_recovery->time=get_date_from_tiff_header(tiff, tiff_size);
- thumb_data=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFOFFSET, &potential_error);
- if(thumb_data!=NULL)
- {
- thumb_offset=thumb_data-(const char*)buffer;
- ifbytecount=find_tag_from_tiff_header(tiff, tiff_size, TIFFTAG_JPEGIFBYTECOUNT, &potential_error);
- }
- if(potential_error!=NULL)
- {
- file_recovery->offset_error=potential_error-(const char*)buffer;
- return 0;
- }
- if(file_recovery->offset_ok<i)
- file_recovery->offset_ok=i;
- if(thumb_data!=NULL && ifbytecount!=NULL)
- {
- const unsigned int thumb_size=ifbytecount-(const char*)tiff;
- if(thumb_offset < nbytes - 1)
- {
- unsigned int j=thumb_offset+2;
- unsigned int thumb_sos_found=0;
-#ifdef DEBUG_JPEG
- unsigned int j_old=j;
-#endif
- if(buffer[thumb_offset]!=0xff)
- {
- file_recovery->offset_error=thumb_offset;
- jpg_search_marker(file_recovery);
- return 0;
- }
- if(buffer[thumb_offset+1]!=0xd8)
- {
- file_recovery->offset_error=thumb_offset+1;
- return 0;
- }
- while(j+4<nbytes && thumb_sos_found==0)
- {
- if(buffer[j]!=0xff)
- {
- file_recovery->offset_error=j;
-#ifdef DEBUG_JPEG
- log_info("%s thumb no marker at 0x%x\n", file_recovery->filename, j);
- log_error("%s Error between %u and %u\n", file_recovery->filename, j_old, j);
-#endif
- jpg_search_marker(file_recovery);
- return 0;
- }
- if(buffer[j+1]==0xff)
- {
- /* See B.1.1.2 Markers in http://www.w3.org/Graphics/JPEG/itu-t81.pdf*/
- j++;
- continue;
- }
-#ifdef DEBUG_JPEG
- log_info("%s thumb marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[j+1], j);
-#endif
- if(buffer[j+1]==0xda) /* Thumb SOS: Start Of Scan */
- thumb_sos_found=1;
- else if(buffer[j+1]==0xc4) /* DHT */
- {
-#if 1
- if(jpg_check_dht(buffer, nbytes, j, 2+(buffer[j+2]<<8)+buffer[j+3])!=0)
- {
- file_recovery->offset_error=j+2;
- return 0;
- }
-#endif
- }
- else if(buffer[j+1]==0xdb || /* DQT */
- buffer[j+1]==0xc0 || /* SOF0 */
- buffer[j+1]==0xdd) /* DRI */
- {
- }
- else if((buffer[j+1]>=0xc0 && buffer[j+1]<=0xcf) || /* SOF0 - SOF15 */
- (buffer[j+1]>=0xe0 && buffer[j+1]<=0xef) || /* APP0 - APP15 */
- buffer[j+1]==0xfe) /* COM */
- {
- /* Unusual marker, bug ? */
- }
- else
- {
- log_info("%s thumb unknown marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[j+1], j);
- file_recovery->offset_error=j;
- return 0;
- }
- if(file_recovery->offset_ok<j)
- file_recovery->offset_ok=j;
-#ifdef DEBUG_JPEG
- j_old=j;
-#endif
- j+=2U+(buffer[j+2]<<8)+buffer[j+3];
- }
- if(thumb_sos_found>0 && extract_thumb>0
- && offset < nbytes && buffer[offset]==0xff)
- {
- char *thumbname;
- char *sep;
- thumbname=strdup(file_recovery->filename);
- sep=strrchr(thumbname,'/');
- if(sep!=NULL && *(sep+1)=='f' && thumb_offset+thumb_size < nbytes)
- {
- FILE *out;
- *(sep+1)='t';
- if((out=fopen(thumbname,"wb"))!=NULL)
- {
- if(fwrite(thumb_data, thumb_size, 1, out) < 1)
- {
- log_error("Can't write to %s: %s\n", thumbname, strerror(errno));
- }
- fclose(out);
- if(file_recovery->time!=0 && file_recovery->time!=(time_t)-1)
- set_date(thumbname, file_recovery->time, file_recovery->time);
- }
- else
- {
- log_error("fopen %s failed\n", thumbname);
- }
- }
- free(thumbname);
- }
- }
- }
+ file_recovery->offset_error=j+2;
+ return 0;
}
-#endif
}
- else if(buffer[i+1]==0xc4) /* DHT */
+ else if(buffer[j+1]==0xdb || /* DQT */
+ buffer[j+1]==0xc0 || /* SOF0 */
+ buffer[j+1]==0xdd) /* DRI */
{
-#if 1
- if(jpg_check_dht(buffer, nbytes, i, 2+size)!=0)
- {
- file_recovery->offset_error=i+2;
- return thumb_offset;
- }
-#endif
- if(file_recovery->offset_ok<i+1)
- file_recovery->offset_ok=i+1;
}
- else if(buffer[i+1]==0xdb || /* DQT */
- (buffer[i+1]>=0xc0 && buffer[i+1]<=0xcf) || /* SOF0 - SOF15 */
- buffer[i+1]==0xdd || /* DRI */
- (buffer[i+1]>=0xe0 && buffer[i+1]<=0xef) || /* APP0 - APP15 */
- buffer[i+1]==0xfe) /* COM */
+ else if((buffer[j+1]>=0xc0 && buffer[j+1]<=0xcf) || /* SOF0 - SOF15 */
+ (buffer[j+1]>=0xe0 && buffer[j+1]<=0xef) || /* APP0 - APP15 */
+ buffer[j+1]==0xfe) /* COM */
{
- if(file_recovery->offset_ok<i+1)
- file_recovery->offset_ok=i+1;
+ /* Unusual marker, bug ? */
}
else
{
- log_info("%s unknown marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[i+1], i+1);
- file_recovery->offset_error=i+1;
- return thumb_offset;
+#ifndef __FRAMAC__
+ log_info("%s thumb unknown marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[j+1], j);
+#endif
+ file_recovery->offset_error=j;
+ return 0;
+ }
+ if(file_recovery->offset_ok<j)
+ file_recovery->offset_ok=j;
+#ifdef DEBUG_JPEG
+ j_old=j;
+#endif
+ {
+ const unsigned int tmp=(buffer[j+2]<<8)+buffer[j+3];
+ /*@ assert 0 <= tmp <= 65535; */
+ j+=2U+tmp;
}
}
- if(offset > nbytes && nbytes < sizeof(buffer))
+ if(thumb_sos_found==0)
+ return 1;
+ }
+ if(extract_thumb==0)
+ return 1;
+ /* APP1 must be followed by a valid marker, this avoids many corrupted thumbnails */
+ if(offset >= nbytes || buffer[offset]!=0xff)
+ return 1;
+ if(thumb_offset+thumb_size > nbytes)
+ return 1;
+ /*@ assert thumb_offset + thumb_size <= nbytes; */
+ /*@ assert 0 < thumb_size; */
+ /*@ assert thumb_offset < nbytes; */
+ jpg_save_thumbnail(file_recovery, (const char *)buffer, nbytes, thumb_offset, thumb_size);
+ return 1;
+}
+
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires file_recovery->blocksize > 0;
+ @ requires \initialized(&file_recovery->time);
+ @ requires valid_read_string((char *)&file_recovery->filename);
+ */
+static uint64_t jpg_check_structure(file_recovery_t *file_recovery, const unsigned int extract_thumb)
+{
+ FILE* infile=file_recovery->handle;
+ unsigned char buffer[40*8192];
+ uint64_t thumb_offset=0;
+ size_t nbytes;
+ unsigned int offset;
+ file_recovery->extra=0;
+ if(my_fseek(infile, 0, SEEK_SET) < 0)
+ return 0;
+ nbytes=fread(&buffer, 1, sizeof(buffer), infile);
+ if(nbytes <= 0)
+ return 0;
+ /*@ assert nbytes > 0; */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)&buffer, sizeof(buffer));
+#endif
+ file_recovery->offset_error=0;
+ for(offset=file_recovery->blocksize; offset + 30 < nbytes && file_recovery->offset_error==0; offset+=file_recovery->blocksize)
+ {
+ if(buffer[offset]==0xff && buffer[offset+1]==0xd8 && buffer[offset+2]==0xff &&
+ ((buffer[offset+3]==0xe1 && memcmp(&buffer[offset+6], "http://ns.adobe.com/xap/", 24)!=0)
+ || buffer[offset+3]==0xec))
+ {
+ file_recovery->offset_error=offset;
+ }
+ }
+ offset=2;
+ while(offset + 4 < nbytes && buffer[offset]==0xff && is_marker_valid(buffer[offset+1]) && (file_recovery->offset_error==0 || offset < file_recovery->offset_error))
+ {
+ const unsigned int i=offset;
+ /*@ assert i + 4 < nbytes; */
+ /*@ assert i < nbytes; */
+ const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
+ if(buffer[i+1]==0xff)
{
- file_recovery->offset_error=nbytes;
- return thumb_offset;
+ /* See B.1.1.2 Markers in http://www.w3.org/Graphics/JPEG/itu-t81.pdf*/
+ offset++;
+ continue;
+ }
+#if defined(DEBUG_JPEG)
+ log_info("%s marker 0x%02x at 0x%x\n", file_recovery->filename, buffer[i+1], i);
+#endif
+ offset+=(uint64_t)2+size;
+ if(buffer[i+1]==0xe1)
+ { /* APP1 Exif information */
+ if(jpg_check_app1(file_recovery, extract_thumb, buffer, i, offset, size, nbytes, &thumb_offset)==0)
+ return 0;
+ }
+ else if(buffer[i+1]==0xc4) /* DHT */
+ {
+ if(jpg_check_dht(buffer, nbytes, i, 2+size)!=0)
+ {
+ file_recovery->offset_error=i+2;
+ return thumb_offset;
+ }
}
+ if(file_recovery->offset_ok<i+1)
+ file_recovery->offset_ok=i+1;
+ }
+ if(offset < nbytes && buffer[offset]!=0xff)
+ {
+#if defined(DEBUG_JPEG)
+ log_info("%s no marker at 0x%x\n", file_recovery->filename, offset);
+#endif
+ file_recovery->offset_error=offset;
+ jpg_search_marker(file_recovery);
+ return thumb_offset;
+ }
+ if(offset + 4 < nbytes)
+ {
+ if(buffer[offset+1]==0xda) /* SOS: Start Of Scan */
+ file_recovery->offset_ok=offset+1;
+ else
+ file_recovery->offset_error=offset+1;
+ return thumb_offset;
+ }
+ if(offset > nbytes && nbytes < sizeof(buffer))
+ {
+ file_recovery->offset_error=nbytes;
+ return thumb_offset;
}
return thumb_offset;
}
+/*@
+ @ requires \valid(file_recovery);
+ @ requires \valid(file_recovery->handle);
+ @ requires valid_read_string((char *)&file_recovery->filename);
+ @ requires \initialized(&file_recovery->time);
+ @ requires file_recovery->file_check == &file_check_mpo || file_recovery->file_check == &file_check_jpg;
+ @*/
static void file_check_jpg(file_recovery_t *file_recovery)
{
uint64_t thumb_offset;
@@ -1731,27 +2093,43 @@ static void file_check_jpg(file_recovery_t *file_recovery)
#endif
}
+/*@
+ @ requires buffer_size >= 2 && (buffer_size&1)==0;
+ @ requires \valid(file_recovery);
+ @ requires file_recovery->calculated_file_size >= 2;
+ @ requires \valid_read(buffer + ( 0 .. buffer_size-1));
+ @ requires file_recovery->data_check == &data_check_jpg2;
+ @ requires separation: \separated(buffer+(..), file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ ensures file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == \null;
+ @ ensures file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2;
+ @ ensures file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0;
+ @ assigns file_recovery->calculated_file_size;
+ @ assigns file_recovery->data_check;
+ @ assigns file_recovery->offset_error;
+ @*/
static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
-#if 0
- unsigned int old_marker=0;
-#endif
- if(file_recovery->calculated_file_size<2)
- {
- /* Reset to the correct file checker */
- file_recovery->data_check=&data_check_jpg;
- return data_check_jpg(buffer, buffer_size, file_recovery);
- }
+ /*@
+ @ loop invariant file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0;
+ @ loop assigns file_recovery->calculated_file_size;
+ @ loop assigns file_recovery->data_check;
+ @ loop assigns file_recovery->offset_error;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 > file_recovery->file_size &&
file_recovery->calculated_file_size < file_recovery->file_size + buffer_size/2)
{
- const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
+ const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
if(buffer[i-1]==0xFF)
{
if(buffer[i]==0xd9)
{
/* JPEG_EOI */
file_recovery->calculated_file_size++;
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ /*@ assert file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0; */
return DC_STOP;
}
else if(buffer[i] >= 0xd0 && buffer[i] <= 0xd7)
@@ -1770,12 +2148,17 @@ static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned
/* TODO: store old_marker in file_recovery */
old_marker=buffer[i];
#endif
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
+ /*@ assert file_recovery->calculated_file_size >= 2; */
}
else if(buffer[i] == 0xda || buffer[i] == 0xc4)
{
/* SOS and DHT may be embedded by progressive jpg */
file_recovery->data_check=NULL;
file_recovery->calculated_file_size=0;
+ /*@ assert file_recovery->data_check == \null; */
+ /*@ assert file_recovery->calculated_file_size == 0; */
+ /*@ assert file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0; */
return DC_CONTINUE;
}
else if(buffer[i]!=0x00)
@@ -1785,29 +2168,65 @@ static data_check_t data_check_jpg2(const unsigned char *buffer, const unsigned
(long long unsigned)file_recovery->calculated_file_size);
#endif
file_recovery->offset_error=file_recovery->calculated_file_size;
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ /*@ assert file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0; */
return DC_STOP;
}
}
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
file_recovery->calculated_file_size++;
}
+ /*@ assert file_recovery->data_check == &data_check_jpg2; */
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ /*@ assert file_recovery->data_check == \null ==> file_recovery->calculated_file_size == 0; */
return DC_CONTINUE;
}
-data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
+/*@
+ @ requires buffer_size >= 8;
+ @ requires (buffer_size&1)==0;
+ @ requires \valid(file_recovery);
+ @ requires buffer_size >= 4;
+ @ requires \valid_read(buffer + ( 0 .. buffer_size-1));
+ @ requires file_recovery->data_check == &data_check_jpg;
+ @ requires separation: \separated(buffer+(..), file_recovery);
+ @ ensures \result == DC_CONTINUE || \result == DC_STOP;
+ @ ensures file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == &data_check_jpg || file_recovery->data_check == &data_check_size || file_recovery->data_check == \null;
+ @ ensures file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2;
+ @ assigns file_recovery->calculated_file_size;
+ @ assigns file_recovery->data_check;
+ @ assigns file_recovery->file_check;
+ @ assigns file_recovery->offset_error;
+ @*/
+/* FIXME requires file_recovery->file_size == 0 || file_recovery->calculated_file_size >= file_recovery->file_size - 4; */
+/* FIXME ensures \result == DC_CONTINUE ==> (file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4); */
+static data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buffer_size, file_recovery_t *file_recovery)
{
/* Skip the SOI */
- if(file_recovery->calculated_file_size==0)
- file_recovery->calculated_file_size+=2;
+ if(file_recovery->calculated_file_size<2)
+ file_recovery->calculated_file_size=2;
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
/* Search SOS */
+ /*@
+ @ loop assigns file_recovery->calculated_file_size;
+ @ loop assigns file_recovery->data_check;
+ @ loop assigns file_recovery->file_check;
+ @ loop assigns file_recovery->offset_error;
+ @*/
while(file_recovery->calculated_file_size + buffer_size/2 >= file_recovery->file_size &&
file_recovery->calculated_file_size + 4 < file_recovery->file_size + buffer_size/2)
{
- const unsigned int i=file_recovery->calculated_file_size - file_recovery->file_size + buffer_size/2;
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
+ const unsigned int i=file_recovery->calculated_file_size + buffer_size/2 - file_recovery->file_size;
+ /*@ assert 0 <= i < buffer_size - 4 ; */
if(buffer[i]==0xFF && buffer[i+1]==0xFF)
file_recovery->calculated_file_size++;
else if(buffer[i]==0xFF)
{
const unsigned int size=(buffer[i+2]<<8)+buffer[i+3];
+ const uint64_t old_calculated_file_size=file_recovery->calculated_file_size;
#ifdef DEBUG_JPEG
log_info("data_check_jpg %02x%02x at %llu, next expected at %llu\n", buffer[i], buffer[i+1],
(long long unsigned)file_recovery->calculated_file_size,
@@ -1817,44 +2236,87 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
if(buffer[i+1]==0xc0) /* SOF0 */
{
if(jpg_check_sof0(buffer, buffer_size, i)!=0)
+ {
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
+ }
}
else if(buffer[i+1]==0xc4) /* DHT */
{
if(jpg_check_dht(buffer, buffer_size, i, 2+size)!=0)
+ {
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
+ }
}
else if(buffer[i+1]==0xda) /* SOS: Start Of Scan */
{
+ data_check_t tmp;
file_recovery->data_check=&data_check_jpg2;
- return data_check_jpg2(buffer, buffer_size, file_recovery);
+ /*@ assert file_recovery->calculated_file_size >= 2; */
+ tmp=data_check_jpg2(buffer, buffer_size, file_recovery);
+ /*@ assert file_recovery->data_check == &data_check_jpg2 || file_recovery->data_check == \null; */
+ /*@ assert file_recovery->data_check == &data_check_jpg2 ==> file_recovery->calculated_file_size >= 2; */
+ return tmp;
}
else if(buffer[i+1]==0xe2) /* APP2 Exif information */
{
if(i+8 < buffer_size &&
buffer[i+4]=='M' && buffer[i+5]=='P' && buffer[i+6]=='F' && buffer[i+7]==0)
{
- unsigned int size_test=size;
- if(i + 2 + size >= buffer_size)
- {
- size_test=buffer_size-i-2;
- }
+ const uint64_t offset=old_calculated_file_size+8;
if(i>=buffer_size/2)
{
- file_recovery->calculated_file_size-=2+size;
+ /* Restore previous value */
+ file_recovery->calculated_file_size=old_calculated_file_size;
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_CONTINUE;
}
- if(size>12)
+ /*@ assert 0 <= i < buffer_size / 2 ; */
+ if( i + size <= buffer_size)
{
- const uint64_t offset=file_recovery->calculated_file_size-(2+size)+8;
- const uint64_t calculated_file_size=check_mpo(buffer+i+8, offset, size_test-8);
- if(calculated_file_size > 0)
+ /*@ assert i + size <= buffer_size; */
+ /*@ assert size <= buffer_size - i; */
+ if(size >= 16)
{
- /* Multi-picture format */
- file_recovery->calculated_file_size=calculated_file_size;
- file_recovery->data_check=&data_check_size;
- file_recovery->file_check=&file_check_mpo;
- return DC_CONTINUE;
+ /*@ assert 16 <= size <= 65535; */
+ /*@ assert \valid_read(buffer + (0 .. buffer_size-1)); */
+ /*@ assert \valid_read(buffer + (0 .. i+size-1)); */
+ /*@ assert \valid_read((buffer + i ) + (0 .. size-1)); */
+ /*@ assert \valid_read((buffer + i + 8) + (0 .. size-8-1)); */
+ const unsigned char *mpo=buffer + i + 8;
+ const unsigned int size_mpo=size-8;
+ /*@ assert \valid_read(mpo + (0 .. size-8-1)); */
+ /*@ assert \valid_read(mpo + (0 .. size_mpo-1)); */
+ const uint64_t calculated_file_size=check_mpo(mpo, offset, size_mpo);
+ if(calculated_file_size > 0)
+ {
+ /* Multi-picture format */
+ file_recovery->calculated_file_size=calculated_file_size;
+ file_recovery->data_check=&data_check_size;
+ file_recovery->file_check=&file_check_mpo;
+ /*@ assert file_recovery->data_check == &data_check_size; */
+ return DC_CONTINUE;
+ }
+ }
+ }
+ else
+ {
+ const unsigned int size_test=buffer_size-i;
+ /*@ assert size_test == buffer_size - i; */
+ if(size_test >= 16)
+ {
+ /*@ assert 16 <= size_test; */
+ const uint64_t calculated_file_size=check_mpo(buffer+i+8, offset, size_test-8);
+ if(calculated_file_size > 0)
+ {
+ /* Multi-picture format */
+ file_recovery->calculated_file_size=calculated_file_size;
+ file_recovery->data_check=&data_check_size;
+ file_recovery->file_check=&file_check_mpo;
+ /*@ assert file_recovery->data_check == &data_check_size; */
+ return DC_CONTINUE;
+ }
}
}
}
@@ -1866,9 +2328,13 @@ data_check_t data_check_jpg(const unsigned char *buffer, const unsigned int buff
log_info("data_check_jpg %02x at %llu\n", buffer[i],
(long long unsigned)file_recovery->calculated_file_size);
#endif
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
return DC_STOP;
}
}
+ /*@ assert file_recovery->data_check == &data_check_jpg; */
+ /*@ assert file_recovery->calculated_file_size < file_recovery->file_size - buffer_size/2 || file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4; */
+ /*X TODO assert file_recovery->calculated_file_size >= file_recovery->file_size + buffer_size/2 - 4; */
return DC_CONTINUE;
}
@@ -1892,3 +2358,138 @@ const char*td_jpeg_version(void)
return "none";
#endif
}
+
+
+/*@
+ @ requires \valid(file_stat);
+ @*/
+static void register_header_check_jpg(file_stat_t *file_stat)
+{
+ static const unsigned char jpg_header[3]= { 0xff,0xd8,0xff};
+ register_header_check(0, jpg_header, sizeof(jpg_header), &header_check_jpg, file_stat);
+}
+#endif
+
+#if defined(MAIN_jpg)
+#define BLOCKSIZE 65536u
+int main()
+{
+ const char fn[] = "recup_dir.1/f0000000.jpg";
+ unsigned char buffer[BLOCKSIZE];
+ file_recovery_t file_recovery_new;
+ file_recovery_t file_recovery;
+ file_stat_t file_stats;
+
+ /*@ assert \valid(buffer + (0 .. (BLOCKSIZE - 1))); */
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)buffer, BLOCKSIZE);
+#endif
+
+ reset_file_recovery(&file_recovery);
+ file_recovery.blocksize=BLOCKSIZE;
+ file_recovery_new.blocksize=BLOCKSIZE;
+ file_recovery_new.data_check=NULL;
+ file_recovery_new.file_stat=NULL;
+ file_recovery_new.file_check=NULL;
+ file_recovery_new.file_rename=NULL;
+ file_recovery_new.calculated_file_size=0;
+ file_recovery_new.file_size=0;
+ file_recovery_new.offset_ok=0;
+ file_recovery_new.checkpoint_status=0;
+ file_recovery_new.location.start=0;
+ file_recovery_new.offset_error=0;
+ file_recovery_new.time=0;
+
+ file_stats.file_hint=&file_hint_jpg;
+ file_stats.not_recovered=0;
+ file_stats.recovered=0;
+ register_header_check_jpg(&file_stats);
+ if(header_check_jpg(buffer, BLOCKSIZE, 0u, &file_recovery, &file_recovery_new)!=1)
+ return 0;
+ /*@ assert file_recovery_new.file_check == file_check_jpg; */
+ /*@ assert file_recovery_new.extension == file_hint_jpg.extension; */
+ /*@ assert valid_read_string(file_recovery_new.extension); */
+ /*@ assert file_recovery_new.file_size == 0; */
+ /*@ assert file_recovery_new.offset_ok == 0; */
+ /*@ assert valid_read_string((char *)&fn); */
+ /*@ assert \initialized(&file_recovery_new.time); */
+ memcpy(file_recovery_new.filename, fn, sizeof(fn));
+ /*@ assert valid_read_string((char *)&file_recovery_new.filename); */
+ /*@ assert file_recovery_new.offset_ok == 0; */
+ file_recovery_new.file_stat=&file_stats;
+ {
+ unsigned char big_buffer[2*BLOCKSIZE];
+ data_check_t res_data_check=DC_CONTINUE;
+ memset(big_buffer, 0, BLOCKSIZE);
+ memcpy(big_buffer + BLOCKSIZE, buffer, BLOCKSIZE);
+ /*@ assert file_recovery_new.data_check == &data_check_jpg; */
+ /*@ assert file_recovery_new.file_size == 0; */;
+ res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ /*@ assert file_recovery_new.data_check == &data_check_jpg2 ==> file_recovery_new.calculated_file_size >= 2; */
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.data_check == &data_check_jpg || file_recovery_new.data_check == &data_check_jpg2 || file_recovery_new.data_check == &data_check_size || file_recovery_new.data_check == NULL; */
+ if(file_recovery_new.data_check == &data_check_jpg)
+ res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_jpg2)
+ res_data_check=data_check_jpg2(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_size)
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ if(res_data_check == DC_CONTINUE)
+ {
+ memcpy(big_buffer, big_buffer + BLOCKSIZE, BLOCKSIZE);
+#if defined(__FRAMAC__)
+ Frama_C_make_unknown((char *)big_buffer + BLOCKSIZE, BLOCKSIZE);
+#endif
+ /*@ assert file_recovery_new.data_check == &data_check_jpg || file_recovery_new.data_check == &data_check_jpg2 || file_recovery_new.data_check == &data_check_size || file_recovery_new.data_check == NULL; */
+ if(file_recovery_new.data_check == &data_check_jpg)
+ res_data_check=data_check_jpg(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_jpg2)
+ res_data_check=data_check_jpg2(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ else if(file_recovery_new.data_check == &data_check_size)
+ res_data_check=data_check_size(big_buffer, 2*BLOCKSIZE, &file_recovery_new);
+ file_recovery_new.file_size+=BLOCKSIZE;
+ }
+ }
+ }
+ /*@ assert file_recovery_new.offset_ok == 0; */
+ {
+ file_recovery_t file_recovery_new2;
+ /* Test when another file of the same is detected in the next block */
+ file_recovery_new2.blocksize=BLOCKSIZE;
+ file_recovery_new2.file_stat=NULL;
+ file_recovery_new2.file_check=NULL;
+ file_recovery_new2.location.start=BLOCKSIZE;
+ file_recovery_new.handle=NULL; /* In theory should be not null */
+ header_check_jpg(buffer, BLOCKSIZE, 0, &file_recovery_new, &file_recovery_new2);
+ }
+ /*@ assert file_recovery_new.offset_ok == 0; */
+ /*@ assert file_recovery_new.file_check == file_check_jpg || file_recovery_new.file_check == file_check_mpo; */
+ if(file_recovery_new.file_check == file_check_jpg)
+ {
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_jpg(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ }
+ else
+ {
+ /*@ assert file_recovery_new.file_check == file_check_mpo; */
+ file_recovery_new.handle=fopen(fn, "rb");
+ if(file_recovery_new.handle!=NULL)
+ {
+ file_check_mpo(&file_recovery_new);
+ fclose(file_recovery_new.handle);
+ }
+ }
+ return 0;
+}
+#endif
diff --git a/src/file_jsonlz4.c b/src/file_jsonlz4.c
index 8d3390e..0035816 100644
--- a/src/file_jsonlz4.c
+++ b/src/file_jsonlz4.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_jsonlz4)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -59,3 +60,4 @@ static void register_header_check_jsonlz4(file_stat_t *file_stat)
{
register_header_check(0, "mozLz40", 8, &header_check_jsonlz4, file_stat);
}
+#endif
diff --git a/src/file_kdb.c b/src/file_kdb.c
index 5f07b82..3b37bab 100644
--- a/src/file_kdb.c
+++ b/src/file_kdb.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_kdb)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_kdb(file_stat_t *file_stat)
static const unsigned char kdb_header[8]= {0x03, 0xd9, 0xa2, 0x9a, 0x65, 0xfb, 0x4b, 0xb5};
register_header_check(0, kdb_header,sizeof(kdb_header), &header_check_kdb, file_stat);
}
+#endif
diff --git a/src/file_kdbx.c b/src/file_kdbx.c
index c47e3ca..f388137 100644
--- a/src/file_kdbx.c
+++ b/src/file_kdbx.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_kdbx)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -54,3 +55,4 @@ static void register_header_check_kdbx(file_stat_t *file_stat)
static const unsigned char kdbx_header[8]= {0x03, 0xd9, 0xa2, 0x9a, 0x67, 0xfb, 0x4b, 0xb5};
register_header_check(0, kdbx_header,sizeof(kdbx_header), &header_check_kdbx, file_stat);
}
+#endif
diff --git a/src/file_key.c b/src/file_key.c
index 8a396a9..534685f 100644
--- a/src/file_key.c
+++ b/src/file_key.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_key)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -55,3 +56,4 @@ static void register_header_check_key(file_stat_t *file_stat)
{
register_header_check(0, "323382b3c4f1c6d2", 16, &header_check_key, file_stat);
}
+#endif
diff --git a/src/file_ldf.c b/src/file_ldf.c
index e3acfe5..937120b 100644
--- a/src/file_ldf.c
+++ b/src/file_ldf.c
@@ -20,6 +20,7 @@
*/
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ldf)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@@ -65,3 +66,4 @@ static int header_check_ldf(const unsigned char *buffer, const unsigned int buff
}
return 0;
}
+#endif
diff --git a/src/file_list.c b/src/file_list.c
index f706680..36dc8b6 100644
--- a/src/file_list.c
+++ b/src/file_list.c
@@ -24,11 +24,13 @@
#endif
#include <stdio.h>
+#include <assert.h>
#include "types.h"
#include "filegen.h"
extern const file_hint_t file_hint_1cd;
extern const file_hint_t file_hint_3dm;
+extern const file_hint_t file_hint_3ds;
extern const file_hint_t file_hint_7z;
extern const file_hint_t file_hint_DB;
extern const file_hint_t file_hint_a;
@@ -60,6 +62,7 @@ extern const file_hint_t file_hint_axx;
extern const file_hint_t file_hint_bac;
extern const file_hint_t file_hint_bdm;
extern const file_hint_t file_hint_berkeley;
+extern const file_hint_t file_hint_bfa;
extern const file_hint_t file_hint_bim;
extern const file_hint_t file_hint_bin;
extern const file_hint_t file_hint_binvox;
@@ -205,6 +208,7 @@ extern const file_hint_t file_hint_mb;
extern const file_hint_t file_hint_mcd;
extern const file_hint_t file_hint_mdb;
extern const file_hint_t file_hint_mdf;
+extern const file_hint_t file_hint_mdp;
extern const file_hint_t file_hint_mfa;
extern const file_hint_t file_hint_mfg;
extern const file_hint_t file_hint_mft;
@@ -288,6 +292,7 @@ extern const file_hint_t file_hint_rpm;
extern const file_hint_t file_hint_rw2;
extern const file_hint_t file_hint_rx2;
extern const file_hint_t file_hint_save;
+extern const file_hint_t file_hint_sdsk;
extern const file_hint_t file_hint_ses;
extern const file_hint_t file_hint_sgcta;
extern const file_hint_t file_hint_shn;
@@ -363,343 +368,1049 @@ extern const file_hint_t file_hint_zcode;
extern const file_hint_t file_hint_zip;
extern const file_hint_t file_hint_zpr;
-file_enable_t list_file_enable[]=
+file_enable_t array_file_enable[]=
{
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_sig)
{ .enable=0, .file_hint=&file_hint_sig },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_1cd)
{ .enable=0, .file_hint=&file_hint_1cd },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_3dm)
{ .enable=0, .file_hint=&file_hint_3dm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_3ds)
+ { .enable=0, .file_hint=&file_hint_3ds },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_7z)
{ .enable=0, .file_hint=&file_hint_7z },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_DB)
{ .enable=0, .file_hint=&file_hint_DB },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_a)
{ .enable=0, .file_hint=&file_hint_a },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_abr)
{ .enable=0, .file_hint=&file_hint_abr },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_acb)
{ .enable=0, .file_hint=&file_hint_acb },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_accdb)
{ .enable=0, .file_hint=&file_hint_accdb},
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ace)
{ .enable=0, .file_hint=&file_hint_ace },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_addressbook)
{ .enable=0, .file_hint=&file_hint_addressbook},
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ado)
{ .enable=0, .file_hint=&file_hint_ado },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_afdesign)
{ .enable=0, .file_hint=&file_hint_afdesign },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ahn)
{ .enable=0, .file_hint=&file_hint_ahn },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_aif)
{ .enable=0, .file_hint=&file_hint_aif },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_all)
{ .enable=0, .file_hint=&file_hint_all },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_als)
{ .enable=0, .file_hint=&file_hint_als },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_amd)
{ .enable=0, .file_hint=&file_hint_amd },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_amr)
{ .enable=0, .file_hint=&file_hint_amr },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_apa)
{ .enable=0, .file_hint=&file_hint_apa },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ape)
{ .enable=0, .file_hint=&file_hint_ape },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_apple)
{ .enable=0, .file_hint=&file_hint_apple },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ari)
{ .enable=0, .file_hint=&file_hint_ari },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_arj)
{ .enable=0, .file_hint=&file_hint_arj },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asf)
{ .enable=0, .file_hint=&file_hint_asf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asl)
{ .enable=0, .file_hint=&file_hint_asl },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_asm)
{ .enable=0, .file_hint=&file_hint_asm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_atd)
{ .enable=0, .file_hint=&file_hint_atd },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_au)
{ .enable=0, .file_hint=&file_hint_au },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_axp)
{ .enable=0, .file_hint=&file_hint_axp },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_axx)
{ .enable=0, .file_hint=&file_hint_axx },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bac)
{ .enable=0, .file_hint=&file_hint_bac },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bdm)
{ .enable=0, .file_hint=&file_hint_bdm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_berkeley)
{ .enable=0, .file_hint=&file_hint_berkeley },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bfa)
+ { .enable=0, .file_hint=&file_hint_bfa },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bim)
{ .enable=0, .file_hint=&file_hint_bim },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bin)
{ .enable=0, .file_hint=&file_hint_bin },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_binvox)
{ .enable=0, .file_hint=&file_hint_binvox },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bkf)
{ .enable=0, .file_hint=&file_hint_bkf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_blend)
{ .enable=0, .file_hint=&file_hint_blend },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bmp)
{ .enable=0, .file_hint=&file_hint_bmp },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bpg)
{ .enable=0, .file_hint=&file_hint_bpg },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bvr)
{ .enable=0, .file_hint=&file_hint_bvr },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_bz2)
{ .enable=0, .file_hint=&file_hint_bz2 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_c4d)
{ .enable=0, .file_hint=&file_hint_c4d },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cab)
{ .enable=0, .file_hint=&file_hint_cab },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_caf)
{ .enable=0, .file_hint=&file_hint_caf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cam)
{ .enable=0, .file_hint=&file_hint_cam },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_catdrawing)
{ .enable=0, .file_hint=&file_hint_catdrawing },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cdt)
{ .enable=0, .file_hint=&file_hint_cdt },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_che)
{ .enable=0, .file_hint=&file_hint_che },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_chm)
{ .enable=0, .file_hint=&file_hint_chm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_class)
{ .enable=0, .file_hint=&file_hint_class },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cm)
{ .enable=0, .file_hint=&file_hint_cm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_compress)
{ .enable=0, .file_hint=&file_hint_compress },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cow)
{ .enable=0, .file_hint=&file_hint_cow },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cpi)
{ .enable=0, .file_hint=&file_hint_cpi },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_crw)
{ .enable=0, .file_hint=&file_hint_crw },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_csh)
{ .enable=0, .file_hint=&file_hint_csh },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ctg)
{ .enable=0, .file_hint=&file_hint_ctg },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_cwk)
{ .enable=0, .file_hint=&file_hint_cwk },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_d2s)
{ .enable=0, .file_hint=&file_hint_d2s },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dad)
{ .enable=0, .file_hint=&file_hint_dad },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dar)
{ .enable=0, .file_hint=&file_hint_dar },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dat)
{ .enable=0, .file_hint=&file_hint_dat },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dbf)
{ .enable=0, .file_hint=&file_hint_dbf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dbn)
{ .enable=0, .file_hint=&file_hint_dbn },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dcm)
{ .enable=0, .file_hint=&file_hint_dcm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ddf)
{ .enable=0, .file_hint=&file_hint_ddf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dex)
{ .enable=0, .file_hint=&file_hint_dex },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dim)
{ .enable=0, .file_hint=&file_hint_dim },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dir)
{ .enable=0, .file_hint=&file_hint_dir },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_djv)
{ .enable=0, .file_hint=&file_hint_djv },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dmp)
{ .enable=0, .file_hint=&file_hint_dmp },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_drw)
{ .enable=0, .file_hint=&file_hint_drw },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_doc)
{ .enable=0, .file_hint=&file_hint_doc },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dpx)
{ .enable=0, .file_hint=&file_hint_dpx },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ds2)
{ .enable=0, .file_hint=&file_hint_ds2 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ds_store)
{ .enable=0, .file_hint=&file_hint_ds_store },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dsc)
{ .enable=0, .file_hint=&file_hint_dsc },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dss)
{ .enable=0, .file_hint=&file_hint_dss },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dst)
{ .enable=0, .file_hint=&file_hint_dst },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dta)
{ .enable=0, .file_hint=&file_hint_dta },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dump)
{ .enable=0, .file_hint=&file_hint_dump },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dv)
{ .enable=0, .file_hint=&file_hint_dv },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dvi)
{ .enable=0, .file_hint=&file_hint_dvi },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dvr)
{ .enable=0, .file_hint=&file_hint_dvr },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dwg)
{ .enable=0, .file_hint=&file_hint_dwg },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_dxf)
{ .enable=0, .file_hint=&file_hint_dxf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_e01)
{ .enable=0, .file_hint=&file_hint_e01 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ecryptfs)
{ .enable=0, .file_hint=&file_hint_ecryptfs },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_edb)
{ .enable=0, .file_hint=&file_hint_edb },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_elf)
{ .enable=0, .file_hint=&file_hint_elf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_emf)
{ .enable=0, .file_hint=&file_hint_emf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ess)
{ .enable=0, .file_hint=&file_hint_ess },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_evt)
{ .enable=0, .file_hint=&file_hint_evt },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_evtx)
{ .enable=0, .file_hint=&file_hint_evtx },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exe)
{ .enable=0, .file_hint=&file_hint_exe },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exr)
{ .enable=0, .file_hint=&file_hint_exr },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_exs)
{ .enable=0, .file_hint=&file_hint_exs },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ext2_sb)
{ .enable=0, .file_hint=&file_hint_ext2_sb },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_ext2_fs)
{ .enable=0, .file_hint=&file_hint_ext2_fs },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fat)
{ .enable=0, .file_hint=&file_hint_fat },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fbf)
{ .enable=0, .file_hint=&file_hint_fbf },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fbk)
{ .enable=0, .file_hint=&file_hint_fbk },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fcp)
{ .enable=0, .file_hint=&file_hint_fcp },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fcs)
{ .enable=0, .file_hint=&file_hint_fcs },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fdb)
{ .enable=0, .file_hint=&file_hint_fdb },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fds)
{ .enable=0, .file_hint=&file_hint_fds },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fh10)
{ .enable=0, .file_hint=&file_hint_fh10 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fh5)
{ .enable=0, .file_hint=&file_hint_fh5 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_filevault)
{ .enable=0, .file_hint=&file_hint_filevault },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fits)
{ .enable=0, .file_hint=&file_hint_fits },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fit)
{ .enable=0, .file_hint=&file_hint_fit },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flac)
{ .enable=0, .file_hint=&file_hint_flac },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flp)
{ .enable=0, .file_hint=&file_hint_flp },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_flv)
{ .enable=0, .file_hint=&file_hint_flv },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fm)
{ .enable=0, .file_hint=&file_hint_fm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fob)
{ .enable=0, .file_hint=&file_hint_fob },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fos)
{ .enable=0, .file_hint=&file_hint_fos },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fp5)
{ .enable=0, .file_hint=&file_hint_fp5 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fp7)
{ .enable=0, .file_hint=&file_hint_fp7 },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_freeway)
{ .enable=0, .file_hint=&file_hint_freeway },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_frm)
{ .enable=0, .file_hint=&file_hint_frm },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fs)
{ .enable=0, .file_hint=&file_hint_fs },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_fwd)
{ .enable=0, .file_hint=&file_hint_fwd },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gam)
{ .enable=0, .file_hint=&file_hint_gam },
+#endif
+#if !defined(SINGLE_FORMAT) || defined(SINGLE_FORMAT_gct)
{ .enable=0, .file_hint=&file_hint_gct },
+#endif
+#if !defined(SINGLE_FORM