/** Change the size of a file */ static int fuse_truncate(const char *path, off_t size) { #ifndef HIDE_COMPLETE tolog(path); tolog(" - truncate "); { char buf[80]; sprintf(buf, "%d\n", (int) size); tolog(buf); } #endif // Fool programs into thinking they can overwite files if (g_strcmp0(path, "/" USAGE_FILE) == 0) { return 0; } if (isOffset(path) || isMetaFilename(path)) { return 0; } return -ENOENT; }
/** Read data from an open file * * Read should return exactly the number of bytes requested except * on EOF or error, otherwise the rest of the data will be * substituted with zeroes. An exception to this is when the * 'direct_io' mount option is specified, in which case the return * value of the read system call will reflect the return value of * this operation. * * Changed in version 2.2 */ static int fuse_read(const char *path, char *buf, size_t buf_size, off_t offset, struct fuse_file_info *info) { #ifndef HIDE_COMPLETED tolog(path); tolog(" - read\n"); #endif if (g_strcmp0(path, "/" USAGE_FILE) == 0) { size_t size = buf_size; if (size > (strlen(USAGE_FILE_CONTENT) - offset)) { size = strlen(USAGE_FILE_CONTENT) - offset; } if (size > 0) { memcpy(buf, USAGE_FILE_CONTENT + offset, size); } return size; } if (isOffset(path)) { off_t file_offset = -1; off_t file_length = -1; sscanf(path + 1, "%llu-%llu", (unsigned long long *) &file_offset, (unsigned long long *) &file_length); fseeko(mappedFile, offset + file_offset, SEEK_SET); if ((file_length == -1) || (file_length > buf_size)) { file_length = buf_size; } int ret = fread(buf, 1, file_length, mappedFile); return ret; } if (isMetaFilename(path)) { return 0; } return -ENOENT; }
/** File open operation * * No creation(O_CREAT, O_EXCL) and by default also no * truncation(O_TRUNC) flags will be passed to open(). If an * application specifies O_TRUNC, fuse first calls truncate() * and then open(). Only if 'atomic_o_trunc' has been * specified and kernel version is 2.6.24 or later, O_TRUNC is * passed on to open. * * Unless the 'default_permissions' mount option is given, * open should check if the operation is permitted for the * given flags. Optionally open may also return an arbitrary * filehandle in the fuse_file_info structure, which will be * passed to all file operations. * * Changed in version 2.2 * * struct fuse_file_info { * int flags; // Open flags. Available in open() and release() * unsigned long fh_old; // Old file handle, don't use * int writepage; // In case of a write operation indicates if * // this was caused by a writepage * unsigned int direct_io : 1; // Can be filled in by open, to * // use direct I/O on this file. * // Introduced in version 2.4 * unsigned int keep_cache : 1; // Can be filled in by open, to * // indicate, that cached file data * // need not be invalidated. * // Introduced in version 2.4 * unsigned int flush : 1; // Indicates a flush operation. Set * // in flush operation, also maybe set * // in highlevel lock operation and * // lowlevel release operation. * // Introduced in version 2.6 * unsigned int nonseekable : 1; // Can be filled in by open, to * // indicate that the file is not * // seekable. * // Introduced in version 2.8 * unsigned int padding : 28; // Padding. Do not use * uint64_t fh; // File handle. * // May be filled in by filesystem in open(). * // Available in all other file operations * uint64_t lock_owner; // Lock owner id. Available in locking * // operations and flush * }; */ static int fuse_open(const char *path, struct fuse_file_info *info) { #ifndef HIDE_COMPLETED tolog(path); tolog(" - open\n"); #endif if (g_strcmp0(path, "/" USAGE_FILE) == 0) { return 0; } if (isOffset(path) || isMetaFilename(path)) { return 0; } return -ENOENT; }
/** Write data to an open file * * Write should return exactly the number of bytes requested * except on error. An exception to this is when the 'direct_io' * mount option is specified(see read operation). * * Changed in version 2.2 */ static int fuse_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *info) { #ifndef HIDE_COMPLETE tolog(path); tolog(" - write\n"); #endif // Fool programs into thinking they can write if (g_strcmp0(path, "/" USAGE_FILE) == 0) { return size; } if (isOffset(path) || isMetaFilename(path)) { return size; } return -ENOENT; }
int main(int argc, const char **argv) { int res = 0; int optCount = 0; dbgIn = stdin; conOut = stdout; (void)conIn; (void)dbgOut; memset(&cache, 0, sizeof(LIST)); memset(&sources, 0, sizeof(LIST)); stat_clear(&summ); memset(&revinfo, 0, sizeof(REVINFO)); clearLastLine(); optionInit(argc, argv); optCount = optionParse(argc, argv); if (optCount < 0) { return optCount; } argc -= optCount; if (opt_Revision && (strcmp(opt_Revision, "update") == 0)) { res = updateSvnlog(); return res; } if (check_directory(opt_force)) return 3; create_cache(opt_force, 0); if (opt_exit) return 0; read_cache(); l2l_dbg(4, "Cache read complete\n"); if (set_LogFile(&logFile)) return 2; l2l_dbg(4, "opt_logFile processed\n"); if (opt_Pipe) { l2l_dbg(3, "Command line: \"%s\"\n",opt_Pipe); if (!(dbgIn = POPEN(opt_Pipe, "r"))) { dbgIn = stdin; //restore l2l_dbg(0, "Could not popen '%s' (%s)\n", opt_Pipe, strerror(errno)); free(opt_Pipe); opt_Pipe = NULL; } } l2l_dbg(4, "opt_Pipe processed\n"); if (argc > 1) { // translate {<exefile> <offset>} int i = 1; const char *exefile = NULL; const char *offset = NULL; char Line[LINESIZE + 1]; while (i < argc) { Line[0] = '\0'; offset = argv[optCount + i++]; if (isOffset(offset)) { if (exefile) { l2l_dbg(2, "translating %s %s\n", exefile, offset); translate_file(exefile, my_atoi(offset), Line); printf("%s\n", Line); report(conOut); } else { l2l_dbg(0, "<exefile> expected\n"); res = 3; break; } } else { // Not an offset so must be an exefile: exefile = offset; } } } else { // translate logging from stdin translate_files(dbgIn, conOut); } if (logFile) fclose(logFile); if (opt_Pipe) PCLOSE(dbgIn); return res; }
/** Get file attributes. * * Similar to stat(). The 'st_dev' and 'st_blksize' fields are * ignored. The 'st_ino' field is ignored except if the 'use_ino' * mount option is given. * * struct stat { * dev_t st_dev; // ID of device containing file * ino_t st_ino; // inode number * mode_t st_mode; // protection * nlink_t st_nlink; // number of hard links * uid_t st_uid; // user ID of owner * gid_t st_gid; // group ID of owner * dev_t st_rdev; // device ID (if special file) * off_t st_size; // total size, in bytes * blksize_t st_blksize; // blocksize for file system I/O * blkcnt_t st_blocks; // number of 512B blocks allocated * time_t st_atime; // time of last access * time_t st_mtime; // time of last modification * time_t st_ctime; // time of last status change * }; */ static int fuse_getattr(const char *path, struct stat *buf) { #ifndef HIDE_COMPLETED tolog(path); tolog(" - getattr\n"); #endif struct timeval tv; if (gettimeofday(&tv, NULL) == 0) { buf->st_atime = tv.tv_sec; buf->st_mtime = tv.tv_sec; buf->st_ctime = tv.tv_sec; } buf->st_uid = FILE_UID; buf->st_gid = FILE_GID; if (isDirectory(path)) { buf->st_mode = S_IFDIR | S_IRWXU; buf->st_nlink = 2; return 0; } if (isSymlink(path)) { buf->st_mode = S_IFLNK | S_IRWXU; buf->st_nlink = 1; return 0; } if (isOffset(path)) { // Even though it's read-only, the write flag is there in case // a library we use requires write access. It won't be able to write to // the file of course, but it will think it can. buf->st_mode = S_IFREG | S_IRUSR | S_IWUSR; buf->st_nlink = 1; off_t offset = -1; off_t length = -1; sscanf(path + 1, "%llu-%llu", (unsigned long long *) &offset, (unsigned long long *) &length); if ((length == -1) || (length > (mappedFile_size - offset))) { if (mappedFile_size < offset) { length = 0; } else { length = mappedFile_size - offset; } } buf->st_size = length; buf->st_blocks = (buf->st_size + 511) / 512; return 0; } if (isMetaFilename(path)) { // While we are aware of such a beast, these are all zero sized. buf->st_mode = S_IFREG | S_IRUSR | S_IWUSR; buf->st_nlink = 1; buf->st_size = 0; buf->st_blocks = 0; return 0; } // They might be enquiring about the usage file. if (g_strcmp0(path, "/" USAGE_FILE) == 0) { buf->st_mode = S_IFREG | S_IRUSR | S_IWUSR; buf->st_nlink = 1; buf->st_size = strlen(USAGE_FILE_CONTENT); buf->st_blocks = (buf->st_size + 511) / 512; return 0; } return -ENOENT; }