📄 storage.c
字号:
} pos++; } GNUNET_free (rdir); return GNUNET_OK;}/** * Create the directory structure for storing * a file. * * @param filename name of a file in the directory * @returns GNUNET_OK on success, GNUNET_SYSERR on failure */intGNUNET_disk_directory_create_for_file (struct GNUNET_GE_Context *ectx, const char *dir){ char *rdir; int len; int ret; rdir = GNUNET_expand_file_name (ectx, dir); if (rdir == NULL) return GNUNET_SYSERR; len = strlen (rdir); while ((len > 0) && (rdir[len] != DIR_SEPARATOR)) len--; rdir[len] = '\0'; ret = GNUNET_disk_directory_create (ectx, rdir); GNUNET_free (rdir); return ret;}/** * Read the contents of a binary file into a buffer. * @param fileName the name of the file, not freed, * must already be expanded! * @param len the maximum number of bytes to read * @param result the buffer to write the result to * @return the number of bytes read on success, -1 on failure */intGNUNET_disk_file_read (struct GNUNET_GE_Context *ectx, const char *fileName, int len, void *result){ /* open file, must exist, open read only */ int handle; int size; GNUNET_GE_ASSERT (ectx, fileName != NULL); GNUNET_GE_ASSERT (ectx, len > 0); if (len == 0) return 0; GNUNET_GE_ASSERT (ectx, result != NULL); handle = GNUNET_disk_file_open (ectx, fileName, O_RDONLY, S_IRUSR); if (handle < 0) return -1; size = READ (handle, result, len); GNUNET_disk_file_close (ectx, fileName, handle); return size;}/** * Convert string to value ('755' for chmod-call) */static intatoo (const char *s){ int n = 0; while (('0' <= *s) && (*s < '8')) { n <<= 3; n += *s++ - '0'; } return n;}/** * Write a buffer to a file. * @param fileName the name of the file, NOT freed! * @param buffer the data to write * @param n number of bytes to write * @param mode permissions to set on the file * @return GNUNET_OK on success, GNUNET_SYSERR on error */intGNUNET_disk_file_write (struct GNUNET_GE_Context *ectx, const char *fileName, const void *buffer, unsigned int n, const char *mode){ int handle; char *fn; /* open file, open with 600, create if not present, otherwise overwrite */ GNUNET_GE_ASSERT (ectx, fileName != NULL); fn = GNUNET_expand_file_name (ectx, fileName); handle = GNUNET_disk_file_open (ectx, fn, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); if (handle == -1) { GNUNET_free (fn); return GNUNET_SYSERR; } GNUNET_GE_ASSERT (ectx, (n == 0) || (buffer != NULL)); /* write the buffer take length from the beginning */ if (n != WRITE (handle, buffer, n)) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_IMMEDIATE, "write", fn); GNUNET_disk_file_close (ectx, fn, handle); GNUNET_free (fn); return GNUNET_SYSERR; } GNUNET_disk_file_close (ectx, fn, handle); if (0 != CHMOD (fn, atoo (mode))) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "chmod", fn); } GNUNET_free (fn); return GNUNET_OK;}/** * Scan a directory for files. The name of the directory * must be expanded first (!). * @param dirName the name of the directory * @param callback the method to call for each file, * can be NULL, in that case, we only count * @param data argument to pass to callback * @return the number of files found, GNUNET_SYSERR on error or * ieration aborted by callback returning GNUNET_SYSERR */intGNUNET_disk_directory_scan (struct GNUNET_GE_Context *ectx, const char *dirName, GNUNET_DirectoryEntryCallback callback, void *data){ DIR *dinfo; struct dirent *finfo; struct stat istat; int count = 0; GNUNET_GE_ASSERT (ectx, dirName != NULL); if (0 != STAT (dirName, &istat)) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "stat", dirName); return GNUNET_SYSERR; } if (!S_ISDIR (istat.st_mode)) { GNUNET_GE_LOG (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, _("Expected `%s' to be a directory!\n"), dirName); return GNUNET_SYSERR; } errno = 0; dinfo = OPENDIR (dirName); if ((errno == EACCES) || (dinfo == NULL)) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "opendir", dirName); if (dinfo != NULL) closedir (dinfo); return GNUNET_SYSERR; } while ((finfo = readdir (dinfo)) != NULL) { if ((0 == strcmp (finfo->d_name, ".")) || (0 == strcmp (finfo->d_name, ".."))) continue; if (callback != NULL) { if (GNUNET_OK != callback (finfo->d_name, dirName, data)) { closedir (dinfo); return GNUNET_SYSERR; } } count++; } closedir (dinfo); return count;}/** * Callback for GNUNET_disk_directory_remove */static intrmHelper (const char *fil, const char *dir, void *ctx){ struct GNUNET_GE_Context *ectx = ctx; char *fn; size_t n; n = strlen (dir) + strlen (fil) + 2; fn = GNUNET_malloc (n); GNUNET_snprintf (fn, n, "%s/%s", dir, fil); if (GNUNET_SYSERR == GNUNET_disk_directory_remove (ectx, fn)) { GNUNET_free (fn); return GNUNET_SYSERR; } GNUNET_free (fn); return GNUNET_OK;}/** * Remove all files in a directory (rm -rf). Call with * caution. * * * @param fileName the file to remove * @return GNUNET_OK on success, GNUNET_SYSERR on error */intGNUNET_disk_directory_remove (struct GNUNET_GE_Context *ectx, const char *fileName){ struct stat istat; if (0 != LSTAT (fileName, &istat)) return GNUNET_NO; /* file may not exist... */ if (UNLINK (fileName) == 0) return GNUNET_OK; if ((errno != EISDIR) && /* EISDIR is not sufficient in all cases, e.g. sticky /tmp directory may result in EPERM on BSD. So we also explicitly check "isDirectory" */ (GNUNET_YES != GNUNET_disk_directory_test (ectx, fileName))) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "rmdir", fileName); return GNUNET_SYSERR; } if (GNUNET_SYSERR == GNUNET_disk_directory_scan (ectx, fileName, &rmHelper, ectx)) return GNUNET_SYSERR; if (0 != RMDIR (fileName)) { GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "rmdir", fileName); return GNUNET_SYSERR; } return GNUNET_OK;}voidGNUNET_disk_file_close (struct GNUNET_GE_Context *ectx, const char *filename, int fd){ if (0 != CLOSE (fd)) GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "close", filename);}intGNUNET_disk_file_open (struct GNUNET_GE_Context *ectx, const char *filename, int oflag, ...){ char *fn; int mode; int ret;#ifdef MINGW char szFile[_MAX_PATH + 1]; long lRet; if ((lRet = plibc_conv_to_win_path (filename, szFile)) != ERROR_SUCCESS) { errno = ENOENT; SetLastError (lRet); GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_DEVELOPER | GNUNET_GE_ADMIN | GNUNET_GE_BULK, "plibc_conv_to_win_path", filename); return -1; } fn = GNUNET_strdup (szFile);#else fn = GNUNET_expand_file_name (ectx, filename);#endif if (oflag & O_CREAT) { va_list arg; va_start (arg, oflag); mode = va_arg (arg, int); va_end (arg); } else { mode = 0; }#ifdef MINGW /* set binary mode */ oflag |= O_BINARY;#endif ret = OPEN (fn, oflag, mode); if (ret == -1) GNUNET_GE_LOG_STRERROR_FILE (ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, "open", fn); GNUNET_free (fn); return ret;}#define COPY_BLK_SIZE 65536/** * Copy a file. * @return GNUNET_OK on success, GNUNET_SYSERR on error */intGNUNET_disk_file_copy (struct GNUNET_GE_Context *ectx, const char *src, const char *dst){ char *buf; unsigned long long pos; unsigned long long size; unsigned long long len; int in; int out; if (GNUNET_OK != GNUNET_disk_file_size (ectx, src, &size, GNUNET_YES)) return GNUNET_SYSERR; pos = 0; in = GNUNET_disk_file_open (ectx, src, O_RDONLY | O_LARGEFILE); if (in == -1) return GNUNET_SYSERR; out = GNUNET_disk_file_open (ectx, dst, O_LARGEFILE | O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); if (out == -1) { GNUNET_disk_file_close (ectx, src, in); return GNUNET_SYSERR; } buf = GNUNET_malloc (COPY_BLK_SIZE); while (pos < size) { len = COPY_BLK_SIZE; if (len > size - pos) len = size - pos; if (len != READ (in, buf, len)) goto FAIL; if (len != WRITE (out, buf, len)) goto FAIL; pos += len; } GNUNET_free (buf); GNUNET_disk_file_close (ectx, src, in); GNUNET_disk_file_close (ectx, dst, out); return GNUNET_OK;FAIL: GNUNET_free (buf); GNUNET_disk_file_close (ectx, src, in); GNUNET_disk_file_close (ectx, dst, out); return GNUNET_SYSERR;}/* end of storage.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -