// Function implementing a FNV inspired hash // on a string int main(int argc, const char * argv[]) { char * str = "Hello, World!"; int buckets = UINT32_MAX; if (argc > 2) buckets = atoi(argv[2]); if (argc > 1) str = (char *) argv[1]; printf("Input: %s\nHashed: %u",str,fnv(str,sizeof(str),buckets)); return 0; }
/// Calculates a full dataset item /// /// This consist of two 512-bit items produced by calculate_dataset_item_partial(). /// Here the computation is done interleaved for better performance. hash1024 calculate_dataset_item(const epoch_context& context, uint32_t index) noexcept { const hash512* const cache = context.light_cache; static constexpr size_t num_half_words = sizeof(hash512) / sizeof(uint32_t); const int64_t num_cache_items = context.light_cache_num_items; const int64_t index0 = int64_t(index) * 2; const int64_t index1 = int64_t(index) * 2 + 1; const uint32_t init0 = static_cast<uint32_t>(index0); const uint32_t init1 = static_cast<uint32_t>(index1); hash512 mix0 = cache[index0 % num_cache_items]; hash512 mix1 = cache[index1 % num_cache_items]; mix0.half_words[0] ^= fix_endianness(init0); mix1.half_words[0] ^= fix_endianness(init1); // Hash and convert to little-endian 32-bit words. mix0 = fix_endianness32(keccak512(mix0)); mix1 = fix_endianness32(keccak512(mix1)); for (uint32_t j = 0; j < full_dataset_item_parents; ++j) { uint32_t t0 = fnv(init0 ^ j, mix0.half_words[j % num_half_words]); int64_t parent_index0 = t0 % num_cache_items; mix0 = fnv(mix0, fix_endianness32(cache[parent_index0])); uint32_t t1 = fnv(init1 ^ j, mix1.half_words[j % num_half_words]); int64_t parent_index1 = t1 % num_cache_items; mix1 = fnv(mix1, fix_endianness32(cache[parent_index1])); } // Covert 32-bit words back to bytes and hash. mix0 = keccak512(fix_endianness32(mix0)); mix1 = keccak512(fix_endianness32(mix1)); return hash1024{{mix0, mix1}}; }
Node CalcDAGItem(const Node *CacheInputNodes, uint32_t NodeCount, uint32_t NodeIdx) { Node DAGNode = CacheInputNodes[NodeIdx % NodeCount]; DAGNode.words[0] ^= NodeIdx; SHA3_512(DAGNode.bytes, DAGNode.bytes, sizeof(Node)); for(uint32_t i = 0; i < 256; ++i) { uint32_t parent_index = fnv(NodeIdx ^ i, DAGNode.words[i % 16]) % NodeCount; Node const *parent = CacheInputNodes + parent_index; //&cache_nodes[parent_index]; for(int i = 0; i < 16; ++i) { DAGNode.words[i] *= FNV_PRIME; DAGNode.words[i] ^= parent->words[i]; } } SHA3_512(DAGNode.bytes, DAGNode.bytes, sizeof(Node)); return DAGNode; }
static ssize_t do_readv_writev(int type, struct file *file, const struct iovec __user * uvector, unsigned long nr_segs, loff_t *pos) { typedef ssize_t (*io_fn_t)(struct file *, char __user *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); size_t tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack, *vector; ssize_t ret; int seg; io_fn_t fn; iov_fn_t fnv; /* * SuS says "The readv() function *may* fail if the iovcnt argument * was less than or equal to 0, or greater than {IOV_MAX}. Linux has * traditionally returned zero for zero segments, so... */ ret = 0; if (nr_segs == 0) goto out; /* * First get the "struct iovec" from user memory and * verify all the pointers */ ret = -EINVAL; if (nr_segs > UIO_MAXIOV) goto out; if (!file->f_op) goto out; if (nr_segs > UIO_FASTIOV) { ret = -ENOMEM; iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL); if (!iov) goto out; } ret = -EFAULT; if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an * ssize_t. The total length is fitting an ssize_t * * Be careful here because iov_len is a size_t not an ssize_t */ tot_len = 0; ret = -EINVAL; for (seg = 0; seg < nr_segs; seg++) { void __user *buf = iov[seg].iov_base; ssize_t len = (ssize_t)iov[seg].iov_len; if (len < 0) /* size_t not fitting an ssize_t .. */ goto out; if (unlikely(!access_ok(vrfy_dir(type), buf, len))) goto Efault; tot_len += len; if ((ssize_t)tot_len < 0) /* maths overflow on the ssize_t */ goto out; } if (tot_len == 0) { ret = 0; goto out; } ret = rw_verify_area(type, file, pos, tot_len); if (ret < 0) goto out; ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); if (ret) goto out; fnv = NULL; if (type == READ) { fn = file->f_op->read; fnv = file->f_op->readv; } else { fn = (io_fn_t)file->f_op->write; fnv = file->f_op->writev; } if (fnv) { ret = fnv(file, iov, nr_segs, pos); goto out; } /* Do it by hand, with file-ops */ ret = 0; vector = iov; while (nr_segs > 0) { void __user * base; size_t len; ssize_t nr; base = vector->iov_base; len = vector->iov_len; vector++; nr_segs--; nr = fn(file, base, len, pos); if (nr < 0) { if (!ret) ret = nr; break; } ret += nr; if (nr != len) break; } out: if (iov != iovstack) kfree(iov); if ((ret + (type == READ)) > 0) { if (type == READ) fsnotify_access(file->f_dentry); else fsnotify_modify(file->f_dentry); } return ret; Efault: ret = -EFAULT; goto out; }
uint32_t SDHashClass::_incHash(uint32_t hash) { return fnv((uint8_t*)&hash, sizeof hash, hash); }
static ssize_t do_readv_writev(int type, struct file *file, const struct iovec * vector, unsigned long count) { typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); size_t tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; ssize_t ret, i; io_fn_t fn; iov_fn_t fnv; struct inode *inode; /* * First get the "struct iovec" from user memory and * verify all the pointers */ ret = 0; if (!count) goto out_nofree; ret = -EINVAL; if (count > UIO_MAXIOV) goto out_nofree; if (!file->f_op) goto out_nofree; if (count > UIO_FASTIOV) { ret = -ENOMEM; iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); if (!iov) goto out_nofree; } ret = -EFAULT; if (copy_from_user(iov, vector, count*sizeof(*vector))) goto out; /* BSD readv/writev returns EINVAL if one of the iov_len values < 0 or tot_len overflowed a 32-bit integer. -ink */ tot_len = 0; ret = -EINVAL; for (i = 0 ; i < count ; i++) { size_t tmp = tot_len; int len = iov[i].iov_len; if (len < 0) goto out; tot_len += len; if (tot_len < tmp || tot_len < (u32)len) goto out; } inode = file->f_dentry->d_inode; /* VERIFY_WRITE actually means a read, as we write to user space */ fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); if (fnv) { ret = fnv(file, iov, count, &file->f_pos); goto out; } /* VERIFY_WRITE actually means a read, as we write to user space */ fn = (type == VERIFY_WRITE ? file->f_op->read : (io_fn_t) file->f_op->write); ret = 0; vector = iov; while (count > 0) { void * base; size_t len; ssize_t nr; base = vector->iov_base; len = vector->iov_len; vector++; count--; nr = fn(file, base, len, &file->f_pos); if (nr < 0) { if (!ret) ret = nr; break; } ret += nr; if (nr != len) break; } out: if (iov != iovstack) kfree(iov); out_nofree: /* VERIFY_WRITE actually means a read, as we write to user space */ return ret; }
static ssize_t do_readv_writev(int type, struct file *file, const struct iovec * vector, unsigned long count) { typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); size_t tot_len; struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov=iovstack; ssize_t ret, i; iov_fn_t fnv; struct inode *inode; /* * First get the "struct iovec" from user memory and * verify all the pointers */ ret = 0; if (!count) goto out_nofree; ret = -EINVAL; if (count > UIO_MAXIOV) goto out_nofree; if (!file->f_op) goto out_nofree; if (count > UIO_FASTIOV) { ret = -ENOMEM; iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); if (!iov) goto out_nofree; } ret = -EFAULT; if (copy_from_user(iov, vector, count*sizeof(*vector))) goto out; /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an ssize_t * The total length is fitting an ssize_t * * Be careful here because iov_len is a size_t not an ssize_t */ tot_len = 0; ret = -EINVAL; for (i = 0 ; i < count ; i++) { ssize_t len = (ssize_t) iov[i].iov_len; if (len < 0) /* size_t not fitting an ssize_t .. */ goto out; tot_len += len; /* We must do this work unsigned - signed overflow is undefined and gcc 3.2 now uses that fact sometimes... FIXME: put in a proper limits.h for each platform */ #if BITS_PER_LONG==64 if (tot_len > 0x7FFFFFFFFFFFFFFFUL) #else if (tot_len > 0x7FFFFFFFUL) #endif goto out; } inode = file->f_dentry->d_inode; /* VERIFY_WRITE actually means a read, as we write to user space */ ret = locks_verify_area((type == VERIFY_WRITE ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE), inode, file, file->f_pos, tot_len); if (ret) goto out; fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev); if (fnv) { ret = fnv(file, iov, count, &file->f_pos); goto out; } ret = fallback_readv_writev(type == VERIFY_WRITE ? READ : WRITE, file, iov, count, &file->f_pos); out: if (iov != iovstack) kfree(iov); out_nofree: /* VERIFY_WRITE actually means a read, as we write to user space */ if ((ret + (type == VERIFY_WRITE)) > 0) dnotify_parent(file->f_dentry, (type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY); return ret; }
static constexpr IntType fnv(IntType hash, const char* pos) { return *pos == '\0' ? hash : fnv((hash * IntType(16777619U)) ^ *pos, (pos+1)); }
std::string getCachedName(const std::string &filename, const std::string &salt){ //---[ Place Somewhere Else ]----- char *c_cachePath = getenv("OCCA_CACHE_DIR"); std::string occaCachePath; if(c_cachePath == NULL){ std::stringstream ss; #if (OCCA_OS == LINUX_OS) || (OCCA_OS == OSX_OS) char *c_home = getenv("HOME"); ss << c_home << "/._occa"; std::string defaultCacheDir = ss.str(); mkdir(defaultCacheDir.c_str(), 0755); #else char *c_home = getenv("USERPROFILE"); ss << c_home << "\\AppData\\Local\\OCCA"; std::string defaultCacheDir = ss.str(); LPCSTR w_defaultCacheDir = defaultCacheDir.c_str(); BOOL mkdirStatus = CreateDirectoryA(w_defaultCacheDir, NULL); if(mkdirStatus == FALSE) assert(GetLastError() == ERROR_ALREADY_EXISTS); # if OCCA_64_BIT ss << "\\amd64"; // use different dir's fro 32 and 64 bit # else ss << "\\x86"; // use different dir's fro 32 and 64 bit # endif defaultCacheDir = ss.str(); w_defaultCacheDir = defaultCacheDir.c_str(); mkdirStatus = CreateDirectoryA(w_defaultCacheDir, NULL); if(mkdirStatus == FALSE) assert(GetLastError() == ERROR_ALREADY_EXISTS); #endif occaCachePath = defaultCacheDir; } else occaCachePath = c_cachePath; const int chars = occaCachePath.size(); OCCA_CHECK(chars > 0); #if (OCCA_OS == LINUX_OS) || (OCCA_OS == OSX_OS) const char slashChar = '/'; #else const char slashChar = '\\'; #endif // Take out the pesky //'s int pos = 0; for(int i = 0; i < chars; ++i){ if(occaCachePath[i] == slashChar) while(i < (chars - 1) && occaCachePath[i + 1] == slashChar) ++i; occaCachePath[pos++] = occaCachePath[i]; } if(occaCachePath[pos - 1] != slashChar){ if(pos != chars) occaCachePath[pos] = slashChar; else occaCachePath += slashChar; } //================================ const std::string fileContents = readFile(filename); const std::string contentsSHA = fnv(fileContents + salt); // Only taking the first 16 characters return occaCachePath + contentsSHA.substr(0, 16); }