xref: /haiku/src/apps/soundrecorder/FileUtils.cpp (revision b8ded2f89783a220c7b3019d48266a682cc79158)
13ee96407SJérôme Duval /******************************************************************************
257e2f323SJérôme Duval /
357e2f323SJérôme Duval /	File:			FileUtils.cpp
457e2f323SJérôme Duval /
557e2f323SJérôme Duval /   Description:	Utility functions for copying file data and attributes.
657e2f323SJérôme Duval /
757e2f323SJérôme Duval /	Copyright 1998-1999, Be Incorporated, All Rights Reserved
857e2f323SJérôme Duval /
93ee96407SJérôme Duval ******************************************************************************/
1057e2f323SJérôme Duval #include "FileUtils.h"
1157e2f323SJérôme Duval 
12*e367c056SJérôme Duval #include <algorithm>
13c1c81d42SStephan Aßmus #include <new>
14c1c81d42SStephan Aßmus #include <stdio.h>
15c1c81d42SStephan Aßmus #include <string.h>
16c1c81d42SStephan Aßmus 
17c1c81d42SStephan Aßmus #include <fs_attr.h>
18c1c81d42SStephan Aßmus 
19c1c81d42SStephan Aßmus #include "AutoDeleter.h"
20c1c81d42SStephan Aßmus 
21c1c81d42SStephan Aßmus 
22c1c81d42SStephan Aßmus using std::nothrow;
23c1c81d42SStephan Aßmus 
24c1c81d42SStephan Aßmus 
25c1c81d42SStephan Aßmus status_t
CopyFileData(BFile & dst,BFile & src)26c1c81d42SStephan Aßmus CopyFileData(BFile& dst, BFile& src)
2757e2f323SJérôme Duval {
2857e2f323SJérôme Duval 	struct stat src_stat;
2957e2f323SJérôme Duval 	status_t err = src.GetStat(&src_stat);
3057e2f323SJérôme Duval 	if (err != B_OK) {
317f4d1af4SSergei Reznikov 		printf("couldn't get stat: %#010" B_PRIx32 "\n", err);
3257e2f323SJérôme Duval 		return err;
3357e2f323SJérôme Duval 	}
3457e2f323SJérôme Duval 
3557e2f323SJérôme Duval 	size_t bufSize = src_stat.st_blksize;
36c1c81d42SStephan Aßmus 	if (bufSize == 0)
3757e2f323SJérôme Duval 		bufSize = 32768;
3857e2f323SJérôme Duval 
39c1c81d42SStephan Aßmus 	char* buf = new (nothrow) char[bufSize];
40c1c81d42SStephan Aßmus 	if (buf == NULL)
41c1c81d42SStephan Aßmus 		return B_NO_MEMORY;
42c1c81d42SStephan Aßmus 	ArrayDeleter<char> _(buf);
4357e2f323SJérôme Duval 
4457e2f323SJérôme Duval 	printf("copy data, bufSize = %ld\n", bufSize);
4557e2f323SJérôme Duval 	// copy data
4657e2f323SJérôme Duval 	while (true) {
4757e2f323SJérôme Duval 		ssize_t bytes = src.Read(buf, bufSize);
4857e2f323SJérôme Duval 		if (bytes > 0) {
4957e2f323SJérôme Duval 			ssize_t result = dst.Write(buf, bytes);
5057e2f323SJérôme Duval 			if (result != bytes) {
51c1c81d42SStephan Aßmus 				fprintf(stderr, "Failed to write %ld bytes: %s\n", bytes,
52c1c81d42SStephan Aßmus 					strerror((status_t)result));
53c1c81d42SStephan Aßmus 				if (result < 0)
54c1c81d42SStephan Aßmus 					return (status_t)result;
55c1c81d42SStephan Aßmus 				else
56c1c81d42SStephan Aßmus 					return B_IO_ERROR;
5757e2f323SJérôme Duval 			}
5857e2f323SJérôme Duval 		} else {
5957e2f323SJérôme Duval 			if (bytes < 0) {
60c1c81d42SStephan Aßmus 				fprintf(stderr, "Failed to read file: %s\n", strerror(
61c1c81d42SStephan Aßmus 					(status_t)bytes));
62c1c81d42SStephan Aßmus 				return (status_t)bytes;
6357e2f323SJérôme Duval 			} else {
6457e2f323SJérôme Duval 				// EOF
6557e2f323SJérôme Duval 				break;
6657e2f323SJérôme Duval 			}
6757e2f323SJérôme Duval 		}
6857e2f323SJérôme Duval 	}
6957e2f323SJérôme Duval 
7057e2f323SJérôme Duval 	// finish up miscellaneous stat stuff
7157e2f323SJérôme Duval 	dst.SetPermissions(src_stat.st_mode);
7257e2f323SJérôme Duval 	dst.SetOwner(src_stat.st_uid);
7357e2f323SJérôme Duval 	dst.SetGroup(src_stat.st_gid);
7457e2f323SJérôme Duval 	dst.SetModificationTime(src_stat.st_mtime);
7557e2f323SJérôme Duval 	dst.SetCreationTime(src_stat.st_crtime);
7657e2f323SJérôme Duval 
7757e2f323SJérôme Duval 	return B_OK;
7857e2f323SJérôme Duval }
7957e2f323SJérôme Duval 
8057e2f323SJérôme Duval 
81c1c81d42SStephan Aßmus status_t
CopyAttributes(BNode & dst,BNode & src)82c1c81d42SStephan Aßmus CopyAttributes(BNode& dst, BNode& src)
8357e2f323SJérôme Duval {
8457e2f323SJérôme Duval 	// copy attributes
8557e2f323SJérôme Duval 	src.RewindAttrs();
86c1c81d42SStephan Aßmus 	char attrName[B_ATTR_NAME_LENGTH];
87c1c81d42SStephan Aßmus 	while (src.GetNextAttrName(attrName) == B_OK) {
8857e2f323SJérôme Duval 		attr_info info;
89c1c81d42SStephan Aßmus 		if (src.GetAttrInfo(attrName, &info) != B_OK) {
90c1c81d42SStephan Aßmus 			fprintf(stderr, "Failed to read info for attribute '%s'\n",
91c1c81d42SStephan Aßmus 				attrName);
92c1c81d42SStephan Aßmus 			continue;
9357e2f323SJérôme Duval 		}
94c1c81d42SStephan Aßmus 		// copy one attribute in chunks of 4096 bytes
95c1c81d42SStephan Aßmus 		size_t size = 4096;
96c1c81d42SStephan Aßmus 		uint8 buffer[size];
97c1c81d42SStephan Aßmus 		off_t offset = 0;
98c1c81d42SStephan Aßmus 		ssize_t read = src.ReadAttr(attrName, info.type, offset, buffer,
99*e367c056SJérôme Duval 			std::min((off_t)size, info.size));
100c1c81d42SStephan Aßmus 		if (read < 0) {
101c1c81d42SStephan Aßmus 			fprintf(stderr, "Error reading attribute '%s'\n", attrName);
102c1c81d42SStephan Aßmus 			return (status_t)read;
103c1c81d42SStephan Aßmus 		}
104c1c81d42SStephan Aßmus 		// NOTE: Attributes of size 0 are perfectly valid!
105c1c81d42SStephan Aßmus 		while (read >= 0) {
1063ee96407SJérôme Duval 			ssize_t written = dst.WriteAttr(attrName, info.type, offset,
1073ee96407SJérôme Duval 				buffer, read);
108c1c81d42SStephan Aßmus 			if (written != read) {
109c1c81d42SStephan Aßmus 				fprintf(stderr, "Error writing attribute '%s'\n", attrName);
110c1c81d42SStephan Aßmus 				if (written < 0)
111c1c81d42SStephan Aßmus 					return (status_t)written;
112c1c81d42SStephan Aßmus 				else
113c1c81d42SStephan Aßmus 					return B_IO_ERROR;
114c1c81d42SStephan Aßmus 			}
115c1c81d42SStephan Aßmus 			offset += read;
116c1c81d42SStephan Aßmus 			read = src.ReadAttr(attrName, info.type, offset, buffer,
117*e367c056SJérôme Duval 				std::min((off_t)size, info.size - offset));
118c1c81d42SStephan Aßmus 			if (read < 0) {
119c1c81d42SStephan Aßmus 				fprintf(stderr, "Error reading attribute '%s'\n", attrName);
120c1c81d42SStephan Aßmus 				return (status_t)read;
121c1c81d42SStephan Aßmus 			}
122c1c81d42SStephan Aßmus 			if (read == 0)
123c1c81d42SStephan Aßmus 				break;
12457e2f323SJérôme Duval 		}
12557e2f323SJérôme Duval 	}
12657e2f323SJérôme Duval 
12757e2f323SJérôme Duval 	return B_OK;
12857e2f323SJérôme Duval }
12957e2f323SJérôme Duval 
13057e2f323SJérôme Duval 
131c1c81d42SStephan Aßmus status_t
CopyFile(BFile & dst,BFile & src)132c1c81d42SStephan Aßmus CopyFile(BFile& dst, BFile& src)
13357e2f323SJérôme Duval {
13457e2f323SJérôme Duval 	status_t err = CopyFileData(dst, src);
13557e2f323SJérôme Duval 	if (err != B_OK)
13657e2f323SJérôme Duval 		return err;
13757e2f323SJérôme Duval 
13857e2f323SJérôme Duval 	return CopyAttributes(dst, src);
13957e2f323SJérôme Duval }
140