254
254
/* procfs file operations */
258
*----------------------------------------------------------------------------
262
* Copy block name from user buffer into kernel space, canonicalize it
263
* by removing all trailing path separators, and execute desired block
267
* 0 on success, negative error code on failure.
272
*----------------------------------------------------------------------------
276
ExecuteBlockOp(const char __user *buf, // IN: buffer with name
277
const os_blocker_id_t blocker, // IN: blocker ID (file)
278
int (*blockOp)(const char *filename, // IN: block operation
279
const os_blocker_id_t blocker))
287
return PTR_ERR(name);
290
for (i = strlen(name) - 1; i >= 0 && name[i] == '/'; i--) {
294
retval = i < 0 ? -EINVAL : blockOp(name, blocker);
257
302
*----------------------------------------------------------------------------
277
322
loff_t *ppos) // IN/OUT: File offset (unused)
284
if (cmd == VMBLOCK_LIST_FILEBLOCKS) {
285
BlockListFileBlocks();
291
* XXX: Can we GPL our modules already? This is gross. On kernels 2.6.6
292
* through 2.6.12 when CONFIG_AUDITSYSCALL is defined, putname() turns into
293
* a macro that calls audit_putname(), which happens to only be exported to
294
* GPL modules (until 2.6.9). Here we work around this by calling
295
* __getname() and __putname() to get our path buffer directly,
296
* side-stepping the syscall auditing and doing the copy from user space
297
* ourself. Change this back once we GPL the module.
299
filename = __getname();
301
Warning("ControlFileOpWrite: Could not obtain memory for filename.\n");
306
* XXX: __getname() returns a pointer to a PATH_MAX-sized buffer.
307
* Hard-coding this size is also gross, but it's our only option here and
308
* InodeOpLookup() already set a bad example by doing this.
310
ret = strncpy_from_user(filename, buf, PATH_MAX);
311
if (ret < 0 || ret >= PATH_MAX) {
312
Warning("ControlFileOpWrite: Could not access provided user buffer.\n");
313
ret = ret < 0 ? ret : -ENAMETOOLONG;
317
/* Remove all trailing path separators. */
318
for (i = ret - 1; i >= 0 && filename[i] == '/'; i--) {
328
327
case VMBLOCK_ADD_FILEBLOCK:
329
ret = BlockAddFileBlock(filename, file);
328
ret = ExecuteBlockOp(buf, file, BlockAddFileBlock);
331
331
case VMBLOCK_DEL_FILEBLOCK:
332
ret = BlockRemoveFileBlock(filename, file);
332
ret = ExecuteBlockOp(buf, file, BlockRemoveFileBlock);
336
case VMBLOCK_LIST_FILEBLOCKS:
337
BlockListFileBlocks();
335
343
Warning("ControlFileOpWrite: unrecognized command (%u) recieved\n",