-
Notifications
You must be signed in to change notification settings - Fork 2
/
cmsfscp.c
210 lines (181 loc) · 6.19 KB
/
cmsfscp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/*
*
* Name: cmsfscp.c
* Author: Rick Troth, BMC Software, Inc., Houston, Texas, USA
* Date: 2000-Oct-17 (Tue)
*
* Mostly like 'cmsfscat' but preserves time stamps.
* cmsfs_read() interpolates NL into the stream for us
* so our work in this module is nicely limitted to
* open(), read(), write(), and finally utime().
*
*
-a ASCII (text), translate the file and add NL (LF)
-i IMAGE (binary), dump the file as a stream of bytes
-v VARREC (raw), dump the file with any
record length information included in-band
*
*
*/
#include <fcntl.h>
#include <utime.h>
/* include <malloc.h> */
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "cmsfs.h"
#define USAGE "Usage: %s [ -d cmsvol ] [ -a | -i ] cmsfile unixfile\n"
int main(int argc,char*argv[])
{
struct utimbuf stdtime;
struct CMSINODE *cmsfile; /* CMS file handle */
int stdfile; /* Unix file handle */
int cmsflags, stdflags;
unsigned char *source, *target, *buffer, *devname,
stdname[256], *sbname, *_bname;
int buflen;
int rc, i, argl;
struct stat targstat;
cmsflags = CMSFSANY;
stdflags = O_RDWR|O_CREAT|O_TRUNC;
source = target = devname = (unsigned char *) "";
/* DRAT COMPILERS THAT DON'T GROK UNSIGNED CHAR! */
/* process options */
for (i = 1 ; i < argc && argv[i][0] == '-' ; i++)
{
switch (argv[i][1])
{
case '?': case 'h': case 'H': /* quickie help */
(void) fprintf(stderr,"%s %s\n",CMSFS_DESCRIPTION,CMSFS_VERSION);
(void) fprintf(stderr,"Copy CMS files, preserving time stamps.\n");
(void) fprintf(stderr,USAGE,argv[0]);
return 0;
case 'd':
case 'f': devname = argv[++i] ;
break;
case 'a': /* ASCII (plain text) */
cmsflags |= CMSFSTXT;
break;
case 'i': /* binary (IMAGE) */
cmsflags |= CMSFSBIN;
break;
case 'v': /* "variable" records in the raw */
/* NOT YET IMPLEMENTED */
break;
default:
break;
}
}
if ((cmsflags & CMSFSTXT) && (cmsflags & CMSFSBIN))
{
(void) fprintf(stderr,"%s: conflicting options\n",argv[0]);
(void) fprintf(stderr,USAGE,argv[0]);
return 24;
}
/* sanity check: must specify exactly two files -or-
must specify at least one file and a target directory */
argl = argc - 1;
if ((argc - i) < 1)
{
(void) fprintf(stderr,"Please specify a CMS file to read.\n");
(void) fprintf(stderr,USAGE,argv[0]);
return 24;
}
if ((argc - i) < 2)
{
(void) fprintf(stderr,"Please specify a Unix file to write.\n");
(void) fprintf(stderr,USAGE,argv[0]);
return 24;
}
/* target practice: if more than three args,
then the last arg (the "target") must be a directory */
target = argv[argc-1];
rc = stat((char*)target,&targstat);
/* if stat() failed, then file probably does not exist,
and we consider it a "regular file" yet to be created */
if (rc != 0) targstat.st_mode = S_IFREG;
if ((argc - i) > 2 && !S_ISDIR(targstat.st_mode))
{
(void) fprintf(stderr,"Last argument must be a directory.\n");
(void) fprintf(stderr,USAGE,argv[0]);
return 24;
}
/* for each source file ... */
for ( ; i < argl ; i++ )
{
source = argv[i];
/* open the source file (CMS file) */
cmsfile = cmsfs_open(source,cmsflags,devname);
if (cmsfile == NULL) return -1;
/* target is file or directory? */
if (S_ISDIR(targstat.st_mode))
{
/* extract "basename" from source string */
sbname = _bname = source;
while (*_bname != 0x00)
{
if (*_bname == '/') sbname = _bname;
_bname++;
}
if (*sbname == '/') sbname++;
if (strlen(target) + strlen(sbname) > 254)
{
(void) fprintf(stderr,"filename too long\n");
return -1;
}
(void) sprintf((char*)stdname,"%s/%s",target,sbname);
}
else
{
if (strlen(target) > 255)
{
(void) fprintf(stderr,"filename too long\n");
return -1;
}
(void) sprintf((char*)stdname,"%s",target);
}
/* open the target file (Unix file) */
stdfile = open((char*)stdname,stdflags,0666);
if (stdfile < 0)
{
(void) perror((char*)stdname);
return -1;
}
/* note the time stamp on the source file */
stdtime.actime = stdtime.modtime = cmsfile->ctime;
/* allocate a buffer to hold the largest possible "record" */
buflen = cmsfile->lrecl + 2; /* plus a little to spare */
buffer = (unsigned char *) malloc(buflen);
if (buffer == NULL) return -1;
/* copy all records from source to target */
while (1)
{
/* read a record */
rc = cmsfs_read(cmsfile,buffer,buflen);
if (rc <= 0) break;
/* write the data */
rc = write(stdfile,buffer,rc);
if (rc <= 0) break;
}
/* was there an error? */
if (rc < 0)
{
(void) cmsfs_close(cmsfile);
(void) close(stdfile);
return rc;
}
/* close files, ignoring return codes */
(void) cmsfs_close(cmsfile);
(void) close(stdfile);
/* stamp the file with the mod time of the CMS source file */
rc = utime((char*)stdname,&stdtime);
if (rc != 0)
{
(void) perror((char*)stdname);
return rc;
}
}
return 0;
}