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