1 /* $Header: /home/cvs/wavplay/save_as.c,v 1.1.1.1 1999/11/21 19:50:56 wwg Exp $
2 * Warren W. Gay VE3WWG Thu Apr 10 21:36:07 1997
3 *
4 * Save record.wav As... Dialog Callback [OK button]
5 *
6 * Copyright (C) 1997 Warren W. Gay VE3WWG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 * Public License for more details (see enclosed file COPYING).
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Send correspondance to:
22 *
23 * Warren W. Gay VE3WWG
24 *
25 * Email:
26 * ve3wwg@yahoo.com
27 * wgay@mackenziefinancial.com
28 *
29 * $Log: save_as.c,v $
30 * Revision 1.1.1.1 1999/11/21 19:50:56 wwg
31 * Import wavplay-1.3 into CVS
32 *
33 * Revision 1.3 1997/04/17 23:43:56 wwg
34 * Added #include <errno.h> for 1.0pl2 fix.
35 *
36 * Revision 1.2 1997/04/14 01:45:53 wwg
37 * Now automatically adds the "save as.." pathname to the list
38 * box, as a selection.
39 *
40 * Revision 1.1 1997/04/14 00:00:14 wwg
41 * Initial revision
42 */
43 static const char rcsid[] = "@(#)save_as.c $Revision: 1.1.1.1 $";
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <time.h>
50 #include <signal.h>
51 #include <string.h>
52 #include <errno.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 #include <assert.h>
56
57 #include <Xm/Xm.h>
58 #include <Xm/FileSB.h>
59 #include <Xm/List.h>
60
61 #include "xmsprint.h"
62 #include "xltwavplay.h"
63 #include "wavplay.h"
64
65 /*
66 * This function is called when the recorded.wav file should be saved
67 * with a new pathname.
68 */
69 void
SaveAsDlgOKCB(Widget w,XtPointer client_data,XtPointer call_data)70 SaveAsDlgOKCB(Widget w,XtPointer client_data,XtPointer call_data) {
71 XmListCallbackStruct *ptr = (XmListCallbackStruct *)call_data;
72 char *path; /* C string copy */
73 struct stat dest_stat, src_stat; /* stat() info on both paths */
74 char bCopy = 0; /* Move or Copy? */
75 char buf[8192]; /* I/O Buffer */
76 int ifd, ofd, n; /* In/Out fds, n is byte count */
77
78 /*
79 * See if the recording exists to save:
80 */
81 if ( stat(RECORD_PATH,&src_stat) != 0 ) {
82 if ( errno == ENOENT )
83 ReportErrorf("No file %s to 'save'.",RECORD_PATH);
84 else ReportErrorf("%s: doing stat on recorded.wav",sys_errlist[errno]);
85 return;
86 }
87
88 /*
89 * If per chance, recorded.wav is a symlink, then force a copy to the
90 * selected "Save As.." file.
91 */
92 if ( S_ISLNK(src_stat.st_mode) ) /* Is recorded.wav a symlink? */
93 bCopy = 1; /* recording is a symlink to another file */
94
95 /*
96 * Get ASCII rendition of the selected pathname to save into:
97 */
98 XmStringGetLtoR(ptr->item,XmSTRING_DEFAULT_CHARSET,&path);
99
100 /*
101 * See if the specified path exists already:
102 */
103 if ( stat(path,&dest_stat) != 0 ) /* Stat save pathname.. */
104 dest_stat.st_ctime = 0; /* Mark as not found by stat() */
105 else if ( !bCopy && dest_stat.st_dev == src_stat.st_dev ) {
106 /*
107 * If here, we can entertain the possibility of just doing a mv
108 * to the destination pathname:
109 */
110 if ( dest_stat.st_ino == src_stat.st_ino ) {
111 ReportErrorf("You tried to save the file to itself (recorded.wav)");
112 return;
113 }
114 /*
115 * Both are on same device, so delete destination file, and just move
116 * contents into place with link()
117 */
118 if ( unlink(path) == 0 )
119 dest_stat.st_ctime = 0; /* File no longer exists */
120 else {
121 ReportErrorf("%s: unlink(%s)\nWill attempt to do a copy instead, next.\n",path);
122 bCopy = 1;
123 }
124 }
125
126 /*
127 * If the destination file already exists, see if its a symbolic link:
128 */
129 if ( !bCopy && dest_stat.st_ctime != 0 ) { /* if not copying, and path exists.. */
130 if ( S_ISLNK(dest_stat.st_mode) ) /* is path a symlink? */
131 bCopy = 1; /* Destination is a symlink, do copy */
132 else if ( dest_stat.st_dev != src_stat.st_dev ) /* are the files on different devs? */
133 bCopy = 1; /* Different devices: force copy */
134 }
135
136 /*
137 * Move the file into place if we can.
138 */
139 if ( !bCopy ) {
140 if ( link(RECORD_PATH,path) == 0 ) { /* mv by linking.. */
141 if ( unlink(RECORD_PATH) != 0 ) /* And removing the old */
142 ReportErrorf("%s: unlink(%s)",sys_errlist[errno]);
143 goto rm; /* Success (or mostly success) */
144 } else ReportErrorf("%s: link(%s,%s)\nWill try a copy next..",
145 sys_errlist[errno],RECORD_PATH,path);
146 }
147
148 /*
149 * Copy the file, if control passes to here:
150 */
151 if ( (ifd = open(RECORD_PATH,O_RDONLY,0)) < 0 ) {
152 ReportErrorf("%s: opening %s for read.",sys_errlist[errno],RECORD_PATH);
153 goto xit;
154 }
155
156 if ( (ofd = open(path,O_WRONLY|O_CREAT|O_TRUNC,0644)) < 0 ) {
157 ReportErrorf("%s: opening %s for read.",sys_errlist[errno],path);
158 close(ifd);
159 goto xit;
160 }
161
162 while ( (n = read(ifd,buf,sizeof buf)) > 0 )
163 if ( write(ofd,buf,n) < 0 ) {
164 ReportErrorf("%s: writing file %s for copy.",sys_errlist[errno],path);
165 close(ifd);
166 close(ofd);
167 unlink(path);
168 goto xit;
169 }
170
171 if ( n < 0 ) {
172 ReportErrorf("%s: reading file %s for copy.",sys_errlist[errno],RECORD_PATH);
173 close(ifd);
174 close(ofd);
175 unlink(path);
176 goto xit;
177 }
178
179 if ( fsync(ofd) != 0 )
180 ReportErrorf("%s: fsync(%s)",sys_errlist[errno],path);
181 if ( close(ofd) == 0 )
182 unlink(RECORD_PATH); /* Delete recorded.wav if copy successful */
183 close(ifd);
184
185 /*
186 * Success exit:
187 */
188 rm: if ( stat(RECORD_PATH,&src_stat) == 0 ) /* If record.wav still exists.. */
189 goto xit; /* ..then don't unmanage this dialog yet */
190
191 if ( XtIsManaged(wSaveAsDlg) ) /* Safety test.. */
192 XtUnmanageChild(wSaveAsDlg); /* Now pop this dialog down */
193
194 /*
195 * Remove the recorded.wav pathname from the list box:
196 */
197 if ( XmListItemExists(wSelectionsListBox,sRecorded_wav) != False )
198 XmListDeleteItem(wSelectionsListBox,sRecorded_wav);
199
200 /*
201 * If the new pathname exists, add it to the list box:
202 */
203 xit: if ( stat(path,&dest_stat) == 0 ) {
204 if ( XmListItemExists(wSelectionsListBox,ptr->item) == False ) /* path */
205 XmListAddItem(wSelectionsListBox,ptr->item,0);
206 }
207
208 XtFree(path); /* Free the allocated string and leave popped up */
209 }
210
211 /* $Source: /home/cvs/wavplay/save_as.c,v $ */
212