xref: /haiku/src/apps/soundrecorder/FileUtils.cpp (revision 579f1dbca962a2a03df54f69fdc6e9423f91f20e)
1 /******************************************************************************
2 /
3 /	File:			FileUtils.cpp
4 /
5 /   Description:	Utility functions for copying file data and attributes.
6 /
7 /	Copyright 1998-1999, Be Incorporated, All Rights Reserved
8 /
9 ******************************************************************************/
10 #include "FileUtils.h"
11 
12 #include <algorithm>
13 #include <new>
14 #include <stdio.h>
15 #include <string.h>
16 
17 #include <fs_attr.h>
18 
19 #include "AutoDeleter.h"
20 
21 
22 using std::nothrow;
23 
24 
25 status_t
26 CopyFileData(BFile& dst, BFile& src)
27 {
28 	struct stat src_stat;
29 	status_t err = src.GetStat(&src_stat);
30 	if (err != B_OK) {
31 		printf("couldn't get stat: %#010" B_PRIx32 "\n", err);
32 		return err;
33 	}
34 
35 	size_t bufSize = src_stat.st_blksize;
36 	if (bufSize == 0)
37 		bufSize = 32768;
38 
39 	char* buf = new (nothrow) char[bufSize];
40 	if (buf == NULL)
41 		return B_NO_MEMORY;
42 	ArrayDeleter<char> _(buf);
43 
44 	printf("copy data, bufSize = %ld\n", bufSize);
45 	// copy data
46 	while (true) {
47 		ssize_t bytes = src.Read(buf, bufSize);
48 		if (bytes > 0) {
49 			ssize_t result = dst.Write(buf, bytes);
50 			if (result != bytes) {
51 				fprintf(stderr, "Failed to write %ld bytes: %s\n", bytes,
52 					strerror((status_t)result));
53 				if (result < 0)
54 					return (status_t)result;
55 				else
56 					return B_IO_ERROR;
57 			}
58 		} else {
59 			if (bytes < 0) {
60 				fprintf(stderr, "Failed to read file: %s\n", strerror(
61 					(status_t)bytes));
62 				return (status_t)bytes;
63 			} else {
64 				// EOF
65 				break;
66 			}
67 		}
68 	}
69 
70 	// finish up miscellaneous stat stuff
71 	dst.SetPermissions(src_stat.st_mode);
72 	dst.SetOwner(src_stat.st_uid);
73 	dst.SetGroup(src_stat.st_gid);
74 	dst.SetModificationTime(src_stat.st_mtime);
75 	dst.SetCreationTime(src_stat.st_crtime);
76 
77 	return B_OK;
78 }
79 
80 
81 status_t
82 CopyAttributes(BNode& dst, BNode& src)
83 {
84 	// copy attributes
85 	src.RewindAttrs();
86 	char attrName[B_ATTR_NAME_LENGTH];
87 	while (src.GetNextAttrName(attrName) == B_OK) {
88 		attr_info info;
89 		if (src.GetAttrInfo(attrName, &info) != B_OK) {
90 			fprintf(stderr, "Failed to read info for attribute '%s'\n",
91 				attrName);
92 			continue;
93 		}
94 		// copy one attribute in chunks of 4096 bytes
95 		size_t size = 4096;
96 		uint8 buffer[size];
97 		off_t offset = 0;
98 		ssize_t read = src.ReadAttr(attrName, info.type, offset, buffer,
99 			std::min((off_t)size, info.size));
100 		if (read < 0) {
101 			fprintf(stderr, "Error reading attribute '%s'\n", attrName);
102 			return (status_t)read;
103 		}
104 		// NOTE: Attributes of size 0 are perfectly valid!
105 		while (read >= 0) {
106 			ssize_t written = dst.WriteAttr(attrName, info.type, offset,
107 				buffer, read);
108 			if (written != read) {
109 				fprintf(stderr, "Error writing attribute '%s'\n", attrName);
110 				if (written < 0)
111 					return (status_t)written;
112 				else
113 					return B_IO_ERROR;
114 			}
115 			offset += read;
116 			read = src.ReadAttr(attrName, info.type, offset, buffer,
117 				std::min((off_t)size, info.size - offset));
118 			if (read < 0) {
119 				fprintf(stderr, "Error reading attribute '%s'\n", attrName);
120 				return (status_t)read;
121 			}
122 			if (read == 0)
123 				break;
124 		}
125 	}
126 
127 	return B_OK;
128 }
129 
130 
131 status_t
132 CopyFile(BFile& dst, BFile& src)
133 {
134 	status_t err = CopyFileData(dst, src);
135 	if (err != B_OK)
136 		return err;
137 
138 	return CopyAttributes(dst, src);
139 }
140