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