1 /*
2      cmap_open.c: Opening CCP4-format map files.
3      Copyright (C) 2001  CCLRC, Charles Ballard
4 
5      This library is free software: you can redistribute it and/or
6      modify it under the terms of the GNU Lesser General Public License
7      version 3, modified in accordance with the provisions of the
8      license to address the requirements of UK law.
9 
10      You should have received a copy of the modified GNU Lesser General
11      Public License along with this library.  If not, copies may be
12      downloaded from http://www.ccp4.ac.uk/ccp4license.php
13 
14      This program is distributed in the hope that it will be useful,
15      but WITHOUT ANY WARRANTY; without even the implied warranty of
16      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17      GNU Lesser General Public License for more details.
18 */
19 
20 /** @file cmap_open.c
21  *
22  *  @brief Opening CCP4-format map files.
23  *
24  *  @author Charles Ballard
25  */
26 
27 #include <string.h>
28 #include <math.h>
29 #include <stdarg.h>
30 #include <fcntl.h>
31 #include "cmaplib.h"
32 #include "cmap_header.h"
33 #include "cmap_labels.h"
34 #include "cmap_errno.h"
35 
36 /*! Internal: malloc CMMFile struct for reading into
37  \return CMMFile */
init_cmap_read(void)38 CMMFile *init_cmap_read(void)
39 {
40   CMMFile *mfile = (CMMFile *) malloc(sizeof(CMMFile));
41   if (mfile)
42     memset(mfile,'\0',sizeof(CMMFile));
43   return mfile;
44 }
45 
46 /*! Internal: malloc CMMFile struct for writing
47  \return CMMFile */
init_cmap_write(void)48 CMMFile *init_cmap_write(void)
49 {
50   CMMFile *mfile = (CMMFile *) malloc(sizeof(CMMFile));
51   if (mfile) {
52     memset(mfile,'\0',sizeof(CMMFile));
53     mfile->data_mode = DEFMODE;
54     mfile->symop.offset = 1024U;
55     mfile->data.offset = 1024U; }
56   return mfile;
57 }
58 
59 /*! Internal: Identify file as a ccp4 format map
60  \param file The (CCP4File *) struct representing the file.
61  \return non-zero on true, 0 on false */
is_cmap(CCP4File * file)62 int is_cmap(CCP4File *file)
63 {
64   char buffer[4];
65   const unsigned int map_offset = 208U;
66   if (file == NULL)
67     return 0;
68   if ( ccp4_file_raw_seek(file,map_offset,SEEK_SET) == EOF)
69     return 0;
70   if (ccp4_file_readchar(file,(uint8 *) buffer,4U) != 4U)
71     return 0;
72   ccp4_file_rewind(file);
73   return !strncmp(buffer,"MAP ",4);
74 }
75 
76 /*! The file is opened.
77  \param filename (char *) the filename
78  \param mode (int) the i/o mode , possible values are O_RDONLY, O_WRONLY,
79        O_RDWR, O_APPEND, O_TMP, O_CREAT, O_TRUNC - see ccp4_sysdep.h
80  \return (void *) CMMFile structure */
ccp4_cmap_open(const char * filename,int mode)81 void *ccp4_cmap_open(const char *filename, int mode)
82 {
83   CMMFile *mfile;
84   CCP4File *cfile;
85   const size_t stamp_offset = 212U;
86 
87   if ((cfile = ccp4_file_open(filename, mode)) == NULL) {
88     ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_CantOpenFile),
89 		 "ccp4_cmap_open",NULL);
90     return (NULL); }
91   ccp4_file_raw_setstamp(cfile, stamp_offset);
92   /* read or write only */
93   if (cfile->read) {
94     if (!is_cmap(cfile) || cfile->length < 1025) {
95       ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_NoHeader),
96 		 "ccp4_cmap_open",NULL);
97       ccp4_file_close(cfile);
98       return NULL; }
99     ccp4_file_rarch(cfile);
100     mfile = init_cmap_read();
101     mfile->stream = cfile;
102     mfile->file_name = cfile->name;
103     parse_mapheader(mfile);
104     parse_maplabels(mfile);
105   } else if (cfile->write) {
106     mfile = init_cmap_write();
107     mfile->stream = cfile;
108     mfile->file_name = cfile->name;
109     write_mapheader(mfile);
110     write_maplabels(mfile);
111   } else {
112     ccp4_signal( CCP4_ERRLEVEL(3) | CMAP_ERRNO(CMERR_CantOpenFile),
113 		 "ccp4_cmap_open",NULL);
114     return (NULL); }
115   return (mfile);
116 }
117 
118